-
🌐 async-utils.jsWeb, 3.69 kB⬇
-
🌐 auth-storage.jsWeb, 735 B⬇
-
🌐 chat-helpers.jsWeb, 8.85 kB⬇
-
🌐 chat-renderer.jsWeb, 70.00 kB⬇
-
🌐 code-overlay.jsWeb, 21.77 kB⬇
-
🌐 confirm-dialog.jsWeb, 3.17 kB⬇
-
🌐 conversation-format-utils.jsWeb, 21.51 kB⬇
-
🌐 diagram-overlay.jsWeb, 7.93 kB⬇
-
🌐 dialog.jsWeb, 2.50 kB⬇
-
🌐 dom-utils.jsWeb, 8.33 kB⬇
-
🌐 drag-reorder.jsWeb, 4.82 kB⬇
-
🌐 elements.jsWeb, 11.06 kB⬇
-
🌐 export-utils.jsWeb, 1.53 kB⬇
-
🌐 format-utils.jsWeb, 29.60 kB⬇
-
🌐 history-navigation.jsWeb, 1.95 kB⬇
-
🌐 hljs-yaml.jsWeb, 5.07 kB⬇
-
🌐 inline-format.jsWeb, 7.35 kB⬇
-
🌐 instant-answer.jsWeb, 19.82 kB⬇
-
🌐 interactive-tools.jsWeb, 38.77 kB⬇
-
🌐 mermaid-fixes.jsWeb, 4.60 kB⬇
-
🌐 mermaid-render.jsWeb, 5.10 kB⬇
-
🌐 mermaid.jsWeb, 195 B⬇
-
🌐 migrations.jsWeb, 12.11 kB⬇
-
🌐 multi-choice-dialog.jsWeb, 1.33 kB⬇
-
🌐 notification-stack.jsWeb, 2.50 kB⬇
-
🌐 options-manager.jsWeb, 45.56 kB⬇
-
🌐 overlay-utils.jsWeb, 4.14 kB⬇
-
🌐 pdf-export.jsWeb, 23.59 kB⬇
-
🌐 pinch-zoom.jsWeb, 3.21 kB⬇
-
🌐 plugin-dialog.jsWeb, 2.17 kB⬇
-
🌐 read-aloud.jsWeb, 33.84 kB⬇
-
🌐 response-pipeline.jsWeb, 55.19 kB⬇
-
🌐 scratchpad-editor.jsWeb, 8.64 kB⬇
-
🌐 scratchpad-export.jsWeb, 3.56 kB⬇
-
🌐 scrollbars.jsWeb, 3.12 kB⬇
-
🌐 selection-manager.jsWeb, 3.76 kB⬇
-
🌐 settings-utils.jsWeb, 31.08 kB⬇
-
🌐 share.jsWeb, 10.75 kB⬇
-
🌐 side-drawer.jsWeb, 9.37 kB⬇
-
🌐 speech-text.jsWeb, 6.60 kB⬇
-
🌐 swipe-navigation.jsWeb, 6.16 kB⬇
-
🌐 table-overlay.jsWeb, 8.10 kB⬇
-
🌐 theme-utils.jsWeb, 8.34 kB⬇
-
🌐 thinking-panel-base.jsWeb, 14.88 kB⬇
-
🌐 ui-sets.jsWeb, 1.00 kB⬇
-
🌐 version-overlay.jsWeb, 4.63 kB⬇
/**
* Automatic repairs for common Mermaid syntax problems that models frequently
* emit. repair_mermaid_code runs each fixer in order after a failed render;
* a fixer returns the corrected code, or null when it does not apply.
*/
/**
* Returns true when the code declares a flowchart, the only diagram type the
* node-label fixers apply to.
* @param {string} code - The mermaid source.
* @returns {boolean}
*/
function is_flowchart(code) {
return /^\s*(?:%%[^\n]*\n)*\s*(?:graph|flowchart)\b/.test(code);
}
/**
* Replaces each bare "quoted string" on the line — outside of node-shape
* brackets, edge-label pipes, and quoted labels — using the callback's
* replacement, and returns the new line.
* @param {string} line - A single mermaid source line.
* @param {function(string): string} replace - Maps the quoted text to its replacement.
* @returns {string}
*/
function replace_quoted_tokens(line, replace) {
let out = '';
let quote = null;
let closer = null;
for (let i = 0; i < line.length; i++) {
const ch = line[i];
if (closer !== null) {
out += ch;
if (ch === closer) closer = null;
continue;
}
if (quote !== null) {
if (ch === '"') {
out += replace(quote) + '["' + quote + '"]';
quote = null;
} else {
quote += ch;
}
continue;
}
if (ch === '"') {
quote = '';
continue;
}
if ('[({|'.includes(ch)) {
closer = { '[': ']', '(': ')', '{': '}', '|': '|' }[ch];
}
out += ch;
}
if (quote !== null) out += '"' + quote;
return out;
}
/**
* Converts bare quoted node labels ("Step 1") into mermaid's bracketed form
* (n1["Step 1"]), reusing one generated id per distinct label so repeated
* references stay the same node.
* @param {string} code - The mermaid source.
* @returns {string|null} The repaired code, or null when nothing changed.
*/
function fix_quoted_node_labels(code) {
const ids = new Map();
let count = 0;
const lines = code.split('\n').map(line => {
const trimmed = line.trim();
if (trimmed.startsWith('%%') || /^subgraph\b/.test(trimmed)) return line;
return replace_quoted_tokens(line, label => {
if (!ids.has(label)) {
count += 1;
ids.set(label, 'q' + count);
}
return ids.get(label);
});
});
if (count === 0) return null;
return lines.join('\n');
}
/**
* Wraps square-bracket node labels that carry unquoted parentheses, braces,
* or brackets in quotes: A[Step (one)] becomes A["Step (one)"].
* @param {string} code - The mermaid source.
* @returns {string|null} The repaired code, or null when nothing changed.
*/
function fix_label_special_chars(code) {
let changed = false;
const lines = code.split('\n').map(line => {
const trimmed = line.trim();
if (trimmed.startsWith('%%') || /^subgraph\b/.test(trimmed)) return line;
const fixed = line.replace(/(?<![\[(])\[(?![\[(])([^[\]]*)\](?![\])])/g, (match, label) => {
const text = label.trim();
if (text.includes('"') || !/[(){}[\]]/.test(text)) return match;
changed = true;
return '[' + label.replace(text, '"' + text + '"') + ']';
});
return fixed;
});
return changed ? lines.join('\n') : null;
}
/**
* Renames bare lowercase "end" node ids — a reserved flowchart word — to a
* bracketed node keeping the visible label. A line that is only "end" closes
* a subgraph and is left alone.
* @param {string} code - The mermaid source.
* @returns {string|null} The repaired code, or null when nothing changed.
*/
function fix_reserved_end_id(code) {
let changed = false;
const lines = code.split('\n').map(line => {
const trimmed = line.trim();
if (trimmed.startsWith('%%') || /^subgraph\b/.test(trimmed) || /^end$/i.test(trimmed)) return line;
if (!/--+>|-{3,}|-\.+->?|={2,}>|~~/.test(line)) return line;
const fixed = line.replace(/(^|[\s;>])(end)(?=$|[\s;]|$)/g, (match, before) => {
changed = true;
return before + 'end_node["end"]';
});
return fixed;
});
return changed ? lines.join('\n') : null;
}
const FIXERS = [
{ applies: is_flowchart, fix: fix_quoted_node_labels },
{ applies: is_flowchart, fix: fix_label_special_chars },
{ applies: is_flowchart, fix: fix_reserved_end_id }
];
/**
* Applies each syntax fixer in order after a failed render.
* @param {string} code - The mermaid source that failed to render.
* @returns {{code: string, applied: number}} The repaired code and how many
* fixes changed it.
*/
export function repair_mermaid_code(code) {
let current = code;
let applied = 0;
for (const fixer of FIXERS) {
if (!fixer.applies(current)) continue;
const fixed = fixer.fix(current);
if (fixed !== null && fixed !== current) {
current = fixed;
applied += 1;
}
}
return { code: current, applied };
}
mermaid-fixes.js
×
Type: Web, text/plain
4.60 Kilobytes
Last Modified 2026-11-04 09:48:28
⬇ Download File
Type: Web, text/plain
4.60 Kilobytes
Last Modified 2026-11-04 09:48:28
⬇ Download File