
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:
- ID of the target textarea element
- A list of which buttons to display on the toolbar (and in what order they should appear) - if none specified, hide toolbar
- Initial Markdown text
- 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
- Function or emit event for handling inserting a new image
- Function or emit event for handling editing existing images
- Function or emit event for handling inserting a new shortcode
- 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
Insert Link
Example Formatting: [link text](https://sample.org)
Icon: fa-link
Keyboard Shortcut: CTRL+K
Insert Image
Example Formatting: 
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