diff options
author | silverwind <me@silverwind.io> | 2020-08-04 21:56:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-04 20:56:37 +0100 |
commit | e61c09ed7331e6ea72e4d9f08c0490713598942d (patch) | |
tree | febdc85a173312afbf293304a3c46dfe498c7725 /web_src/js/markdown | |
parent | 5e5c893555411bcbeedc4a3f0d853731b63f05c4 (diff) | |
download | gitea-e61c09ed7331e6ea72e4d9f08c0490713598942d.tar.gz gitea-e61c09ed7331e6ea72e4d9f08c0490713598942d.zip |
Add loading spinners and mermaid error handling (#12358)
- Add loading spinners on editor and mermaid renderers
- Add error handling and inline error box for mermaid
- Fix Mermaid rendering by using the .init api
Diffstat (limited to 'web_src/js/markdown')
-rw-r--r-- | web_src/js/markdown/content.js | 2 | ||||
-rw-r--r-- | web_src/js/markdown/mermaid.js | 55 |
2 files changed, 45 insertions, 12 deletions
diff --git a/web_src/js/markdown/content.js b/web_src/js/markdown/content.js index f41800ee30..918cd6fe81 100644 --- a/web_src/js/markdown/content.js +++ b/web_src/js/markdown/content.js @@ -1,5 +1,5 @@ import {renderMermaid} from './mermaid.js'; export default async function renderMarkdownContent() { - await renderMermaid(document.querySelectorAll('.language-mermaid')); + await renderMermaid(document.querySelectorAll('code.language-mermaid')); } diff --git a/web_src/js/markdown/mermaid.js b/web_src/js/markdown/mermaid.js index 1fda101dc0..a518bc7345 100644 --- a/web_src/js/markdown/mermaid.js +++ b/web_src/js/markdown/mermaid.js @@ -1,23 +1,56 @@ -import {random} from '../utils.js'; +const MAX_SOURCE_CHARACTERS = 5000; + +function displayError(el, err) { + el.closest('pre').classList.remove('is-loading'); + const errorNode = document.createElement('div'); + errorNode.setAttribute('class', 'ui message error markdown-block-error mono'); + errorNode.textContent = err.str || err.message || String(err); + el.closest('pre').before(errorNode); +} export async function renderMermaid(els) { if (!els || !els.length) return; - const {mermaidAPI} = await import(/* webpackChunkName: "mermaid" */'mermaid'); + const mermaid = await import(/* webpackChunkName: "mermaid" */'mermaid'); - mermaidAPI.initialize({ - startOnLoad: false, + mermaid.initialize({ + mermaid: { + startOnLoad: false, + }, + flowchart: { + useMaxWidth: true, + htmlLabels: false, + }, theme: 'neutral', securityLevel: 'strict', }); for (const el of els) { - mermaidAPI.render(`mermaid-${random(12)}`, el.textContent, (svg, bindFunctions) => { - const div = document.createElement('div'); - div.classList.add('mermaid-chart'); - div.innerHTML = svg; - if (typeof bindFunctions === 'function') bindFunctions(div); - el.closest('pre').replaceWith(div); - }); + if (el.textContent.length > MAX_SOURCE_CHARACTERS) { + displayError(el, new Error(`Mermaid source of ${el.textContent.length} characters exceeds the maximum allowed length of ${MAX_SOURCE_CHARACTERS}.`)); + continue; + } + + let valid; + try { + valid = mermaid.parse(el.textContent); + } catch (err) { + displayError(el, err); + } + + if (!valid) { + el.closest('pre').classList.remove('is-loading'); + continue; + } + + try { + mermaid.init(undefined, el, (id) => { + const svg = document.getElementById(id); + svg.classList.add('mermaid-chart'); + svg.closest('pre').replaceWith(svg); + }); + } catch (err) { + displayError(el, err); + } } } |