- Name:
markdown - UI: Toast UI Editor (Docs)
- Data type:
markdown string
The markdown widget provides a full fledged text editor allowing users to format text with features such as headings and blockquotes. Users can change their editing view with a handy toggle button.
Please note: If you want to use your markdown editor to fill a markdown file contents after its frontmatter, you will have to name the field body so Static CMS recognizes it and saves the file accordingly.
Widget Options
For common options, see Common widget options.
|
Name |
Type |
Default |
Description |
|---|---|---|---|
|
default |
string |
|
Optional. The default value for the field. Accepts markdown content |
|
media_folder |
string |
Optional. Specifies the folder path where uploaded files should be saved, relative to the base of the repo | |
|
public_folder |
string |
Optional. Specifies the folder path where the files uploaded by the media library will be accessed, relative to the base of the built site | |
|
media_library |
Media Library Options |
|
Optional. Media library settings to apply when the media library is opened by the current widget. See Media Library |
|
choose_url |
boolean |
|
Optional. When set to |
|
toolbar_buttons |
object |
[] |
Optional. Specifies which toolbar items to show for the markdown widget. See Toolbar Customization |
|
show_raw |
boolean |
|
Optional. Specifies if the raw markdown editor should be shown |
Example
name: body
label: Body
widget: markdownname: 'body',
label: 'Body',
widget: 'markdown',This would render as:

Please note: The markdown widget outputs a raw markdown string. Your static site generator may or may not render the markdown to HTML automatically. Consult with your static site generator’s documentation for more information about rendering markdown.
Toolbar Customization
|
Name |
Type |
Default |
Description |
|---|---|---|---|
|
main |
object |
See Main Toolbar |
Optional. A list of buttons and menus for the top level toolbar |
|
empty |
object |
See Empty Toolbar |
Optional. A list of buttons and menus for the popup toolbar when in an empty paragraph |
|
selection |
object |
Optional. A list of buttons and menus for the popup toolbar when selecting text outside of a table cell | |
|
table_empty |
object |
Optional. A list of buttons and menus for the popup toolbar when in an empty table cell | |
|
table_selection |
object |
Optional. A list of buttons and menus for the popup toolbar when selecting text in a table cell |
Options
All toolbars can be customized with a list consisting of buttons and dropdown menus.
Buttons
Buttons can be configured simply with their name. The following options are available:
blockquoteboldcodecode-blockdecrease-indentdelete-columndelete-rowdelete-tablefile-linkfontimageincrease-indentinsert-columninsert-rowinsert-tableitalicordered-listshortcodestrikethroughunordered-list
Menus
The following options are available for menus:
|
Name |
Type |
Description |
|---|---|---|
|
label |
string |
The name and tooltip label for the menu |
|
icon |
string |
Optional. The icon to use for the menu. If not supplied a default add icon will be used |
|
groups |
list of groups |
A list groups of menu items. Each group is separated by a divider |
Menu Groups
The following options are available for menu groups:
|
Name |
Type |
Description |
|---|---|---|
|
items |
list of strings |
The name of the toolbar buttons in the group. All buttons are available in menus except |
Default Values
Below are the default values for the various toolbars:
Main Toolbar
main:
- bold
- italic
- strikethrough
- code
- font
- unordered-list
- ordered-list
- decrease-indent
- increase-indent
- shortcode
- label: Insert
groups:
- items:
- blockquote
- code-block
- items:
- insert-table
- items:
- image
- file-linkmain: [
'bold',
'italic',
'strikethrough',
'code',
'font',
'unordered-list',
'ordered-list',
'decrease-indent',
'increase-indent',
'shortcode',
{
label: 'Insert',
groups: [
{
items: ['blockquote', 'code-block'],
},
{
items: ['insert-table'],
},
{
items: ['image', 'file-link'],
},
],
},
];Empty Toolbar
empty: []empty: [];Selection Toolbar
selection:
- bold
- italic
- strikethrough
- code
- font
- file-linkselection: ['bold', 'italic', 'strikethrough', 'code', 'font', 'file-link'];Empty Table Cell Toolbar
table_empty:
- bold
- italic
- strikethrough
- code
- insert-row
- delete-row
- insert-column
- delete-column
- delete-table
- file-link
- image
- shortcodetable_empty: [
'bold',
'italic',
'strikethrough',
'code',
'insert-row',
'delete-row',
'insert-column',
'delete-column',
'delete-table',
'file-link',
'image',
'shortcode',
];Table Selection Toolbar
table_selection:
- bold
- italic
- strikethrough
- code
- insert-row
- delete-row
- insert-column
- delete-column
- delete-table
- file-linktable_selection: [
'bold',
'italic',
'strikethrough',
'code',
'insert-row',
'delete-row',
'insert-column',
'delete-column',
'delete-table',
'file-link',
];Shortcodes
Shortcodes can be added to customize the Markdown editor via registerShortcode.
Usage
[youtube|p6h-rYSVX90]CMS.registerShortcode('youtube', {
label: 'YouTube',
openTag: '[',
closeTag: ']',
separator: '|',
toProps: args => {
if (args.length > 0) {
return { src: args[0] };
}
return { src: '' };
},
toArgs: ({ src }) => {
return [src];
},
control: ({ src, onChange }) => {
return h('span', {}, [
h('input', {
key: 'control-input',
value: src,
onChange: event => {
onChange({ src: event.target.value });
},
}),
h(
'iframe',
{
key: 'control-preview',
width: '420',
height: '315',
src: `https://www.youtube.com/embed/${src}`,
},
'',
),
]);
},
preview: ({ src }) => {
return h(
'span',
{},
h(
'iframe',
{
width: '420',
height: '315',
src: `https://www.youtube.com/embed/${src}`,
},
'',
),
);
},
});import CMS from '@staticcms/core';
CMS.registerShortcode('youtube', {
label: 'YouTube',
openTag: '[',
closeTag: ']',
separator: '|',
toProps: args => {
if (args.length > 0) {
return { src: args[0] };
}
return { src: '' };
},
toArgs: ({ src }) => {
return [src];
},
control: ({ src, onChange }) => {
return (
<span>
<input
key="control-input"
value={src}
onChange={event => {
onChange({ src: event.target.value });
}}
/>
<iframe
key="control-preview"
width="420"
height="315"
src={`https://web.archive.org/web/20240224001642/https://www.youtube.com/embed/${src}`}
/>
</span>
);
},
preview: ({ src }) => {
return (
<span>
<iframe width="420" height="315" src={`https://web.archive.org/web/20240224001642/https://www.youtube.com/embed/${src}`} />
</span>
);
},
});
import CMS from '@staticcms/core';
interface YouTubeShortcodeProps {
src: string;
}
CMS.registerShortcode<YouTubeShortcodeProps>('youtube', {
label: 'YouTube',
openTag: '[',
closeTag: ']',
separator: '|',
toProps: args => {
if (args.length > 0) {
return { src: args[0] };
}
return { src: '' };
},
toArgs: ({ src }) => {
return [src];
},
control: ({ src, onChange }) => {
return (
<span>
<input
key="control-input"
value={src}
onChange={event => {
onChange({ src: event.target.value });
}}
/>
<iframe
key="control-preview"
width="420"
height="315"
src={`https://web.archive.org/web/20240224001642/https://www.youtube.com/embed/${src}`}
/>
</span>
);
},
preview: ({ src }) => {
return (
<span>
<iframe width="420" height="315" src={`https://web.archive.org/web/20240224001642/https://www.youtube.com/embed/${src}`} />
</span>
);
},
});Interacting With The Media Library
If you want to use the media library in your shortcode you will need to use the useMediaInsert and useMediaAsset hooks.
useMediaInsert– Takes the current url to your media, details about your field and a callback method for when new media is uploaded. If you want to select folders instead of files, set theforFoldervariable in options.useMediaAsset– Transforms your stored url into a usable url for displaying as a preview.
const ImageControl = ({ src, onChange, controlProps }) => {
const { collection, field, entry } = controlProps;
const handleChange = ({ path }) => {
onChange({ src: path });
};
const handleOpenMediaLibrary = useMediaInsert(
src,
{ collection: collection, field },
handleChange,
);
const assetSource = useMediaAsset(src, collection, field, entry);
return [
h('button', { type: 'button', onClick: handleOpenMediaLibrary }, 'Upload'),
h('img', { role: 'presentation', src: assetSource }),
];
};import useMediaAsset from '@staticcms/core/lib/hooks/useMediaAsset';
import useMediaInsert from '@staticcms/core/lib/hooks/useMediaInsert';
const ImageControl = ({ src, onChange, controlProps }) => {
const { collection, field, entry } = controlProps;
const handleChange = ({ path }) => {
onChange({ src: path });
};
const handleOpenMediaLibrary = useMediaInsert(
src,
{ collection: collection, field },
handleChange,
);
const assetSource = useMediaAsset(src, collection, field, entry);
return (
<>
<button type="button" onClick={handleOpenMediaLibrary}>
Upload
</button>
<img role="presentation" src={assetSource} />
</>
);
};import useMediaAsset from '@staticcms/core/lib/hooks/useMediaAsset';
import useMediaInsert from '@staticcms/core/lib/hooks/useMediaInsert';
import type { WidgetControlProps, MediaPath } from '@staticcms/core/interface';
import type { FC } from 'react';
const FileControl: FC<WidgetControlProps<string, MyField>> = ({ src, onChange, controlProps }) => {
const { collection, field, entry } = controlProps;
const handleChange = ({ path }: MediaPath) => {
onChange({ src: path });
};
const handleOpenMediaLibrary = useMediaInsert(src, { collection, field }, handleChange);
const assetSource = useMediaAsset(value, collection, field, entry);
return (
<>
<button type="button" onClick={handleOpenMediaLibrary}>
Upload
</button>
<img role="presentation" src={assetSource} />
</>
);
};