diff options
-rw-r--r-- | package-lock.json | 11 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/markdownit/containers.js | 25 | ||||
-rw-r--r-- | src/markdownit/index.js | 2 | ||||
-rw-r--r-- | src/nodes/CustomContainer.js | 9 | ||||
-rw-r--r-- | src/tests/markdownit.spec.js | 28 |
6 files changed, 66 insertions, 10 deletions
diff --git a/package-lock.json b/package-lock.json index f9d555938..6e5bdadad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "highlight.js": "^10.7.2", "lowlight": "^1.20.0", "markdown-it": "^12.3.2", + "markdown-it-container": "^3.0.0", "markdown-it-task-lists": "^2.1.1", "prosemirror-collab": "^1.2.2", "prosemirror-inputrules": "^1.1.3", @@ -14932,6 +14933,11 @@ "markdown-it": "bin/markdown-it.js" } }, + "node_modules/markdown-it-container": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-3.0.0.tgz", + "integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==" + }, "node_modules/markdown-it-task-lists": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", @@ -32795,6 +32801,11 @@ } } }, + "markdown-it-container": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-3.0.0.tgz", + "integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==" + }, "markdown-it-task-lists": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", diff --git a/package.json b/package.json index b29374308..3b0ed071f 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "highlight.js": "^10.7.2", "lowlight": "^1.20.0", "markdown-it": "^12.3.2", + "markdown-it-container": "^3.0.0", "markdown-it-task-lists": "^2.1.1", "prosemirror-collab": "^1.2.2", "prosemirror-inputrules": "^1.1.3", diff --git a/src/markdownit/containers.js b/src/markdownit/containers.js new file mode 100644 index 000000000..1196f9b8e --- /dev/null +++ b/src/markdownit/containers.js @@ -0,0 +1,25 @@ +import container from 'markdown-it-container' + +export const typesAvailable = ['info', 'warn', 'error', 'success'] + +const buildRender = type => (tokens, idx, options, env, slf) => { + // add a class to the opening tag + const tag = tokens[idx] + + if (tag.nesting === 1) { + tag.attrSet('data-container', type) + tag.attrJoin('class', `custom-container custom-container-${type}`) + } + + return slf.renderToken(tokens, idx, options, env, slf) +} + +export default (md) => { + typesAvailable.forEach(type => { + md.use(container, type, { + render: buildRender(type), + }) + }) + + return md +} diff --git a/src/markdownit/index.js b/src/markdownit/index.js index aaeafa4c9..3143f8453 100644 --- a/src/markdownit/index.js +++ b/src/markdownit/index.js @@ -2,11 +2,13 @@ import MarkdownIt from 'markdown-it' import taskLists from 'markdown-it-task-lists' import underline from './underline' import splitMixedLists from './splitMixedLists' +import containers from './containers' const markdownit = MarkdownIt('commonmark', { html: false, breaks: false }) .enable('strikethrough') .use(taskLists, { enable: true, labelAfter: true }) .use(splitMixedLists) .use(underline) + .use(containers) export default markdownit diff --git a/src/nodes/CustomContainer.js b/src/nodes/CustomContainer.js index 606a6da53..a1ebd391b 100644 --- a/src/nodes/CustomContainer.js +++ b/src/nodes/CustomContainer.js @@ -1,6 +1,5 @@ import { Node, mergeAttributes } from '@tiptap/core' - -export const inputRegex = /^\s*>\s$/ +import { typesAvailable } from '../markdownit/containers' export default Node.create({ @@ -14,7 +13,7 @@ export default Node.create({ addOptions() { return { - types: ['info', 'warn', 'error', 'success'], + types: typesAvailable, HTMLAttributes: { class: 'custom-container', }, @@ -26,10 +25,10 @@ export default Node.create({ type: { default: 'info', rendered: false, - parseHTML: element => element.getAttribute('data-type'), + parseHTML: element => element.getAttribute('data-container'), renderHTML: attributes => { return { - 'data-type': attributes.type, + 'data-container': attributes.type, class: attributes.type, } }, diff --git a/src/tests/markdownit.spec.js b/src/tests/markdownit.spec.js index 08d5cb0a9..c44713659 100644 --- a/src/tests/markdownit.spec.js +++ b/src/tests/markdownit.spec.js @@ -1,22 +1,23 @@ import markdownit from './../markdownit' +import { typesAvailable } from './../markdownit/containers' describe('markdownit', () => { it('renders task lists', () => { const rendered = markdownit.render('* [ ] task\n* not a task') - expect(rendered).toBe(stripIndent(` + expect(stripIndent(rendered)).toBe(stripIndent(` <ul class="contains-task-list"> <li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"> task</li> </ul> <ul> <li>not a task</li> - </ul> -`)) + </ul>` + )) }) it('renders bullet and task lists separately', () => { const rendered = markdownit.render('* not a task\n* [ ] task') - expect(rendered).toBe(stripIndent(` + expect(stripIndent(rendered)).toBe(stripIndent(` <ul> <li>not a task</li> </ul> @@ -26,8 +27,25 @@ describe('markdownit', () => { `)) }) + describe('custom containers', () => { + typesAvailable.forEach((type) => { + it(`render ${type}`, () => { + const rendered = markdownit.render(`::: ${type}\nHey there!\n:::`) + expect(stripIndent(rendered)).toBe(stripIndent( + `<div data-container="${type}" class="custom-container custom-container-${type}"> + <p>Hey there!</p> + </div>` + )) + }) + }) + }) + }) function stripIndent(content) { - return content.replace(/\t/g, '').replace('\n','') + return content + .replace(/\n/g, "") + .replace(/[\t ]+\</g, "<") + .replace(/\>[\t ]+\</g, "><") + .replace(/\>[\t ]+$/g, ">") } |