const MarkdownIt = require('markdown-it'); const md5 = require('md5'); const noteStyle = require('./noteStyle'); const { fileExtension } = require('./pathUtils'); const memoryCache = require('memory-cache'); const rules = { image: require('./MdToHtml/rules/image'), checkbox: require('./MdToHtml/rules/checkbox'), katex: require('./MdToHtml/rules/katex'), link_open: require('./MdToHtml/rules/link_open'), html_image: require('./MdToHtml/rules/html_image'), highlight_keywords: require('./MdToHtml/rules/highlight_keywords'), code_inline: require('./MdToHtml/rules/code_inline'), fountain: require('./MdToHtml/rules/fountain'), mermaid: require('./MdToHtml/rules/mermaid').default, sanitize_html: require('./MdToHtml/rules/sanitize_html').default, }; const setupLinkify = require('./MdToHtml/setupLinkify'); const hljs = require('highlight.js'); const uslug = require('uslug'); const markdownItAnchor = require('markdown-it-anchor'); // The keys must match the corresponding entry in Setting.js const plugins = { mark: { module: require('markdown-it-mark') }, footnote: { module: require('markdown-it-footnote') }, sub: { module: require('markdown-it-sub') }, sup: { module: require('markdown-it-sup') }, deflist: { module: require('markdown-it-deflist') }, abbr: { module: require('markdown-it-abbr') }, emoji: { module: require('markdown-it-emoji') }, insert: { module: require('markdown-it-ins') }, multitable: { module: require('markdown-it-multimd-table'), options: { multiline: true, rowspan: true, headerless: true } }, toc: { module: require('markdown-it-toc-done-right'), options: { listType: 'ul', slugify: uslugify } }, expand_tabs: { module: require('markdown-it-expand-tabs'), options: { tabWidth: 4 } }, }; const defaultNoteStyle = require('./defaultNoteStyle'); function uslugify(s) { return uslug(s); } class MdToHtml { constructor(options = null) { if (!options) options = {}; // Must include last "/" this.resourceBaseUrl_ = 'resourceBaseUrl' in options ? options.resourceBaseUrl : null; this.cachedOutputs_ = {}; this.lastCodeHighlightCacheKey_ = null; this.cachedHighlightedCode_ = {}; this.ResourceModel_ = options.ResourceModel; this.pluginOptions_ = options.pluginOptions ? options.pluginOptions : {}; this.contextCache_ = new memoryCache.Cache(); } pluginOptions(name) { let o = this.pluginOptions_[name] ? this.pluginOptions_[name] : {}; o = Object.assign({ enabled: true, }, o); return o; } pluginEnabled(name) { return this.pluginOptions(name).enabled; } processPluginAssets(pluginAssets) { const files = []; const cssStrings = []; for (const pluginName in pluginAssets) { for (const asset of pluginAssets[pluginName]) { let mime = asset.mime; if (!mime && asset.inline) throw new Error('Mime type is required for inline assets'); if (!mime) { const ext = fileExtension(asset.name).toLowerCase(); // For now it's only useful to support CSS and JS because that's what needs to be added // by the caller with