humanonlyweb/writer

Editor

Markdown in, a live preview while you write.

Markdown

<WriterEditor> edits Markdown, held in its v-model. In plain Vue, import WriterEditor.

Examples

Basic

A heading

Some bold, some italic, a link and code.

  • A list

  • A done task

A quote.

Copy code

Source mode

Plain Markdown throughout, with the source highlighted.

Copy code

Uploads

Pass upload and files can be pasted, dropped or picked. It gets the File and resolves to its URL.

Drop, paste or choose an image:

Ready to save

Copy code

links suggests targets as the author types ](, e.g. your site's pages.

Type ]( after some text in brackets: the council

Copy code

Live preview

The document is always Markdown, but it reads like the page:

  • Formatting: marks hide except in the element being edited. **bold** shows its asterisks only while the cursor is in it. Heading, quote and list marks show on the cursor's line.

  • Blocks render with your components. Click or arrow into one and its source opens, framed, in the same spot. Set --writer-block-inset and --writer-block-background to your blocks' padding and background, and the text doesn't jump.

  • Images on their own line are cards: the published figure, with caption and alt text typed in place. Drop, paste or pick a file to fill or replace one.

  • Leaving the editor shows everything as published. The cursor stays put for when you come back.

mode="source" turns it off.

Props

PropTypeDescription
v-modelstringThe Markdown.
labelstringAccessible name. Default: "Markdown editor".
labelledbystringId of the element naming it, instead of label.
describedbystringId of a hint or error.
namestringSubmits the Markdown with its form.
placeholderstring
readonlyboolean
mode"live" | "source"Live preview (default) or plain Markdown.
upload(file: File) => Promise<string>Enables pasting, dropping and picking files. Resolve to the URL.
links(query) => { label, url }[] (or a promise)Suggests link targets after ](.
codeLanguagesLanguageDescription[]Highlighting inside fenced code, e.g. languages from @codemirror/language-data.
extensionsExtensionExtra CodeMirror extensions. Read once, on mount.

Events

EventPayloadWhen
focusThe editor gets focus.
blurIt loses it.
upload-error(error: unknown, file: File)An upload rejected. Its placeholder is gone, or the card's old image is back.

Exposed

Through a template ref:

MemberDescription
readyCodeMirror has loaded.
activeFormatting at the cursor, a Set of command names.
canUploadupload is set.
canUndo, canRedo
uploadingUploads in progress. Save when it's 0.
run(command)Applies a command. image opens the file picker with upload, else inserts an empty card.
insert(text)Replaces the selection.
insertFiles(files)Uploads and inserts files at the cursor.
focus()
view()The CodeMirror EditorView, for anything else.

Keyboard

Mod is Ctrl, or ⌘ on a Mac.

KeysDescription
Mod+B Mod+I Mod+E Mod+KBold, italic, code, link
Mod+Shift+XStrikethrough
Mod+Alt+1 … 3Heading 1–3
Mod+Shift+7 8 9Numbered, bulleted, task list
Mod+Alt+FFootnote
Mod+Z Mod+Shift+ZUndo, redo
EnterNew paragraph (in a quote, inside it); in a list, a new item
Shift+EnterLine break inside the paragraph (\ at the line end)
/ on an empty lineBlock menu
Mod+] Mod+[Indent, outdent

Tab leaves the editor, so keyboard users aren't trapped. Pasting a URL over a selection links it.

Uploads

While a file uploads, the Markdown holds an #upload-… placeholder where its URL will go, and uploading counts what's in flight. Wait for 0 before saving: the URL landing changes the Markdown, so a save-on-change runs again by itself. A placeholder saved anyway renders nothing, and in the editor it's an empty card to fill again.

Loading another document

Change the editor's key. An outside v-model change is applied as an edit, keeping undo history; a new document should start fresh.

Server rendering

The server renders the content as it will read (a <textarea> in source mode). CodeMirror loads in the browser and takes over, keeping anything typed before it did. Pages without an editor never load CodeMirror.