diff --git a/src/core/render/compiler.js b/src/core/render/compiler.js index d01e65aea..b86166301 100644 --- a/src/core/render/compiler.js +++ b/src/core/render/compiler.js @@ -5,63 +5,18 @@ import { tree as treeTpl } from './tpl.js'; import { genTree } from './gen-tree.js'; import { slugify } from './slugify.js'; import { emojify } from './emojify.js'; -import { - getAndRemoveConfig, - removeAtag, - getAndRemoveDocsifyIgnoreConfig, -} from './utils.js'; +import { getAndRemoveConfig } from './utils.js'; import { imageCompiler } from './compiler/image.js'; +import { headingCompiler } from './compiler/heading.js'; import { highlightCodeCompiler } from './compiler/code.js'; import { paragraphCompiler } from './compiler/paragraph.js'; import { taskListCompiler } from './compiler/taskList.js'; import { taskListItemCompiler } from './compiler/taskListItem.js'; import { linkCompiler } from './compiler/link.js'; +import { compileMedia } from './compiler/media.js'; const cachedLinks = {}; -const compileMedia = { - markdown(url) { - return { - url, - }; - }, - mermaid(url) { - return { - url, - }; - }, - iframe(url, title) { - return { - html: ``, - }; - }, - video(url, title) { - return { - html: ``, - }; - }, - audio(url, title) { - return { - html: ``, - }; - }, - code(url, title) { - let lang = url.match(/\.(\w+)$/); - - lang = title || (lang && lang[1]); - if (lang === 'md') { - lang = 'markdown'; - } - - return { - url, - lang, - }; - }, -}; - export class Compiler { constructor(config, router) { this.config = config; @@ -173,7 +128,7 @@ export class Compiler { type = 'audio'; } - embed = compileMedia[type].call(this, href, title); + embed = compileMedia[type](href, title); embed.type = type; } @@ -198,47 +153,22 @@ export class Compiler { _initRenderer() { const renderer = new marked.Renderer(); const { linkTarget, linkRel, router, contentBase } = this; - const _self = this; + // Supports mermaid const origin = {}; - /** - * Render anchor tag - * @link https://github.com/markedjs/marked#overriding-renderer-methods - * @param {String} tokens the content tokens - * @param {Number} depth Type of heading (h tag) - * @returns {String} Heading element - */ - origin.heading = renderer.heading = function ({ tokens, depth }) { - const text = this.parser.parseInline(tokens); - let { str, config } = getAndRemoveConfig(text); - const nextToc = { depth, title: str }; - - const { content, ignoreAllSubs, ignoreSubHeading } = - getAndRemoveDocsifyIgnoreConfig(str); - str = content.trim(); - - nextToc.title = removeAtag(str); - nextToc.ignoreAllSubs = ignoreAllSubs; - nextToc.ignoreSubHeading = ignoreSubHeading; - const slug = slugify(config.id || str); - const url = router.toURL(router.getCurrentPath(), { id: slug }); - nextToc.slug = url; - _self.toc.push(nextToc); - - // Note: tabindex="-1" allows programmatically focusing on heading - // elements after navigation. This is preferred over focusing on the link - // within the heading because it matches the focus behavior of screen - // readers when navigating page content. - return `${str}`; - }; - + // renderer customizers + origin.heading = headingCompiler({ + renderer, + router, + compiler: this, + }); origin.code = highlightCodeCompiler({ renderer }); origin.link = linkCompiler({ renderer, router, linkTarget, linkRel, - compilerClass: _self, + compiler: this, }); origin.paragraph = paragraphCompiler({ renderer }); origin.image = imageCompiler({ renderer, contentBase, router }); diff --git a/src/core/render/compiler/heading.js b/src/core/render/compiler/heading.js new file mode 100644 index 000000000..5fbc81f80 --- /dev/null +++ b/src/core/render/compiler/heading.js @@ -0,0 +1,31 @@ +import { + getAndRemoveConfig, + removeAtag, + getAndRemoveDocsifyIgnoreConfig, +} from '../utils.js'; +import { slugify } from '../slugify.js'; + +export const headingCompiler = ({ renderer, router, compiler }) => + (renderer.heading = function ({ tokens, depth }) { + const text = this.parser.parseInline(tokens); + let { str, config } = getAndRemoveConfig(text); + const nextToc = { depth, title: str }; + + const { content, ignoreAllSubs, ignoreSubHeading } = + getAndRemoveDocsifyIgnoreConfig(str); + str = content.trim(); + + nextToc.title = removeAtag(str); + nextToc.ignoreAllSubs = ignoreAllSubs; + nextToc.ignoreSubHeading = ignoreSubHeading; + const slug = slugify(config.id || str); + const url = router.toURL(router.getCurrentPath(), { id: slug }); + nextToc.slug = url; + compiler.toc.push(nextToc); + + // Note: tabindex="-1" allows programmatically focusing on heading + // elements after navigation. This is preferred over focusing on the link + // within the heading because it matches the focus behavior of screen + // readers when navigating page content. + return `${str}`; + }); diff --git a/src/core/render/compiler/headline.js b/src/core/render/compiler/headline.js deleted file mode 100644 index 48a7c1302..000000000 --- a/src/core/render/compiler/headline.js +++ /dev/null @@ -1,27 +0,0 @@ -import { - getAndRemoveConfig, - removeAtag, - getAndRemoveDocsifyIgnoreConfig, -} from '../utils.js'; -import { slugify } from './slugify.js'; - -export const headingCompiler = ({ renderer, router, _self }) => - (renderer.code = (text, level) => { - let { str, config } = getAndRemoveConfig(text); - const nextToc = { level, title: str }; - - const { content, ignoreAllSubs, ignoreSubHeading } = - getAndRemoveDocsifyIgnoreConfig(str); - str = content.trim(); - - nextToc.title = removeAtag(str); - nextToc.ignoreAllSubs = ignoreAllSubs; - nextToc.ignoreSubHeading = ignoreSubHeading; - - const slug = slugify(config.id || str); - const url = router.toURL(router.getCurrentPath(), { id: slug }); - nextToc.slug = url; - _self.toc.push(nextToc); - - return /* html */ `${str}`; - }); diff --git a/src/core/render/compiler/link.js b/src/core/render/compiler/link.js index c7a3559eb..9483dd88b 100644 --- a/src/core/render/compiler/link.js +++ b/src/core/render/compiler/link.js @@ -6,7 +6,7 @@ export const linkCompiler = ({ router, linkTarget, linkRel, - compilerClass, + compiler, }) => (renderer.link = function ({ href, title = '', tokens }) { const attrs = []; @@ -15,16 +15,16 @@ export const linkCompiler = ({ linkTarget = config.target || linkTarget; linkRel = linkTarget === '_blank' - ? compilerClass.config.externalLinkRel || 'noopener' + ? compiler.config.externalLinkRel || 'noopener' : ''; title = str; if ( !isAbsolutePath(href) && - !compilerClass._matchNotCompileLink(href) && + !compiler._matchNotCompileLink(href) && !config.ignore ) { - if (href === compilerClass.config.homepage) { + if (href === compiler.config.homepage) { href = 'README'; } diff --git a/src/core/render/compiler/media.js b/src/core/render/compiler/media.js new file mode 100644 index 000000000..d12b1fb0d --- /dev/null +++ b/src/core/render/compiler/media.js @@ -0,0 +1,42 @@ +export const compileMedia = { + markdown(url) { + return { + url, + }; + }, + mermaid(url) { + return { + url, + }; + }, + iframe(url, title) { + return { + html: ``, + }; + }, + video(url, title) { + return { + html: ``, + }; + }, + audio(url, title) { + return { + html: ``, + }; + }, + code(url, title) { + let lang = url.match(/\.(\w+)$/); + + lang = title || (lang && lang[1]); + if (lang === 'md') { + lang = 'markdown'; + } + + return { + url, + lang, + }; + }, +}; diff --git a/src/core/render/index.js b/src/core/render/index.js index 06f900bb7..3ee35513b 100644 --- a/src/core/render/index.js +++ b/src/core/render/index.js @@ -82,7 +82,7 @@ export function Render(Base) { } } - this._renderTo(markdownElm, html); + dom.setHTML(markdownElm, html); // Execute markdown