57 lines
1.9 KiB
JavaScript
57 lines
1.9 KiB
JavaScript
|
/**
|
||
|
* A Remark plugin for escaping markdown entities.
|
||
|
*
|
||
|
* When markdown entities are entered in raw markdown, they don't appear as
|
||
|
* characters in the resulting AST; for example, dashes surrounding a piece of
|
||
|
* text cause the text to be inserted in a special node type, but the asterisks
|
||
|
* themselves aren't present as text. Therefore, we generally don't expect to
|
||
|
* encounter markdown characters in text nodes.
|
||
|
*
|
||
|
* However, the CMS visual editor does not interpret markdown characters, and
|
||
|
* users will expect these characters to be represented literally. In that case,
|
||
|
* we need to escape them, otherwise they'll be interpreted during
|
||
|
* stringification.
|
||
|
*/
|
||
|
export default function remarkEscapeMarkdownEntities() {
|
||
|
/**
|
||
|
* Escape all occurrences of '[', '*', '_', '`', and '~'.
|
||
|
*/
|
||
|
function escapeCommonChars(text) {
|
||
|
return text.replace(/[\[*_`~]/g, '\\$&');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Runs escapeCommonChars, and also escapes '#' and '-' when found at the
|
||
|
* beginning of any node's first child node.
|
||
|
*/
|
||
|
function escapeAllChars(text) {
|
||
|
const partiallyEscapedMarkdown = escapeCommonChars(text);
|
||
|
return partiallyEscapedMarkdown.replace(/^\s*([#-])/, '$`\\$1');
|
||
|
}
|
||
|
|
||
|
const transform = (node, index) => {
|
||
|
const children = node.children && node.children.map(transform);
|
||
|
|
||
|
/**
|
||
|
* Escape characters in text and html nodes only. We store a lot of normal
|
||
|
* text in html nodes to keep Remark from escaping html entities.
|
||
|
*/
|
||
|
if (['text', 'html'].includes(node.type)) {
|
||
|
|
||
|
/**
|
||
|
* Escape all characters if this is the first child node, otherwise only
|
||
|
* common characters.
|
||
|
*/
|
||
|
const value = index === 0 ? escapeAllChars(node.value) : escapeCommonChars(node.value);
|
||
|
return { ...node, value, children };
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Always return nodes with recursively mapped children.
|
||
|
*/
|
||
|
return {...node, children };
|
||
|
};
|
||
|
|
||
|
return transform;
|
||
|
}
|