npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@michaelcuneo/markdown-editor

v0.0.31

Published

A Svelte-based Markdown editor component with ProseMirror and CodeMirror integration.

Readme

@michaelcuneo/markdown-editor

A modern WYSIWYM Markdown editor for Svelte 5, built with ProseMirror and CodeMirror 6.

It supports live Markdown editing, task lists, fenced code blocks with syntax highlighting, keyboard shortcuts, and a fully themeable light/dark design system powered by CSS variables.


Live Demo

Demo: https://markdown-editor.michaelcuneo.com.au

Try headings, inline formatting, code fences, lists, and interactive task items rendered live as you type.

Built with Svelte 5, TypeScript, ProseMirror, and CodeMirror 6.


Features

  • WYSIWYM Markdown editing
  • Fast WYSIWYG ↔ Markdown source switching
  • Two-way binding with bind:markdown
  • Task lists with interactive checkboxes
  • Image manipulation tools (replace, remove, caption, drag, resize)
  • Optional responsive image optimization controls
  • Fenced code blocks with CodeMirror 6
  • Syntax highlighting
  • Keyboard shortcuts
  • Read-only and runtime editable modes
  • Per-document reset support with docId
  • Fully themeable via CSS custom properties
  • Optional HTML sanitization with DOMPurify
  • Works in SSR and SPA environments

Install

Install the package plus its peer dependencies:

npm install @michaelcuneo/markdown-editor \
  prosemirror-state \
  prosemirror-view \
  prosemirror-model \
  prosemirror-commands \
  prosemirror-markdown \
  prosemirror-history \
  prosemirror-keymap \
  prosemirror-inputrules \
  prosemirror-schema-list \
  codemirror \
  @codemirror/state \
  @codemirror/view \
  @codemirror/language \
  @codemirror/theme-one-dark \
  @codemirror/lang-javascript \
  @codemirror/lang-markdown \
  @codemirror/lang-python

If you use pnpm:

pnpm add @michaelcuneo/markdown-editor \
  prosemirror-state \
  prosemirror-view \
  prosemirror-model \
  prosemirror-commands \
  prosemirror-markdown \
  prosemirror-history \
  prosemirror-keymap \
  prosemirror-inputrules \
  prosemirror-schema-list \
  codemirror \
  @codemirror/state \
  @codemirror/view \
  @codemirror/language \
  @codemirror/theme-one-dark \
  @codemirror/lang-javascript \
  @codemirror/lang-markdown \
  @codemirror/lang-python

These are peer dependencies so your app can control versions and avoid conflicts.


Usage

<script lang="ts">
	import { SvelteMarkdownEditor } from '@michaelcuneo/markdown-editor';
	import '@michaelcuneo/markdown-editor/styles.css';

	let content = `# Welcome

This is a **Markdown editor** built with Svelte 5.

- [x] Task lists
- [ ] Live preview
- [ ] Syntax highlighting

\`\`\`ts
function greet(name: string): string {
  return \`Hello, \${name}!\`;
}
\`\`\`
`;
</script>

<SvelteMarkdownEditor bind:markdown={content} />

Two-Way Binding

The editor is reactive by design.

<script lang="ts">
	import { SvelteMarkdownEditor } from '@michaelcuneo/markdown-editor';

	let markdown = '# Hello';
</script>

<SvelteMarkdownEditor bind:markdown />

<p>Characters: {markdown.length}</p>

Props

| Prop | Type | Bindable | Default | Description | | -------------- | ------------------------------- | -------- | ----------- | ------------------------------------------------------------------------------------------------------------------ | | markdown | string | ✅ | '' | The markdown content. Updates as the user types. | | toolbar | boolean | | true | Whether to render the toolbar above the editor. | | imageQueue | Record<string, MarkdownImage> | ✅ | {} | Image queue map, updated as images are added, optimised, and uploaded. | | clearDraft | boolean | ✅ | false | Set to true to clear the auto-saved draft. Resets to false after. | | docId | string | | 'default' | Namespaces the auto-saved draft in localStorage. Change per document. | | editable | boolean | | true | Whether the editor content is editable. | | bare | boolean | | false | Removes all border, background, and toolbar for display-only/readonly markdown. Best used with editable={false}. | | allowHtml | boolean | | false | Allow raw HTML passthrough in WYSIWYG mode. | | viewMode | 'wysiwyg' \| 'markdown' | ✅ | 'wysiwyg' | Switches between rich-text and raw markdown source mode. | | imageOptions | MarkdownImageOptions | | {} | Image handling options — storage strategy, optimization, upload callback. |

View modes

  • Markdown mode shows a raw markdown source textarea for direct editing.

imageOptions (optional)

The editor stays neutral by default: images are added to imageQueue and previewed locally. This README focuses on built-in image manipulation + optimization behavior.

| Key | Type | Default | Description | | -------------------- | ------------------------------------ | ------------------------------------------ | -------------------------------------------------------------------- | | enableOptimization | boolean | false | Enables Sharpless-based optimization controls in image UI. | | optimizeOnDrop | boolean | true | If optimization is enabled, auto-optimizes dropped/pasted images. | | quality | number | 0.82 | Default optimization quality target. | | formats | string[] | ['image/webp','image/jpeg','image/avif'] | Output formats requested from optimizer. | | targets | { width: number; label: string }[] | Built-in responsive targets | Output widths/labels for responsive variants and generated srcSet. | | preferredFormat | string | 'image/webp' | Preferred format for preview + responsive source selection. |

Image manipulation behavior

  • Inline caption editing (alt text)
  • Replace image from local file picker
  • Remove image node from document
  • Drag-to-reorder image blocks
  • Corner resize handles with persisted dimensions
  • Optional optimization panel (quality, widths, format) with Apply action

Example: keep everything local (no uploads)

<script lang="ts">
	import { SvelteMarkdownEditor } from '@michaelcuneo/markdown-editor';

	let markdown = '# Hello';
	let imageQueue = {};
</script>

<SvelteMarkdownEditor
	bind:markdown
	{imageQueue}
	imageOptions={{
		enableOptimization: true,
		storage: 'local',
		optimizeOnDrop: false
	}}
/>

Save contract (consumer-owned)

On Save, host applications decide what to do with imageQueue and generated variants. Typical flows include persisting markdown as-is, replacing refs, uploading files, or discarding transient queue state.


Examples

Reset on document change

<script lang="ts">
	import { SvelteMarkdownEditor } from '@michaelcuneo/markdown-editor';

	let docId = 'intro';
	let markdown = '# Welcome';

	function loadNewDoc() {
		docId = 'notes';
		markdown = '## Empty new document';
	}
</script>

<button onclick={loadNewDoc}>New Document</button>

<SvelteMarkdownEditor bind:markdown {docId} />

Display-only/readonly Markdown (bare mode)

<script lang="ts">
	import { SvelteMarkdownEditor } from '@michaelcuneo/markdown-editor';

	let markdown = '# Hello';
</script>

<SvelteMarkdownEditor bind:markdown {markdown} editable={false} bare={true} />

This renders the markdown with no border, background, or toolbar—ideal for embedding read-only markdown content in your app.


Start in Markdown source mode

<script lang="ts">
	import { SvelteMarkdownEditor } from '@michaelcuneo/markdown-editor';

	let markdown = '# Hello';
	let viewMode: 'wysiwyg' | 'markdown' = 'markdown';
</script>

<SvelteMarkdownEditor bind:markdown bind:viewMode />

Toolbar & Shortcuts

| Action | Shortcut | | ----------- | ------------------------ | | Bold | Ctrl/Cmd + B | | Italic | Ctrl/Cmd + I | | Headings | Toolbar or # syntax | | Blockquote | > then space | | Lists | -, *, 1. then space | | Task item | - [ ] or - [x] | | Code block | ``` + language + Enter | | Link | Ctrl/Cmd + K | | View mode | Ctrl/Cmd + Shift + M | | Undo / Redo | Ctrl/Cmd + Z / Shift + Z |


Markdown Support

  • Headings
  • Bold, italic, strikethrough
  • Inline code and fenced code blocks
  • Blockquotes
  • Lists and task lists
  • Tables (GFM)
  • Links
  • Horizontal rules
  • Syntax-highlighted code blocks

Styling & Theming

Uses CSS custom properties under the --md-* namespace.

Global theme

:root {
	--md-bg: #fdfdfd;
	--md-fg: #222;
	--md-accent: #0b57d0;
	--md-code-bg: #f9fafb;
	--md-code-fg: #0056b3;
}

Per-instance theme

<div class="markdown-theme-ocean">
	<SvelteMarkdownEditor bind:markdown />
</div>
.markdown-theme-ocean {
	--md-bg: #001a26;
	--md-fg: #cde9ff;
	--md-accent: #00b7ff;
	--md-code-bg: #011e2a;
	--md-selection-bg: #00384d;
}

Styles

import '@michaelcuneo/markdown-editor/styles.css';

CodeMirror Integration

  • Uses One Dark-style theme in dark mode
  • GitHub-style palette in light mode
  • Fully overrideable via your own theme configuration

Architecture

| Layer | Role | | -------------- | ----------------------------------------- | | ProseMirror | Document model, schema, commands, history | | CodeMirror 6 | Fenced code block editor | | Custom plugins | Task lists, sync, enhancements | | DOMPurify | HTML sanitization | | Svelte 5 | Reactive component layer |


Compatibility

| Feature | Status | | ----------------- | ------ | | Svelte 5 | ✅ | | TypeScript | ✅ | | SSR + SPA | ✅ | | Light/Dark themes | ✅ | | CSS variables | ✅ | | Task lists | ✅ | | CodeMirror blocks | ✅ | | One Dark support | ✅ | | docId / editable | ✅ |


License

MIT © Michael Cuneo