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

<template>
  <MdEditor :value="content" @change="(val) => (content = val)" />
</template>

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

const content = ref("");
</script>

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.

<template>
  <MdEditor
    :value="content"
    @change="(val) => (content = val)"
    :config="{ uploadHandler: upload_handler }"
  />
</template>

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

const props = defineProps<{ username: string }>();
const content = ref("");

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

Preview Modes

"split"

Editor and preview side by side

"tab"

Switchable Write/Preview tabs

"off"

Editor only (default)

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

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

Custom Toolbar

Filter or reorder DEFAULT_TOOLBAR to create a minimal editor.

<template>
  <MdEditor
    :value="content"
    @change="(val) => (content = val)"
    :config="{ toolbar: minimal_toolbar }"
  />
</template>

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

const content = ref("");

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

Draft Auto-save

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

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

Dark Mode

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

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

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

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