2022-08-21 16:04:09 +02:00
|
|
|
import SimpleMarkdown from '@khanacademy/simple-markdown';
|
2022-01-31 16:58:42 +01:00
|
|
|
|
2022-08-21 16:04:09 +02:00
|
|
|
const {
|
|
|
|
defaultRules, parserFor, outputFor, anyScopeRegex, blockRegex, inlineRegex, htmlTag, sanitizeText,
|
|
|
|
} = SimpleMarkdown;
|
2022-01-31 16:58:42 +01:00
|
|
|
|
2022-08-21 16:04:09 +02:00
|
|
|
function mathHtml(wrap, node) {
|
|
|
|
return htmlTag(wrap, htmlTag('code', sanitizeText(node.content)), { 'data-mx-maths': node.content });
|
2022-01-31 16:58:42 +01:00
|
|
|
}
|
|
|
|
|
2022-08-21 16:04:09 +02:00
|
|
|
const rules = {
|
|
|
|
...defaultRules,
|
|
|
|
Array: {
|
|
|
|
...defaultRules.Array,
|
|
|
|
plain: (arr, output, state) => arr.map((node) => output(node, state)).join(''),
|
2022-01-31 16:58:42 +01:00
|
|
|
},
|
2022-08-21 16:04:09 +02:00
|
|
|
displayMath: {
|
|
|
|
order: defaultRules.list.order + 0.5,
|
|
|
|
match: blockRegex(/^\$\$\n*([\s\S]+?)\n*\$\$/),
|
|
|
|
parse: (capture) => ({ content: capture[1] }),
|
|
|
|
plain: (node) => `$$\n${node.content}\n$$`,
|
|
|
|
html: (node) => mathHtml('div', node),
|
2022-01-31 16:58:42 +01:00
|
|
|
},
|
2022-08-21 16:04:09 +02:00
|
|
|
newline: {
|
|
|
|
...defaultRules.newline,
|
|
|
|
plain: () => '\n',
|
|
|
|
},
|
|
|
|
paragraph: {
|
|
|
|
...defaultRules.paragraph,
|
|
|
|
plain: (node, output, state) => `${output(node.content, state)}\n\n`,
|
|
|
|
html: (node, output, state) => htmlTag('p', output(node.content, state)),
|
|
|
|
},
|
|
|
|
escape: {
|
|
|
|
...defaultRules.escape,
|
|
|
|
plain: (node, output, state) => `\\${output(node.content, state)}`,
|
2022-04-24 17:48:35 +02:00
|
|
|
},
|
2022-08-21 16:04:09 +02:00
|
|
|
em: {
|
|
|
|
...defaultRules.em,
|
|
|
|
plain: (node, output, state) => `_${output(node.content, state)}_`,
|
|
|
|
},
|
|
|
|
strong: {
|
|
|
|
...defaultRules.strong,
|
|
|
|
plain: (node, output, state) => `**${output(node.content, state)}**`,
|
|
|
|
},
|
|
|
|
u: {
|
|
|
|
...defaultRules.u,
|
|
|
|
plain: (node, output, state) => `__${output(node.content, state)}__`,
|
|
|
|
},
|
|
|
|
del: {
|
|
|
|
...defaultRules.del,
|
|
|
|
plain: (node, output, state) => `~~${output(node.content, state)}~~`,
|
|
|
|
},
|
|
|
|
spoiler: {
|
|
|
|
order: defaultRules.em.order - 0.5,
|
|
|
|
match: inlineRegex(/^\|\|([\s\S]+?)\|\|(?:\(([\s\S]+?)\))?/),
|
|
|
|
parse: (capture, parse, state) => ({
|
|
|
|
content: parse(capture[1], state),
|
|
|
|
reason: capture[2],
|
|
|
|
}),
|
|
|
|
plain: (node) => `[spoiler${node.reason ? `: ${node.reason}` : ''}](mxc://somewhere)`,
|
|
|
|
html: (node, output, state) => `<span data-mx-spoiler${node.reason ? `="${sanitizeText(node.reason)}"` : ''}>${output(node.content, state)}</span>`,
|
|
|
|
},
|
|
|
|
inlineMath: {
|
|
|
|
order: defaultRules.del.order + 0.5,
|
|
|
|
match: inlineRegex(/^\$(\S[\s\S]+?\S|\S)\$(?!\d)/),
|
|
|
|
parse: (capture) => ({ content: capture[1] }),
|
|
|
|
plain: (node) => `$${node.content}$`,
|
|
|
|
html: (node) => mathHtml('span', node),
|
|
|
|
},
|
|
|
|
br: {
|
|
|
|
...defaultRules.br,
|
|
|
|
match: anyScopeRegex(/^ *\n/),
|
|
|
|
plain: () => '\n',
|
|
|
|
},
|
|
|
|
text: {
|
|
|
|
...defaultRules.text,
|
|
|
|
match: anyScopeRegex(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]| *\n|\w+:\S|$)/),
|
|
|
|
plain: (node) => node.content,
|
2022-04-24 17:48:35 +02:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-08-21 16:04:09 +02:00
|
|
|
const parser = parserFor(rules);
|
|
|
|
|
|
|
|
const plainOutput = outputFor(rules, 'plain');
|
|
|
|
const htmlOutput = outputFor(rules, 'html');
|
|
|
|
|
2022-04-24 17:48:35 +02:00
|
|
|
export {
|
2022-08-21 16:04:09 +02:00
|
|
|
parser, plainOutput, htmlOutput,
|
2022-04-24 17:48:35 +02:00
|
|
|
};
|