Honeycomb

Markdown Editor

CodeMirror-based Markdown editor with toolbar, live preview, image upload, draft auto-save, and Hive blockchain integration.

Full Toolbar

Bold, italic, headings, lists, tables, code blocks, links, images, spoilers

Live Preview

Split, tab, or off -- three preview modes

Hive Image Upload

Upload to Hive imagehoster with signing challenge

Draft Auto-save

LocalStorage drafts with debounce and TTL

Dark Mode

Auto, light, or dark theme (one-dark-pro)

Plugin System

Custom toolbar items, keyboard shortcuts, paste handlers

CodeMirror peer dependencies

The editor uses CodeMirror 6 internally. You need to install the CodeMirror packages as peer dependencies alongside the honeycomb package.

Installation

pnpm add @codemirror/state @codemirror/view @codemirror/language @codemirror/lang-markdown @codemirror/commands @codemirror/theme-one-dark

Basic Usage

<script lang="ts">
  import { MdEditor } from "@hiveio/honeycomb-svelte";

  let content = $state("");
</script>

<MdEditor value={content} onChange={(val) => (content = val)} />

Preview

Write your markdown here...

Examples

Hive Image Upload

Use create_hive_upload_handler to upload images to the Hive imagehoster with a signing challenge.

<script lang="ts">
  import { MdEditor, create_hive_upload_handler } from "@hiveio/honeycomb-svelte";

  let { username }: { username: string } = $props();
  let content = $state("");

  const upload_handler = $derived(
    create_hive_upload_handler({
      imageEndpoint: "https://images.hive.blog/",
      username,
      signChallenge: async (challenge) => {
        return await keychain.requestSignBuffer(username, challenge);
      },
    }),
  );
</script>

<MdEditor
  value={content}
  onChange={(val) => (content = val)}
  config={{ uploadHandler: upload_handler }}
/>

Preview Modes

"split"

Editor and preview side by side

"tab"

Switchable Write/Preview tabs

"off"

Editor only (default)

<!-- Side-by-side editor and preview -->
<MdEditor
  value={content}
  onChange={(val) => (content = val)}
  config={{ previewMode: "split" }}
/>

<!-- Switchable Write/Preview tabs -->
<MdEditor
  value={content}
  onChange={(val) => (content = val)}
  config={{ previewMode: "tab" }}
/>

Custom Toolbar

Filter or reorder DEFAULT_TOOLBAR to create a minimal editor.

<script lang="ts">
  import { MdEditor, DEFAULT_TOOLBAR } from "@hiveio/honeycomb-svelte";

  let content = $state("");

  const minimal_toolbar = DEFAULT_TOOLBAR.filter(
    (item) =>
      item.type === "bold" ||
      item.type === "italic" ||
      item.type === "link" ||
      item.type === "image" ||
      item.type === "separator",
  );
</script>

<MdEditor
  value={content}
  onChange={(val) => (content = val)}
  config={{ toolbar: minimal_toolbar }}
/>

Draft Auto-save

Enable draft auto-save to localStorage with configurable debounce and TTL.

<MdEditor
  value={content}
  onChange={(val) => (content = val)}
  config={{
    draftConfig: {
      enabled: true,
      key: "post-draft-my-post",
      debounceMs: 1000,
      ttlMs: 7 * 24 * 60 * 60 * 1000,
    },
  }}
/>

Dark Mode

The "auto" value follows the system preference via prefers-color-scheme.

<!-- "auto" follows system preference (default) -->
<MdEditor
  value={content}
  onChange={(val) => (content = val)}
  config={{ theme: "auto" }}
/>

<!-- Force dark -->
<MdEditor
  value={content}
  onChange={(val) => (content = val)}
  config={{ theme: "dark" }}
/>

Props

PropTypeDefaultDescription
valuestring-Markdown content (controlled)
onChange(value: string) => void-Called on content change
configPartial<MdEditorConfig>See config tableEditor configuration
classstring-CSS class on wrapper element
rendererOptionsPartial<RendererOptions>-Options passed to the preview renderer
onFocus() => void-Called when editor gains focus
onBlur() => void-Called when editor loses focus
onUploadStart(file: File) => void-Called when image upload starts
onUploadComplete(result: UploadResult) => void-Called when upload succeeds
onUploadError(error: Error) => void-Called when upload fails
onDraftSave(draft: DraftData) => void-Called when draft is saved
onDraftRestore(draft: DraftData) => void-Called when draft is restored on mount

MdEditorConfig

Pass via the config prop. All fields are optional.

FieldTypeDefaultDescription
placeholderstring-Placeholder text
minHeightnumber300Minimum height in pixels
maxHeightnumber-Maximum height in pixels
autoFocusbooleanfalseFocus editor on mount
toolbarToolbarItem[]DEFAULT_TOOLBARCustom toolbar actions
pluginsEditorPlugin[][]Editor plugins (toolbar items, shortcuts, paste handlers)
uploadHandlerUploadHandler-Image upload handler (enables upload button)
draftConfigDraftConfig-Auto-save draft configuration
previewMode"split" | "tab" | "off""off"Initial preview mode
theme"light" | "dark" | "auto""auto"Editor color theme
convertHiveUrlsbooleanfalseAuto-convert Hive blog URLs to @mention/permlink format

Default Toolbar Actions

Keyboard shortcuts use Mod (Cmd on macOS, Ctrl on Windows/Linux).

ActionTypeShortcut
BoldboldMod-B
ItalicitalicMod-I
StrikethroughstrikethroughMod-Shift-S
Inline CodecodeMod-E
Headingheading-
Quotequote-
Horizontal Rulehorizontal_rule-
Code Blockcode_block-
Tabletable-
LinklinkMod-K
Imageimage-
Spoilerspoiler-
Unordered Listunordered_list-
Ordered Listordered_list-
Task Listtask_list-
Content Renderer