background

Markdown Editor Spec

KoiMDE: Markdown Editor Spec

This document aims to specify a custom JavaScript-based Markdown editor which is easy to use and covers all features supported by Hugo, the fastest static site generator. It’s a WYSIWYG editor which takes over a textarea element in a web app.

Probably the closest editor which is similar (but not identical) is https://simplemde.com/

Tech Alignment

  • Assumed to be delivered in a .js file and a .css file and run in a browser.
  • Compatible with jQuery v1.11.3 (assumed to already be loaded on page).
  • Must work on latest version of Firefox, Chrome and Edge on desktop and mobile/tablet.
  • Internet Explorer support not required.

Parameters & Initialisation

To be invoked with the following params:

  1. ID of the target textarea element
  2. A list of which buttons to display on the toolbar (and in what order they should appear) - if none specified, hide toolbar
  3. Initial Markdown text
  4. URL stub to use for displaying a preview of an image, eg https://sample.org which can then be added to image URLs which are path only (eg missing http: or https:) like /photo.jpg to make https://sample.org/photo.jpg
  5. Function or emit event for handling inserting a new image
  6. Function or emit event for handling editing existing images
  7. Function or emit event for handling inserting a new shortcode
  8. Function or emit event for handling editing existing shortcodes

Must be able to have multiple instances on the same page (attached to different textarea elements).

Must increase size of textarea element to satisfy length of Markdown text.

Must not introduce scrollbar within textarea element (scrollbar on containing page is OK).

Compatible with Markdown formatting

All formatting described on this page needs to be formatted in a WYSIWYG way: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet Except: YouTube Videos

Markdown tags should be removed from display. So, the user won’t see the hashes, asterisks, etc.

Toolbar Buttons

Toolbar to “float” above currently selected line (where the text cursor is). So it will follow the I beam text cursor around the page negating the need for the user to scroll to find it.

Needs to be responsive and stack on smaller screen sizes (use Bootstrap classes if required).

Assumed to use Font Awesome v4.0 icons for the tool bar.

Bold

Example Formatting: *text*

Icon: fa-bold

Keyboard Shortcut: CTRL+B

Italic

Example Formatting: *text*

Icon: fa-italic

Keyboard Shortcut: CTRL+I

Strikethrough

Example Formatting: ~~text~~

Icon: fa-strikethrough

Keyboard Shortcut: None

H1 Heading

Example Formatting: # H1

Icon: fa-h1

Keyboard Shortcut: CTRL+1

H2 Heading

Example Formatting: ## H2

Icon: fa-h2

Keyboard Shortcut: CTRL+2

H3 Heading

Example Formatting: ### H3

Icon: fa-h3

Keyboard Shortcut: CTRL+3

H4 Heading

Example Formatting: #### H4

Icon: fa-heading

Keyboard Shortcut: CTRL+4

H5 Heading

Example Formatting: ##### H5

Icon: fa-heading

Keyboard Shortcut: CTRL+5

H6 Heading

Example Formatting: ###### H6

Icon: fa-heading

Keyboard Shortcut: CTRL+6

Code

Example Formatting: ```text```

Icon: fa-code

Keyboard Shortcut: CTRL+ALT+C

Blockquote

Example Formatting: > text

Icon: fa-quote-left

Keyboard Shortcut: CTRL+’

Bullet list

Example Formatting: * text

Icon: fa-list-ul

Keyboard Shortcut: CTRL+L

Numbered list

Example Formatting: 1. text

Icon: fa-list-ol

Keyboard Shortcut: CTRL+ALT+L

Clear formatting

Example Formatting: text

Icon: fa-eraser

Keyboard Shortcut: CTRL+E

Example Formatting: [link text](https://sample.org)

Icon: fa-link

Keyboard Shortcut: CTRL+K

Insert Image

Example Formatting: ![alt text](https://sample.org/photo.jpg)

Icon: fa-image

Keyboard Shortcut: None

Refer to section below for specific Image functionality.

Insert Horizontal Line

Example Formatting: —

Icon: fa-minus

Keyboard Shortcut: None

Insert Table

Example Formatting:

| Tables        | Are           | Cool  |
| ------------- |:-------------:| -----:|
| col 3 is      | right-aligned | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |

Icon: fa-table

Keyboard Shortcut: None

Insert Shortcode

Example Formatting: {{ % shortcodename % }}

Icon: fa-object-group

Keyboard Shortcut: None

Refer to section below for specific Shortcode functionality.

“WYSIWYG”

Need to style and format text so it appears with expected bold, italic, heading size, etc. however automatically remove the specific Markdown formatting (for example, H1 headings should look like H1 headings but the user can’t see the “# " preceding the text).

Cut (CTRL+X), Copy (CTRL+C) and Paste (CTRL+V) should work and copy the Markdown formatting (for example, if a heading is copied and pasted, the pasted text should also be a heading).

Other shortcuts like Select All (CTRL+A) and Undo (CTRL+Z) should also function.

Undo should have unlimited history.

Copying from other sources (HTML, Word, etc) is NOT expected to be converted to Markdown formatting.

Selecting text, shortcodes or images does NOT allow the user to ‘drag’ or move the selection around using the mouse.

Integration

Need to be able to extract the raw Markdown text from the JS object.

Need to be able to modify the raw Markdown text in the JS object and reload.

Shortcodes

Shortcodes are a specific Hugo concept. Refer to https://gohugo.io/content-management/shortcodes/

Basically, they allow for richer templates by allowing snippets to appear inside Markdown files.

There are 2 styles of shortcodes:

1. Single tag

{{ % shortcodename property1="value" property2="value" % }}

2. Opening and closing tags, a bit like HTML

{{ % shortcodename property1="value" property2="value" % }}

Some amount of markdown with **formatting**.

{{ % /shortcodename }}

More Details on Shortcodes

This should be represented on the textarea as a large icon (fa-object-group) followed by the name of the shortcode. The shortcode should have some shading so the user can tell it’s a shortcode. The remaining properties should be listed in a neat format, eg:

  • property1: value
  • property2: value

If the shortcode contains markdown text (shortcode style #2), this can be represented by a simple phrase “Edit…”

The shortcode cannot be edited directly in the Markdown component. Instead, when an existing Shortcode is clicked, the function (provided) to handle editing a shortcode can be invoked. Parameters include the entire shortcode value from the first {{ % to the last % }}. There needs to be the ability for the function to return a modified shortcode.

The shortcode can be deleted by selecting it and pressing delete or backspace.

The shortcode can be duplicated using Copy and Paste functions.

Images

This should be represented on the textarea as a preview of the image. If it cannot be found (404) then a placeholder should be shown.

The image cannot be edited directly in the Markdown component. Instead, when an existing Image is clicked, the function (provided) to handle editing a image can be invoked. Parameters include the entire image raw markdown value. There needs to be the ability for the function to return modified markdown.

The image can be deleted by selecting it and pressing delete or backspace.

The image can be duplicated using Copy and Paste functions.

Testing & Build Pipeline

Automated functional/unit testing: Not required.

Linting: eslint with airbnb style, see https://github.com/airbnb/javascript

Minification: Not required.

Other JS editor implementations (for inspiration)

A large list can be found here, if filtered by editors that output Markdown:

https://m0ru.github.io/article/js-based-text/markdown-editors/

Keep in touch, contact us today

Got a question? Great! Send us a message and we'll get back to you as soon as we can.

Get in contact