diff --git a/core/dev-test/config.yml b/core/dev-test/config.yml index 81750a9c..bbcb5b6a 100644 --- a/core/dev-test/config.yml +++ b/core/dev-test/config.yml @@ -56,7 +56,7 @@ collections: required: false - label: Body name: body - widget: mdx + widget: markdown hint: Main content goes here. - name: faq label: FAQ diff --git a/core/src/widgets/markdown/plate/PlateEditor.tsx b/core/src/widgets/markdown/plate/PlateEditor.tsx index 34bd689e..158d5ebf 100644 --- a/core/src/widgets/markdown/plate/PlateEditor.tsx +++ b/core/src/widgets/markdown/plate/PlateEditor.tsx @@ -77,7 +77,12 @@ import { UnorderedListElement, } from './components/nodes/list'; import ParagraphElement from './components/nodes/paragraph/ParagraphElement'; -import { TableCellElement, TableElement, TableRowElement } from './components/nodes/table'; +import { + TableCellElement, + TableElement, + TableHeaderCellElement, + TableRowElement, +} from './components/nodes/table'; import { Toolbar } from './components/toolbar'; import editableProps from './editableProps'; import { createMdPlugins, ELEMENT_SHORTCODE } from './plateTypes'; @@ -152,7 +157,7 @@ const PlateEditor: FC = ({ [ELEMENT_PARAGRAPH]: ParagraphElement, [ELEMENT_TABLE]: TableElement, [ELEMENT_TR]: TableRowElement, - [ELEMENT_TH]: TableCellElement, + [ELEMENT_TH]: TableHeaderCellElement, [ELEMENT_TD]: TableCellElement, [ELEMENT_BLOCKQUOTE]: BlockquoteElement, [ELEMENT_CODE_BLOCK]: CodeBlockElement, diff --git a/core/src/widgets/markdown/plate/components/nodes/blockquote/BlockquoteElement.tsx b/core/src/widgets/markdown/plate/components/nodes/blockquote/BlockquoteElement.tsx index f9ca343d..84387f95 100644 --- a/core/src/widgets/markdown/plate/components/nodes/blockquote/BlockquoteElement.tsx +++ b/core/src/widgets/markdown/plate/components/nodes/blockquote/BlockquoteElement.tsx @@ -1,3 +1,4 @@ +import Box from '@mui/system/Box'; import React from 'react'; import type { MdBlockquoteElement, MdValue } from '@staticcms/markdown'; @@ -7,7 +8,14 @@ import type { FC } from 'react'; const BlockquoteElement: FC> = ({ children, }) => { - return
{children}
; + return ( + + {children} + + ); }; export default BlockquoteElement; diff --git a/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/TableCellElement.tsx b/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/TableCellElement.tsx index 849123b4..4ba0a975 100644 --- a/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/TableCellElement.tsx +++ b/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/TableCellElement.tsx @@ -1,19 +1,30 @@ +import Box from '@mui/material/Box'; import React from 'react'; import type { MdTableCellElement, MdValue } from '@staticcms/markdown'; import type { PlateRenderElementProps } from '@udecode/plate'; import type { FC } from 'react'; -const TableCellElement: FC> = ({ +const TableHeaderCellElement: FC> = ({ attributes, children, nodeProps, }) => { return ( - +
{children}
- +
); }; -export default TableCellElement; +export default TableHeaderCellElement; diff --git a/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/TableHeaderCellElement.tsx b/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/TableHeaderCellElement.tsx new file mode 100644 index 00000000..602aefa8 --- /dev/null +++ b/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/TableHeaderCellElement.tsx @@ -0,0 +1,32 @@ +import Box from '@mui/material/Box'; +import React from 'react'; + +import type { MdTableCellElement, MdValue } from '@staticcms/markdown'; +import type { PlateRenderElementProps } from '@udecode/plate'; +import type { FC } from 'react'; + +const TableHeaderCellElement: FC> = ({ + attributes, + children, + nodeProps, +}) => { + return ( + +
{children}
+
+ ); +}; + +export default TableHeaderCellElement; diff --git a/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/index.ts b/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/index.ts index 845ca5d7..8a417ab6 100644 --- a/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/index.ts +++ b/core/src/widgets/markdown/plate/components/nodes/table/TableCellElement/index.ts @@ -1,2 +1,2 @@ -// eslint-disable-next-line import/prefer-default-export export { default as TableCellElement } from './TableCellElement'; +export { default as TableHeaderCellElement } from './TableHeaderCellElement'; diff --git a/core/src/widgets/markdown/plate/components/nodes/table/TableElement/TableElement.tsx b/core/src/widgets/markdown/plate/components/nodes/table/TableElement/TableElement.tsx index 7046efd5..1cdf0654 100644 --- a/core/src/widgets/markdown/plate/components/nodes/table/TableElement/TableElement.tsx +++ b/core/src/widgets/markdown/plate/components/nodes/table/TableElement/TableElement.tsx @@ -1,3 +1,4 @@ +import Box from '@mui/system/Box'; import { useSelectedCells } from '@udecode/plate'; import React from 'react'; @@ -13,9 +14,19 @@ const TableElement: FC> = ({ useSelectedCells(); return ( - - {children} -
+ + {children ? ( + <> + {children[0]} + {children.slice(1)} + + ) : null} + ); }; diff --git a/core/src/widgets/markdown/plate/components/nodes/table/TableRowElement/TableRowElement.tsx b/core/src/widgets/markdown/plate/components/nodes/table/TableRowElement/TableRowElement.tsx index 1dc3173e..fb1317a1 100644 --- a/core/src/widgets/markdown/plate/components/nodes/table/TableRowElement/TableRowElement.tsx +++ b/core/src/widgets/markdown/plate/components/nodes/table/TableRowElement/TableRowElement.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import Box from '@mui/system/Box'; import type { PlateRenderElementProps } from '@udecode/plate'; import type { FC } from 'react'; @@ -10,9 +11,18 @@ const TableRowElement: FC> = nodeProps, }) => { return ( - + {children} - + ); }; diff --git a/docs/content/docs/widget-markdown.mdx b/docs/content/docs/widget-markdown.mdx index 5cbef035..7f95cc8c 100644 --- a/docs/content/docs/widget-markdown.mdx +++ b/docs/content/docs/widget-markdown.mdx @@ -54,62 +54,71 @@ 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. -## Customization +## Shortcodes -Several customization options are available for the markdown editor. You can register the options by calling `setMarkdownEditorOptions` (also available on the global `window.CMS`). +Shortcodes can be added to customize the Markdown editor via `registerShortcode`. -### Available Options +### Usage -| Name | Type | Default | Description | -| --------------- | ---------------------------- | ----------------------------------- | --------------------------------------------------------------------------- | -| initialEditType | 'markdown'
\| 'wysiwyg' | `'wysiwyg'` | _Optional_. Sets which editor view that is active when the editor is loaded | -| height | string | `'600px'` | _Optional_. Specify the height of the editor | -| toolbarItems | factory of list of strings | See [Toolbar Items](#toolbar-items) | _Optional_. See [Toolbar Items](#toolbar-items) | -| plugins | list of plugin factories | | _Optional_. See [Plugins](#plugins) | - -### Toolbar Items - -`toolbarItems` accepts a factory function that returns a list of toolbar buttons for the editor. See the [ToastUI Editor toolbar docs](https://github.com/nhn/tui.editor/blob/master/docs/en/toolbar.md). - -#### Default Value + ```js -[ - ['heading', 'bold', 'italic', 'strike'], - ['hr', 'quote'], - ['ul', 'ol', 'task', 'indent', 'outdent'], - ['table', imageToolbarButton, 'link'], - ['code', 'codeblock'], -]; +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}`, + }, + '', + ), + ); + }, +}); ``` -#### Factory Props - -| Name | Type | Description | -| ------------------ | ------------------ | ----------------------------------------------------------- | -| imageToolbarButton | ToolbarItemOptions | An image insert button tied into Static CMS's media library | - -### Plugins - -`plugins` accepts a list of factory functions that returns a plugin for the editor. See the [ToastUI Editor plugins docs](https://github.com/nhn/tui.editor/blob/master/docs/en/plugin.md). - -#### Default Value - -```js -[imagePlugin]; +```markdown +[youtube|p6h-rYSVX90] ``` -#### Factory Props - -| Name | Type | Description | -| ------ | ----------------------- | ---------------------------------------------------------------------------------------------- | -| config | Config | The current Static CMS config. See [configuration options](/docs/configuration-options) | -| field | MarkdownField | The field configuration for the current Markdown widget. See [Widget Options](#widget-options) | -| media | MediaHolder | See [Media Holder](#media-holder) | -| mode | 'editor'
\| 'preview' | Specifies if your plugin is running in the markdown editor or the markdown preview | - -##### Media Holder - -Media holder is a javascript class that holds the loaded media assets (images or files) that are present in the markdown content. It exposes a method called `getMedia` that takes a `url` and returns the loaded image or file as an blob asset. - -This is utilized by the `imagePlugin` to be able to render images present in the markdown that are currently only available in backend or are not yet persisted to the backend. +
diff --git a/docs/src/components/docs/components/CodeTabs.tsx b/docs/src/components/docs/components/CodeTabs.tsx index 7bdd7617..294d58f2 100644 --- a/docs/src/components/docs/components/CodeTabs.tsx +++ b/docs/src/components/docs/components/CodeTabs.tsx @@ -55,6 +55,11 @@ const supportedLanguages: Record = { grammar: Prism.languages.javascript, language: 'javascript', }, + 'language-markdown': { + title: 'Markdown', + grammar: Prism.languages.markdown, + language: 'markdown', + }, }; interface TabData { diff --git a/docs/src/components/layout/search/SearchModal.tsx b/docs/src/components/layout/search/SearchModal.tsx index cd6771d5..5e76c96b 100644 --- a/docs/src/components/layout/search/SearchModal.tsx +++ b/docs/src/components/layout/search/SearchModal.tsx @@ -97,7 +97,9 @@ const SearchModal: FC = ({ open, onClose, searchablePages }) = const handleClose = useCallback(() => { setCanFocus(true); - onClose(); + setTimeout(() => { + onClose(); + }); }, [onClose]); const handleSearchChange = useCallback((event: ChangeEvent) => { diff --git a/docs/src/pages/_app.tsx b/docs/src/pages/_app.tsx index 93233605..ab6049f9 100644 --- a/docs/src/pages/_app.tsx +++ b/docs/src/pages/_app.tsx @@ -24,6 +24,7 @@ require('prismjs/components/prism-json'); require('prismjs/components/prism-toml'); require('prismjs/components/prism-markup-templating'); require('prismjs/components/prism-handlebars'); +require('prismjs/components/prism-markdown'); function MyApp({ Component, pageProps }: AppProps) { const [mode, setMode] = useState('dark');