diff --git a/docs/src/markdown/extras.md b/docs/src/markdown/extras.md index ea49c2b..ff63d7b 100644 --- a/docs/src/markdown/extras.md +++ b/docs/src/markdown/extras.md @@ -128,16 +128,18 @@ you can include the following libraries to transform `sequence` and `flow` block and [flowchart.js][flow] respectively. ```js - "js": [ - // Required libraries to transform UML notation - "https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js", - "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js", - "https://cdnjs.cloudflare.com/ajax/libs/js-sequence-diagrams/1.0.6/sequence-diagram-min.js", - "https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.6.5/flowchart.min.js", - - // This library applies the above libraries to the fenced code blocks `flow` and `sequence`. - "res://MarkdownPreview/js/uml.js" - ] + "js": { + "markdown": [ + // Required libraries to transform UML notation + "https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js", + "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js", + "https://cdnjs.cloudflare.com/ajax/libs/js-sequence-diagrams/1.0.6/sequence-diagram-min.js", + "https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.6.5/flowchart.min.js", + + // This library applies the above libraries to the fenced code blocks `flow` and `sequence`. + "res://MarkdownPreview/js/uml.js" + ] + } ``` Please see the `MarkdownPreview.sublime-settings` file to see how custom fences are configured in case you need to @@ -145,20 +147,32 @@ configure them manually. Check out our [example file][example] if using YAML fro ## Mermaid UML Support -Mermaid is an alternate approach for rendering UML in a browser. Like the aforementioned [UML Support](#uml-support), it -also uses [SuperFences extension][superfences] to create special, custom fences. Then we can just add the needed -libraries, are custom loader, and configuration file. If you would like to tweak the configuration file, you can create -your own and load it instead. +Mermaid is an alternate approach for rendering UML in a browser. It uses [SuperFences extension][superfences] to create +special, custom fences. Mermaid support is included by default for the `markdown` parser — no additional configuration +is required. Simply use fenced code blocks with the `mermaid` language identifier: + +```` +```mermaid +graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` +```` + +The default configuration is provided in `MarkdownPreview/js/mermaid_config.js`. If you would like to tweak the +configuration, you can create your own and reference it in the `js` setting: ```js - "js": [ - // Mermaid library - "https://unpkg.com/mermaid@8.8.4/dist/mermaid.min.js", - // User configuration, should be loaded before the loader - "res://MarkdownPreview/js/mermaid_config.js", - // Mermaid loader - "res://MarkdownPreview/js/mermaid.js" - ] + "js": { + "markdown": [ + "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js", + // Your custom configuration, should be loaded before the loader + "/path/to/your/mermaid_config.js", + "res://MarkdownPreview/js/mermaid.js" + ] + } ``` Please see the `MarkdownPreview.sublime-settings` file to see how custom fences are configured in case you need to diff --git a/examples/test.md b/examples/test.md index 48e83a4..fc0ba8c 100644 --- a/examples/test.md +++ b/examples/test.md @@ -21,7 +21,7 @@ - https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js - https://cdnjs.cloudflare.com/ajax/libs/js-sequence-diagrams/1.0.6/sequence-diagram-min.js - https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.6.5/flowchart.min.js - - https://unpkg.com/mermaid@8.8.4/dist/mermaid.min.js + - https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js - res://MarkdownPreview/js/uml.js - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js - res://MarkdownPreview/js/math_config.js diff --git a/js/gitlab_config.js b/js/gitlab_config.js index 24ce893..c13b8ee 100644 --- a/js/gitlab_config.js +++ b/js/gitlab_config.js @@ -35,19 +35,24 @@ function syntaxHighlight(el) { el.classList.add(HIGHLIGHT_THEME); } -function renderMermaid(el) { +async function renderMermaid(el) { const source = el.textContent; // Remove any extra spans added by the backend syntax highlighting. Object.assign(el, { textContent: source }); - mermaid.init(undefined, el, (id) => { - const svg = document.getElementById(id); + try { + const id = `mermaid-${Math.random().toString(36).slice(2)}`; + const { svg } = await mermaid.render(id, source); + + const svgContainer = document.createElement('div'); + svgContainer.innerHTML = svg; + const svgEl = svgContainer.querySelector('svg'); - svg.classList.add('mermaid'); + svgEl.classList.add('mermaid'); // `pre > code > svg` - svg.closest('pre').replaceWith(svg); + el.closest('pre').replaceWith(svgEl); // We need to add the original source into the DOM to allow Copy-as-GFM // to access it. @@ -56,14 +61,16 @@ function renderMermaid(el) { sourceEl.setAttribute('display', 'none'); sourceEl.textContent = source; - svg.appendChild(sourceEl); - }); + svgEl.appendChild(sourceEl); + } catch (err) { + console.error('Mermaid rendering failed:', err); + } } function renderGFM(el) { el.querySelectorAll('.js-syntax-highlight').forEach(syntaxHighlight); el.querySelectorAll('.js-render-math').forEach(renderMath); - el.querySelectorAll('.js-render-mermaid').forEach(renderMermaid); + el.querySelectorAll('.js-render-mermaid').forEach(el => renderMermaid(el)); }; document.addEventListener("DOMContentLoaded", () => { diff --git a/js/mermaid.js b/js/mermaid.js index 4d4a3c6..b23e3f3 100644 --- a/js/mermaid.js +++ b/js/mermaid.js @@ -1,4 +1,4 @@ -const uml = className => { +const uml = async className => { // Custom element to encapsulate Mermaid content. class MermaidDiv extends HTMLElement { @@ -68,9 +68,8 @@ const uml = className => { messageFontSize: "16px" } } - + // Load up the config - mermaid.mermaidAPI.globalReset() const config = (typeof mermaidConfig === "undefined") ? defaultConfig : mermaidConfig mermaid.initialize(config) @@ -95,27 +94,21 @@ const uml = className => { surrogate.appendChild(temp) try { - mermaid.mermaidAPI.render( - `_diagram_${i}`, - getFromCode(parentEl), - content => { - const el = document.createElement("div") - el.className = className - el.innerHTML = content + const { svg } = await mermaid.render(`_diagram_${i}`, getFromCode(parentEl)) - // Insert the render where we want it and remove the original text source. - // Mermaid will clean up the temporary element. - const shadow = document.createElement("diagram-div") - shadow.shadowRoot.appendChild(el) - block.parentNode.insertBefore(shadow, block) - parentEl.style.display = "none" - shadow.shadowRoot.appendChild(parentEl) - if (parentEl !== block) { - block.parentNode.removeChild(block) - } - }, - temp - ) + const el = document.createElement("div") + el.className = className + el.innerHTML = svg + + // Insert the render where we want it and remove the original text source. + const shadow = document.createElement("diagram-div") + shadow.shadowRoot.appendChild(el) + block.parentNode.insertBefore(shadow, block) + parentEl.style.display = "none" + shadow.shadowRoot.appendChild(parentEl) + if (parentEl !== block) { + block.parentNode.removeChild(block) + } } catch (err) {} // eslint-disable-line no-empty if (surrogate.contains(temp)) { @@ -125,4 +118,4 @@ const uml = className => { } // This should be run on document load -document.addEventListener("DOMContentLoaded", () => {uml("mermaid")}) +document.addEventListener("DOMContentLoaded", () => { uml("mermaid") }) diff --git a/markdown_preview.py b/markdown_preview.py index 5182a58..738fed4 100644 --- a/markdown_preview.py +++ b/markdown_preview.py @@ -798,7 +798,7 @@ class GitlabCompiler(OnlineCompiler): ] default_js = [ "https://cdn.jsdelivr.net/npm/katex@0.10.0-alpha/dist/katex.min.js", - "https://unpkg.com/mermaid@8.0.0-rc.8/dist/mermaid.min.js", + "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js", # Calling `mermaid.initialize` at the first lines of `gitlab_config.js` # should come immediately after `mermaid.js.` "res://MarkdownPreview/js/gitlab_config.js" @@ -901,6 +901,11 @@ class MarkdownCompiler(Compiler): compiler_name = "markdown" default_css = ["res://MarkdownPreview/css/markdown.css"] + default_js = [ + "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js", + "res://MarkdownPreview/js/mermaid_config.js", + "res://MarkdownPreview/js/mermaid.js" + ] def set_highlight(self, pygments_style, css_class): """Set the Pygments CSS."""