forgejo-federation/web_src/js/markup/mermaid.js
silverwind 23bd7b1211
Add copy button to markdown code blocks (#17638)
* Add copy button to markdown code blocks

Done mostly in JS because I think it's better not to try getting buttons
past the markup sanitizer.

* add svg module tests

* fix sanitizer regexp

* remove outdated comment

* vertically center button in issue comments as well

* add comment to css

* fix undefined on view file line copy

* combine animation less files

* Update modules/markup/markdown/markdown.go

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* add test for different sizes

* add cloneNode and add tests for it

* use deep clone

* remove useless optional chaining

* remove the svg node cache

* unify clipboard copy string and i18n

* remove unused var

* remove unused localization

* minor css tweaks to the button

* comment tweak

* remove useless attribute

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2021-11-16 16:16:05 +08:00

57 lines
1.6 KiB
JavaScript

const {mermaidMaxSourceCharacters} = window.config;
function displayError(el, err) {
el.closest('pre').classList.remove('is-loading');
const errorNode = document.createElement('div');
errorNode.setAttribute('class', 'ui message error markup-block-error mono');
errorNode.textContent = err.str || err.message || String(err);
el.closest('pre').before(errorNode);
}
export async function renderMermaid() {
const els = document.querySelectorAll('.markup code.language-mermaid');
if (!els.length) return;
const {default: mermaid} = await import(/* webpackChunkName: "mermaid" */'mermaid');
mermaid.initialize({
mermaid: {
startOnLoad: false,
},
flowchart: {
useMaxWidth: true,
htmlLabels: false,
},
theme: 'neutral',
securityLevel: 'strict',
});
for (const el of els) {
if (mermaidMaxSourceCharacters >= 0 && el.textContent.length > mermaidMaxSourceCharacters) {
displayError(el, new Error(`Mermaid source of ${el.textContent.length} characters exceeds the maximum allowed length of ${mermaidMaxSourceCharacters}.`));
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);
}
}
}