Stackedit/src/extensions/markdownExtension.js
2022-09-04 17:28:24 +08:00

164 lines
4.5 KiB
JavaScript

import Prism from 'prismjs';
import markdownitAbbr from 'markdown-it-abbr';
import markdownitDeflist from 'markdown-it-deflist';
import markdownitFootnote from 'markdown-it-footnote';
import markdownitMark from 'markdown-it-mark';
import markdownitImgsize from 'markdown-it-imsize';
import markdownitSub from 'markdown-it-sub';
import markdownitSup from 'markdown-it-sup';
import markdownitTasklist from './libs/markdownItTasklist';
import markdownitAnchor from './libs/markdownItAnchor';
import extensionSvc from '../services/extensionSvc';
const coreBaseRules = [
'normalize',
'block',
'inline',
'linkify',
'replacements',
'smartquotes',
];
const blockBaseRules = [
'code',
'fence',
'blockquote',
'hr',
'list',
'reference',
'heading',
'lheading',
'html_block',
'table',
'paragraph',
];
const inlineBaseRules = [
'text',
'newline',
'escape',
'backticks',
'strikethrough',
'emphasis',
'link',
'image',
'autolink',
'html_inline',
'entity',
];
const inlineBaseRules2 = [
'balance_pairs',
'strikethrough',
'emphasis',
'text_collapse',
];
extensionSvc.onGetOptions((options, properties) => Object
.assign(options, properties.extensions.markdown));
extensionSvc.onInitConverter(0, (markdown, options) => {
markdown.set({
html: true,
breaks: !!options.breaks,
linkify: !!options.linkify,
typographer: !!options.typographer,
langPrefix: 'prism language-',
});
markdown.core.ruler.enable(coreBaseRules);
const blockRules = blockBaseRules.slice();
if (!options.fence) {
blockRules.splice(blockRules.indexOf('fence'), 1);
}
if (!options.table) {
blockRules.splice(blockRules.indexOf('table'), 1);
}
markdown.block.ruler.enable(blockRules);
const inlineRules = inlineBaseRules.slice();
const inlineRules2 = inlineBaseRules2.slice();
if (!options.del) {
inlineRules.splice(blockRules.indexOf('strikethrough'), 1);
inlineRules2.splice(blockRules.indexOf('strikethrough'), 1);
}
markdown.inline.ruler.enable(inlineRules);
markdown.inline.ruler2.enable(inlineRules2);
if (options.abbr) {
markdown.use(markdownitAbbr);
}
if (options.deflist) {
markdown.use(markdownitDeflist);
}
if (options.footnote) {
markdown.use(markdownitFootnote);
}
if (options.imgsize) {
markdown.use(markdownitImgsize);
}
if (options.mark) {
markdown.use(markdownitMark);
}
if (options.sub) {
markdown.use(markdownitSub);
}
if (options.sup) {
markdown.use(markdownitSup);
}
if (options.tasklist) {
markdown.use(markdownitTasklist);
}
markdown.use(markdownitAnchor);
// Wrap tables into a div for scrolling
markdown.renderer.rules.table_open = (tokens, idx, opts) =>
`<div class="table-wrapper">${markdown.renderer.renderToken(tokens, idx, opts)}`;
markdown.renderer.rules.table_close = (tokens, idx, opts) =>
`${markdown.renderer.renderToken(tokens, idx, opts)}</div>`;
// Transform style into align attribute to pass the HTML sanitizer
const textAlignLength = 'text-align:'.length;
markdown.renderer.rules.td_open = (tokens, idx, opts) => {
const token = tokens[idx];
if (token.attrs && token.attrs.length && token.attrs[0][0] === 'style') {
token.attrs = [
['align', token.attrs[0][1].slice(textAlignLength)],
];
}
return markdown.renderer.renderToken(tokens, idx, opts);
};
markdown.renderer.rules.th_open = markdown.renderer.rules.td_open;
markdown.renderer.rules.footnote_ref = (tokens, idx) => {
const n = `${Number(tokens[idx].meta.id + 1)}`;
let id = `fnref${n}`;
if (tokens[idx].meta.subId > 0) {
id += `:${tokens[idx].meta.subId}`;
}
return `<sup class="footnote-ref"><a href="#fn${n}" id="${id}">[${n}]</a></sup>`;
};
});
extensionSvc.onSectionPreview((elt, options, isEditor) => {
// Highlight with Prism
elt.querySelectorAll('.prism').cl_each((prismElt) => {
if (!prismElt.$highlightedWithPrism) {
Prism.highlightElement(prismElt);
prismElt.$highlightedWithPrism = true;
}
});
// Transform task spans into checkboxes
elt.querySelectorAll('span.task-list-item-checkbox').cl_each((spanElt) => {
const checkboxElt = document.createElement('input');
checkboxElt.type = 'checkbox';
checkboxElt.className = 'task-list-item-checkbox';
if (spanElt.classList.contains('checked')) {
checkboxElt.setAttribute('checked', true);
}
if (!isEditor) {
checkboxElt.disabled = 'disabled';
}
spanElt.parentNode.replaceChild(checkboxElt, spanElt);
});
});