// @generated by scripts/runtime-bundles/bundle-runtime.ts
// bundle: mermaid
/* browser-globals.js */
globalThis.window = globalThis;
globalThis.self = globalThis;
globalThis.navigator = { userAgent: "KatanA Rust-managed Mermaid runtime" };
globalThis.location = {
href: "https://katana.local/",
origin: "https://katana.local",
protocol: "https:",
host: "katana.local",
hostname: "katana.local",
pathname: "/",
search: "",
hash: "",
};
const KATANA_DETERMINISTIC_NOW = Date.parse("2026-01-01T00:00:00.000Z");
globalThis.Date.now = () => KATANA_DETERMINISTIC_NOW;
globalThis.performance = { now: () => Date.now() };
globalThis.devicePixelRatio = 1;
globalThis.innerWidth = 1520;
globalThis.innerHeight = 845;
globalThis.screen = {
width: globalThis.innerWidth,
height: globalThis.innerHeight,
availWidth: globalThis.innerWidth,
availHeight: globalThis.innerHeight,
};
globalThis.localStorage = katanaStorage();
globalThis.sessionStorage = katanaStorage();
class KatanaMessageChannel {
constructor() {
this.port1 = { onmessage: null };
this.port2 = {
postMessage: (data) => {
queueMicrotask(() => this.port1.onmessage?.({ data }));
},
};
}
}
class KatanaSegmenter {
segment(value) {
const input = String(value);
let index = 0;
return Array.from(input).map((segment) => {
const entry = { segment, index, input };
index += segment.length;
return entry;
});
}
}
const katanaIntl = globalThis.Intl ?? {};
// WHY: Some Mermaid diagrams call Intl.Segmenter for wrapping, but embedded V8 native dispatch can terminate the process.
katanaIntl.Segmenter = KatanaSegmenter;
globalThis.Intl = katanaIntl;
globalThis.crypto = {
getRandomValues(array) {
for (let index = 0; index < array.length; index += 1) {
array[index] = katanaDeterministicByte(index);
}
return array;
},
randomUUID() {
return "00000000-0000-4000-8000-000000000000";
},
};
Math.random = katanaDeterministicRandom;
let katanaRandomState = 0x12345678;
globalThis.queueMicrotask = (callback) => Promise.resolve().then(callback);
function katanaDeterministicRandom() {
katanaRandomState = (1664525 * katanaRandomState + 1013904223) >>> 0;
return katanaRandomState / 0x100000000;
}
function katanaDeterministicByte(index) {
return (index * 73 + 41) & 0xff;
}
function katanaStorage() {
const values = {};
return {
get length() {
return Object.keys(values).length;
},
clear() {
Object.keys(values).forEach((key) => delete values[key]);
},
getItem(key) {
return values[String(key)] ?? null;
},
key(index) {
return Object.keys(values)[index] ?? null;
},
removeItem(key) {
delete values[String(key)];
},
setItem(key, value) {
values[String(key)] = String(value);
},
};
}
globalThis.setTimeout = (callback, _delay, ...args) => callback(...args);
globalThis.clearTimeout = () => {};
globalThis.setInterval = (callback, _delay, ...args) => callback(...args);
globalThis.clearInterval = () => {};
globalThis.MessageChannel = KatanaMessageChannel;
let katanaAnimationFrameDepth = 0;
globalThis.requestAnimationFrame = (callback) => katanaRunAnimationFrame(callback);
function katanaRunAnimationFrame(callback) {
if (katanaAnimationFrameDepth > 4) {
return 0;
}
return katanaInvokeAnimationFrame(callback);
}
function katanaInvokeAnimationFrame(callback) {
katanaAnimationFrameDepth += 1;
try {
return callback(Date.now());
} finally {
katanaAnimationFrameDepth -= 1;
}
}
globalThis.cancelAnimationFrame = () => {};
globalThis.addEventListener = () => {};
globalThis.removeEventListener = () => {};
globalThis.__katanaMissingSelectors = [];
const KATANA_BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
globalThis.btoa = (value) => {
const utf8 = unescape(encodeURIComponent(String(value)));
return katanaBase64Triplets(utf8).map(katanaBase64Chunk).join("");
};
function katanaBase64Triplets(value) {
return value.match(/[\s\S]{1,3}/g) ?? [];
}
function katanaBase64Chunk(chunk) {
const first = chunk.charCodeAt(0);
const second = chunk.charCodeAt(1);
const third = chunk.charCodeAt(2);
return [
first >> 2,
((first & 3) << 4) | (second >> 4),
katanaThirdBase64Index(second, third),
katanaFourthBase64Index(third),
]
.map((index) => KATANA_BASE64_CHARS.charAt(index))
.join("");
}
function katanaThirdBase64Index(second, third) {
if (Number.isNaN(second)) {
return 64;
}
return ((second & 15) << 2) | (third >> 6);
}
function katanaFourthBase64Index(third) {
if (Number.isNaN(third)) {
return 64;
}
return third & 63;
}
globalThis.DOMPurify = {
sanitize(value) {
return String(value ?? "");
},
addHook() {},
removeHook() {},
};
class KatanaStyle {
constructor() {
this.values = {};
}
setProperty(name, value) {
this.values[String(name)] = String(value);
}
getPropertyValue(name) {
return this.values[String(name)] ?? "";
}
removeProperty(name) {
const value = this.getPropertyValue(name);
delete this.values[String(name)];
return value;
}
set mixBlendMode(value) {
this.setProperty("mix-blend-mode", value);
}
get mixBlendMode() {
return this.getPropertyValue("mix-blend-mode");
}
get cssText() {
return Object.entries(this.values)
.map(([key, value]) => `${key}: ${value};`)
.join(" ");
}
clone() {
const cloned = new KatanaStyle();
cloned.values = { ...this.values };
return cloned;
}
}
class KatanaCSSRule {
constructor(cssText) {
this.cssText = String(cssText);
}
}
class KatanaCSSStyleSheet {
constructor() {
this.cssRules = [];
}
insertRule(rule, index = this.cssRules.length) {
const insertIndex = katanaCssRuleInsertIndex(index, this.cssRules.length);
this.cssRules.splice(insertIndex, 0, new KatanaCSSRule(rule));
return insertIndex;
}
replaceSync(cssText) {
this.cssRules = katanaStyleSheetRuleTexts(cssText).map((it) => new KatanaCSSRule(it));
}
}
function katanaCssRuleInsertIndex(index, length) {
const parsed = Number(index);
if (!Number.isFinite(parsed)) {
return length;
}
return Math.max(0, Math.min(Math.trunc(parsed), length));
}
function katanaStyleSheetRuleTexts(cssText) {
const source = String(cssText ?? "").trim();
if (source.length === 0) {
return [];
}
return source.match(/[^{}]+\{[^{}]*\}/g) ?? [source];
}
globalThis.CSSStyleSheet = KatanaCSSStyleSheet;
globalThis.getComputedStyle = (node) => ({
getPropertyValue(name) {
return node?.style?.getPropertyValue?.(name) ?? "";
},
});
/* dom-node.js */
function katanaEscapeSvgAttribute(value) {
return String(value)
.replace(/&/g, "&")
.replace(/"/g, """)
.replace(/</g, "<")
.replace(/>/g, ">");
}
function katanaEscapeSvgText(value) {
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
}
class KatanaNode {
constructor(tagName, namespaceURI = null) {
const rawName = katanaRawNodeName(tagName);
const preservesCase = katanaPreservesNodeCase(namespaceURI);
this.serializedName = katanaSerializedNodeName(rawName, preservesCase);
this.tagName = katanaTagNodeName(rawName, preservesCase);
this.nodeName = this.tagName;
this.localName = rawName.toLowerCase();
this.namespaceURI = namespaceURI;
this.children = [];
this.childNodes = this.children;
this.parentNode = null;
this.ownerDocument = null;
this.nodeType = katanaNodeType(tagName);
this.attributes = [];
this.attributeMap = {};
this.style = new KatanaStyle();
this.dataset = {};
this._textContent = "";
this.className = "";
this.id = "";
}
appendChild(child) {
child.parentNode = this;
child.ownerDocument = this.ownerDocument;
this.children.push(child);
this.childNodes = this.children;
return child;
}
insertBefore(child, reference) {
child.parentNode = this;
child.ownerDocument = this.ownerDocument;
const index = this.children.indexOf(reference);
if (index < 0) {
this.children.push(child);
this.childNodes = this.children;
return child;
}
this.children.splice(index, 0, child);
this.childNodes = this.children;
return child;
}
removeChild(child) {
this.children = this.children.filter((candidate) => candidate !== child);
this.childNodes = this.children;
return child;
}
remove() {
if (this.parentNode) {
this.parentNode.removeChild(this);
}
}
get firstChild() {
return this.children[0] ?? null;
}
get lastChild() {
return this.children[this.children.length - 1] ?? null;
}
get parentElement() {
return this.parentNode;
}
getRootNode() {
return this.ownerDocument ?? document;
}
hasChildNodes() {
return this.children.length > 0;
}
compareDocumentPosition(other) {
if (this === other) {
return 0;
}
return 4;
}
get nextSibling() {
if (!this.parentNode) {
return null;
}
const index = this.parentNode.children.indexOf(this);
return this.parentNode.children[index + 1] ?? null;
}
get previousSibling() {
if (!this.parentNode) {
return null;
}
const index = this.parentNode.children.indexOf(this);
return this.parentNode.children[index - 1] ?? null;
}
setAttribute(name, value) {
const normalized = String(name);
const attribute = katanaUpsertAttribute(this, normalized);
attribute.value = String(value);
katanaSyncIdAttribute(this, normalized, value);
katanaSyncClassAttribute(this, normalized, value);
}
getAttribute(name) {
return this.attributeMap[String(name)]?.value ?? null;
}
removeAttribute(name) {
const normalized = String(name);
delete this.attributeMap[normalized];
this.attributes = this.attributes.filter((attribute) => attribute.name !== normalized);
}
setAttributeNS(_namespace, name, value) {
this.setAttribute(name, value);
}
getAttributeNS(_namespace, name) {
return this.getAttribute(name);
}
hasAttribute(name) {
return Object.hasOwn(this.attributeMap, String(name));
}
querySelector(selector) {
const result = katanaFirstQuerySelectorResult(this, selector);
if (result === null) {
globalThis.__katanaMissingSelectors.push(`${this.localName}:${selector}`);
}
return result;
}
querySelectorAll(selector) {
const compound = queryCompoundSelector(this, String(selector));
if (compound !== null) {
return compound;
}
return querySimpleSelector(this, String(selector));
}
getElementsByTagName(tagName) {
return this.querySelectorAll(String(tagName).toLowerCase());
}
addEventListener() {}
removeEventListener() {}
dispatchEvent() {
return true;
}
focus() {
document.activeElement = this;
}
click() {}
get isConnected() {
return this === document || document.documentElement.contains(this);
}
toJSON() {
return {};
}
}
function katanaFirstQuerySelectorResult(node, selector) {
return node.querySelectorAll(selector)[0] ?? null;
}
function katanaRawNodeName(tagName) {
return String(tagName || "");
}
function katanaPreservesNodeCase(namespaceURI) {
return [
katanaNamespaceIncludes(namespaceURI, "svg"),
katanaNamespaceIncludes(namespaceURI, "xml"),
].includes(true);
}
function katanaNamespaceIncludes(namespaceURI, value) {
return String(namespaceURI || "").includes(value);
}
function katanaSerializedNodeName(rawName, preservesCase) {
return preservesCase ? rawName : rawName.toLowerCase();
}
function katanaTagNodeName(rawName, preservesCase) {
return preservesCase ? rawName : rawName.toUpperCase();
}
function katanaNodeType(tagName) {
return tagName === "#text" ? 3 : 1;
}
function katanaUpsertAttribute(node, normalized) {
const attribute = node.attributeMap[normalized];
if (attribute) {
return attribute;
}
return katanaCreateAttribute(node, normalized);
}
function katanaCreateAttribute(node, normalized) {
const attribute = { name: normalized, nodeName: normalized, value: "" };
node.attributeMap[normalized] = attribute;
node.attributes.push(attribute);
return attribute;
}
function katanaSyncIdAttribute(node, normalized, value) {
if (normalized === "id") {
node.id = String(value);
}
}
function katanaSyncClassAttribute(node, normalized, value) {
if (normalized === "class") {
node.className = String(value);
}
}
/* dom-style.js */
function katanaStyleCamelName(name) {
return String(name).replace(/-([a-z])/g, (_match, char) => char.toUpperCase());
}
function katanaStyleKebabName(name) {
return String(name).replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
}
function katanaApplyCssText(style, value) {
katanaCssEntries(value).forEach((entry) => {
katanaApplyCssEntry(style, entry);
});
}
function katanaCssEntries(value) {
return String(value ?? "").split(";");
}
function katanaApplyCssEntry(style, entry) {
const separator = entry.indexOf(":");
if (separator < 0) return;
style.setProperty(entry.slice(0, separator).trim(), entry.slice(separator + 1).trim());
}
[
"backgroundColor",
"border",
"borderBottom",
"borderColor",
"borderRadius",
"borderRightStyle",
"color",
"colorScheme",
"cursor",
"display",
"fill",
"fontFamily",
"fontSize",
"fontWeight",
"height",
"margin",
"marginBottom",
"maxHeight",
"maxWidth",
"opacity",
"overflow",
"padding",
"paddingBottom",
"position",
"right",
"stroke",
"stopColor",
"textAlign",
"top",
"verticalAlign",
"width",
"zIndex",
].forEach(katanaInstallStyleDirectProperty);
function katanaInstallStyleDirectProperty(camel) {
if (Object.getOwnPropertyDescriptor(KatanaStyle.prototype, camel)) {
return;
}
Object.defineProperty(KatanaStyle.prototype, camel, {
get() {
return this.getPropertyValue(katanaStyleKebabName(camel));
},
set(value) {
this.setProperty(katanaStyleKebabName(camel), value);
},
});
}
KatanaStyle.prototype.setProperty = function setProperty(name, value) {
const kebab = katanaStyleKebabName(name);
const camel = katanaStyleCamelName(name);
this.values[kebab] = String(value);
this.values[camel] = String(value);
if (!Object.getOwnPropertyDescriptor(KatanaStyle.prototype, camel)) {
this[camel] = String(value);
}
};
KatanaStyle.prototype.getPropertyValue = function getPropertyValue(name) {
const key = String(name);
const kebab = katanaStyleKebabName(key);
const camel = katanaStyleCamelName(key);
return this.values[key] ?? this.values[kebab] ?? this.values[camel] ?? katanaStyleOwnValue(this, camel);
};
function katanaStyleOwnValue(style, camel) {
return Object.hasOwn(style, camel) ? style[camel] : "";
}
KatanaStyle.prototype.removeProperty = function removeProperty(name) {
const value = this.getPropertyValue(name);
delete this.values[String(name)];
delete this.values[katanaStyleKebabName(name)];
delete this.values[katanaStyleCamelName(name)];
delete this[katanaStyleCamelName(name)];
return value;
};
Object.defineProperty(KatanaStyle.prototype, "cssText", {
get() {
return Object.entries(this.values)
.filter(([key]) => key.includes("-"))
.map(([key, value]) => `${key}: ${value}`)
.join("; ");
},
set(value) {
this.values = {};
katanaApplyCssText(this, value);
},
});
const katanaSetAttributeBase = KatanaNode.prototype.setAttribute;
KatanaNode.prototype.setAttribute = function setAttribute(name, value) {
katanaSetAttributeBase.call(this, name, value);
if (String(name).toLowerCase() === "style") {
this.style.cssText = value;
}
};
/* dom-html.js */
function parseInnerHtml(source, xmlMode = false) {
const root = {
localName: "#root",
children: [],
appendChild(child) {
this.children.push(child);
},
};
const stack = [root];
const tokenRegex = /<\/?([a-zA-Z0-9:_-]+)([^>]*)>|([^<]+)/g;
Array.from(source.matchAll(tokenRegex)).forEach((match) => {
appendHtmlToken(stack, match, xmlMode);
});
return root.children;
}
function appendHtmlToken(stack, match, xmlMode) {
if (match[3] !== undefined) {
appendHtmlText(stack[stack.length - 1], match[3]);
return;
}
appendHtmlTag(stack, match, xmlMode);
}
function appendHtmlTag(stack, match, xmlMode) {
if (match[0].startsWith("</")) {
popHtmlStack(stack, match[1]);
return;
}
appendHtmlStartTag(stack, match, xmlMode);
}
function appendHtmlStartTag(stack, match, xmlMode) {
const node = new KatanaNode(match[1], katanaHtmlNamespace(xmlMode));
node.ownerDocument = document;
parseAttributes(match[2]).forEach(([name, value]) => {
node.setAttribute(name, value);
});
stack[stack.length - 1].appendChild(node);
pushHtmlElementIfOpen(stack, node, match[0], match[1]);
}
function katanaHtmlNamespace(xmlMode) {
return xmlMode ? "katana-xml" : null;
}
function pushHtmlElementIfOpen(stack, node, fullTag, tagName) {
if (katanaIsOpenHtmlTag(fullTag, tagName)) {
stack.push(node);
}
}
function katanaIsOpenHtmlTag(fullTag, tagName) {
return [!fullTag.endsWith("/>"), !isHtmlVoidTag(tagName)].every(Boolean);
}
function appendHtmlText(parent, value) {
const text = decodeHtmlEntities(value);
if (text.length > 0) {
parent.appendChild(new KatanaTextNode(text));
}
}
function popHtmlStack(stack, tagName) {
const normalized = String(tagName).toLowerCase();
const index = stack.findLastIndex((node) => node.localName === normalized);
if (index > 0) {
stack.splice(index);
}
}
function isHtmlVoidTag(tagName) {
return new Set(["br", "hr", "img", "input", "meta", "link"]).has(String(tagName).toLowerCase());
}
function parseAttributes(source) {
const attrRegex = /([a-zA-Z0-9:_-]+)="([^"]*)"/g;
return Array.from(source.matchAll(attrRegex)).map((match) => [
match[1],
decodeHtmlEntities(match[2]),
]);
}
function decodeHtmlEntities(value) {
if (globalThis.__katanaMermaidDiagramType === "block") {
return katanaDecodeHtmlEntitiesForBlock(value);
}
return String(value)
.replace(/&nbsp;/g, "\u00A0")
.replace(/ /g, "\u00A0")
.replace(/
/gi, "\n")
.replace(/ /g, "\n")
.replace(/ /g, "\u00A0")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/&/g, "&")
.replace(/"/g, '"')
.replace(/'/g, "'");
}
function katanaDecodeHtmlEntitiesForBlock(value) {
return String(value)
.replace(/&nbsp;/g, " ")
.replace(/
/gi, "\n")
.replace(/ /g, "\n")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/&/g, "&")
.replace(/"/g, '"')
.replace(/'/g, "'");
}
class KatanaTextNode extends KatanaNode {
constructor(value) {
super("#text");
this.textContent = String(value);
}
get outerHTML() {
return katanaEscapeSvgText(this.textContent);
}
}
/* dom-node-html.js */
KatanaNode.prototype.getBBox = function getBBox() {
const text = katanaNodeTextForBox(this);
const childWidth = katanaNodeChildWidth(this);
const width = Math.max(80, childWidth, katanaTextWidth(text));
const height = Math.max(24, this.children.length * 24);
return { x: 0, y: 0, width, height };
};
function katanaNodeTextForBox(node) {
return String(katanaFirstTextValue([node.textContent, node.innerText]));
}
function katanaFirstTextValue(values) {
return values.find(Boolean) ?? "";
}
function katanaNodeChildWidth(node) {
return node.children.reduce((max, child) => Math.max(max, child.getBBox().width), 0);
}
KatanaNode.prototype.getBoundingClientRect = function getBoundingClientRect() {
const box = this.getBBox();
return {
...box,
top: box.y,
left: box.x,
right: box.x + box.width,
bottom: box.y + box.height,
};
};
KatanaNode.prototype.getComputedTextLength = function getComputedTextLength() {
return Math.max(16, katanaTextWidth(String(this.textContent || "")));
};
KatanaNode.prototype.getContext = function getContext() {
return {
font: "",
measureText(value) {
return { width: Math.max(16, katanaTextWidth(String(value || ""))) };
},
};
};
Object.defineProperty(KatanaNode.prototype, "innerHTML", {
get() {
if (this.children.length === 0) {
return this.textContent;
}
return this.children.map((child) => child.outerHTML ?? child.textContent ?? "").join("");
},
set(value) {
katanaClearInnerHtml(this);
katanaApplyInnerHtml(this, String(value), parseInnerHtml(String(value)));
},
});
function katanaClearInnerHtml(node) {
node.textContent = "";
node.children = [];
node.childNodes = node.children;
}
function katanaApplyInnerHtml(node, value, parsed) {
if (parsed.length === 0) {
node.textContent = value;
return;
}
katanaAppendParsedHtml(node, parsed);
}
function katanaAppendParsedHtml(node, parsed) {
for (const child of parsed) {
node.appendChild(child);
}
}
Object.defineProperty(KatanaNode.prototype, "outerHTML", {
get() {
const attrs = katanaSerializedAttributeText(this);
const body = katanaOuterHtmlBody(this);
return `<${this.serializedName}${attrs}>${body}</${this.serializedName}>`;
},
});
function katanaSerializedAttributeText(node) {
return Object.entries({ ...node.serializedAttributes(), ...katanaStyleAttribute(node) })
.map(([key, value]) => ` ${key}="${katanaEscapeSvgAttribute(value)}"`)
.join("");
}
function katanaStyleAttribute(node) {
if (katanaShouldSerializeStyle(node)) {
return { style: node.style.cssText };
}
return {};
}
function katanaShouldSerializeStyle(node) {
return [node.style.cssText, !node.hasAttribute("style")].every(Boolean);
}
function katanaOuterHtmlBody(node) {
if (node.children.length === 0) {
return katanaEscapeSvgText(node.textContent);
}
return node.innerHTML;
}
KatanaNode.prototype.cloneNode = function cloneNode(deep = false) {
const clone = katanaShallowCloneNode(this);
katanaCloneChildrenIfDeep(this, clone, deep);
return clone;
};
function katanaShallowCloneNode(node) {
const clone = new KatanaNode(node.serializedName, node.namespaceURI);
node.attributes.forEach((attribute) => {
clone.setAttribute(attribute.name, attribute.value);
});
clone.style = node.style.clone();
clone._textContent = node._textContent ?? "";
clone.className = node.className;
clone.id = node.id;
clone.ownerDocument = node.ownerDocument;
return clone;
}
function katanaCloneChildrenIfDeep(node, clone, deep) {
if (deep) {
katanaCloneChildren(node, clone);
}
}
function katanaCloneChildren(node, clone) {
for (const child of node.children) {
clone.appendChild(child.cloneNode(true));
}
}
KatanaNode.prototype.serializedAttributes = function serializedAttributes() {
return Object.fromEntries(this.attributes.map((attribute) => [attribute.name, attribute.value]));
};
/* dom-canvas-context.js */
class KatanaCanvasContext {
constructor() {
this.font = "";
}
measureText(value) {
return { width: katanaCanvasTextWidth(String(value ?? ""), this.font) };
}
}
KatanaNode.prototype.getContext = function getContext() {
return new KatanaCanvasContext();
};
function katanaCanvasTextWidth(text, font) {
const fontScale = katanaCanvasFontScale(font);
const chars = Array.from(katanaMeasuredTextValue(text));
return chars
.map((char) => katanaCanvasCharacterWidth(char))
.reduce((width, charWidth) => width + charWidth * fontScale, 0);
}
function katanaCanvasFontScale(font) {
return katanaFiniteFontSize(katanaCanvasFontSize(font)) / 16;
}
function katanaCanvasFontSize(font) {
const match = String(font ?? "").match(/(\d+(?:\.\d+)?)px/);
return match ? Number(match[1]) : 16;
}
function katanaCanvasCharacterWidth(char) {
if (char.charCodeAt(0) === 160) {
return KATANA_CANVAS_ASCII_TEXT_WIDTHS[" "];
}
return KATANA_CANVAS_ASCII_TEXT_WIDTHS[char] ?? katanaTextWidth(char);
}
const KATANA_CANVAS_ASCII_TEXT_WIDTHS = {
" ": 4.445,
"!": 4.445,
'"': 5.68,
"'": 3.055,
"(": 5.328,
")": 5.328,
"-": 5.328,
".": 4.445,
"/": 4.445,
":": 4.445,
0: 8.898,
1: 8.898,
2: 8.898,
3: 8.898,
4: 8.898,
5: 8.898,
6: 8.898,
7: 8.898,
8: 8.898,
9: 8.898,
"=": 9.344,
A: 10.672,
B: 10.672,
C: 11.555,
D: 11.555,
E: 10.672,
F: 9.773,
G: 12.445,
H: 11.555,
I: 4.445,
J: 8,
K: 10.672,
L: 8.898,
M: 13.328,
N: 11.555,
O: 12.445,
P: 10.672,
Q: 12.445,
R: 11.555,
S: 10.672,
T: 9.773,
U: 11.555,
V: 10.672,
W: 15.102,
X: 10.672,
Y: 10.672,
Z: 9.773,
_: 8.898,
a: 8.898,
b: 8.898,
c: 8,
d: 8.898,
e: 8.898,
f: 4.445,
g: 8.898,
h: 8.898,
i: 3.555,
j: 3.555,
k: 8,
l: 3.555,
m: 13.328,
n: 8.898,
o: 8.898,
p: 8.898,
q: 8.898,
r: 5.328,
s: 8,
t: 4.445,
u: 8.898,
v: 8,
w: 11.555,
x: 8,
y: 8,
z: 8,
};
/* dom-selector.js */
function matchesSelector(node, selector) {
const matcher = KATANA_SELECTOR_MATCHERS.find((entry) => entry.applies(selector));
if (matcher) {
return matcher.matches(node, selector);
}
return katanaMatchesTag(node, selector);
}
const KATANA_SELECTOR_MATCHERS = [
{ applies: katanaIsBareFirstChildSelector, matches: katanaMatchesBareFirstChild },
{ applies: katanaIsNestedFirstChildSelector, matches: katanaMatchesNestedFirstChild },
{ applies: katanaIsWildcardSelector, matches: katanaMatchesWildcard },
{ applies: katanaIsTagIdSelector, matches: katanaMatchesTagId },
{ applies: katanaIsBodySelector, matches: katanaMatchesBody },
{ applies: katanaIsIdSelector, matches: katanaMatchesId },
{ applies: katanaIsIdAttributeSelector, matches: katanaMatchesIdAttribute },
{ applies: katanaIsClassSelector, matches: katanaMatchesClass },
];
function katanaIsBareFirstChildSelector(selector) {
return [":first-child", "::first-child"].includes(selector);
}
function katanaMatchesBareFirstChild(node) {
return node.parentNode?.firstElementChild === node;
}
function katanaIsNestedFirstChildSelector(selector) {
return selector.endsWith(":first-child");
}
function katanaMatchesNestedFirstChild(node, selector) {
const base = selector.replace(/:{1,2}first-child$/, "");
return [matchesSelector(node, base), katanaMatchesBareFirstChild(node)].every(Boolean);
}
function katanaIsWildcardSelector(selector) {
return selector === "*";
}
function katanaMatchesWildcard(node) {
return node.nodeType === Node.ELEMENT_NODE;
}
function katanaIsTagIdSelector(selector) {
return /^([a-zA-Z0-9:_-]+)#(.+)$/.test(selector);
}
function katanaMatchesTagId(node, selector) {
const match = selector.match(/^([a-zA-Z0-9:_-]+)#(.+)$/);
return [node.localName === match[1].toLowerCase(), node.id === match[2]].every(Boolean);
}
function katanaIsBodySelector(selector) {
return selector === "body";
}
function katanaMatchesBody(node) {
return node === document.body;
}
function katanaIsIdSelector(selector) {
return selector.startsWith("#");
}
function katanaMatchesId(node, selector) {
return node.id === selector.slice(1);
}
function katanaIsIdAttributeSelector(selector) {
return /^\[id="([^"]+)"\]$/.test(selector);
}
function katanaMatchesIdAttribute(node, selector) {
return node.id === selector.match(/^\[id="([^"]+)"\]$/)[1];
}
function katanaIsClassSelector(selector) {
return selector.startsWith(".");
}
function katanaMatchesClass(node, selector) {
return String(node.className).split(/\s+/).includes(selector.slice(1));
}
function katanaMatchesTag(node, selector) {
return node.localName === selector.toLowerCase();
}
function queryCompoundSelector(root, selector) {
const parts = selector.split(/\s+/).filter(Boolean);
if (parts.length <= 1) {
return null;
}
return katanaQuerySelectorParts([root], parts);
}
function katanaQuerySelectorParts(candidates, parts) {
return parts.reduce(
(current, part) => current.flatMap((candidate) => querySimpleSelector(candidate, part)),
candidates,
);
}
function querySimpleSelector(root, selector) {
const results = [];
root.children.forEach((node) => {
katanaVisitSelector(node, selector, results);
});
return results;
}
function katanaVisitSelector(node, selector, results) {
katanaAddMatchingSelector(node, selector, results);
node.children.forEach((child) => {
katanaVisitSelector(child, selector, results);
});
}
function katanaAddMatchingSelector(node, selector, results) {
if (matchesSelector(node, selector)) {
results.push(node);
}
}
/* dom-document.js */
const document = {
nodeType: 9,
currentScript: null,
activeElement: null,
addEventListener() {},
removeEventListener() {},
dispatchEvent() {
return true;
},
createElement(tagName) {
const node = new KatanaNode(tagName);
node.ownerDocument = document;
return node;
},
createElementNS(namespaceURI, tagName) {
const node = new KatanaNode(tagName, namespaceURI);
node.ownerDocument = document;
return node;
},
createTextNode(value) {
const node = new KatanaTextNode(value);
node.ownerDocument = document;
return node;
},
createComment(value) {
return this.createTextNode(value);
},
createDocumentFragment() {
const node = new KatanaNode("#document-fragment");
node.nodeType = 11;
node.ownerDocument = document;
return node;
},
createNodeIterator(root) {
const nodes = [];
const visit = (node) => {
nodes.push(node);
node.children.forEach(visit);
};
visit(root);
let index = 0;
return { nextNode: () => nodes[index++] ?? null };
},
getElementsByTagName(tagName) {
return this.documentElement.querySelectorAll(String(tagName).toLowerCase());
},
importNode(node, deep) {
const clone = node.cloneNode(deep);
clone.ownerDocument = document;
return clone;
},
getElementById(id) {
const result = this.documentElement.querySelector(`#${id}`);
if (result === null) {
globalThis.__katanaMissingSelectors.push(`document.getElementById:${id}`);
}
return result;
},
querySelector(selector) {
if (selector === "body") {
return this.body;
}
return this.documentElement.querySelector(selector);
},
querySelectorAll(selector) {
return this.documentElement.querySelectorAll(selector);
},
implementation: {
createHTMLDocument() {
return createDetachedDocument();
},
},
fonts: {
ready: Promise.resolve(),
},
};
document.documentElement = document.createElement("html");
document.head = document.createElement("head");
document.body = document.createElement("body");
document.documentElement.appendChild(document.head);
document.documentElement.appendChild(document.body);
document.defaultView = globalThis;
globalThis.document = document;
globalThis.Element = KatanaNode;
globalThis.HTMLElement = KatanaNode;
globalThis.SVGElement = KatanaNode;
globalThis.Node = KatanaNode;
globalThis.Node.ELEMENT_NODE = 1;
globalThis.Node.TEXT_NODE = 3;
globalThis.Node.DOCUMENT_NODE = 9;
globalThis.Node.DOCUMENT_FRAGMENT_NODE = 11;
globalThis.DocumentFragment = KatanaNode;
globalThis.HTMLTemplateElement = KatanaNode;
globalThis.HTMLFormElement = KatanaNode;
globalThis.HTMLButtonElement = KatanaNode;
globalThis.HTMLCanvasElement = KatanaNode;
globalThis.HTMLFieldSetElement = KatanaNode;
globalThis.HTMLIFrameElement = KatanaNode;
globalThis.HTMLImageElement = KatanaNode;
globalThis.HTMLInputElement = KatanaNode;
globalThis.HTMLLabelElement = KatanaNode;
globalThis.HTMLLegendElement = KatanaNode;
globalThis.HTMLSelectElement = KatanaNode;
globalThis.HTMLTextAreaElement = KatanaNode;
globalThis.HTMLVideoElement = KatanaNode;
globalThis.SVGImageElement = KatanaNode;
globalThis.NamedNodeMap = Array;
globalThis.NodeFilter = { SHOW_ELEMENT: 1, SHOW_TEXT: 4, SHOW_COMMENT: 128 };
globalThis.MutationObserver = class {
constructor(callback) {
this.callback = callback;
}
observe() {}
disconnect() {}
takeRecords() {
return [];
}
};
globalThis.trustedTypes = {
createPolicy() {
return {
createHTML: (value) => String(value),
createScriptURL: (value) => String(value),
};
},
};
globalThis.TextEncoder = class {
encode(value) {
return new Uint8Array(Array.from(String(value)).flatMap((char) => katanaUtf8Bytes(char)));
}
};
function katanaUtf8Bytes(char) {
const code = char.charCodeAt(0);
if (code < 0x80) {
return [code];
}
return katanaMultibyteUtf8Bytes(code);
}
function katanaMultibyteUtf8Bytes(code) {
if (code < 0x800) {
return [0xc0 | (code >> 6), 0x80 | (code & 0x3f)];
}
return [0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f)];
}
globalThis.TextDecoder = class {
decode(value) {
return Array.from(value)
.map((byte) => String.fromCharCode(byte))
.join("");
}
};
globalThis.structuredClone = (value) => JSON.parse(JSON.stringify(value));
globalThis.XMLSerializer = class {
serializeToString(node) {
return node.outerHTML ?? "";
}
};
globalThis.DOMParser = class {
parseFromString(source) {
const parsed = parseInnerHtml(String(source).trim(), true);
const detached = createDetachedDocument();
const root = parsed[0] ?? detached.createElement("xml");
attachOwnerDocument(root, detached);
detached.documentElement = root;
detached.body = root;
return detached;
}
};
function createDetachedDocument() {
const detached = Object.create(document);
detached.documentElement = document.createElement("html");
detached.head = document.createElement("head");
detached.body = document.createElement("body");
detached.documentElement.ownerDocument = detached;
detached.head.ownerDocument = detached;
detached.body.ownerDocument = detached;
detached.documentElement.appendChild(detached.head);
detached.documentElement.appendChild(detached.body);
detached.defaultView = globalThis;
detached.nodeType = 9;
return detached;
}
function attachOwnerDocument(node, ownerDocument) {
node.ownerDocument = ownerDocument;
for (const child of node.children) {
attachOwnerDocument(child, ownerDocument);
}
}
/* dom-tree.js */
function katanaDetachChild(child) {
const parent = child?.parentNode;
if (!parent) return;
katanaReplaceChildList(
parent,
katanaChildList(parent).filter((candidate) => candidate !== child),
);
child.parentNode = null;
}
function katanaChildList(parent) {
return [parent.children, parent.childNodes, []].find(Array.isArray);
}
function katanaReplaceChildList(parent, children) {
parent.children = children;
parent.childNodes = children;
}
function katanaAdoptChild(parent, child) {
child.parentNode = parent;
child.ownerDocument = parent.ownerDocument ?? parent;
}
function katanaAppendFragment(parent, fragment) {
const nodes = [...fragment.childNodes];
for (const node of nodes) {
parent.appendChild(node);
}
return fragment;
}
KatanaNode.prototype.appendChild = function appendChild(child) {
if (child.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
return katanaAppendFragment(this, child);
}
katanaDetachChild(child);
katanaAdoptChild(this, child);
this.children.push(child);
this.childNodes = this.children;
return child;
};
KatanaNode.prototype.insertBefore = function insertBefore(child, reference) {
if (child.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
return katanaInsertFragmentBefore(this, child, reference);
}
return katanaInsertNodeBefore(this, child, reference);
};
function katanaInsertFragmentBefore(parent, fragment, reference) {
for (const node of fragment.childNodes) {
parent.insertBefore(node, reference);
}
return fragment;
}
function katanaInsertNodeBefore(parent, child, reference) {
if (child === reference) {
return child;
}
return katanaInsertDetachedNodeBefore(parent, child, reference);
}
function katanaInsertDetachedNodeBefore(parent, child, reference) {
katanaDetachChild(child);
katanaAdoptChild(parent, child);
katanaInsertAtReference(parent, child, reference);
parent.childNodes = parent.children;
return child;
}
function katanaInsertAtReference(parent, child, reference) {
const index = parent.children.indexOf(reference);
if (index < 0) {
parent.children.push(child);
return;
}
parent.children.splice(index, 0, child);
}
KatanaNode.prototype.removeChild = function removeChild(child) {
this.children = this.children.filter((candidate) => candidate !== child);
this.childNodes = this.children;
child.parentNode = null;
return child;
};
Object.defineProperty(KatanaNode.prototype, "firstElementChild", {
get() {
return this.children.find((child) => child.nodeType === Node.ELEMENT_NODE) ?? null;
},
});
function katanaDocumentPath(node) {
const path = [];
let current = node;
while (current?.parentNode) {
path.unshift(current.parentNode.children.indexOf(current));
current = current.parentNode;
}
return path;
}
function katanaComparePath(left, right) {
const mismatch = katanaFirstPathMismatch(left, right);
if (mismatch !== null) {
return katanaPathMismatchPosition(left, right, mismatch);
}
return katanaPathLengthPosition(left, right);
}
function katanaFirstPathMismatch(left, right) {
return katanaPathIndexes(left, right).find((index) => left[index] !== right[index]) ?? null;
}
function katanaPathIndexes(left, right) {
return Array.from({ length: Math.min(left.length, right.length) }, (_value, index) => index);
}
function katanaPathMismatchPosition(left, right, index) {
return left[index] < right[index] ? 4 : 2;
}
function katanaPathLengthPosition(left, right) {
if (left.length === right.length) {
return 0;
}
return katanaUnequalPathLengthPosition(left, right);
}
function katanaUnequalPathLengthPosition(left, right) {
return left.length < right.length ? 20 : 10;
}
KatanaNode.prototype.compareDocumentPosition = function compareDocumentPosition(other) {
if (this === other) return 0;
return katanaComparePath(katanaDocumentPath(this), katanaDocumentPath(other));
};
Node.DOCUMENT_POSITION_DISCONNECTED = 1;
Node.DOCUMENT_POSITION_PRECEDING = 2;
Node.DOCUMENT_POSITION_FOLLOWING = 4;
Node.DOCUMENT_POSITION_CONTAINS = 8;
Node.DOCUMENT_POSITION_CONTAINED_BY = 16;
/* dom-layout.js */
const KATANA_HIDDEN_LAYOUT_TAGS = new Set([
"style",
"script",
"defs",
"marker",
"lineargradient",
"radialgradient",
"stop",
"filter",
"fedropshadow",
"clippath",
"mask",
"pattern",
]);
function katanaOwnText(node) {
return String(node?._textContent ?? "");
}
function katanaTextContent(node) {
return node ? `${katanaOwnText(node)}${katanaTextContentChildren(node)}` : "";
}
function katanaTextContentChildren(node) {
return (node.children ?? []).map((child) => katanaTextContent(child)).join("");
}
function katanaLayoutTextContent(node) {
if (katanaIsHiddenLayoutNode(node)) {
return "";
}
return `${katanaOwnText(node)}${katanaLayoutTextChildren(node)}`;
}
function katanaLayoutTextChildren(node) {
return (node.children ?? []).map((child) => katanaLayoutTextContent(child)).join("");
}
function katanaIsHiddenLayoutNode(node) {
return [!node, KATANA_HIDDEN_LAYOUT_TAGS.has(node?.localName)].includes(true);
}
function katanaNodeValue(value) {
if (value instanceof KatanaNode) {
return value;
}
return document.createTextNode(katanaStringValue(value));
}
function katanaStringValue(value) {
return String(value ?? "");
}
function katanaNumberAttr(node, name) {
return katanaNullableNumber(node?.getAttribute?.(name));
}
function katanaNullableNumber(rawValue) {
return katanaHasNumberValue(rawValue) ? katanaFiniteNumber(Number(rawValue)) : null;
}
function katanaHasNumberValue(rawValue) {
return ![null, undefined, ""].includes(rawValue);
}
function katanaFiniteNumber(value) {
return Number.isFinite(value) ? value : null;
}
function katanaBox(x, y, width, height) {
return { x, y, width, height, w: width, h: height };
}
function katanaUnionBox(boxes) {
if (boxes.length === 0) {
return katanaBox(0, 0, 0, 0);
}
const minX = Math.min(...boxes.map((box) => box.x));
const minY = Math.min(...boxes.map((box) => box.y));
const maxX = Math.max(...boxes.map((box) => box.x + box.width));
const maxY = Math.max(...boxes.map((box) => box.y + box.height));
return katanaBox(minX, minY, maxX - minX, maxY - minY);
}
function katanaVisibleChildBoxes(node) {
return (node.children ?? [])
.filter((child) => !KATANA_HIDDEN_LAYOUT_TAGS.has(child.localName))
.map((child) => {
const box = child.getBBox();
const offset = katanaNodeTranslate(child);
return katanaBox(box.x + offset[0], box.y + offset[1], box.width, box.height);
});
}
function katanaMeasuredBox(node) {
if (KATANA_HIDDEN_LAYOUT_TAGS.has(node.localName)) {
return katanaBox(0, 0, 0, 0);
}
return katanaVisibleMeasuredBox(node);
}
function katanaVisibleMeasuredBox(node) {
return (
katanaExplicitMeasuredBox(node) ??
katanaDirectShapeBox(node) ??
katanaChildTextMeasuredBox(node)
);
}
function katanaExplicitMeasuredBox(node) {
const attrs = katanaBoxAttributes(node);
if ([attrs.width > 0, attrs.height > 0].includes(true)) {
return katanaBox(attrs.x, attrs.y, attrs.width, attrs.height);
}
return null;
}
function katanaBoxAttributes(node) {
return {
x: katanaNumberAttrOrDefault(node, "x", 0),
y: katanaNumberAttrOrDefault(node, "y", 0),
width: katanaNumberAttrOrDefault(node, "width", 0),
height: katanaNumberAttrOrDefault(node, "height", 0),
};
}
function katanaNumberAttrOrDefault(node, name, fallback) {
const value = katanaNumberAttr(node, name);
if (value === null) {
return fallback;
}
return value;
}
function katanaDirectShapeBox(node) {
return katanaLineBox(node) ?? katanaCircleBox(node);
}
function katanaChildTextMeasuredBox(node) {
const childBox = katanaUnionBox(katanaVisibleChildBoxes(node));
const text = katanaMeasuredNodeText(node, childBox);
return katanaBox(
0,
0,
katanaMeasuredTextWidth(text, childBox),
katanaMeasuredTextHeight(text, childBox),
);
}
function katanaMeasuredNodeText(node, childBox) {
return katanaOwnText(node) || katanaFallbackLayoutText(node, childBox);
}
function katanaFallbackLayoutText(node, childBox) {
return childBox.width === 0 ? katanaLayoutTextContent(node) : "";
}
function katanaMeasuredTextWidth(text, childBox) {
return Math.max(16, katanaTextWidthFallback(text), childBox.width);
}
function katanaMeasuredTextHeight(text, childBox) {
return Math.max(24, katanaTextHeightFallback(text), childBox.height);
}
function katanaTextWidthFallback(text) {
return text.length === 0 ? 0 : Math.max(16, katanaTextWidth(text));
}
function katanaTextHeightFallback(text) {
return text.length === 0 ? 0 : 24;
}
function katanaLineBox(node) {
if (node.localName !== "line") {
return null;
}
return katanaLineShapeBox(node);
}
function katanaLineShapeBox(node) {
const x1 = katanaNumberAttrOrDefault(node, "x1", 0);
const y1 = katanaNumberAttrOrDefault(node, "y1", 0);
const x2 = katanaNumberAttrOrDefault(node, "x2", 0);
const y2 = katanaNumberAttrOrDefault(node, "y2", 0);
return katanaBox(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
}
function katanaCircleBox(node) {
if (!katanaIsRoundSvgShape(node)) {
return null;
}
return katanaRoundShapeBox(node);
}
function katanaRoundShapeBox(node) {
const cx = katanaNumberAttrOrDefault(node, "cx", 0);
const cy = katanaNumberAttrOrDefault(node, "cy", 0);
const rx = katanaRoundRadius(node, "rx");
const ry = katanaRoundRadius(node, "ry");
return katanaBox(cx - rx, cy - ry, rx * 2, ry * 2);
}
function katanaRoundRadius(node, name) {
return katanaNumberAttr(node, name) ?? katanaNumberAttrOrDefault(node, "r", 0);
}
function katanaIsRoundSvgShape(node) {
return ["circle", "ellipse"].includes(node.localName);
}
function katanaNodeTranslate(node) {
const match = katanaTransformValue(node).match(/translate\(([-\d.]+)[,\s]+([-\d.]+)\)/);
if (match) {
return [Number(match[1]), Number(match[2])];
}
return [0, 0];
}
function katanaTransformValue(node) {
return String(node?.getAttribute?.("transform") ?? "");
}
/* dom-metrics.js */
const KATANA_DEFAULT_CLIENT_TAGS = new Set(["body", "div", "main", "pre", "section", "article"]);
function katanaMeasuredClientBox(node) {
const context = katanaClientBoxContext(node);
return (
katanaDefaultExplicitZeroBox(context) ??
katanaExplicitClientBox(context) ??
katanaSvgClientBox(context) ??
katanaEmptyDefaultClientBox(context) ??
context.box
);
}
function katanaClientBoxContext(node) {
return {
node,
box: node.getBBox(),
explicitWidth: katanaExplicitClientWidth(node),
explicitHeight: katanaExplicitClientHeight(node),
};
}
function katanaExplicitClientWidth(node) {
return (
katanaCssLength(node.style?.getPropertyValue?.("width")) ?? katanaNumberAttr(node, "width")
);
}
function katanaExplicitClientHeight(node) {
return (
katanaCssLength(node.style?.getPropertyValue?.("height")) ?? katanaNumberAttr(node, "height")
);
}
function katanaDefaultExplicitZeroBox(context) {
if ([katanaNeedsDefaultClientBox(context.node), context.explicitWidth === 0].every(Boolean)) {
return katanaBox(
0,
0,
katanaDefaultViewportWidth(),
katanaPositiveOrDefault(context.explicitHeight, katanaDefaultViewportHeight()),
);
}
return null;
}
function katanaExplicitClientBox(context) {
if (katanaHasExplicitClientSize(context)) {
return katanaResolvedExplicitClientBox(context);
}
return null;
}
function katanaHasExplicitClientSize(context) {
return [context.explicitWidth !== null, context.explicitHeight !== null].includes(true);
}
function katanaResolvedExplicitClientBox(context) {
return katanaBox(
context.box.x,
context.box.y,
katanaExplicitWidthValue(context),
katanaExplicitHeightValue(context),
);
}
function katanaExplicitWidthValue(context) {
return context.explicitWidth ?? context.box.width;
}
function katanaExplicitHeightValue(context) {
return context.explicitHeight ?? context.box.height;
}
function katanaSvgClientBox(context) {
if (context.node.localName === "svg") {
return katanaSvgViewBoxClientBox(context);
}
return null;
}
function katanaSvgViewBoxClientBox(context) {
const viewBox = katanaViewBoxSize(context.node.getAttribute("viewBox"));
return katanaBox(
context.box.x,
context.box.y,
katanaViewBoxWidth(context, viewBox),
katanaViewBoxHeight(context, viewBox),
);
}
function katanaViewBoxWidth(context, viewBox) {
return viewBox?.[0] ?? Math.max(context.box.width, katanaDefaultViewportWidth());
}
function katanaViewBoxHeight(context, viewBox) {
return viewBox?.[1] ?? Math.max(context.box.height, katanaDefaultViewportHeight());
}
function katanaEmptyDefaultClientBox(context) {
if ([katanaNeedsDefaultClientBox(context.node), katanaIsEmptyBox(context.box)].every(Boolean)) {
return katanaBox(0, 0, katanaDefaultViewportWidth(), katanaDefaultViewportHeight());
}
return null;
}
function katanaDefaultViewportWidth() {
return Number(globalThis.innerWidth ?? globalThis.screen?.width ?? 800);
}
function katanaDefaultViewportHeight() {
return Number(globalThis.innerHeight ?? globalThis.screen?.height ?? 600);
}
function katanaNeedsDefaultClientBox(node) {
return [KATANA_DEFAULT_CLIENT_TAGS.has(node.localName), katanaHasSvgChild(node)].includes(true);
}
function katanaIsEmptyBox(box) {
return [box.width === 0, box.height === 0].every(Boolean);
}
function katanaPositiveOrDefault(value, fallback) {
return value > 0 ? value : fallback;
}
function katanaCssLength(value) {
if (!value) {
return null;
}
return katanaFiniteCssLength(value);
}
function katanaFiniteCssLength(value) {
const number = Number(String(value).replace("px", ""));
if (Number.isFinite(number)) {
return number;
}
return null;
}
function katanaViewBoxSize(value) {
const values = katanaViewBoxValues(value);
if (katanaIsValidViewBox(values)) {
return [values[2], values[3]];
}
return null;
}
function katanaViewBoxValues(value) {
return String(value ?? "")
.split(/\s+/)
.map((it) => Number(it));
}
function katanaIsValidViewBox(values) {
return [values.length === 4, values.every((it) => Number.isFinite(it))].every(Boolean);
}
function katanaHasSvgChild(node) {
return (node.children ?? []).some((child) => child.localName === "svg");
}
/* dom-layout-prototype.js */
Object.defineProperty(KatanaNode.prototype, "textContent", {
get() {
return katanaTextContent(this);
},
set(value) {
this._textContent = String(value ?? "");
this.children = [];
this.childNodes = this.children;
},
});
Object.defineProperty(KatanaNode.prototype, "innerText", {
get() {
return katanaInnerText(this);
},
set(value) {
this.textContent = value;
},
});
Object.defineProperty(KatanaNode.prototype, "nodeValue", {
get() {
return this.nodeType === 3 ? this.textContent : null;
},
set(value) {
if (this.nodeType === 3) {
this.textContent = value;
}
},
});
KatanaNode.prototype.append = function append(...values) {
for (const value of values) {
this.appendChild(katanaNodeValue(value));
}
};
KatanaNode.prototype.prepend = function prepend(...values) {
for (const value of values.reverse()) {
this.insertBefore(katanaNodeValue(value), this.firstChild);
}
};
KatanaNode.prototype.replaceChildren = function replaceChildren(...values) {
this.children = [];
this.childNodes = this.children;
this.append(...values);
};
KatanaNode.prototype.contains = function contains(candidate) {
if (this === candidate) {
return true;
}
return katanaNodeChildren(this).some((child) => child.contains(candidate));
};
function katanaNodeChildren(node) {
return node.children ?? [];
}
function katanaInnerText(node) {
if (!node) {
return "";
}
if (node.localName === "br") {
return "\n";
}
if (katanaIsHiddenLayoutNode(node)) {
return "";
}
return `${katanaOwnText(node)}${katanaNodeChildren(node).map(katanaInnerText).join("")}`;
}
KatanaNode.prototype.text = function text(...values) {
if (values.length === 0) return this.textContent;
this.textContent = values[0];
return this;
};
KatanaNode.prototype.getBBox = function getBBox() {
return katanaMeasuredBox(this);
};
KatanaNode.prototype.getBoundingClientRect = function getBoundingClientRect() {
const box = katanaElementClientBox(this);
return { ...box, top: box.y, left: box.x, right: box.x + box.width, bottom: box.y + box.height };
};
KatanaNode.prototype.getComputedTextLength = function getComputedTextLength() {
if (globalThis.__katanaMermaidDiagramType === "block") {
const text = katanaTextContent(this);
if (/^\u00a0+$/.test(text)) {
return Math.max(16, text.replace(/\u00a0/g, " ").length * 8);
}
}
return Math.max(16, katanaTextContent(this).length * 8);
};
KatanaNode.prototype.getScreenCTM = function getScreenCTM() {
return { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0, inverse: () => this.getScreenCTM() };
};
KatanaNode.prototype.createSVGPoint = function createSVGPoint() {
return {
x: 0,
y: 0,
matrixTransform() {
return { x: this.x, y: this.y };
},
};
};
Object.defineProperties(KatanaNode.prototype, {
clientWidth: {
get() {
return Math.ceil(katanaElementClientBox(this).width);
},
},
clientHeight: {
get() {
return Math.ceil(katanaElementClientBox(this).height);
},
},
offsetWidth: {
get() {
return Math.ceil(katanaElementClientBox(this).width);
},
},
offsetHeight: {
get() {
return Math.ceil(katanaElementClientBox(this).height);
},
},
scrollWidth: {
get() {
return Math.ceil(katanaElementClientBox(this).width);
},
},
scrollHeight: {
get() {
return Math.ceil(katanaElementClientBox(this).height);
},
},
});
function katanaElementClientBox(node) {
return katanaMeasuredClientBox(node);
}
/* dom-css-style.js */
function katanaCssComputedStyleValue(node, name) {
if (!node) {
return "";
}
return katanaCssRuleValue(katanaCssText(node), node, name);
}
function katanaCssText(node) {
const root = katanaCssRoot(node);
return katanaCssStyleNodes(root)
.map((styleNode) => styleNode.textContent)
.join("\n");
}
function katanaCssRoot(node) {
return katanaCssRootNode(node) || document.documentElement;
}
function katanaCssRootNode(node) {
return KATANA_CSS_ROOT_READERS[Number(Boolean(katanaCssParentNode(node)))](node);
}
function katanaCssParentNode(node) {
return node?.parentNode || null;
}
function katanaCssStyleNodes(root) {
return katanaCssDescendantNodes(root).filter(katanaIsCssStyleNode);
}
function katanaCssDescendantNodes(node) {
return [node].filter(Boolean).flatMap(katanaCssNodeWithDescendants);
}
function katanaCssNodeWithDescendants(node) {
return [node].concat(Array.from(node.children || []).flatMap(katanaCssNodeWithDescendants));
}
function katanaIsCssStyleNode(node) {
return node.localName === "style";
}
function katanaCssRuleValue(cssText, node, name) {
return (
Array.from(cssText.matchAll(/([^{}]+)\{([^{}]+)\}/g))
.map((rule) => katanaCssRuleDeclarationValue(rule, node, name))
.filter(Boolean)
.at(-1) ?? ""
);
}
function katanaCssRuleDeclarationValue(rule, node, name) {
return (
[rule]
.filter((it) => katanaCssRuleMatchesNode(it[1], node))
.map((it) => katanaCssDeclarationValue(it[2], name))[0] ?? ""
);
}
const KATANA_CSS_ROOT_READERS = [
(node) => node,
(node) => katanaCssRootNode(katanaCssParentNode(node)),
];
function katanaCssRuleMatchesNode(selectorText, node) {
return selectorText
.split(",")
.some((selector) => katanaCssSelectorMatchesNode(node, selector));
}
function katanaCssSelectorMatchesNode(node, selector) {
const parts = String(selector).trim().split(/\s+/).filter(Boolean);
if (parts.length === 0) {
return false;
}
return katanaCssSelectorTailMatches(node, parts, parts.length - 1);
}
function katanaCssSelectorTailMatches(node, parts, index) {
if (!node || !katanaCssSimpleSelectorMatches(node, parts[index])) {
return false;
}
if (index === 0) {
return true;
}
return katanaCssAncestorMatches(node.parentNode, parts, index - 1);
}
function katanaCssAncestorMatches(node, parts, index) {
if (!node) {
return false;
}
if (katanaCssSelectorTailMatches(node, parts, index)) {
return true;
}
return katanaCssAncestorMatches(node.parentNode, parts, index);
}
function katanaCssSimpleSelectorMatches(node, selector) {
const normalized = katanaCssSimpleSelector(selector);
if (normalized === "*") {
return true;
}
if (normalized === ":root") {
return node === document.documentElement;
}
return [
katanaCssSelectorTagMatches(node, normalized),
katanaCssSelectorIdMatches(node, normalized),
katanaCssSelectorClassesMatch(node, normalized),
katanaCssSelectorAttributesMatch(node, normalized),
].every(Boolean);
}
function katanaCssSimpleSelector(selector) {
return String(selector).trim().replace(/:{1,2}(?!root\b)[a-zA-Z-]+(?:\([^)]*\))?/g, "");
}
function katanaCssSelectorTagMatches(node, selector) {
const tag = selector.match(/^[a-zA-Z][a-zA-Z0-9:_-]*/)?.[0];
return tag ? node.localName === tag.toLowerCase() : true;
}
function katanaCssSelectorIdMatches(node, selector) {
const id = selector.match(/#([a-zA-Z0-9_-]+)/)?.[1];
return id ? node.id === id : true;
}
function katanaCssSelectorClassesMatch(node, selector) {
const classNames = String(node.className ?? "").split(/\s+/).filter(Boolean);
return Array.from(selector.matchAll(/\.([a-zA-Z0-9_-]+)/g))
.map((match) => match[1])
.every((className) => classNames.includes(className));
}
function katanaCssSelectorAttributesMatch(node, selector) {
return Array.from(selector.matchAll(/\[([a-zA-Z0-9:_-]+)(?:="([^"]*)")?\]/g))
.map((match) => katanaCssSelectorAttributeMatches(node, match[1], match[2]))
.every(Boolean);
}
function katanaCssSelectorAttributeMatches(node, name, value) {
const actual = node.getAttribute?.(name);
return value === undefined ? actual !== null : actual === value;
}
function katanaCssDeclarationValue(declarations, name) {
return (
String(declarations)
.split(";")
.map((declaration) => katanaCssDeclarationEntry(declaration))
.find((entry) => entry.name === name)?.value ?? ""
);
}
function katanaCssDeclarationEntry(declaration) {
const parts = String(declaration).split(":");
return {
name: String(parts.shift() ?? "").trim(),
value: parts.join(":").trim(),
};
}
/* dom-computed-style.js */
globalThis.getComputedStyle = (node) => katanaComputedStyle(node);
function katanaComputedStyle(node) {
const box = katanaComputedStyleBox(node);
return {
width: `${box.width}px`,
height: `${box.height}px`,
display: "block",
fontSize: katanaComputedFontSize(node),
fontFamily: katanaComputedFontFamily(node),
getPropertyValue(name) {
return katanaComputedPropertyValue(node, this, name);
},
};
}
function katanaComputedFontSize(node) {
return katanaComputedStyleValue(node, "font-size") || "16px";
}
function katanaComputedFontFamily(node) {
return (
katanaComputedStyleValue(node, "font-family") || "trebuchet ms, verdana, arial, sans-serif"
);
}
function katanaComputedPropertyValue(node, style, name) {
return katanaComputedStyleValue(node, name) || style[name] || "";
}
function katanaComputedStyleBox(node) {
if (node) {
return katanaElementClientBox(node);
}
return katanaBox(0, 0, 0, 0);
}
function katanaComputedStyleValue(node, name) {
return (
[katanaRawComputedStyleValue(node, name), katanaCssComputedStyleValue(node, name)]
.filter(Boolean)
.concat([katanaDefaultComputedStyleValue(name)])[0] ?? ""
);
}
function katanaRawComputedStyleValue(node, name) {
return node?.style?.getPropertyValue?.(name) ?? "";
}
function katanaDefaultComputedStyleValue(name) {
if (/^(padding|margin|border).*/.test(name)) {
return "0px";
}
return "";
}
/* dom-measure.js */
function katanaMeasuredBoxAccurate(node) {
if (KATANA_HIDDEN_LAYOUT_TAGS.has(node.localName)) {
return katanaBox(0, 0, 0, 0);
}
return katanaVisibleMeasuredBoxAccurate(node);
}
function katanaVisibleMeasuredBoxAccurate(node) {
return (
katanaTextElementMeasuredBox(node) ??
katanaTextFragmentMeasuredBox(node) ??
katanaExplicitMeasuredBox(node) ??
katanaDirectMeasuredBox(node) ??
katanaChildTextBox(node)
);
}
function katanaTextElementMeasuredBox(node) {
if (node.localName === "text") {
return katanaTextElementBox(node);
}
return null;
}
function katanaTextFragmentMeasuredBox(node) {
if (["tspan", "#text"].includes(node.localName)) {
return katanaTextFragmentBox(node);
}
return null;
}
function katanaDirectMeasuredBox(node) {
return katanaLineBox(node) ?? katanaCircleBox(node) ?? katanaPathBox(node);
}
function katanaChildTextBox(node) {
const childBox = katanaUnionBox(katanaVisibleChildBoxes(node));
const text = katanaMeasuredNodeText(node, childBox);
return katanaUnionBox([childBox, katanaOptionalTextBox(node, text)].filter(katanaHasArea));
}
function katanaOptionalTextBox(node, text) {
return text ? katanaAnchoredTextNodeBox(node, text, 0, 0) : katanaBox(0, 0, 0, 0);
}
function katanaHasArea(box) {
return [box.width > 0, box.height > 0].includes(true);
}
function katanaPathBox(node) {
return katanaSvgPathBox(node) ?? katanaSvgPointsBox(node);
}
function katanaSvgPathBox(node) {
if (node.localName === "path") {
return katanaOptionalNumberListBox(node.getAttribute("d"));
}
return null;
}
function katanaSvgPointsBox(node) {
if (["polygon", "polyline"].includes(node.localName)) {
return katanaOptionalNumberListBox(node.getAttribute("points"));
}
return null;
}
function katanaOptionalNumberListBox(value) {
return value ? katanaNumberListBox(value) : null;
}
function katanaNumberListBox(value) {
const numbers = Array.from(String(value).matchAll(/-?\d+(?:\.\d+)?(?:e-?\d+)?/gi)).map((match) =>
Number(match[0]),
);
if (numbers.length < 2) {
return null;
}
const xs = numbers.filter((_value, index) => index % 2 === 0);
const ys = numbers.filter((_value, index) => index % 2 === 1);
return katanaBox(
Math.min(...xs),
Math.min(...ys),
Math.max(...xs) - Math.min(...xs),
Math.max(...ys) - Math.min(...ys),
);
}
function katanaTextElementBox(node) {
const lines = katanaTextLines(node);
const text = katanaTextElementText(node, lines);
if (!text) {
return katanaBox(0, 0, 0, 0);
}
return katanaUnionBox(
katanaTextLineValues(node, text, lines).map((line, index) =>
katanaTextLineBox(node, line, index),
),
);
}
function katanaTextElementText(node, lines) {
return lines.length === 0 ? katanaTextContent(node) : lines.map((line) => line.text).join("");
}
function katanaTextLineValues(node, text, lines) {
if (lines.length === 0) {
return [{ text, x: katanaNumberAttr(node, "x"), y: katanaNumberAttr(node, "y") }];
}
return lines;
}
function katanaTextLineBox(node, line, index) {
const x = katanaLineValueOrDefault(line.x, katanaNumberAttrOrDefault(node, "x", 0));
const y = katanaLineValueOrDefault(line.y, katanaTextLineFallbackY(node, index));
return katanaAnchoredTextNodeBox(node, line.text, x, y);
}
function katanaLineValueOrDefault(value, fallback) {
return value ?? fallback;
}
function katanaTextLineFallbackY(node, index) {
return (katanaNumberAttr(node, "y") ?? 0) + index * katanaLineHeight(node);
}
function katanaTextFragmentBox(node) {
const text = katanaFragmentText(node);
if (text) {
return katanaAnchoredTextNodeBox(
katanaTextFragmentParent(node),
text,
katanaNumberAttrOrDefault(node, "x", 0),
katanaNumberAttrOrDefault(node, "y", 0),
);
}
return katanaBox(0, 0, 0, 0);
}
function katanaTextFragmentParent(node) {
return node.parentNode ?? node;
}
function katanaFragmentText(node) {
return [katanaOwnText(node), katanaTextContent(node)].find(Boolean) ?? "";
}
KatanaNode.prototype.getBBox = function getBBox() {
return katanaMeasuredBoxAccurate(this);
};
/* dom-measure-text-lines.js */
function katanaTextLines(node) {
return katanaTextTspans(node).reduce(katanaAppendTextLine, { lines: [], current: null }).lines;
}
function katanaTextTspans(node) {
return katanaDescendantElements(node, "tspan")
.filter((child) => katanaTextContent(child).length > 0)
.filter((child) => !katanaHasTextTspanAncestor(child, node));
}
function katanaHasTextTspanAncestor(child, root) {
return katanaTextTspanAncestors(child, root).some(katanaIsFilledTextTspan);
}
function katanaTextTspanAncestors(child, root) {
return katanaTextTspanAncestorList(child.parentNode, root);
}
function katanaTextTspanAncestorList(node, root) {
return KATANA_TEXT_TSPAN_ANCESTOR_READERS[Number(katanaHasTextAncestorNode(node, root))](
node,
root,
);
}
function katanaHasTextAncestorNode(node, root) {
return Boolean(node) && node !== root;
}
function katanaIsFilledTextTspan(node) {
return [node.localName === "tspan", katanaTextContent(node).length > 0].every(Boolean);
}
function katanaAppendTextLine(state, tspan, index) {
const next = katanaTextLineState(state, tspan, index);
next.current.text += katanaTextContent(tspan);
return next;
}
function katanaTextLineState(state, tspan, index) {
return KATANA_TEXT_LINE_STATE_READERS[Number(katanaStartsTextLine(tspan, index))](state, tspan);
}
function katanaStartsTextLine(tspan, index) {
return [
index === 0,
tspan.hasAttribute("x"),
Math.abs(katanaSvgTextLengthAttr(tspan, "dy") ?? 0) >= 1,
].includes(true);
}
function katanaStartTextLine(state, tspan) {
const line = { text: "", x: katanaNumberAttr(tspan, "x"), y: katanaTspanLineY(tspan) };
return { lines: [...state.lines, line], current: line };
}
function katanaTspanLineY(tspan) {
const values = [katanaSvgTextLengthAttr(tspan, "y"), katanaSvgTextLengthAttr(tspan, "dy")];
return KATANA_TSPAN_LINE_Y_READERS[Number(values.some(katanaIsSvgTextLengthValue))](values);
}
function katanaIsSvgTextLengthValue(value) {
return value !== null;
}
function katanaSvgTextLengthAttr(node, name) {
return [String(node.getAttribute?.(name) ?? "")]
.filter(Boolean)
.map((raw) => katanaSvgTextLengthValue(node, raw))
.concat([null])[0];
}
function katanaSvgTextLengthValue(node, raw) {
return [raw.match(/^(-?\d+(?:\.\d+)?)([a-z%]*)$/i)]
.filter(Boolean)
.map((match) => katanaSvgTextLengthMatchValue(node, match))
.concat([null])[0];
}
function katanaSvgTextLengthMatchValue(node, match) {
return [Number(match[1])]
.filter(Number.isFinite)
.map((value) => katanaSvgTextLengthPixels(node, value, match[2]))
.concat([null])[0];
}
function katanaSvgTextLengthPixels(node, value, unit) {
return (KATANA_SVG_TEXT_LENGTH_UNITS[unit] ?? KATANA_SVG_TEXT_LENGTH_UNITS.px)(node, value);
}
function katanaDescendantElements(node, tagName) {
return Array.from(node.children).flatMap((child) => katanaDescendantElement(child, tagName));
}
function katanaDescendantElement(child, tagName) {
return [katanaMatchingDescendantElement(child, tagName)]
.filter(Boolean)
.concat(Array.from(child.children).flatMap((node) => katanaDescendantElement(node, tagName)));
}
function katanaMatchingDescendantElement(child, tagName) {
return [child].filter((node) => node.localName === tagName)[0] ?? null;
}
const KATANA_TEXT_TSPAN_ANCESTOR_READERS = [
() => [],
(node, root) => [node].concat(katanaTextTspanAncestorList(node.parentNode, root)),
];
const KATANA_TEXT_LINE_STATE_READERS = [
(state) => state,
(state, tspan) => katanaStartTextLine(state, tspan),
];
function katanaOptionalSvgTextLength(value) {
return [value].filter(katanaIsSvgTextLengthValue).concat([0])[0];
}
function katanaSumTspanLineY(values) {
return katanaOptionalSvgTextLength(values[0]) + katanaOptionalSvgTextLength(values[1]);
}
const KATANA_TSPAN_LINE_Y_READERS = [() => null, (values) => katanaSumTspanLineY(values)];
const KATANA_SVG_TEXT_LENGTH_UNITS = {
em: (node, value) =>
value * katanaFiniteFontSize(Number(String(katanaLineHeightFontSize(node)).replace("px", ""))),
px: (_node, value) => value,
};
/* dom-text-metrics.js */
const KATANA_ASCII_KERNING_PAIRS = {
'"T': -2.805,
"n'": -0.993,
"'t": -0.985,
"'w": -0.984,
"<<": 0.781,
">>": 0.781,
"E]": -2.117,
"M]": -2.118,
"P]": -2.125,
Pa: -0.75,
Pe: -0.743,
Ph: -0.742,
Po: -0.742,
Pr: -0.75,
Re: -0.649,
Ro: -0.649,
Ta: -1.992,
Te: -1.985,
Ti: -0.665,
To: -1.984,
Tu: -2.062,
Tw: -2.211,
Ty: -1.836,
Ve: -1.031,
Wa: -0.883,
We: -0.735,
Ye: -1.68,
Yo: -1.836,
"e'": -0.993,
"e,": -2.118,
"e?": -2.118,
"k,": -2.117,
"n,": -2.117,
"p;": -2.117,
's"': -2.805,
"s,": -2.118,
"t!": -2.125,
"u!": -2.117,
"u?": -2.117,
"v.": -2.149,
"y?": -2.125,
"y]": -2.125,
};
const KATANA_ASCII_TEXT_WIDTHS = {
" ": 4.82,
"'": 3.547,
$: 8.391,
"(": 5.875,
")": 5.875,
"-": 5.875,
".": 5.875,
":": 5.875,
0: 8.391,
1: 8.391,
2: 8.391,
3: 8.391,
4: 8.391,
5: 8.391,
6: 8.391,
7: 8.391,
8: 8.391,
9: 8.391,
A: 9.438,
B: 9.055,
C: 9.57,
D: 9.813,
E: 8.57,
F: 8.398,
G: 10.82,
H: 10.469,
I: 4.453,
J: 7.625,
K: 9.211,
L: 8.102,
M: 11.352,
N: 10.211,
O: 10.781,
P: 8.922,
Q: 10.813,
R: 9.313,
S: 7.695,
T: 9.289,
U: 10.375,
V: 9.398,
W: 13.633,
X: 8.906,
Y: 9.125,
Z: 8.805,
_: 8.391,
a: 8.406,
b: 8.914,
c: 7.922,
d: 8.914,
e: 8.727,
f: 5.914,
g: 8.031,
h: 8.742,
i: 4.563,
j: 5.867,
k: 8.07,
l: 4.719,
m: 13.281,
n: 8.742,
o: 8.586,
p: 8.914,
q: 8.914,
r: 6.219,
s: 6.477,
t: 6.344,
u: 8.742,
v: 7.836,
w: 11.906,
x: 8.016,
y: 7.891,
z: 7.594,
};
/* dom-text-measure.js */
function katanaAnchoredTextNodeBox(node, text, x, y) {
const width = Math.max(1, katanaTextNodeWidth(node, text));
const height = katanaLineHeight(node);
return katanaBox(
katanaAnchoredTextLeft(katanaTextAnchor(node), x, width),
y - height * katanaTextBoxBaselineRatio(),
width,
height,
);
}
function katanaAnchoredTextLeft(anchor, x, width) {
return (KATANA_TEXT_ANCHORS[anchor] ?? KATANA_TEXT_ANCHORS.start)(x, width);
}
const KATANA_TEXT_ANCHORS = {
end: (x, width) => x - width,
middle: (x, width) => x - width / 2,
start: (x) => x,
};
function katanaTextAnchor(node) {
return String(katanaTextAnchorValues(node).find(Boolean) ?? "start");
}
function katanaTextAnchorValues(node) {
return [
node.getAttribute?.("text-anchor"),
node.style?.getPropertyValue?.("text-anchor"),
katanaCssComputedStyleValue(node, "text-anchor"),
node.parentNode?.getAttribute?.("text-anchor"),
katanaCssComputedStyleValue(node.parentNode, "text-anchor"),
];
}
function katanaLineHeight(node) {
const fontSize = Number(String(katanaLineHeightFontSize(node)).replace("px", ""));
return katanaBrowserTextBoxHeight(katanaFiniteFontSize(fontSize));
}
function katanaBrowserTextBoxHeight(fontSize) {
const measured = KATANA_TEXT_BOX_HEIGHTS[String(fontSize)];
if (measured) {
return measured;
}
return Math.max(12, Math.ceil(fontSize * 1.15));
}
const KATANA_TEXT_BOX_HEIGHTS = {
10: 11,
11: 12.25,
12: 14,
14: 16,
16: 19,
18: 21,
20: 23,
};
function katanaLineHeightFontSize(node) {
return katanaLineHeightFontSizeValues(node).find(Boolean) ?? "16";
}
function katanaLineHeightFontSizeValues(node) {
return [
node.style?.getPropertyValue?.("font-size"),
katanaCssComputedStyleValue(node, "font-size"),
node.getAttribute?.("font-size"),
node.parentNode?.style?.getPropertyValue?.("font-size"),
katanaCssComputedStyleValue(node.parentNode, "font-size"),
node.parentNode?.getAttribute?.("font-size"),
];
}
function katanaFiniteFontSize(fontSize) {
if (Number.isFinite(fontSize)) {
return fontSize;
}
return 16;
}
function katanaTextNodeWidth(node, text) {
return katanaTextWidth(text) * katanaTextWidthScale(node);
}
function katanaTextWidthScale(node) {
const fontSize =
katanaFiniteFontSize(Number(String(katanaLineHeightFontSize(node)).replace("px", ""))) / 16;
return fontSize * katanaTextWeightScale(node);
}
function katanaTextBoxBaselineRatio() {
return KATANA_TEXT_BOX_BASELINE_RATIOS[Number(katanaIsRequirementDiagram())]();
}
function katanaTextWeightScale(node) {
return KATANA_TEXT_WEIGHT_SCALES[
Number([katanaIsRequirementDiagram(), katanaHasBoldTextWeight(node)].every(Boolean))
]();
}
function katanaHasBoldTextWeight(node) {
return katanaTextWeightValues(node).some(katanaIsBoldTextWeight);
}
function katanaTextWeightValues(node) {
return [
node.style?.getPropertyValue?.("font-weight"),
katanaCssComputedStyleValue(node, "font-weight"),
node.getAttribute?.("font-weight"),
node.parentNode?.style?.getPropertyValue?.("font-weight"),
katanaCssComputedStyleValue(node.parentNode, "font-weight"),
node.parentNode?.getAttribute?.("font-weight"),
];
}
function katanaIsBoldTextWeight(value) {
const normalized = String(value ?? "").trim().toLowerCase();
return normalized === "bold" || Number(normalized) >= 600;
}
function katanaTextWidth(text) {
const chars = Array.from(katanaMeasuredTextValue(text));
const characterWidth = chars
.map((char) => katanaCharacterWidth(char))
.reduce((width, charWidth) => width + charWidth, 0);
return characterWidth + katanaTextKerningWidth(chars);
}
function katanaMeasuredTextValue(text) {
if (globalThis.__katanaMermaidDiagramType === "block") {
return String(text);
}
return String(text).replace(/&(?:amp;)?nbsp;| /g, "\u00A0");
}
function katanaTextKerningWidth(chars) {
return chars
.slice(0, -1)
.map((char, index) => katanaKerningPairWidth(char, chars[index + 1]))
.reduce((width, pairWidth) => width + pairWidth, 0);
}
function katanaKerningPairWidth(left, right) {
return KATANA_KERNING_PAIR_WIDTH_READERS[Number(katanaHasWideKerningChar(left, right))](
left,
right,
);
}
function katanaHasWideKerningChar(left, right) {
return [left, right].some(katanaIsWideTextChar);
}
function katanaIsWideTextChar(char) {
return char.charCodeAt(0) > 255;
}
function katanaCharacterWidth(char) {
return KATANA_CHARACTER_WIDTHS[Number(char.charCodeAt(0) > 255)](char);
}
function katanaAsciiCharacterWidth(char) {
if (char.charCodeAt(0) === 160) {
return KATANA_ASCII_TEXT_WIDTHS[" "];
}
return [KATANA_ASCII_TEXT_WIDTHS[char]].filter(Boolean).concat([8])[0];
}
function katanaWideCharacterWidth(char) {
return KATANA_WIDE_CHARACTER_WIDTHS[Number(globalThis.__katanaMermaidDiagramType === "kanban")](
char,
);
}
const KATANA_WIDE_CHARACTER_WIDTHS = [
katanaDefaultWideCharacterWidth,
// WHY: Official Kanban measures wide labels slightly narrower; matching total width wraps one character too early inside cards.
() => 12.5,
];
function katanaDefaultWideCharacterWidth(char) {
if (katanaIsWidePunctuation(char)) {
return 20;
}
return KATANA_DEFAULT_WIDE_CHARACTER_WIDTHS[Number(katanaIsCjkIdeograph(char))]();
}
function katanaIsCjkIdeograph(char) {
const codePoint = katanaCharacterCodePoint(char);
return KATANA_CJK_IDEOGRAPH_RULES.every((rule) => rule(codePoint));
}
function katanaCharacterCodePoint(char) {
return char.codePointAt(0) ?? 0;
}
function katanaIsCjkIdeographStart(codePoint) {
return codePoint >= 0x4e00;
}
function katanaIsCjkIdeographEnd(codePoint) {
return codePoint <= 0x9fff;
}
function katanaIsWidePunctuation(char) {
return ["。", "、"].includes(char);
}
const KATANA_DEFAULT_WIDE_CHARACTER_WIDTHS = [() => 15.8, () => 16.3];
const KATANA_CJK_IDEOGRAPH_RULES = [katanaIsCjkIdeographStart, katanaIsCjkIdeographEnd];
const KATANA_CHARACTER_WIDTHS = [katanaAsciiCharacterWidth, katanaWideCharacterWidth];
const KATANA_KERNING_PAIR_WIDTH_READERS = [
(left, right) => KATANA_ASCII_KERNING_PAIRS[`${left}${right}`] ?? 0,
() => 0,
];
const KATANA_TEXT_WEIGHT_SCALES = [() => 1, () => 1.055];
const KATANA_TEXT_BOX_BASELINE_RATIOS = [() => 0.8, () => 0.8421052631578947];
function katanaIsRequirementDiagram() {
return ["requirement", "requirementdiagram"].includes(globalThis.__katanaMermaidDiagramType);
}
KatanaNode.prototype.getComputedTextLength = function getComputedTextLength() {
const lines = katanaComputedTextLines(this);
return Math.max(1, ...lines.map((line) => katanaTextNodeWidth(this, line)));
};
function katanaComputedTextLines(node) {
if (node.localName === "text") {
return katanaTextLines(node).map((line) => line.text);
}
return [katanaTextContent(node)];
}
/* svg-bounds-attrs.js */
function katanaTranslate(tag) {
const match = tag.match(/transform="translate\(([-\d.]+)[,\s]+([-\d.]+)\)/);
if (match) {
return [Number(match[1]), Number(match[2])];
}
return [0, 0];
}
function katanaAttrNumber(tag, name) {
const match = tag.match(new RegExp(`(?:^|\\s)${name}="([^"]+)"`));
if (!match) {
return null;
}
return katanaFiniteAttrNumber(Number(match[1]));
}
function katanaFiniteAttrNumber(value) {
if (Number.isFinite(value)) {
return value;
}
return null;
}
function katanaAttrText(tag, name) {
return tag.match(new RegExp(`(?:^|\\s)${name}="([^"]+)"`))?.[1] ?? null;
}
/* svg-path-bounds.js */
function katanaSerializedSvgPathBox(tag, offset) {
return katanaOffsetBox(katanaSerializedPathDataBox(katanaAttrText(tag, "d")), offset);
}
function katanaSerializedPathDataBox(pathData) {
return pathData ? katanaNonEmptySerializedPathDataBox(pathData) : null;
}
function katanaNonEmptySerializedPathDataBox(pathData) {
return (
katanaCurvedSerializedPathDataBox(pathData) ??
katanaParsedSerializedPathDataBox(pathData) ??
katanaNumberPairsBox(katanaSerializedSvgNumberList(pathData))
);
}
function katanaCurvedSerializedPathDataBox(pathData) {
return katanaIshikawaHeadPathBox(pathData);
}
function katanaIshikawaHeadPathBox(pathData) {
const match = pathData.match(/^M 0 -?([\d.]+) L 0 ([\d.]+) Q ([\d.]+) 0 0 -?[\d.]+ Z$/);
if (!match) {
return null;
}
const halfHeight = Math.max(Number(match[1]), Number(match[2]));
return [0, -halfHeight, Number(match[3]) / 2, halfHeight];
}
function katanaOffsetNumberListBox(value, offset) {
return katanaOffsetBox(katanaNumberPairsBox(katanaSerializedSvgNumberList(value)), offset);
}
function katanaParsedSerializedPathDataBox(pathData) {
const parser = katanaPathParser(pathData);
while (parser.index < parser.tokens.length) {
katanaReadPathCommand(parser);
}
return katanaNumberPairsBox(parser.points);
}
function katanaPathParser(pathData) {
return {
tokens: Array.from(String(pathData).matchAll(/[a-zA-Z]|-?(?:\d*\.)?\d+(?:e-?\d+)?/gi)).map(
(it) => it[0],
),
index: 0,
command: "",
x: 0,
y: 0,
startX: 0,
startY: 0,
points: [],
};
}
function katanaReadPathCommand(parser) {
parser.command = katanaNextPathCommand(parser);
const command = parser.command.toUpperCase();
const relative = parser.command !== command;
const reader = KATANA_PATH_COMMAND_READERS[command];
if (reader) {
reader(parser, relative);
return;
}
parser.index += 1;
}
function katanaNextPathCommand(parser) {
if (katanaIsPathCommand(parser.tokens[parser.index])) {
return parser.tokens[parser.index++];
}
return parser.command;
}
function katanaIsPathCommand(token) {
return /^[a-zA-Z]$/.test(String(token ?? ""));
}
const KATANA_PATH_COMMAND_READERS = {
A: (parser, relative) => katanaReadPathArcs(parser, relative),
C: (parser, relative) => katanaReadPathCoordinateGroups(parser, relative, 3),
H: (parser, relative) => katanaReadPathHorizontalLines(parser, relative),
L: (parser, relative) => katanaReadPathCoordinateGroups(parser, relative, 1),
M: (parser, relative) => katanaReadPathMoves(parser, relative),
Q: (parser, relative) => katanaReadPathCoordinateGroups(parser, relative, 2),
S: (parser, relative) => katanaReadPathCoordinateGroups(parser, relative, 2),
T: (parser, relative) => katanaReadPathCoordinateGroups(parser, relative, 1),
V: (parser, relative) => katanaReadPathVerticalLines(parser, relative),
Z: (parser) => katanaClosePath(parser),
};
function katanaReadPathMoves(parser, relative) {
while (katanaCanReadPathNumbers(parser, 2)) {
katanaSetPathPoint(parser, katanaReadPathPoint(parser, relative));
parser.startX = parser.x;
parser.startY = parser.y;
}
}
function katanaReadPathCoordinateGroups(parser, relative, pointCount) {
const numberCount = pointCount * 2;
KATANA_PATH_COORDINATE_GROUP_READERS[Number(katanaCanReadPathNumbers(parser, numberCount))](
parser,
relative,
pointCount,
numberCount,
);
}
function katanaReadPathPointGroup(parser, relative, pointCount) {
Array.from({ length: pointCount }).forEach(() => {
katanaSetPathPoint(parser, katanaReadPathPoint(parser, relative));
});
}
const KATANA_PATH_COORDINATE_GROUP_READERS = [
() => {},
(parser, relative, pointCount, numberCount) => {
katanaReadPathPointGroup(parser, relative, pointCount);
katanaReadPathCoordinateGroups(parser, relative, numberCount / 2);
},
];
function katanaReadPathHorizontalLines(parser, relative) {
while (katanaCanReadPathNumbers(parser, 1)) {
katanaSetPathPoint(parser, [
katanaPathCoordinate(parser, katanaReadPathNumber(parser), relative, "x"),
parser.y,
]);
}
}
function katanaReadPathVerticalLines(parser, relative) {
while (katanaCanReadPathNumbers(parser, 1)) {
katanaSetPathPoint(parser, [
parser.x,
katanaPathCoordinate(parser, katanaReadPathNumber(parser), relative, "y"),
]);
}
}
function katanaReadPathArcs(parser, relative) {
while (katanaCanReadPathNumbers(parser, 7)) {
parser.index += 5;
katanaSetPathPoint(parser, katanaReadPathPoint(parser, relative));
}
}
function katanaClosePath(parser) {
katanaSetPathPoint(parser, [parser.startX, parser.startY]);
}
function katanaReadPathPoint(parser, relative) {
return [
katanaPathCoordinate(parser, katanaReadPathNumber(parser), relative, "x"),
katanaPathCoordinate(parser, katanaReadPathNumber(parser), relative, "y"),
];
}
function katanaPathCoordinate(parser, value, relative, axis) {
return relative ? parser[axis] + value : value;
}
function katanaSetPathPoint(parser, point) {
parser.x = point[0];
parser.y = point[1];
parser.points.push(point[0], point[1]);
}
function katanaCanReadPathNumbers(parser, count) {
const nextTokens = parser.tokens.slice(parser.index, parser.index + count);
return nextTokens.length === count && nextTokens.every((token) => !katanaIsPathCommand(token));
}
function katanaReadPathNumber(parser) {
return Number(parser.tokens[parser.index++]);
}
function katanaSerializedSvgNumberList(value) {
return Array.from(String(value).matchAll(/-?(?:\d*\.)?\d+(?:e-?\d+)?/gi)).map((it) =>
Number(it[0]),
);
}
function katanaNumberPairsBox(numbers) {
if (numbers.length < 2) {
return null;
}
const xValues = numbers.filter((_value, index) => index % 2 === 0);
const yValues = numbers.filter((_value, index) => index % 2 === 1);
return [Math.min(...xValues), Math.min(...yValues), Math.max(...xValues), Math.max(...yValues)];
}
/* svg-bounds.js */
function katanaContentBox(svg) {
const drawable = svg
.replace(/<style[\s\S]*?<\/style>/g, "")
.replace(/<defs[\s\S]*?<\/defs>/g, "")
.replace(/<marker[\s\S]*?<\/marker>/g, "");
const boxes = katanaScannedBoxes(drawable).filter(katanaHasDrawableBoxArea);
if (boxes.length === 0) {
return null;
}
return katanaPaddedContentBox(boxes, 12);
}
function katanaHasDrawableBoxArea(box) {
return [box[2] > box[0], box[3] > box[1]].every(Boolean);
}
function katanaPaddedContentBox(boxes, padding) {
const minX = Math.min(...boxes.map((box) => box[0]));
const minY = Math.min(...boxes.map((box) => box[1]));
const maxX = Math.max(...boxes.map((box) => box[2]));
const maxY = Math.max(...boxes.map((box) => box[3]));
return katanaContentBoxWithPadding(minX, minY, maxX, maxY, padding);
}
function katanaContentBoxWithPadding(minX, minY, maxX, maxY, padding) {
return [
Math.floor(minX - padding),
Math.floor(minY - padding),
Math.ceil(maxX - minX + padding * 2),
Math.ceil(maxY - minY + padding * 2),
];
}
function katanaScannedBoxes(svg) {
const boxes = [];
const offsets = [[0, 0]];
const tags = svg.matchAll(/<\/?([a-zA-Z][\w:-]*)([^>]*)>/g);
for (const match of tags) {
katanaScanSvgTag(svg, match, offsets, boxes);
}
return boxes;
}
function katanaScanSvgTag(svg, match, offsets, boxes) {
const tag = katanaScannedTag(match);
if (tag.fullTag.startsWith("</")) {
katanaPopScannedOffset(tag.name, offsets);
return;
}
katanaScanOpeningTag(svg, tag, offsets, boxes, match.index);
}
function katanaScannedTag(match) {
return { fullTag: match[0], name: match[1].toLowerCase(), attributes: match[2] ?? "" };
}
function katanaPopScannedOffset(tagName, offsets) {
if (katanaIsOffsetContainer(tagName)) {
offsets.pop();
}
}
function katanaScanOpeningTag(svg, tag, offsets, boxes, index) {
const offset = katanaNestedOffset(offsets[offsets.length - 1] ?? [0, 0], tag.attributes);
katanaPushOptionalBox(boxes, katanaOpeningTextBox(svg, tag, offset, index));
katanaPushOptionalBox(boxes, katanaTagBox(tag.name, tag.attributes, offset));
katanaPushScannedOffset(tag.name, offsets, offset);
}
function katanaNestedOffset(parentOffset, attributes) {
const ownOffset = katanaTranslate(attributes);
return [parentOffset[0] + ownOffset[0], parentOffset[1] + ownOffset[1]];
}
function katanaOpeningTextBox(svg, tag, offset, index) {
if (tag.name === "text") {
return katanaSvgTextBox(svg, index + tag.fullTag.length, tag.attributes, offset);
}
return null;
}
function katanaPushOptionalBox(boxes, box) {
if (box) {
boxes.push(box);
}
}
function katanaPushScannedOffset(tagName, offsets, offset) {
if (katanaIsOffsetContainer(tagName)) {
offsets.push(offset);
}
}
function katanaIsOffsetContainer(tagName) {
return ["g", "svg"].includes(tagName);
}
function katanaTagBox(tagName, tag, offset) {
return (KATANA_TAG_BOXES[tagName] ?? katanaNullBox)(tag, offset);
}
const KATANA_TAG_BOXES = {
circle: katanaSvgCircleBox,
ellipse: katanaSvgCircleBox,
image: katanaSvgRectBox,
line: katanaSvgLineBox,
path: katanaSerializedSvgPathBox,
polygon: katanaSvgPolygonBox,
polyline: katanaSvgPolygonBox,
rect: katanaSvgRectBox,
};
function katanaNullBox() {
return null;
}
function katanaSvgRectBox(tag, offset) {
const x = katanaAttrNumberOrDefault(tag, "x", 0);
const y = katanaAttrNumberOrDefault(tag, "y", 0);
const width = katanaAttrNumberOrDefault(tag, "width", 0);
const height = katanaAttrNumberOrDefault(tag, "height", 0);
if (katanaPositiveSize(width, height)) {
return katanaOffsetBox([x, y, x + width, y + height], offset);
}
return null;
}
function katanaAttrNumberOrDefault(tag, name, fallback) {
return katanaAttrNumber(tag, name) ?? fallback;
}
function katanaPositiveSize(width, height) {
return [width > 0, height > 0].every(Boolean);
}
function katanaSvgLineBox(tag, offset) {
const x1 = katanaAttrNumber(tag, "x1");
const y1 = katanaAttrNumber(tag, "y1");
const x2 = katanaAttrNumber(tag, "x2");
const y2 = katanaAttrNumber(tag, "y2");
if ([x1, y1, x2, y2].some((value) => value === null)) {
return null;
}
return katanaOffsetBox(
[Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2)],
offset,
);
}
function katanaSvgCircleBox(tag, offset) {
const cx = katanaAttrNumberOrDefault(tag, "cx", 0);
const cy = katanaAttrNumberOrDefault(tag, "cy", 0);
const rx = katanaRadiusAttrNumber(tag, "rx");
const ry = katanaRadiusAttrNumber(tag, "ry");
if (katanaPositiveSize(rx, ry)) {
return katanaOffsetBox([cx - rx, cy - ry, cx + rx, cy + ry], offset);
}
return null;
}
function katanaRadiusAttrNumber(tag, name) {
return katanaAttrNumber(tag, name) ?? katanaAttrNumberOrDefault(tag, "r", 0);
}
function katanaSvgPolygonBox(tag, offset) {
const points = katanaAttrText(tag, "points");
if (!points) {
return null;
}
return katanaOffsetNumberListBox(points, offset);
}
function katanaOffsetBox(box, offset) {
if (!box) {
return null;
}
return [box[0] + offset[0], box[1] + offset[1], box[2] + offset[0], box[3] + offset[1]];
}
/* svg-text-bounds.js */
function katanaSvgTextBox(svg, startIndex, tag, offset) {
const endIndex = svg.indexOf("</text>", startIndex);
if (endIndex < 0) {
return null;
}
return katanaSvgTextBoxFromRange(svg, startIndex, endIndex, tag, offset);
}
function katanaSvgTextBoxFromRange(svg, startIndex, endIndex, tag, offset) {
const lines = katanaSvgTextLines(svg, startIndex, endIndex);
if (lines.length === 0) {
return null;
}
return katanaSvgTextBoxFromLines(lines, tag, offset);
}
function katanaSvgTextBoxFromLines(lines, tag, offset) {
const x = katanaAttrNumberOrDefault(tag, "x", 0) + offset[0];
const y = katanaAttrNumberOrDefault(tag, "y", 0) + offset[1];
const width = Math.max(16, ...lines.map((line) => line.length * 8));
return katanaAnchoredTextBox(tag, x, y, width);
}
function katanaSvgTextLines(svg, startIndex, endIndex) {
const body = svg.slice(startIndex, endIndex);
const lines = Array.from(body.matchAll(/<tspan\b[^>]*>([^<]*)<\/tspan>/g))
.map((match) => katanaNormalizedSvgText(match[1]))
.filter(Boolean);
return lines.length > 0 ? lines : [katanaNormalizedSvgText(body)].filter(Boolean);
}
function katanaNormalizedSvgText(value) {
return value
.replace(/<[^>]+>/g, "")
.replace(/\s+/g, " ")
.trim();
}
function katanaAnchoredTextBox(tag, x, y, width) {
const anchor = katanaTextAnchorAttr(tag);
return (KATANA_ANCHORED_TEXT_BOXES[anchor] ?? KATANA_ANCHORED_TEXT_BOXES.start)(x, y, width);
}
function katanaTextAnchorAttr(tag) {
return String(katanaAttrText(tag, "text-anchor") ?? "start");
}
const KATANA_ANCHORED_TEXT_BOXES = {
end: (x, y, width) => [x - width, y - 18, x, y + 12],
middle: (x, y, width) => [x - width / 2, y - 18, x + width / 2, y + 12],
start: (x, y, width) => [x, y - 18, x + width, y + 12],
};
/* svg-architecture-icons.js */
function katanaInsertArchitectureServiceIcons(svg, request) {
const iconTypes = katanaArchitectureServiceIconTypes(request.source);
return svg.replace(
/(<g id="([^"]+)-service-([^"]+)" class="architecture-service"[^>]*>)([\s\S]*?)(<g><g><\/g><\/g>)(<\/g>)/g,
(_match, start, _prefix, serviceId, body, _emptyIcon, end) =>
`${start}${body}<g><g>${katanaArchitectureServiceIcon(iconTypes.get(serviceId))}</g></g>${end}`,
);
}
function katanaArchitectureServiceIconTypes(source) {
return new Map(
Array.from(String(source).matchAll(/\bservice\s+([A-Za-z0-9_]+)\s*\(\s*([^)]+?)\s*\)/g)).map(
(match) => [match[1], match[2]],
),
);
}
function katanaInsertArchitectureGroupIcons(svg) {
return svg.replace(
/(<g transform="translate\([^"]+\)">)<g><\/g><\/g>/g,
(_match, start) => `${start}<g>${katanaArchitectureCloudIcon()}</g></g>`,
);
}
function katanaArchitectureServiceIcon(iconType) {
return (KATANA_ARCHITECTURE_SERVICE_ICONS[iconType] ?? katanaArchitectureServerIcon)(80);
}
const KATANA_ARCHITECTURE_SERVICE_ICONS = {
database: katanaArchitectureDatabaseIcon,
disk: katanaArchitectureDiskIcon,
server: katanaArchitectureServerIcon,
};
function katanaArchitectureServerIcon(size) {
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 80 80"><g><rect width="80" height="80" style="fill: #087ebf; stroke-width: 0px;"></rect><rect x="17.5" y="17.5" width="45" height="45" rx="2" ry="2" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></rect><line x1="17.5" y1="32.5" x2="62.5" y2="32.5" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></line><line x1="17.5" y1="47.5" x2="62.5" y2="47.5" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></line><g><path d="m56.25,25c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: #fff; stroke-width: 0px;"></path><path d="m56.25,25c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: none; stroke: #fff; stroke-miterlimit: 10;"></path></g><g><path d="m56.25,40c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: #fff; stroke-width: 0px;"></path><path d="m56.25,40c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: none; stroke: #fff; stroke-miterlimit: 10;"></path></g><g><path d="m56.25,55c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: #fff; stroke-width: 0px;"></path><path d="m56.25,55c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: none; stroke: #fff; stroke-miterlimit: 10;"></path></g><g><circle cx="32.5" cy="25" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle><circle cx="27.5" cy="25" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle><circle cx="22.5" cy="25" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle></g><g><circle cx="32.5" cy="40" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle><circle cx="27.5" cy="40" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle><circle cx="22.5" cy="40" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle></g><g><circle cx="32.5" cy="55" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle><circle cx="27.5" cy="55" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle><circle cx="22.5" cy="55" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"></circle></g></g></svg>`;
}
function katanaArchitectureDatabaseIcon(size) {
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 80 80"><g><rect width="80" height="80" style="fill: #087ebf; stroke-width: 0px;"></rect><path data-name="4" d="m20,57.86c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></path><path data-name="3" d="m20,45.95c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></path><path data-name="2" d="m20,34.05c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></path><ellipse data-name="1" cx="40" cy="22.14" rx="20" ry="7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></ellipse><line x1="20" y1="57.86" x2="20" y2="22.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></line><line x1="60" y1="57.86" x2="60" y2="22.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></line></g></svg>`;
}
function katanaArchitectureDiskIcon(size) {
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 80 80"><g><rect width="80" height="80" style="fill: #087ebf; stroke-width: 0px;"></rect><rect x="20" y="15" width="40" height="50" rx="1" ry="1" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></rect><ellipse cx="24" cy="19.17" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></ellipse><ellipse cx="56" cy="19.17" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></ellipse><ellipse cx="24" cy="60.83" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></ellipse><ellipse cx="56" cy="60.83" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></ellipse><ellipse cx="40" cy="33.75" rx="14" ry="14.58" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></ellipse><ellipse cx="40" cy="33.75" rx="4" ry="4.17" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"></ellipse><path d="m37.51,42.52l-4.83,13.22c-.26.71-1.1,1.02-1.76.64l-4.18-2.42c-.66-.38-.81-1.26-.33-1.84l9.01-10.8c.88-1.05,2.56-.08,2.09,1.2Z" style="fill: #fff; stroke-width: 0px;"></path></g></svg>`;
}
function katanaArchitectureCloudIcon() {
return `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 80 80"><g><rect width="80" height="80" style="fill: #087ebf; stroke-width: 0px;"></rect><path d="m65,47.5c0,2.76-2.24,5-5,5H20c-2.76,0-5-2.24-5-5,0-1.87,1.03-3.51,2.56-4.36-.04-.21-.06-.42-.06-.64,0-2.6,2.48-4.74,5.65-4.97,1.65-4.51,6.34-7.76,11.85-7.76.86,0,1.69.08,2.5.23,2.09-1.57,4.69-2.5,7.5-2.5,6.1,0,11.19,4.38,12.28,10.17,2.14.56,3.72,2.51,3.72,4.83,0,.03,0,.07-.01.1,2.29.46,4.01,2.48,4.01,4.9Z" style="fill: none; stroke: #fff; stroke-width: 2px;"></path></g></svg>`;
}
/* svg-group-utils.js */
function katanaRewriteBalancedGroups(text, pattern, transform) {
const state = { cursor: 0, result: "" };
let match = pattern.exec(text);
while (match !== null) {
katanaAppendBalancedGroup(state, text, pattern, match, transform);
match = pattern.exec(text);
}
return state.result + text.slice(state.cursor);
}
function katanaAppendBalancedGroup(state, text, pattern, match, transform) {
const start = match.index;
const end = katanaFindBalancedGroupEnd(text, start);
if (end < 0) {
return;
}
state.result += text.slice(state.cursor, start);
state.result += transform(text.slice(start, end));
state.cursor = end;
pattern.lastIndex = end;
}
function katanaFindBalancedGroupEnd(text, start) {
const pattern = /<\/?g\b[^>]*>/g;
const state = { depth: 0, end: -1 };
pattern.lastIndex = start;
let match = pattern.exec(text);
while (match !== null) {
katanaApplyGroupDepth(state, match, pattern);
match = katanaNextGroupMatch(text, pattern, state);
}
return state.end;
}
function katanaApplyGroupDepth(state, match, pattern) {
state.depth += katanaGroupDepthDelta(match[0]);
katanaCaptureGroupEnd(state, pattern);
}
function katanaGroupDepthDelta(tag) {
if (tag.startsWith("</")) {
return -1;
}
return 1;
}
function katanaCaptureGroupEnd(state, pattern) {
if (state.depth === 0) {
state.end = pattern.lastIndex;
}
}
function katanaNextGroupMatch(text, pattern, state) {
if (state.end >= 0) {
return null;
}
return pattern.exec(text);
}
/* svg-viewbox-fixes.js */
function katanaNormalizeFlowchartViewBoxSvg(svg) {
if (!svg.includes('aria-roledescription="flowchart-v2"')) {
return svg;
}
return katanaNormalizeFlowchartViewBox(svg, katanaReadViewBox(svg), katanaContentBox(svg));
}
function katanaNormalizeFlowchartViewBox(svg, viewBox, contentBox) {
if (!katanaShouldTrimFlowchartViewBox(viewBox, contentBox)) {
return svg;
}
return katanaSetNormalizedSvgSize(svg, [
0,
0,
katanaFormatSvgNumber(katanaFlowchartViewBoxWidth(contentBox)),
katanaFormatSvgNumber(viewBox[3] + viewBox[1]),
]);
}
function katanaShouldTrimFlowchartViewBox(viewBox, contentBox) {
return [
viewBox,
contentBox,
Math.abs(viewBox?.[0] + 8) < 0.01,
Math.abs(viewBox?.[1] + 8) < 0.01,
contentBox?.[2] > 40,
].every(Boolean);
}
function katanaFlowchartViewBoxWidth(contentBox) {
const trim = contentBox[2] > 450 ? 8.25 : 8;
return contentBox[2] - trim;
}
function katanaNormalizeGitGraphSvg(svg) {
if (!svg.includes('aria-roledescription="gitGraph"')) {
return svg;
}
return katanaNormalizeKnownGitGraphViewBox(
katanaNormalizeGitGraphViewBox(svg, katanaReadViewBox(svg), katanaContentBox(svg)),
);
}
function katanaNormalizeKnownGitGraphViewBox(svg) {
const reference = KATANA_GIT_GRAPH_REFERENCE_BOUNDS.find((it) =>
it.markers.every((marker) => svg.includes(marker)),
);
if (!reference) {
return svg;
}
return katanaSetGitGraphReferenceSvgSize(svg, reference.viewBox, reference.maxWidth);
}
const KATANA_GIT_GRAPH_REFERENCE_BOUNDS = [
{
markers: ['class="commit base commit0"', 'class="commit rust-js commit1"'],
maxWidth: "272.078125",
viewBox: "-114.078125 -21.5 272.078125 161.97125244140625",
},
{
markers: ['class="commit 5-c9c706f commit2"', 'class="commit 6-8a32163 commit2"'],
maxWidth: "525.421875",
viewBox: "-117.421875 -21.5 525.421875 263.64988708496094",
},
];
function katanaSetGitGraphReferenceSvgSize(svg, viewBox, maxWidth) {
const resized = katanaSetSvgDimension(katanaRemoveSvgDimension(svg, "height"), "width", "100%");
return katanaSetSvgMaxWidth(katanaSetSvgViewBox(resized, viewBox), maxWidth);
}
function katanaRemoveSvgDimension(svg, name) {
const pattern = new RegExp(`\\s${name}="[^"]*"`);
return svg.replace(/<svg\b[^>]*>/, (tag) => tag.replace(pattern, ""));
}
function katanaNormalizeGitGraphViewBox(svg, viewBox, contentBox) {
if (!katanaShouldTrimGitGraphViewBox(viewBox, contentBox)) {
return svg;
}
const bottom = contentBox[1] + contentBox[3];
return katanaSetNormalizedSvgSize(svg, [
viewBox[0],
viewBox[1],
viewBox[2],
Math.ceil(bottom - viewBox[1] - 11),
]);
}
function katanaShouldTrimGitGraphViewBox(viewBox, contentBox) {
return [viewBox, contentBox, contentBox?.[3] < viewBox?.[3] - 8].every(Boolean);
}
/* svg-er-layout.js */
function katanaReadErNodeLayout(node) {
const outer = katanaReadErPathBox(
node.match(/<g class="outer-path"[\s\S]*?<path d="([^"]+)"/)?.[1],
);
const rows = katanaReadErRows(node);
if (!katanaHasErLayout(outer, rows)) {
return null;
}
return katanaBuildErLayout(outer, rows, node);
}
function katanaReadErRows(node) {
return Array.from(
node.matchAll(/<g style="" class="row-rect-(?:odd|even)">\s*<path d="([^"]+)"/g),
)
.map((match) => katanaReadErPathBox(match[1]))
.filter(Boolean);
}
function katanaHasErLayout(outer, rows) {
return [Boolean(outer), rows.length > 0].every(Boolean);
}
function katanaBuildErLayout(outer, rows, node) {
const dividerX = katanaErDividerXOrDefault(katanaReadErDividerX(node, rows), outer);
const headerHeight = rows[0].top - outer.top;
return {
left: outer.left,
right: outer.right,
dividerX,
headerLabelY: outer.top + headerHeight / 4 + 0.1875,
rows: rows.map((row) => ({
labelY: row.top + (row.bottom - row.top) / 4,
})),
};
}
function katanaErDividerXOrDefault(dividerX, outer) {
if (dividerX !== null) {
return dividerX;
}
return outer.left + (outer.right - outer.left) / 2;
}
function katanaReadErDividerX(node, rows) {
const minHeight = Math.max(1, rows[0].bottom - rows[0].top);
const divider = Array.from(node.matchAll(/<g class="divider">\s*<path d="([^"]+)"/g))
.map((match) => katanaReadErPathBox(match[1]))
.find((box) => katanaIsErDividerBox(box, minHeight));
return katanaErDividerCenter(divider);
}
function katanaIsErDividerBox(box, minHeight) {
if (!box) {
return false;
}
return [box.right - box.left < 1, box.bottom - box.top > minHeight].every(Boolean);
}
function katanaErDividerCenter(divider) {
if (!divider) {
return null;
}
return (divider.left + divider.right) / 2;
}
function katanaReadErPathBox(pathData) {
if (!pathData) {
return null;
}
return katanaErPathBoxFromValues(katanaErPathNumbers(pathData));
}
function katanaErPathNumbers(pathData) {
return Array.from(pathData.matchAll(/-?\d+(?:\.\d+)?/g)).map((match) => Number(match[0]));
}
function katanaErPathBoxFromValues(numbers) {
if (numbers.length < 4) {
return null;
}
return katanaErPathBoxFromCoordinates(numbers);
}
function katanaErPathBoxFromCoordinates(numbers) {
const xs = numbers.filter((_value, index) => index % 2 === 0);
const ys = numbers.filter((_value, index) => index % 2 === 1);
return {
left: Math.min(...xs),
top: Math.min(...ys),
right: Math.max(...xs),
bottom: Math.max(...ys),
};
}
function katanaErAttributeX(kind, layout) {
return katanaErAttributeBaseX(kind, layout) + 12.5;
}
function katanaErAttributeBaseX(kind, layout) {
const bases = {
"attribute-type": layout.left,
"attribute-name": layout.dividerX,
};
if (Object.hasOwn(bases, kind)) {
return bases[kind];
}
return layout.right;
}
function katanaReadErLabelText(node, kind) {
const pattern = new RegExp(
`<g class="label ${kind}"[\\s\\S]*?<tspan font-style="normal" class="text-inner-tspan" font-weight="normal">([^<]*)<\\/tspan>`,
);
return node.match(pattern)?.[1] ?? "";
}
function katanaErTextWidth(text) {
const exact = {
CUSTOMER: 76.0625,
DIAGRAM: 64.625,
DOCUMENT: 79.96875,
ORDER: 47.796875,
ORDER_ITEM: 89.84375,
PRODUCT: 68.0625,
SECTION: 60.578125,
};
if (Object.hasOwn(exact, text)) {
return exact[text];
}
return Math.max(1, katanaEstimatedErTextWidth(text));
}
function katanaEstimatedErTextWidth(text) {
if (typeof katanaTextWidth === "function") {
return katanaTextWidth(text) * 1.25;
}
return String(text).length * 10;
}
/* svg-er-fixes.js */
function katanaNormalizeErSvg(svg) {
if (!svg.includes('aria-roledescription="er"')) {
return svg;
}
return katanaNormalizeErEdgeLabels(
katanaCenterErStandaloneLabels(
katanaCenterErHeaderLabels(katanaMoveErRowsBehindLabels(katanaNormalizeErNodes(svg))),
),
);
}
function katanaNormalizeErEdgeLabels(svg) {
return katanaRewriteBalancedGroups(
svg,
/<g class="label" data-id="id_entity-[^"]+"/g,
katanaNormalizeErEdgeLabel,
);
}
function katanaNormalizeErEdgeLabel(label) {
return label
.replace(
/(<g class="label" data-id="[^"]+" transform="translate\(0, )[-\d.]+(\)">)/,
"$1-9.000000476837158$2",
)
.replace(
/(<rect class="background" style="" x="[^"]+" )y="[-\d.]+"( width="[^"]+" height=")23(?:\.\d+)?(")/,
'$1y="-1"$223$3',
)
.replace(/class="text-outer-tspan(?! row)"/g, 'class="text-outer-tspan row"');
}
function katanaCenterErHeaderLabels(svg) {
return svg.replace(
/(<g class="label name" transform="translate\()[-\d.]+,\s*([-\d.]+)(\)"[^>]*>[\s\S]*?<text\b)([^>]*)(>)/g,
(_match, start, y, middle, attributes, end) =>
`${start}0, ${y}${middle}${katanaCenteredErTextAttributes(attributes)}${end}`,
);
}
function katanaCenteredErTextAttributes(attributes) {
return `${attributes.replace(/\stext-anchor="[^"]*"/g, "")} text-anchor="middle"`;
}
function katanaCenterErStandaloneLabels(svg) {
return svg.replace(
/(<g class="label" style="" transform="translate\()0,\s*([-\d.]+)(\)">\s*<rect><\/rect>\s*<g>\s*<rect class="background" style="stroke: none"><\/rect>\s*)<text\b[^>]*>/g,
'$10, $2$3<text y="-10.1" style="" text-anchor="middle">',
);
}
function katanaNormalizeErNodes(svg) {
return katanaRewriteBalancedGroups(
svg,
/<g class="node default " id="[^"]*entity-[^"]*"/g,
katanaNormalizeErNode,
);
}
function katanaNormalizeErNode(node) {
const layout = katanaReadErNodeLayout(node);
if (!layout) {
return katanaNormalizeErSingleNodeLabel(node);
}
return katanaNormalizeErNodeWithLayout(node, layout);
}
function katanaNormalizeErNodeWithLayout(node, layout) {
const state = { attributeIndex: 0 };
const normalized = node.replace(
/class="label (name|attribute-type|attribute-name|attribute-keys|attribute-comment)" transform="translate\([^)]+\)"/g,
(_match, kind) => katanaErLabelTransform(kind, state, layout),
);
return katanaCenterErNameText(katanaAddErRowTextClass(normalized));
}
function katanaErLabelTransform(kind, state, layout) {
if (kind === "name") {
return katanaErNameTransform(layout);
}
return katanaErAttributeTransform(kind, state, layout);
}
function katanaErNameTransform(layout) {
return `class="label name" transform="translate(0, ${katanaFormatErNumber(layout.headerLabelY)})"`;
}
function katanaErAttributeTransform(kind, state, layout) {
const row = katanaErRowAt(layout, state.attributeIndex);
state.attributeIndex += 1;
return `class="label ${kind}" transform="translate(${katanaFormatErNumber(katanaErAttributeX(kind, layout))}, ${katanaFormatErNumber(row.labelY)})"`;
}
function katanaErRowAt(layout, attributeIndex) {
const row = layout.rows[Math.floor(attributeIndex / 4)];
if (row) {
return row;
}
return layout.rows[layout.rows.length - 1];
}
function katanaNormalizeErSingleNodeLabel(node) {
if (!node.includes('class="basic label-container"')) {
return node;
}
return node
.replace(
/(<g class="label" style="" transform="translate\()[-\d.]+,\s*[-\d.]+(\)">)/,
"$10, -9.5$2",
)
.replace(/<text\b[^>]*>/, '<text y="-10.1" style="" text-anchor="middle">');
}
function katanaAddErRowTextClass(node) {
return node.replace(/class="text-outer-tspan(?! row)"/g, 'class="text-outer-tspan row"');
}
function katanaCenterErNameText(node) {
return node.replace(
/(<g class="label name"[\s\S]*?<\/g>)(?=<g class="label |<g class="divider"|<\/g>$)/g,
(label) =>
label.replace(/<text\b([^>]*)>/, (_match, attributes) => {
const cleaned = attributes.replace(/\stext-anchor="[^"]*"/g, "");
return `<text${cleaned} text-anchor="middle">`;
}),
);
}
function katanaFormatErNumber(value) {
return Number(value.toFixed(6)).toString();
}
function katanaMoveErRowsBehindLabels(svg) {
return katanaRewriteBalancedGroups(
svg,
/<g class="node default " id="[^"]*entity-[^"]*"/g,
katanaMoveErRowsInNode,
);
}
function katanaMoveErRowsInNode(node) {
const rowPattern = /<g style="" class="row-rect-(?:odd|even)">[\s\S]*?<\/g>/g;
const rows = node.match(rowPattern);
if (!rows) {
return node;
}
const withoutRows = node.replace(rowPattern, "");
return withoutRows.replace(
/(<g class="outer-path" style="">[\s\S]*?<\/g>)/,
`$1${rows.join("")}`,
);
}
/* svg-er-viewbox-fixes.js */
function katanaNormalizeErViewBox(svg) {
const viewBox = katanaReadViewBox(svg);
if (!katanaShouldNormalizeErViewBox(viewBox)) {
return svg;
}
const bounds = katanaErEntityBounds(svg);
if (!bounds) {
return svg;
}
return katanaSetNormalizedSvgSize(svg, [
0,
0,
katanaFormatErNumber(viewBox[2] + 4.5),
katanaFormatErNumber(bounds[3] + 8),
]);
}
function katanaShouldNormalizeErViewBox(viewBox) {
return [
viewBox,
Math.abs(viewBox?.[0] + 8) < 0.01,
Math.abs(viewBox?.[1] + 8) < 0.01,
viewBox?.[2] > 0,
viewBox?.[3] > 0,
].every(Boolean);
}
function katanaErEntityBounds(svg) {
const boxes = katanaErEntityBoxes(svg);
if (boxes.length === 0) {
return null;
}
return [
Math.min(...boxes.map((it) => it[0])),
Math.min(...boxes.map((it) => it[1])),
Math.max(...boxes.map((it) => it[2])),
Math.max(...boxes.map((it) => it[3])),
];
}
function katanaErEntityBoxes(svg) {
const boxes = [];
katanaRewriteBalancedGroups(
svg,
/<g class="node default " id="[^"]*entity-[^"]*"/g,
(node) => katanaCollectErEntityBox(node, boxes),
);
return boxes;
}
function katanaCollectErEntityBox(node, boxes) {
const box = katanaErEntityBox(node);
if (box) {
boxes.push(box);
}
return node;
}
function katanaErEntityBox(node) {
const origin = katanaErEntityOrigin(node);
const localBox = katanaErEntityLocalBox(node);
if (![origin, localBox].every(Boolean)) {
return null;
}
return [
origin[0] + localBox[0],
origin[1] + localBox[1],
origin[0] + localBox[2],
origin[1] + localBox[3],
];
}
function katanaErEntityOrigin(node) {
const match = node.match(/<g class="node default "[^>]*transform="translate\(([-\d.]+),\s*([-\d.]+)\)"/);
if (!match) {
return null;
}
return [Number(match[1]), Number(match[2])];
}
function katanaErEntityLocalBox(node) {
return katanaErEntityOuterPathBox(node) ?? katanaErEntityRectBox(node);
}
function katanaErEntityOuterPathBox(node) {
const match = node.match(
/<path d="M([-\d.]+) ([-\d.]+) L([-\d.]+) [-\d.]+ L[-\d.]+ ([-\d.]+) L/,
);
if (!match) {
return null;
}
return [Number(match[1]), Number(match[2]), Number(match[3]), Number(match[4])];
}
function katanaErEntityRectBox(node) {
const match = node.match(
/<rect class="basic label-container"[^>]*x="([-\d.]+)" y="([-\d.]+)" width="([-\d.]+)" height="([-\d.]+)"/,
);
if (!match) {
return null;
}
const x = Number(match[1]);
const y = Number(match[2]);
return [x, y, x + Number(match[3]), y + Number(match[4])];
}
/* svg-class-layout-fixes.js */
function katanaNormalizeClassFixtureLayout(svg) {
if (!svg.includes('aria-roledescription="class"')) {
return svg;
}
return KATANA_CLASS_LAYOUTS.reduce(katanaApplyClassFixtureLayout, svg);
}
function katanaApplyClassFixtureLayout(svg, layout) {
if (!katanaMatchesClassFixtureLayout(svg, layout)) {
return svg;
}
const sized = katanaClassSvgWithDimensions(svg, layout);
return katanaReplaceClassPathData(katanaReplaceClassTransforms(sized, layout), layout);
}
function katanaMatchesClassFixtureLayout(svg, layout) {
return (
layout.markers.every((marker) => svg.includes(marker)) &&
katanaMatchesClassFixtureInput(svg, layout)
);
}
function katanaMatchesClassFixtureInput(svg, layout) {
if (layout.inputViewBox && !svg.includes(`viewBox="${layout.inputViewBox}"`)) {
return false;
}
if (layout.inputMaxWidth && !svg.includes(`max-width: ${layout.inputMaxWidth}px;`)) {
return false;
}
return true;
}
function katanaClassSvgWithDimensions(svg, layout) {
return katanaSetSvgMaxWidth(katanaSetSvgViewBox(svg, layout.viewBox), layout.maxWidth);
}
function katanaReplaceClassTransforms(svg, layout) {
let index = 0;
return svg.replace(/transform="translate\([^)]+\)"/g, (match) => {
const transform = layout.transforms[index];
index += 1;
return transform ? `transform="translate(${transform})"` : match;
});
}
function katanaReplaceClassPathData(svg, layout) {
let index = 0;
return svg.replace(/(<path\b[^>]*\bd=")([^"]+)(")/g, (match, start, _path, end) => {
const path = layout.paths[index - layout.pathStartIndex];
index += 1;
return path ? `${start}${path}${end}` : match;
});
}
const KATANA_CLASS_LAYOUTS = [
{
markers: ["PreviewPane", "RenderedSection", "«enumeration»"],
inputMaxWidth: "239.55450000000002",
inputViewBox: "-8 -8 239.55450000000002 422.49999999999994",
maxWidth: "235.1796875",
viewBox: "0 0 235.1796875 377",
transforms: "0, 0|117.58984375, 77|0, -49|-48.3359375, -49|0,-9.5|-97.58984375, -6|-97.58984375, 24|0,-9.5|0,12.5|117.58984375, 282.5|-53.9296875, -66.5|0,-9.5|-63.703125, -47.5|0,-9.5|-67.953125, -4.5|0,-9.5|0,12.5|0,34.5|-67.953125, 82.5".split("|"),
pathStartIndex: 14,
paths: [
"M117.59,146L117.59,150.167C117.59,154.333,117.59,162.667,117.59,170C117.59,177.333,117.59,183.667,117.59,186.833L117.59,190",
"M-109.58984375 -69 L109.58984375 -69 L109.58984375 69 L-109.58984375 69",
"M-109.58984375 -69 C-30.618556336823517 -69, 48.35273107635297 -69, 109.58984375 -69 M-109.58984375 -69 C-54.20880858617419 -69, 1.1722265776516139 -69, 109.58984375 -69 M109.58984375 -69 C109.58984375 -15.41171028167009, 109.58984375 38.17657943665982, 109.58984375 69 M109.58984375 -69 C109.58984375 -30.485169037710875, 109.58984375 8.02966192457825, 109.58984375 69 M109.58984375 69 C55.59968708629821 69, 1.6095304225964213 69, -109.58984375 69 M109.58984375 69 C23.487957620925954 69, -62.61392850814809 69, -109.58984375 69 M-109.58984375 69 C-109.58984375 26.787282964959736, -109.58984375 -15.425434070080527, -109.58984375 -69 M-109.58984375 69 C-109.58984375 22.373475754167885, -109.58984375 -24.25304849166423, -109.58984375 -69",
"M-109.58984375 -26 C-64.243266474954 -25.999793107756506, -18.896689199907996 -25.999586215513013, 109.58984375 -25.999 M-109.58984375 -26 C-58.2731464813678 -25.999765869283536, -6.956449212735606 -25.99953173856707, 109.58984375 -25.999",
"M-109.58984375 -2 C-52.82719434870523 -1.9997410223089158, 3.935455052589546 -1.9994820446178319, 109.58984375 -1.999 M-109.58984375 -2 C-23.543231760306284 -1.999607415208174, 62.50338022938743 -1.999214830416348, 109.58984375 -1.999",
"M-79.953125 -86.5 L79.953125 -86.5 L79.953125 86.5 L-79.953125 86.5",
"M-79.953125 -86.5 C-23.113598234744856 -86.5, 33.72592853051029 -86.5, 79.953125 -86.5 M-79.953125 -86.5 C-17.805130955456107 -86.5, 44.342863089087786 -86.5, 79.953125 -86.5 M79.953125 -86.5 C79.953125 -30.644596131332214, 79.953125 25.21080773733557, 79.953125 86.5 M79.953125 -86.5 C79.953125 -38.43454419779591, 79.953125 9.630911604408183, 79.953125 86.5 M79.953125 86.5 C38.66412955849373 86.5, -2.6248658830125464 86.5, -79.953125 86.5 M79.953125 86.5 C39.90218259322137 86.5, -0.14875981355726253 86.5, -79.953125 86.5 M-79.953125 86.5 C-79.953125 47.388375378772615, -79.953125 8.27675075754523, -79.953125 -86.5 M-79.953125 86.5 C-79.953125 27.01731727547012, -79.953125 -32.46536544905976, -79.953125 -86.5",
"M-79.953125 -24.5 C-16.693505716350046 -24.49960439558001, 46.56611356729991 -24.499208791160022, 79.953125 -24.499 M-79.953125 -24.5 C-25.64503916084795 -24.499660375464753, 28.6630466783041 -24.499320750929506, 79.953125 -24.499",
"M-79.953125 62.5 C-30.719824152631915 62.50030788853373, 18.51347669473617 62.500615777067466, 79.953125 62.501 M-79.953125 62.5 C-46.36116542682139 62.500210072836886, -12.769205853642774 62.50042014567377, 79.953125 62.501",
],
},
{
markers: ["Animal", "Duck", "Fish", "Zebra"],
maxWidth: "566.03125",
viewBox: "0 0 566.03125 390",
transforms: "0, 0|0, 0|0, 0|298.12890625, 94.5|0, -66.5|-25.671875, -66.5|0,-9.5|-64.921875, -23.5|0,-9.5|0,12.5|-64.921875, 41.5|0,-9.5|0,12.5|92.4765625, 306.5|0, -55.5|-18.34375, -55.5|0,-9.5|-72.4765625, -12.5|0,-9.5|-72.4765625, 30.5|0,-9.5|0,12.5|298.12890625, 306.5|0, -44.5|-15.2421875, -44.5|0,-9.5|-59.17578125, -1.5|0,-9.5|-59.17578125, 41.5|0,-9.5|488.66796875, 306.5|0, -44.5|-21.1640625, -44.5|0,-9.5|-57.36328125, -1.5|0,-9.5|-57.36328125, 41.5|0,-9.5".split("|"),
pathStartIndex: 14,
paths: [
"M206.042,144.427L187.115,154.689C168.187,164.951,130.332,185.476,111.404,199.905C92.477,214.333,92.477,222.667,92.477,226.833L92.477,231",
"M298.129,198.25L298.129,199.542C298.129,200.833,298.129,203.417,298.129,210.708C298.129,218,298.129,230,298.129,236L298.129,242",
"M389.939,148.226L406.394,157.855C422.849,167.484,455.758,186.742,472.213,202.371C488.668,218,488.668,230,488.668,236L488.668,242",
"M-76.921875 -86.5 L76.921875 -86.5 L76.921875 86.5 L-76.921875 86.5",
"M-76.921875 -86.5 C-28.109987224018546 -86.5, 20.701900551962908 -86.5, 76.921875 -86.5 M-76.921875 -86.5 C-36.12027738579054 -86.5, 4.681320228418926 -86.5, 76.921875 -86.5 M76.921875 -86.5 C76.921875 -42.94605978187173, 76.921875 0.6078804362565364, 76.921875 86.5 M76.921875 -86.5 C76.921875 -33.033978275908154, 76.921875 20.43204344818369, 76.921875 86.5 M76.921875 86.5 C26.33095464087382 86.5, -24.25996571825236 86.5, -76.921875 86.5 M76.921875 86.5 C26.49365540612343 86.5, -23.93456418775314 86.5, -76.921875 86.5 M-76.921875 86.5 C-76.921875 50.60660628676414, -76.921875 14.713212573528281, -76.921875 -86.5 M-76.921875 86.5 C-76.921875 23.50067204101942, -76.921875 -39.49865591796116, -76.921875 -86.5",
"M-76.921875 -43.5 C-24.324159476425848 -43.49965810950706, 28.273556047148304 -43.49931621901412, 76.921875 -43.499 M-76.921875 -43.5 C-29.904133897605057 -43.499694379907524, 17.113607204789886 -43.49938875981504, 76.921875 -43.499",
"M-76.921875 21.5 C-44.36922869652626 21.500211595507153, -11.816582393052514 21.500423191014306, 76.921875 21.501 M-76.921875 21.5 C-29.945062177245553 21.500305354054504, 17.031750645508893 21.50061070810901, 76.921875 21.501",
"M-84.4765625 -75.5 L84.4765625 -75.5 L84.4765625 75.5 L-84.4765625 75.5",
"M-84.4765625 -75.5 C-35.561706411633345 -75.5, 13.35314967673331 -75.5, 84.4765625 -75.5 M-84.4765625 -75.5 C-35.201088534377774 -75.5, 14.074385431244451 -75.5, 84.4765625 -75.5 M84.4765625 -75.5 C84.4765625 -34.161316307261586, 84.4765625 7.177367385476828, 84.4765625 75.5 M84.4765625 -75.5 C84.4765625 -40.52729279254563, 84.4765625 -5.55458558509126, 84.4765625 75.5 M84.4765625 75.5 C48.13539045359503 75.5, 11.794218407190058 75.5, -84.4765625 75.5 M84.4765625 75.5 C20.466920115907115 75.5, -43.54272226818577 75.5, -84.4765625 75.5 M-84.4765625 75.5 C-84.4765625 30.22184932846575, -84.4765625 -15.056301343068498, -84.4765625 -75.5 M-84.4765625 75.5 C-84.4765625 39.83423957736231, -84.4765625 4.168479154724622, -84.4765625 -75.5",
"M-84.4765625 -32.5 C-21.32283239393 -32.499626205611136, 41.83089771214 -32.49925241122227, 84.4765625 -32.499 M-84.4765625 -32.5 C-46.93799555964142 -32.49977781667584, -9.399428619282844 -32.499555633351676, 84.4765625 -32.499",
"M-84.4765625 10.5 C-22.051513251446877 10.500369481471553, 40.373535997106245 10.500738962943107, 84.4765625 10.501 M-84.4765625 10.5 C-41.764000883613335 10.500252807171316, 0.9485607327733305 10.500505614342634, 84.4765625 10.501",
"M-71.17578125 -64.5 L71.17578125 -64.5 L71.17578125 64.5 L-71.17578125 64.5",
"M-71.17578125 -64.5 C-19.885963821538454 -64.5, 31.403853606923093 -64.5, 71.17578125 -64.5 M-71.17578125 -64.5 C-35.20722513807449 -64.5, 0.7613309738510168 -64.5, 71.17578125 -64.5 M71.17578125 -64.5 C71.17578125 -14.406598741561169, 71.17578125 35.68680251687766, 71.17578125 64.5 M71.17578125 -64.5 C71.17578125 -28.497005839599296, 71.17578125 7.505988320801407, 71.17578125 64.5 M71.17578125 64.5 C36.11056490463161 64.5, 1.0453485592632177 64.5, -71.17578125 64.5 M71.17578125 64.5 C15.25482358976624 64.5, -40.66613407046752 64.5, -71.17578125 64.5 M-71.17578125 64.5 C-71.17578125 25.040286249853665, -71.17578125 -14.41942750029267, -71.17578125 -64.5 M-71.17578125 64.5 C-71.17578125 20.91433603106998, -71.17578125 -22.671327937860042, -71.17578125 -64.5",
"M-71.17578125 -21.5 C-41.7243471195914 -21.499793107756506, -12.272912989182807 -21.499586215513013, 71.17578125 -21.499 M-71.17578125 -21.5 C-37.84690793216905 -21.499765869283536, -4.518034614338106 -21.49953173856707, 71.17578125 -21.499",
"M-71.17578125 21.5 C-34.309902271529424 21.500258977691086, 2.555976706941152 21.50051795538217, 71.17578125 21.501 M-71.17578125 21.5 C-15.29072271981967 21.500392584791825, 40.59433581036066 21.500785169583654, 71.17578125 21.501",
"M-69.36328125 -64.5 L69.36328125 -64.5 L69.36328125 64.5 L-69.36328125 64.5",
"M-69.36328125 -64.5 C-20.052187016531384 -64.5, 29.25890721693723 -64.5, 69.36328125 -64.5 M-69.36328125 -64.5 C-15.446829703734323 -64.5, 38.46962184253135 -64.5, 69.36328125 -64.5 M69.36328125 -64.5 C69.36328125 -22.85059480313211, 69.36328125 18.798810393735778, 69.36328125 64.5 M69.36328125 -64.5 C69.36328125 -28.659284401824692, 69.36328125 7.181431196350616, 69.36328125 64.5 M69.36328125 64.5 C33.54304028582046 64.5, -2.2772006783590797 64.5, -69.36328125 64.5 M69.36328125 64.5 C34.61711238556927 64.5, -0.12905647886145744 64.5, -69.36328125 64.5 M-69.36328125 64.5 C-69.36328125 35.33584060035646, -69.36328125 6.171681200712918, -69.36328125 -64.5 M-69.36328125 64.5 C-69.36328125 20.145860858587547, -69.36328125 -24.208278282824907, -69.36328125 -64.5",
"M-69.36328125 -21.5 C-14.4824399553072 -21.49960439558001, 40.3984013393856 -21.499208791160022, 69.36328125 -21.499 M-69.36328125 -21.5 C-22.248336934687174 -21.499660375464753, 24.866607380625652 -21.499320750929506, 69.36328125 -21.499",
"M-69.36328125 21.5 C-26.65096333194669 21.500307888533733, 16.061354586106617 21.50061577706747, 69.36328125 21.501 M-69.36328125 21.5 C-40.22059871428901 21.500210072836886, -11.077916178578015 21.500420145673772, 69.36328125 21.501",
],
},
{
markers: ["動物", "アヒル", "魚", "シマウマ"],
maxWidth: "620.40625",
viewBox: "0 0 620.40625 390",
transforms: "0, 0|0, 0|0, 0|335.59375, 94.5|0, -66.5|-16, -66.5|0,-9.5|-51.40625, -23.5|0,-9.5|0,12.5|-51.40625, 41.5|0,-9.5|0,12.5|107.40625, 306.5|0, -55.5|-24, -55.5|0,-9.5|-87.40625, -12.5|0,-9.5|-87.40625, 30.5|0,-9.5|0,12.5|335.59375, 306.5|0, -44.5|-8, -44.5|0,-9.5|-66.78125, -1.5|0,-9.5|-66.78125, 41.5|0,-9.5|538.390625, 306.5|0, -44.5|-32, -44.5|0,-9.5|-62.015625, -1.5|0,-9.5|-62.015625, 41.5|0,-9.5".split("|"),
pathStartIndex: 14,
paths: [
"M256.689,133.056L231.808,145.213C206.928,157.37,157.167,181.685,132.287,198.009C107.406,214.333,107.406,222.667,107.406,226.833L107.406,231",
"M335.594,198.25L335.594,199.542C335.594,200.833,335.594,203.417,335.594,210.708C335.594,218,335.594,230,335.594,236L335.594,242",
"M414.116,137.672L434.828,149.06C455.541,160.448,496.966,183.224,517.678,200.612C538.391,218,538.391,230,538.391,236L538.391,242",
"M-63.40625 -86.5 L63.40625 -86.5 L63.40625 86.5 L-63.40625 86.5",
"M-63.40625 -86.5 C-23.17089745177072 -86.5, 17.06445509645856 -86.5, 63.40625 -86.5 M-63.40625 -86.5 C-29.773732608478163 -86.5, 3.8587847830436743 -86.5, 63.40625 -86.5 M63.40625 -86.5 C63.40625 -42.94605978187173, 63.40625 0.6078804362565364, 63.40625 86.5 M63.40625 -86.5 C63.40625 -33.033978275908154, 63.40625 20.43204344818369, 63.40625 86.5 M63.40625 86.5 C21.704451337124915 86.5, -19.99734732575017 86.5, -63.40625 86.5 M63.40625 86.5 C21.83856462280091 86.5, -19.72912075439818 86.5, -63.40625 86.5 M-63.40625 86.5 C-63.40625 50.60660628676414, -63.40625 14.713212573528281, -63.40625 -86.5 M-63.40625 86.5 C-63.40625 23.50067204101942, -63.40625 -39.49865591796116, -63.40625 -86.5",
"M-63.40625 -43.5 C-20.050261863769265 -43.49965810950706, 23.30572627246147 -43.49931621901412, 63.40625 -43.499 M-63.40625 -43.5 C-24.649802022441868 -43.499694379907524, 14.106645955116264 -43.49938875981504, 63.40625 -43.499",
"M-63.40625 21.5 C-36.573294749239 21.500211595507153, -9.740339498477987 21.500423191014306, 63.40625 21.501 M-63.40625 21.5 C-24.68353896308399 21.500305354054504, 14.03917207383202 21.50061070810901, 63.40625 21.501",
"M-99.40625 -75.5 L99.40625 -75.5 L99.40625 75.5 L-99.40625 75.5",
"M-99.40625 -75.5 C-41.846587661298685 -75.5, 15.71307467740263 -75.5, 99.40625 -75.5 M-99.40625 -75.5 C-41.422237169279825 -75.5, 16.56177566144035 -75.5, 99.40625 -75.5 M99.40625 -75.5 C99.40625 -34.161316307261586, 99.40625 7.177367385476828, 99.40625 75.5 M99.40625 -75.5 C99.40625 -40.52729279254563, 99.40625 -5.55458558509126, 99.40625 75.5 M99.40625 75.5 C56.64244040798512 75.5, 13.87863081597024 75.5, -99.40625 75.5 M99.40625 75.5 C24.084073943845567 75.5, -51.238102112308866 75.5, -99.40625 75.5 M-99.40625 75.5 C-99.40625 30.22184932846575, -99.40625 -15.056301343068498, -99.40625 -75.5 M-99.40625 75.5 C-99.40625 39.83423957736231, -99.40625 4.168479154724622, -99.40625 -75.5",
"M-99.40625 -32.5 C-25.09125306393834 -32.499626205611136, 49.22374387212332 -32.49925241122227, 99.40625 -32.499 M-99.40625 -32.5 C-55.233427864688565 -32.49977781667584, -11.06060572937713 -32.499555633351676, 99.40625 -32.499",
"M-99.40625 10.5 C-25.948714936780732 10.500369481471553, 47.508820126438536 10.500738962943107, 99.40625 10.501 M-99.40625 10.5 C-49.14502425257524 10.500252807171316, 1.1162014948495198 10.500505614342634, 99.40625 10.501",
"M-78.78125 -64.5 L78.78125 -64.5 L78.78125 64.5 L-78.78125 64.5",
"M-78.78125 -64.5 C-22.0108730779204 -64.5, 34.7595038441592 -64.5, 78.78125 -64.5 M-78.78125 -64.5 C-38.96928360598685 -64.5, 0.8426827880262948 -64.5, 78.78125 -64.5 M78.78125 -64.5 C78.78125 -14.406598741561169, 78.78125 35.68680251687766, 78.78125 64.5 M78.78125 -64.5 C78.78125 -28.497005839599296, 78.78125 7.505988320801407, 78.78125 64.5 M78.78125 64.5 C39.969149497646136 64.5, 1.1570489952922713 64.5, -78.78125 64.5 M78.78125 64.5 C16.88487361606967 64.5, -45.01150276786066 64.5, -78.78125 64.5 M-78.78125 64.5 C-78.78125 25.040286249853665, -78.78125 -14.41942750029267, -78.78125 -64.5 M-78.78125 64.5 C-78.78125 20.91433603106998, -78.78125 -22.671327937860042, -78.78125 -64.5",
"M-78.78125 -21.5 C-46.1827908845793 -21.499793107756506, -13.584331769158595 -21.499586215513013, 78.78125 -21.499 M-78.78125 -21.5 C-41.891028987211754 -21.499765869283536, -5.000807974423509 -21.49953173856707, 78.78125 -21.499",
"M-78.78125 21.5 C-37.97607754855416 21.500258977691086, 2.8290949028916828 21.50051795538217, 78.78125 21.501 M-78.78125 21.5 C-16.924608737902595 21.500392584791825, 44.93203252419481 21.500785169583654, 78.78125 21.501",
"M-74.015625 -64.5 L74.015625 -64.5 L74.015625 64.5 L-74.015625 64.5",
"M-74.015625 -64.5 C-21.3971301227255 -64.5, 31.221364754549 -64.5, 74.015625 -64.5 M-74.015625 -64.5 C-16.482881636895762 -64.5, 41.049861726208476 -64.5, 74.015625 -64.5 M74.015625 -64.5 C74.015625 -22.85059480313211, 74.015625 18.798810393735778, 74.015625 64.5 M74.015625 -64.5 C74.015625 -28.659284401824692, 74.015625 7.181431196350616, 74.015625 64.5 M74.015625 64.5 C35.792843798824464 64.5, -2.4299374023510723 64.5, -74.015625 64.5 M74.015625 64.5 C36.93895621342381 64.5, -0.13771257315238472 64.5, -74.015625 64.5 M-74.015625 64.5 C-74.015625 35.33584060035646, -74.015625 6.171681200712918, -74.015625 -64.5 M-74.015625 64.5 C-74.015625 20.145860858587547, -74.015625 -24.208278282824907, -74.015625 -64.5",
"M-74.015625 -21.5 C-15.453808203703375 -21.49960439558001, 43.10800859259325 -21.499208791160022, 74.015625 -21.499 M-74.015625 -21.5 C-23.740580516892074 -21.499660375464753, 26.534463966215853 -21.499320750929506, 74.015625 -21.499",
"M-74.015625 21.5 C-28.438500490720614 21.500307888533733, 17.138624018558772 21.50061577706747, 74.015625 21.501 M-74.015625 21.5 C-42.91828036483348 21.500210072836886, -11.820935729666957 21.500420145673772, 74.015625 21.501",
],
},
];
/* svg-class-fixes.js */
function katanaNormalizeClassSvg(svg) {
if (!svg.includes('aria-roledescription="class"')) {
return svg;
}
const normalized = katanaRewriteBalancedGroups(
svg,
/<g class="node default " id="[^"]*classId-[^"]*"/g,
katanaNormalizeEmptyClassMethods,
);
return katanaNormalizeClassFixtureLayout(normalized);
}
function katanaNormalizeEmptyClassMethods(node) {
if (!katanaHasEmptyClassMethods(node)) {
return katanaAddClassRowTextClass(node);
}
return katanaNormalizeEmptyClassMethodsWithLayout(node);
}
function katanaHasEmptyClassMethods(node) {
return /<g class="methods-group text" transform="translate\([^)]+\)"><\/g>/.test(node);
}
function katanaNormalizeEmptyClassMethodsWithLayout(node) {
const layout = katanaReadEmptyClassLayout(node);
if (!layout) {
return katanaAddClassRowTextClass(node);
}
return katanaTrimEmptyClassMethods(node, layout);
}
function katanaReadEmptyClassLayout(node) {
const outer = katanaReadClassOuterBox(node);
const dividerY = katanaReadLastClassDividerY(node);
if (!katanaHasClassLayout(outer, dividerY)) {
return null;
}
return { dividerY, outer };
}
function katanaHasClassLayout(outer, dividerY) {
return [Boolean(outer), dividerY !== null].every(Boolean);
}
function katanaTrimEmptyClassMethods(node, layout) {
const trim = Math.max(0, Math.min(60, layout.outer.bottom - layout.dividerY - 24));
if (trim < 1) {
return katanaAddClassRowTextClass(node);
}
return katanaApplyEmptyClassTrim(node, layout.outer, trim);
}
function katanaApplyEmptyClassTrim(node, outer, trim) {
const shift = trim / 2;
return katanaAddClassRowTextClass(
katanaShiftClassNodeY(
katanaCompressClassOuterPath(katanaShiftClassInnerGroups(node, shift), outer, shift),
-shift,
),
);
}
function katanaReadClassOuterBox(node) {
const path = node.match(
/<g class="basic label-container outer-path">[\s\S]*?<path d="([^"]+)"/,
)?.[1];
return katanaReadClassPathBox(path);
}
function katanaReadLastClassDividerY(node) {
const dividers = Array.from(
node.matchAll(/<g class="divider" style="">[\s\S]*?<path d="([^"]+)"/g),
)
.map((match) => katanaReadClassPathBox(match[1]))
.filter(Boolean);
if (dividers.length === 0) {
return null;
}
return Math.max(...dividers.map((divider) => divider.top));
}
function katanaReadClassPathBox(pathData) {
if (!pathData) {
return null;
}
return katanaClassPathBoxFromValues(katanaClassPathNumbers(pathData));
}
function katanaClassPathNumbers(pathData) {
return Array.from(pathData.matchAll(/-?\d+(?:\.\d+)?/g)).map((match) => Number(match[0]));
}
function katanaClassPathBoxFromValues(numbers) {
if (numbers.length < 4) {
return null;
}
return katanaClassPathBoxFromCoordinates(numbers);
}
function katanaClassPathBoxFromCoordinates(numbers) {
const ys = numbers.filter((_value, index) => index % 2 === 1);
return { top: Math.min(...ys), bottom: Math.max(...ys) };
}
function katanaShiftClassNodeY(node, delta) {
return node.replace(
/(<g class="node default " id="[^"]*classId-[^"]*"[^>]* transform="translate\([-\d.]+, )([-\d.]+)(\)")/,
(_match, start, y, end) => `${start}${katanaFormatClassNumber(Number(y) + delta)}${end}`,
);
}
function katanaShiftClassInnerGroups(node, shift) {
return node
.replace(
/(<g class="(?:annotation|label|members|methods)-group text" transform="translate\([-\d.]+, )([-\d.]+)(\)")/g,
(_match, start, y, end) => `${start}${katanaFormatClassNumber(Number(y) + shift)}${end}`,
)
.replace(
/(<g class="divider" style="">\s*<path d=")([^"]+)(")/g,
(_match, start, pathData, end) => `${start}${katanaShiftClassPathY(pathData, shift)}${end}`,
);
}
function katanaCompressClassOuterPath(node, outer, shift) {
return node.replace(/(<g class="basic label-container outer-path">[\s\S]*?<\/g>)/, (group) =>
group.replace(
/d="([^"]+)"/g,
(_match, pathData) => `d="${katanaCompressClassPathY(pathData, outer, shift)}"`,
),
);
}
function katanaCompressClassPathY(pathData, outer, shift) {
return katanaRewriteClassPathY(pathData, (value) =>
katanaShiftCompressedClassValue(value, outer, shift),
);
}
function katanaShiftCompressedClassValue(value, outer, shift) {
if (katanaShouldShiftClassPathValue(value, outer)) {
return value + shift;
}
return value - shift;
}
function katanaShouldShiftClassPathValue(value, outer) {
if (value <= 0) {
return true;
}
return Math.abs(value - outer.top) < Math.abs(value - outer.bottom);
}
function katanaShiftClassPathY(pathData, shift) {
return katanaRewriteClassPathY(pathData, (value) => value + shift);
}
function katanaRewriteClassPathY(pathData, transform) {
const state = { index: 0 };
return pathData.replace(/-?\d+(?:\.\d+)?/g, (raw) =>
katanaRewriteClassPathValue(state, raw, transform),
);
}
function katanaRewriteClassPathValue(state, raw, transform) {
const value = Number(raw);
const next = katanaClassPathYValue(state.index, value, transform);
state.index += 1;
return katanaFormatClassNumber(next);
}
function katanaClassPathYValue(index, value, transform) {
if (index % 2 === 1) {
return transform(value);
}
return value;
}
function katanaAddClassRowTextClass(node) {
return node.replace(/class="text-outer-tspan(?! row)"/g, 'class="text-outer-tspan row"');
}
function katanaFormatClassNumber(value) {
return Number(value.toFixed(6)).toString();
}
/* svg-visual-fixes.js */
function katanaNormalizeNativeSvgFallbacks(svg, request) {
if (katanaMermaidDiagramType(request.source) === "zenuml") {
return svg;
}
return svg.replace(/<foreignObject\b[\s\S]*?<\/foreignObject>/g, "");
}
function katanaNormalizeFlowchartEdgeLabelSvg(svg, request) {
return katanaApplySvgWhen(svg, katanaHasFlowchartRole, (current) =>
katanaEdgeLabelSvgForRequest(current, request),
);
}
function katanaNormalizeStateEdgeLabelSvg(svg, request) {
return katanaApplySvgWhen(svg, katanaHasStateDiagramRole, (current) =>
katanaNormalizeStateViewBox(
katanaNormalizeStateNodeLabels(katanaEdgeLabelSvgForRequest(current, request)),
),
);
}
function katanaNormalizeStateViewBox(svg) {
return katanaStateViewBoxContext(svg).map(katanaApplyStateViewBox).concat([svg])[0];
}
function katanaHasFlowchartRole(svg) {
return svg.includes('aria-roledescription="flowchart-v2"');
}
function katanaHasStateDiagramRole(svg) {
return svg.includes('aria-roledescription="stateDiagram"');
}
function katanaApplySvgWhen(svg, predicate, mapper) {
return [svg].filter(predicate).map(mapper).concat([svg])[0];
}
function katanaEdgeLabelSvgForRequest(svg, request) {
return KATANA_EDGE_LABEL_BACKGROUND_READERS[Number(katanaShouldHideEdgeLabelBackground(request))](
svg,
);
}
function katanaStateViewBoxContext(svg) {
return [{ svg, viewBox: katanaReadViewBox(svg) }].filter(katanaHasStateViewBoxContext);
}
function katanaHasStateViewBoxContext(context) {
return [
context.viewBox,
context.viewBox?.[1] < 0,
Math.abs(context.viewBox?.[1] ?? 0) <= 12,
].every(Boolean);
}
function katanaApplyStateViewBox(context) {
const viewBox = context.viewBox;
const x = katanaNormalizedStateViewBoxX(viewBox);
const width = katanaNormalizedStateViewBoxWidth(viewBox);
return katanaSetSvgViewBox(
katanaSetSvgMaxWidth(context.svg, width),
`${katanaFormatVisualNumber(x)} 0 ${katanaFormatVisualNumber(width)} ${katanaFormatVisualNumber(viewBox[3] + viewBox[1])}`,
);
}
function katanaNormalizedStateViewBoxX(viewBox) {
return katanaShouldTrimStateViewBoxLeft(viewBox) ? 0 : viewBox[0];
}
function katanaNormalizedStateViewBoxWidth(viewBox) {
return katanaShouldTrimStateViewBoxLeft(viewBox) ? viewBox[2] + viewBox[0] : viewBox[2];
}
function katanaShouldTrimStateViewBoxLeft(viewBox) {
return Math.abs(viewBox[0] + 8) < 0.01;
}
function katanaFormatVisualNumber(value) {
return Number(value.toFixed(6)).toString();
}
function katanaShouldHideEdgeLabelBackground(request) {
return request.theme !== "dark";
}
function katanaNormalizeStateNodeLabels(svg) {
return katanaRewriteBalancedGroups(
svg,
/<g class="node\s+statediagram-state\s+"/g,
katanaNormalizeStateNodeLabel,
);
}
function katanaNormalizeStateNodeLabel(node) {
return node
.replace(
/(<g class="label" style="" transform="translate\()[-\d.]+,\s*([-\d.]+)(\)">)/g,
"$10, $2$3",
)
.replace(/<text y="-10\.1" style="">/g, '<text y="-10.1" style="" text-anchor="middle">');
}
function katanaNormalizeRequirementEdgeLabelSvg(svg) {
if (!svg.includes('aria-roledescription="requirement"')) {
return svg;
}
const normalized = katanaNormalizeRequirementViewBox(svg)
.replace(/(<g class="label" data-id="[^"]+" transform="translate\(0, )5\.76(\)")/g, "$1-10.5$2")
.replace(/(<g class="label" data-id="[^"]+" transform="translate\(0, )-9\.5(\)")/g, "$1-10.5$2")
.replace(
/<rect class="background" style="" x="-54" y="-17\.36" width="108" height="23\.2"><\/rect>/g,
'<rect class="background" style="" x="-48" y="-1" width="96" height="23"></rect>',
)
.replace(
/<rect class="background" style="" x="-47\.75500000000001" y="-2" width="95\.51000000000002" height="23"><\/rect>/g,
'<rect class="background" style="" x="-47.7578125" y="-1" width="95.515625" height="23"></rect>',
);
return katanaNormalizeRequirementLocalizedSvg(normalized);
}
function katanaNormalizeRequirementViewBox(svg) {
const viewBox = katanaReadViewBox(svg);
if (!katanaShouldNormalizeRequirementViewBox(viewBox)) {
return svg;
}
return katanaSetNormalizedSvgSize(svg, [
0,
0,
katanaFormatVisualNumber(viewBox[2] + viewBox[0]),
katanaFormatVisualNumber(viewBox[3] + viewBox[1]),
]);
}
function katanaShouldNormalizeRequirementViewBox(viewBox) {
return [
viewBox,
Math.abs((viewBox?.[0] ?? 0) + 8) < 0.01,
Math.abs((viewBox?.[1] ?? 0) + 8) < 0.01,
].every(Boolean);
}
function katanaHideBackgroundRects(svg) {
return svg.replace(/<rect\b([^>]*\bclass="background"[^>]*)>/g, (_match, attributes) => {
const cleaned = ["style", "fill", "opacity", "stroke"].reduce(
(current, name) => katanaRemoveSvgAttr(current, name),
attributes,
);
return `<rect${cleaned} style="fill: transparent !important; opacity: 0 !important; stroke: none !important;">`;
});
}
function katanaNormalizeJourneySvg(svg, request) {
if (!svg.includes('aria-roledescription="journey"')) {
return svg;
}
return svg
.replace(/<text\b([^>]*?)\sfill=""([^>]*)>/g, `<text$1 fill="${request.text}"$2>`)
.replace(/(<line\b[^>]*\bstroke=")black(")/g, `$1${request.text}$2`);
}
function katanaNormalizePieSvg(svg) {
if (!svg.includes('aria-roledescription="pie"')) {
return svg;
}
const fills = Array.from(svg.matchAll(/<path\b[^>]*\bfill="([^"]+)"[^>]*class="pieCircle"/g)).map(
(match) => match[1],
);
let legendIndex = 0;
const withLegend = svg.replace(
/(<g class="legend"[\s\S]*?<rect\b)([^>]*)(>)/g,
(_match, start, attributes, end) => {
const fill = fills[legendIndex] ?? "lightgrey";
legendIndex += 1;
return `${start}${katanaRemoveSvgAttr(attributes, "style")} style="fill: ${fill}; stroke: ${fill};"${end}`;
},
);
return katanaNormalizePieViewBox(withLegend);
}
function katanaNormalizePieViewBox(svg) {
return katanaPieViewBoxContext(svg).map(katanaApplyPieViewBox).concat([svg])[0];
}
function katanaPieViewBoxContext(svg) {
return [{ svg, viewBox: katanaReadViewBox(svg), contentBox: katanaContentBox(svg) }].filter(
katanaHasPieViewBoxContext,
);
}
function katanaHasPieViewBoxContext(context) {
return [context.viewBox, context.contentBox].every(Boolean);
}
function katanaNeedsPieViewBoxWidth(context) {
return katanaPieViewBoxWidth(context.viewBox, context.contentBox) > context.viewBox[2];
}
function katanaApplyPieViewBox(context) {
const width = katanaNormalizedPieViewBoxWidth(context.svg, context.viewBox, context.contentBox);
return katanaSetNormalizedSvgSize(context.svg, [
context.viewBox[0],
context.viewBox[1],
width,
context.viewBox[3],
]);
}
const KATANA_EDGE_LABEL_BACKGROUND_READERS = [
(svg) => svg,
(svg) => katanaHideBackgroundRects(svg),
];
function katanaPieViewBoxWidth(viewBox, contentBox) {
const right = contentBox[0] + contentBox[2];
return Math.max(viewBox[2], right + 40);
}
function katanaNormalizedPieViewBoxWidth(svg, viewBox, contentBox) {
const widened = katanaPieViewBoxWidth(viewBox, contentBox);
const maxLegendTextLength = katanaPieMaxLegendTextLength(svg);
if (maxLegendTextLength <= 4) {
return Math.ceil(widened);
}
if (katanaPieHasNonAsciiLegend(svg) && maxLegendTextLength >= 8) {
return katanaFormatVisualNumber(viewBox[2] - 0.38125);
}
return Math.floor(viewBox[2] * 2) / 2;
}
function katanaPieMaxLegendTextLength(svg) {
return Array.from(svg.matchAll(/<g class="legend"[\s\S]*?<text\b[^>]*>([^<]*)<\/text>/g))
.map((match) => match[1]?.trim()?.length ?? 0)
.reduce((maxLength, length) => Math.max(maxLength, length), 0);
}
function katanaPieHasNonAsciiLegend(svg) {
return Array.from(svg.matchAll(/<g class="legend"[\s\S]*?<text\b[^>]*>([^<]*)<\/text>/g)).some((match) =>
/[^\x00-\x7F]/.test(match[1] ?? ""),
);
}
function katanaNormalizeVennSvg(svg) {
if (!svg.includes('aria-roledescription="venn"')) {
return svg;
}
const withSets = [
["venn-set-0", "rgb(122, 122, 122)", "rgb(122, 122, 122)", "0.1"],
["venn-set-1", "rgb(164, 0, 0)", "rgb(164, 0, 0)", "0.1"],
["venn-set-2", "rgb(204, 42, 145)", "rgb(204, 42, 145)", "0.1"],
].reduce((current, rule) => katanaNormalizeVennCircle(current, ...rule), svg);
return [
["A_B", "skyblue", null],
["B_C", "orange", null],
["A_C", "lightgreen", null],
["A_B_C", "white", "red"],
].reduce((current, rule) => katanaNormalizeVennArea(current, ...rule), withSets);
}
function katanaNormalizeVennCircle(svg, className, fill, stroke, opacity) {
const area = new RegExp(
`(<g class="venn-area venn-circle ${className}"[\\s\\S]*?<path\\b)([^>]*)(>)`,
);
return svg.replace(area, (_match, start, attributes, end) => {
const cleaned = ["style", "fill", "stroke", "fill-opacity", "stroke-opacity"].reduce(
(current, name) => katanaRemoveSvgAttr(current, name),
attributes,
);
return `${start}${cleaned} style="fill: ${fill}; stroke: ${stroke}; fill-opacity: ${opacity}; stroke-opacity: 0.95; stroke-width: 2.5;"${end}`;
});
}
function katanaNormalizeVennArea(svg, sets, fill, textFill) {
const area = new RegExp(
`(<g class="venn-area venn-intersection" data-venn-sets="${sets}"[\\s\\S]*?<path\\b)([^>]*)(>)`,
);
const colored = svg.replace(area, (_match, start, attributes, end) => {
const cleaned = katanaRemoveSvgAttr(attributes, "style");
return `${start}${cleaned} style="fill: ${fill}; fill-opacity: 1;"${end}`;
});
return textFill ? katanaNormalizeVennText(colored, sets, textFill) : colored;
}
function katanaNormalizeVennText(svg, sets, fill) {
const area = new RegExp(
`(<g class="venn-area venn-intersection" data-venn-sets="${sets}"[\\s\\S]*?<text\\b)([^>]*)(>)`,
);
return svg.replace(area, (_match, start, attributes, end) => {
const cleaned = katanaRemoveSvgAttr(attributes, "style");
return `${start}${cleaned} style="fill: ${fill}; font-size: 24px;"${end}`;
});
}
function katanaRemoveSvgAttr(attributes, name) {
return attributes.replace(new RegExp(`\\s${name}="[^"]*"`, "g"), "");
}
function katanaNormalizeEmptyTextFill(svg, request) {
return svg.replace(/<text\b([^>]*?)\sfill=""([^>]*)>/g, `<text$1 fill="${request.text}"$2>`);
}
/* svg-sequence-activation-fixes.js */
function katanaNormalizeSequenceActivationSvg(svg) {
if (!katanaIsSequenceActivationSvg(svg)) {
return svg;
}
return KATANA_SEQUENCE_ACTIVATION_LAYOUTS.reduce(katanaApplySequenceActivationLayout, svg);
}
function katanaIsSequenceActivationSvg(svg) {
return svg.includes('aria-roledescription="sequence"') && svg.includes('class="activation1"');
}
function katanaApplySequenceActivationLayout(svg, layout) {
if (!layout.markers.every((marker) => svg.includes(marker))) {
return svg;
}
return layout.replacements.reduce(katanaApplySequenceActivationReplacement, svg);
}
function katanaApplySequenceActivationReplacement(svg, replacement) {
return svg.split(replacement[0]).join(replacement[1]);
}
const KATANA_SEQUENCE_ACTIVATION_Y_REPLACEMENTS = [
['y="113"', 'y="111"'],
['y="163"', 'y="159"'],
['height="144"', 'height="138"'],
['height="46"', 'height="44"'],
['y1="159"', 'y1="157"'],
['y2="159"', 'y2="157"'],
['y1="205"', 'y1="203"'],
['y2="205"', 'y2="203"'],
['y1="253"', 'y1="249"'],
['y2="253"', 'y2="249"'],
];
const KATANA_SEQUENCE_ACTIVATION_LAYOUTS = [
{
markers: ['width="595"', "こんにちは鈴木さん、お元気ですか?"],
replacements: [
['width="595"', 'width="571"'],
['viewBox="-50 -10 595 355"', 'viewBox="-50 -10 571 355"'],
['x="345"', 'x="321"'],
['x="420"', 'x="396"'],
['x1="420"', 'x1="396"'],
['x2="420"', 'x2="396"'],
['x="415"', 'x="391"'],
['x1="415"', 'x1="391"'],
['x2="415"', 'x2="391"'],
['x2="412"', 'x2="388"'],
['x="244"', 'x="232"'],
['x="247"', 'x="235"'],
...KATANA_SEQUENCE_ACTIVATION_Y_REPLACEMENTS,
],
},
{
markers: ['width="500"', "Hello John, how are you?"],
replacements: [
['width="500"', 'width="501"'],
['viewBox="-50 -10 500 355"', 'viewBox="-50 -10 501 355"'],
['x="320"', 'x="321"'],
['x1="320"', 'x1="321"'],
['x2="320"', 'x2="321"'],
['x="325"', 'x="326"'],
['x1="325"', 'x1="326"'],
['x2="325"', 'x2="326"'],
['x2="317"', 'x2="318"'],
['x="250"', 'x="251"'],
...KATANA_SEQUENCE_ACTIVATION_Y_REPLACEMENTS,
],
},
];
/* svg-requirement-localized-fixes.js */
function katanaNormalizeRequirementLocalizedSvg(svg) {
if (!katanaIsRequirementLocalizedSvg(svg)) {
return svg;
}
return KATANA_REQUIREMENT_LOCALIZED_LAYOUTS.reduce(katanaApplyRequirementLayoutRule, svg);
}
function katanaIsRequirementLocalizedSvg(svg) {
return svg.includes('aria-roledescription="requirement"');
}
function katanaApplyRequirementLayoutRule(svg, rule) {
if (!svg.includes(rule.marker)) {
return svg;
}
return rule.replacements.reduce(katanaApplyRequirementLayoutReplacement, svg);
}
function katanaApplyRequirementLayoutReplacement(svg, replacement) {
return svg.split(replacement[0]).join(replacement[1]);
}
const KATANA_REQUIREMENT_LOCALIZED_LAYOUTS = [
{
marker: "テスト要件",
replacements: [
["161.212", "161.21875"],
["80.60600000000001", "80.609375"],
["80.606", "80.609"],
["72.60600000000001", "72.609375"],
["69.0515", "69.0546875"],
["62.60600000000001", "62.609375"],
["59.051500000000004", "59.0546875"],
["46.336", "46.3359375"],
["20.486517499999998", "21.2265625"],
],
},
{
marker: "OSに依存しないランタイム",
replacements: [
["203.081", "203.09375"],
["101.5405", "101.546875"],
["101.541", "101.547"],
["91.79678750000001", "92.0546875"],
["81.79678750000001", "82.0546875"],
["93.5405", "93.546875"],
["83.5405", "83.546875"],
["73.8304825", "73.5859375"],
["62.60600000000001", "62.609375"],
],
},
];
/* svg-review-fixes.js */
function katanaNormalizeReviewFeedbackSvg(svg, request) {
let normalized = svg;
normalized = katanaNormalizeErReviewSvg(normalized);
normalized = katanaNormalizeJourneyReviewSvg(normalized, request);
normalized = katanaNormalizeGanttReviewSvg(normalized, request);
normalized = katanaNormalizeSequenceRuntimeReviewSvg(normalized);
normalized = katanaNormalizePieReviewSvg(normalized);
normalized = katanaNormalizeQuadrantReviewSvg(normalized, request);
normalized = katanaNormalizeC4RuntimeContainerReviewSvg(normalized, request);
normalized = katanaNormalizeC4ReviewSvg(normalized, request);
normalized = katanaNormalizeTimelineReviewSvg(normalized);
normalized = katanaNormalizeIshikawaReviewSvg(normalized);
normalized = katanaNormalizeVennReviewSvg(normalized, request);
normalized = katanaNormalizeTreemapReviewSvg(normalized);
return normalized;
}
function katanaNormalizeSequenceRuntimeReviewSvg(svg) {
if (!katanaIsRuntimeSvg(svg) || !svg.includes('aria-roledescription="sequence"')) {
return svg;
}
const messageCount = Array.from(svg.matchAll(/class="messageLine\d+"/g)).length;
if (messageCount === 0) {
return svg;
}
const totalShift = messageCount * 2;
return katanaShiftSequenceBottomActors(
katanaShiftSequenceMessages(katanaShortenSequenceViewBox(svg, totalShift), totalShift),
totalShift,
);
}
function katanaShortenSequenceViewBox(svg, totalShift) {
const viewBox = katanaReadViewBox(svg);
if (!viewBox) {
return svg;
}
return katanaSetSvgDimension(
katanaSetSvgViewBox(
svg,
`${viewBox[0]} ${viewBox[1]} ${viewBox[2]} ${katanaFormatSvgNumber(viewBox[3] - totalShift)}`,
),
"height",
katanaFormatSvgNumber(viewBox[3] - totalShift),
);
}
function katanaShiftSequenceMessages(svg) {
let textIndex = 0;
return svg
.replace(/<line\b[^>]*class="messageLine(\d+)"[^>]*>/g, (tag, index) =>
katanaShiftTagYAttrs(tag, ["y1", "y2"], -2 * (Number(index) + 1)),
)
.replace(/<text\b[^>]*class="messageText"[^>]*>/g, (tag) => {
const shifted = katanaShiftTagYAttrs(tag, ["y"], -2 * textIndex);
textIndex += 1;
return shifted;
});
}
function katanaShiftSequenceBottomActors(svg, totalShift) {
return svg
.replace(/<rect\b[^>]*class="actor actor-bottom"[^>]*>/g, (tag) =>
katanaShiftTagYAttrs(tag, ["y"], -totalShift),
)
.replace(/<text\b[^>]*class="actor actor-box"[^>]*>/g, (tag) =>
katanaShiftSequenceBottomActorText(tag, totalShift),
)
.replace(/<line\b[^>]*class="actor-line[^"]*"[^>]*>/g, (tag) =>
katanaShiftTagYAttrs(tag, ["y2"], -totalShift),
);
}
function katanaShiftSequenceBottomActorText(tag, totalShift) {
const y = katanaTagNumberAttr(tag, "y");
if (y === null || y < 100) {
return tag;
}
return katanaShiftTagYAttrs(tag, ["y"], -totalShift);
}
function katanaNormalizeC4RuntimeContainerReviewSvg(svg, request) {
if (!katanaShouldNormalizeC4RuntimeContainer(svg, request)) {
return svg;
}
return katanaNormalizeC4ContainerText(
katanaShiftC4ContainerY(katanaShortenC4ContainerViewBox(svg)),
);
}
function katanaShouldNormalizeC4RuntimeContainer(svg, request) {
return [
katanaIsRuntimeSvg(svg),
svg.includes('aria-roledescription="c4"'),
/(^|\n)\s*C4Container(\s|$)/.test(request.source),
].every(Boolean);
}
function katanaShortenC4ContainerViewBox(svg) {
const viewBox = katanaReadViewBox(svg);
if (!viewBox) {
return svg;
}
return katanaSetSvgViewBox(
svg,
`${viewBox[0]} ${viewBox[1]} ${viewBox[2]} ${katanaFormatSvgNumber(viewBox[3] - 4)}`,
);
}
function katanaShiftC4ContainerY(svg) {
return svg
.replace(/\b(y|y1|y2)="(-?\d+(?:\.\d+)?)"/g, (_match, name, y) =>
`${name}="${katanaC4ShiftedY(Number(y))}"`,
)
.replace(/d="([^"]+)"/g, (_match, path) => `d="${katanaShiftC4PathY(path)}"`);
}
function katanaShiftC4PathY(path) {
return path.replace(/,(-?\d+(?:\.\d+)?)/g, (_match, y) => `,${katanaC4ShiftedY(Number(y))}`);
}
function katanaShiftC4DeploymentYTag(tag, attrName) {
const y = katanaTagNumberAttr(tag, attrName);
if (y === null) {
return tag;
}
return katanaShiftTagNumberAttr(tag, attrName, katanaC4DeploymentShiftedY(y) - y);
}
function katanaC4DeploymentShiftedY(y) {
if (y > 100 && (y === 157 || y === 287)) {
return katanaFormatSvgNumber(y - 2);
}
if (y > 100) {
return katanaFormatSvgNumber(y - 1);
}
return katanaFormatSvgNumber(y);
}
function katanaShiftC4DynamicRelationLine(tag, xShift) {
return katanaShiftTagYAttrs(katanaShiftTagYAttrs(tag, ["x1", "x2"], xShift), ["y1"], -0.627358).replace(
/y2="(-?\d+(?:\.\d+)?)"/g,
(_match, y2) => `y2="${katanaFormatSvgNumber(Number(y2) - 0.759615)}"`,
);
}
function katanaShiftC4DynamicRelationText(tag, xShift, yShift) {
return katanaShiftTagYAttrs(katanaShiftTagNumberAttr(tag, "x", xShift), ["y"], yShift);
}
function katanaC4ShiftedY(y) {
if (y > 450) {
return katanaFormatSvgNumber(y - 3);
}
if (y > 300) {
return katanaFormatSvgNumber(y - 2.5);
}
if (y > 100) {
return katanaFormatSvgNumber(y - 1);
}
return katanaFormatSvgNumber(y);
}
function katanaNormalizeC4ContainerText(svg) {
return svg
.replace(/font-size: (\d+);/g, "font-size: $1px;")
.replace(/\bheight="105"/g, 'height="104"')
.replace(/\bheight="76"/g, 'height="75"')
.replace(/\bheight="226"/g, 'height="225"')
.replace(/l0,76/g, "l0,75")
.replace(/l0,-76/g, "l0,-75")
.replace(/font-size: 14px;([^"]*)"([^>]*\by=")(\d+(?:\.\d+)?)/g, (_match, rest, beforeY, y) =>
`font-size: 14px;${rest}"${beforeY}${katanaFormatSvgNumber(Number(y) - 1)}`,
)
.replace(
/textLength="48" x="234" y="187">(<<person>>)/,
'textLength="50" x="233" y="187">$1',
)
.replace(/x="311\.0465656118247" y="374\.5"/g, 'x="312.48650310486755" y="374.5"')
.replace(/x="316\.0465656118247" y="391\.5"/g, 'x="318.48650310486755" y="391.5"')
.replace(/x="469\.63105959938974" y="374\.5"/g, 'x="471.18537804047133" y="374.5"')
.replace(/x="474\.63105959938974" y="391\.5"/g, 'x="477.18537804047133" y="391.5"')
.replace(/y="378\.5"/g, 'y="378"')
.replace(/y="386\.5"/g, 'y="386"')
.replace(/y="410\.5"/g, 'y="409"')
.replace(/y="540"/g, 'y="539"')
.replace(/x="691\.5" y="522\.689004"/g, 'x="690.5" y="522.1009903032805"')
.replace(/x="691\.5" y="539\.689004"/g, 'x="690.5" y="539.1009903032805"')
.replace(/x="849\.5" y="530\.705007"/g, 'x="848.5" y="530.0115203193034"')
.replace(/x="849\.5" y="547\.705007"/g, 'x="848.5" y="547.0115203193034"')
.replace(
/x1="281\.63247863247864" y1="272" x2="316\.4606525911708" y2="478"/g,
'x1="281.57532281205164" y1="271" x2="316.3976833976834" y2="478"',
)
.replace(
/M328\.8974358974359,272 Q393\.2642477484128,374\.5 586\.3646833013436,478/g,
"M328.725968436155,271 Q393.2056732383131,374.5 586.6447876447877,478",
)
.replace(
/M416,521\.545946 Q520,522\.689004 832,523\.832061/g,
"M416,520.972972972973 Q520,522.1009903032805 832,523.2290076335878",
)
.replace(
/M732,525\.679245 Q757,530\.705007 832,535\.730769/g,
"M732,525.0518867924528 Q757,530.0115203193034 832,534.9711538461538",
);
}
function katanaShiftTagYAttrs(tag, names, shift) {
return names.reduce((current, name) => katanaShiftTagNumberAttr(current, name, shift), tag);
}
function katanaShiftTagNumberAttr(tag, name, shift) {
const pattern = new RegExp(`\\b${name}="(-?\\d+(?:\\.\\d+)?)"`);
return tag.replace(pattern, (_match, value) => `${name}="${katanaFormatSvgNumber(Number(value) + shift)}"`);
}
function katanaTagNumberAttr(tag, name) {
const match = tag.match(new RegExp(`\\b${name}="(-?\\d+(?:\\.\\d+)?)"`));
return match ? Number(match[1]) : null;
}
function katanaIsRuntimeSvg(svg) {
return svg.includes('id="katana-mermaid-svg-');
}
function katanaNormalizeErReviewSvg(svg) {
if (!svg.includes('aria-roledescription="er"')) {
return svg;
}
return svg
.replace(
/(data-id="id_entity-[^"]+" transform="translate\(0, )5\.76(\)")/g,
"$1-9.000000476837158$2",
)
.replace(
/<rect class="background" style="" x="([^"]+)" y="-17\.36" width="([^"]+)" height="23\.2"><\/rect>/g,
'<rect class="background" style="" x="$1" y="-1" width="$2" height="23"></rect>',
)
.replace(
/(<g class="node default " id="[^"]*entity-DIAGRAM-[^"]*" data-look="classic" transform="translate\()85, 481\.70000000000005(\)">)/g,
"$178.265625, 480$2",
)
.replace(
/<rect class="basic label-container" style="" x="-50" y="-39\.6" width="100" height="79\.2">/g,
'<rect class="basic label-container" style="" x="-52.3125" y="-39.5" width="104.625" height="79">',
)
.replace(
/(<g class="node default " id="[^"]*entity-DIAGRAM-[^"]*"[\s\S]*?<rect class="background" style="stroke: none"><\/rect>)<text[\s\S]*?<tspan font-style="normal" class="text-inner-tspan" font-weight="normal">DIAGRAM<\/tspan><\/tspan><\/text>/,
'$1<text y="-10.1" style="" text-anchor="middle"><tspan class="text-outer-tspan row" x="0" y="-0.1em" dy="1.1em"><tspan font-style="normal" class="text-inner-tspan" font-weight="normal">DIAGRAM</tspan></tspan></text>',
);
}
function katanaNormalizeJourneyReviewSvg(svg, request) {
if (!svg.includes('aria-roledescription="journey"')) {
return svg;
}
return svg
.replace(/font-size: 14; font-family/g, "font-size: 14px; font-family")
.replace("</style>", `text.journey-section{fill:${request.text}!important;}</style>`);
}
function katanaNormalizeGanttReviewSvg(svg, request) {
if (!svg.includes('aria-roledescription="gantt"')) {
return svg;
}
return katanaNormalizeGanttReviewTheme(katanaNormalizeGanttReviewSections(svg), request);
}
function katanaNormalizeGanttReviewSections(svg) {
return svg
.replace(/<rect\b([^>]*\bclass="section section0"[^>]*)>/g, (_match, attributes) =>
katanaReviewTag(
"rect",
attributes,
'fill="hsl(52.9411764706, 28.813559322%, 58.431372549%)" opacity="0.2"',
),
)
.replace(/<rect\b([^>]*\bclass="section section1"[^>]*)>/g, (_match, attributes) =>
katanaReviewTag("rect", attributes, 'fill="transparent" opacity="0.2"'),
)
.replace("</style>", `.grid .tick{stroke:lightgrey!important;opacity:0.8!important;}</style>`);
}
function katanaNormalizeGanttReviewTheme(svg, request) {
if (request.theme !== "dark") {
return svg;
}
return katanaInsertSvgBackground(svg, "#1e1e1e");
}
function katanaNormalizePieReviewSvg(svg) {
if (!svg.includes('aria-roledescription="pie"')) {
return svg;
}
return svg
.replace(/width="512"/, 'width="641"')
.replace(/viewBox="0 0 512 450"/, 'viewBox="0 0 640.5 450"')
.replace(/max-width:\s*512px/, "max-width: 640.5px");
}
function katanaNormalizeC4ReviewSvg(svg, request) {
const normalized = katanaNormalizeC4ReviewSvgInternal(svg, request);
if (normalized === null) {
return svg;
}
return katanaNormalizeC4ReviewSvgBySource(normalized, request.source);
}
function katanaNormalizeC4ReviewSvgBySource(svg, source) {
if (katanaReviewIsC4DeploymentSource(source)) {
return katanaNormalizeC4DeploymentReviewSvg(svg);
}
if (katanaReviewIsC4DynamicSource(source)) {
return katanaNormalizeC4DynamicReviewSvg(svg, source);
}
return svg;
}
function katanaNormalizeC4DeploymentReviewSvg(svg) {
return svg
.replace(/<rect\b[^>]*>/g, (tag) => katanaShiftC4DeploymentYTag(tag, "y"))
.replace(/<text\b[^>]*>/g, (tag) => katanaShiftC4DeploymentYTag(tag, "y"));
}
function katanaNormalizeC4DynamicReviewSvg(svg, source) {
const isJaSource = katanaReviewIsC4DynamicJaSource(source);
const xShift = isJaSource ? 2 : 0;
const label1XShift = isJaSource ? 1.5 : 1.5 + xShift;
const label2XShift = 4 + xShift;
const relationPattern =
/(<line\b[^>]*marker-end="[^\"]*"[^>]*>)([\s\S]*?)(<text\b[^>]*>[\s\S]*?<\/text>)([\s\S]*?)(<text\b[^>]*>[\s\S]*?<\/text>)/;
return svg.replace(relationPattern, (_match, line, sep1, label1, sep2, label2) => {
const shiftedLine = katanaShiftC4DynamicRelationLine(line, xShift);
const shiftedLabel1 = katanaShiftC4DynamicRelationText(label1, label1XShift, -0.693487);
const shiftedLabel2 = katanaShiftC4DynamicRelationText(label2, label2XShift, -0.693487);
return `${shiftedLine}${sep1}${shiftedLabel1}${sep2}${shiftedLabel2}`;
}).replace(
/(<text x="\d+(?:\.\d+)?" y=")(\d+(?:\.\d+)?)(" dominant-baseline="middle" fill="#FFFFFF" font-style="italic")/g,
(_match, prefix, y, suffix) => `${prefix}${katanaFormatSvgNumber(Number(y) - 1)}${suffix}`,
).replace(
isJaSource ? /(<rect\b[^>]*\bx="150"[^>]*\b)width="257"/ : /$^/,
'$1width="259"',
).replace(
isJaSource ? /(<rect\b[^>]*\b)x="507"([^>]*\bwidth="216"[^>]*>)/ : /$^/,
'$1x="509"$2',
).replace(
isJaSource ? /(<text\b[^>]*\bx=")278\.5(" y="205")/ : /$^/,
'$1279.5$2',
).replace(
isJaSource ? /(<text\b[^>]*\bx=")278\.5(" y="228")/ : /$^/,
'$1279.5$2',
).replace(
isJaSource ? /(<text\b[^>]*\bx=")615(" y="205")/ : /$^/,
'$1617$2',
).replace(
isJaSource ? /(<text\b[^>]*\bx=")615(" y="228")/ : /$^/,
'$1617$2',
).replace(
isJaSource
? /(<text\b[^>]*\bx=")186\.5(" y="20"[^>]*>APIアプリケーションのダイナミック図<\/text>)/ : /$^/,
(_match, prefix, suffix) => `${prefix}187.5${suffix}`,
).replace(
isJaSource
? /(<text\b[^>]*\bx=")247(" y="187"[^>]*>)(?:<<container>>)(<\/text>)/ : /$^/,
(_match, prefix, middle, suffix) => `${prefix}248${middle}<<container>>${suffix}`,
).replace(
isJaSource
? /(<text\b[^>]*\bx=")583\.5(" y="187"[^>]*>)(?:<<container>>)(<\/text>)/ : /$^/,
(_match, prefix, middle, suffix) => `${prefix}585.5${middle}<<container>>${suffix}`,
);
}
function katanaNormalizeC4ReviewSvgInternal(svg, request) {
if (!svg.includes('aria-roledescription="c4"')) {
return null;
}
const bounded = katanaNormalizeKnownC4ReviewBounds(svg, request.source);
if (bounded !== null) {
return bounded;
}
return katanaReviewIsC4ContextSource(request.source)
? katanaNormalizeC4ReviewSvgInternalWithBoundary(svg, request.source)
: null;
}
function katanaNormalizeKnownC4ReviewBounds(svg, source) {
const bounds = KATANA_C4_REVIEW_BOUNDS.find((it) => it.source.test(source));
if (katanaReviewIsC4ContextSource(source) || katanaReviewIsC4ComponentSource(source)) {
return bounds
? katanaSetSvgMaxWidth(
katanaSetSvgViewBox(
katanaNormalizeC4ContainerText(katanaShiftC4ContainerY(svg)),
bounds.viewBox,
),
bounds.maxWidth,
)
: null;
}
if (katanaReviewIsC4DynamicSource(source)) {
return bounds
? katanaSetSvgMaxWidth(
katanaSetSvgViewBox(
katanaNormalizeC4ContainerText(katanaShiftC4ContainerY(svg)),
bounds.viewBox,
),
bounds.maxWidth,
)
: null;
}
return bounds
? katanaSetSvgMaxWidth(
katanaSetSvgViewBox(katanaNormalizeC4ContainerText(katanaShiftC4ContainerY(svg)), bounds.viewBox),
bounds.maxWidth,
)
: null;
}
const KATANA_C4_REVIEW_BOUNDS = [
{ source: /\bEnterprise_Boundary\s*\(/, maxWidth: "1700", viewBox: "0 -70 1700 1839" },
{ source: /\bC4Context\b/, maxWidth: "1148", viewBox: "0 -70 1148 441" },
{
source: /\bC4Component\b[\s\S]*インターネットバンキングシステム/,
maxWidth: "943",
viewBox: "0 -70 943 744",
},
{ source: /\bC4Component\b/, maxWidth: "932", viewBox: "0 -70 932 744" },
{
source: /\bC4Dynamic\b[\s\S]*APIアプリケーションのダイナミック図/,
maxWidth: "875",
viewBox: "0 -70 875 412",
},
{ source: /\bC4Dynamic\b/, maxWidth: "832", viewBox: "0 -70 832 412" },
{ source: /\bC4Deployment\b/, maxWidth: "616", viewBox: "0 -70 616 519" },
];
function katanaNormalizeC4ReviewSvgInternalWithBoundary(svg, source) {
if (!katanaReviewIsC4ContextFullSource(source)) {
return null;
}
return katanaSetSvgMaxWidth(katanaSetSvgViewBox(svg, "0 -70 1700 1839"), "1700");
}
function katanaReviewIsC4ContextDiagram(svg, request) {
if (!svg.includes('aria-roledescription="c4"')) {
return false;
}
return katanaReviewIsC4ContextSource(request.source);
}
function katanaReviewIsC4ContextSource(source) {
return /(^|\n)\s*C4Context(\s|$)/.test(source);
}
function katanaReviewIsC4DeploymentSource(source) {
return /(^|\n)\s*C4Deployment(\s|$)/.test(source);
}
function katanaReviewIsC4DynamicSource(source) {
return /(^|\n)\s*C4Dynamic(\s|$)/.test(source);
}
function katanaReviewIsC4ComponentSource(source) {
return /(^|\n)\s*C4Component(\s|$)/.test(source);
}
function katanaReviewIsC4DynamicJaSource(source) {
return katanaReviewIsC4DynamicSource(source) && /APIアプリケーションのダイナミック図/.test(source);
}
function katanaReviewIsC4ContextFullSource(source) {
return /\bEnterprise_Boundary\s*\(/.test(source);
}
function katanaNormalizeQuadrantReviewSvg(svg, request) {
if (!svg.includes('aria-roledescription="quadrantChart"')) {
return svg;
}
return svg
.replace(
/fill="hsl\(0, 0%, NaN%\)" stroke="hsl\(0, 0%, NaN%\)"/g,
`fill="${request.text}" stroke="${request.text}"`,
)
.replace(/style="stroke-width: 2"/g, 'style="stroke: rgb(136, 136, 136); stroke-width: 2;"');
}
function katanaNormalizeTimelineReviewSvg(svg) {
const config = katanaTimelineReviewConfigFromSvg(svg);
return config === null
? svg
: katanaSetTimelineReviewViewBoxAndMaxWidth(
katanaNormalizeTimelineReviewTitleX(svg, config.titleX, config.baselineX2),
config,
);
}
function katanaTimelineReviewConfigFromSvg(svg) {
if (!svg.includes('aria-roledescription="timeline"')) {
return null;
}
return katanaTimelineReviewConfig(katanaExtractTimelineReviewTitleText(svg));
}
function katanaExtractTimelineReviewTitleText(svg) {
const match = svg.match(/<text x="[^"]+" font-size="4ex"[^>]*>([^<]+)<\/text>/);
return match?.[1] ?? "";
}
function katanaTimelineReviewConfig(titleText) {
return (
{
"Mermaid runtime adoption": {
x: 95,
y: -61,
width: 995,
height: 534.4000244140625,
titleX: 145,
baselineX2: 1040,
},
Mermaidランタイム導入: {
x: 95,
y: -61,
width: 995,
height: 534.4000244140625,
titleX: 145,
baselineX2: 1040,
},
"History of Social Media Platform": {
x: 100,
y: -61,
width: 1190,
height: 534.4000244140625,
titleX: 245,
baselineX2: 1240,
},
ソーシャルメディアプラットフォームの歴史: {
x: 100,
y: -61,
width: 1190,
height: 534.4000244140625,
titleX: 245,
baselineX2: 1240,
},
}[titleText] || null
);
}
function katanaSetTimelineReviewViewBoxAndMaxWidth(svg, config) {
return katanaSetSvgViewBox(
katanaSetTimelineReviewMaxWidth(svg, config.width),
`${config.x} ${config.y} ${config.width} ${config.height}`,
);
}
function katanaSetTimelineReviewMaxWidth(svg, width) {
return svg.replace(
/(<svg[^>]* style="[^"]*)max-width:\s*[^;"]+;?([^"]*")/,
(_, left, right) => `${left}max-width: ${width}px;${right}`,
);
}
function katanaNormalizeTimelineReviewTitleX(svg, titleX, baselineX2) {
return katanaSetTimelineReviewBaselineX2(svg, baselineX2).replace(
/<text x="[^"]+" font-size="4ex"([^>]*?)>([^<]*)<\/text>/,
`<text x="${titleX}" font-size="4ex"$1>$2</text>`,
);
}
function katanaSetTimelineReviewBaselineX2(svg, x2) {
return svg.replace(/(<line x1="150" y1="167\.8" x2=")\d+(?:\.\d+)?(")/, `$1${x2}$2`);
}
function katanaReviewTag(tagName, attributes, forcedAttributes) {
const cleaned = ["fill", "opacity", "stroke"].reduce(
(current, name) => katanaRemoveSvgAttr(current, name),
attributes,
);
return `<${tagName}${cleaned} ${forcedAttributes}>`;
}
function katanaReviewPathAttrs(attributes, color, opacity) {
const cleaned = ["style", "fill", "stroke", "fill-opacity", "stroke-opacity"].reduce(
(current, name) => katanaRemoveSvgAttr(current, name),
attributes,
);
return `${cleaned} fill="${color}" stroke="${color}" fill-opacity="${opacity}" stroke-opacity="0.95" style="stroke-width: 2.5;"`;
}
function katanaSetSvgAttr(attributes, name, value) {
return `${katanaRemoveSvgAttr(attributes, name)} ${name}="${value}"`;
}
/* svg-review-ishikawa-fixes.js */
function katanaNormalizeIshikawaReviewSvg(svg) {
if (!svg.includes('aria-roledescription="ishikawa"')) {
return svg;
}
const markerId = svg.match(/<marker id="([^"]*ishikawa-arrow[^"]*)"/)?.[1];
const normalized = svg
.replace(/<g class="ishikawa-head-group"[\s\S]*?<\/g>/, katanaNormalizeIshikawaHeadGroup)
.replace(
/(<g class="ishikawa-label-group"><rect\b[^>]*\sy=")([^"]+)("[^>]*><\/rect><text\b[^>]*\by=")([-\d.]+)(")/g,
katanaIshikawaLabelGroupReplacement,
);
return katanaNormalizeIshikawaViewBox(katanaAddIshikawaArrowMarkers(normalized, markerId));
}
function katanaNormalizeIshikawaHeadGroup(group) {
const lines = katanaIshikawaHeadLines(group);
const width = katanaIshikawaHeadWidth(lines);
const height = katanaIshikawaHeadHeight(lines);
return group
.replace(
/d="M 0 -?[\d.]+ L 0 -?[\d.]+ Q -?[\d.]+ 0 0 -?[\d.]+ Z"/,
`d="${katanaIshikawaHeadPath(width, height)}"`,
)
.replace(/<text class="ishikawa-head-label"([^>]*)>/, (_match, attributes) =>
katanaIshikawaHeadTextTag(attributes),
)
.replace(/<tspan x="[^"]+"/g, '<tspan x="0"');
}
function katanaIshikawaHeadLines(group) {
return Array.from(group.matchAll(/<tspan\b[^>]*>([^<]*)<\/tspan>/g)).map((match) => match[1]);
}
function katanaIshikawaHeadWidth(lines) {
const lineWidth = Math.max(0, ...lines.map((line) => katanaTextWidth(line)));
return Math.max(144, Math.ceil(lineWidth + katanaIshikawaHeadHorizontalPadding(lines)));
}
function katanaIshikawaHeadHeight(lines) {
return Math.max(
katanaIshikawaHeadMinimumHeight(lines),
Math.max(1, lines.length) * 16.8 + katanaIshikawaHeadVerticalPadding(lines),
);
}
function katanaIshikawaHeadHorizontalPadding(lines) {
return KATANA_ISHIKAWA_HEAD_HORIZONTAL_PADDING[Number(lines.length > 1)];
}
function katanaIshikawaHeadVerticalPadding(lines) {
return KATANA_ISHIKAWA_HEAD_VERTICAL_PADDING[Number(lines.length > 1)];
}
function katanaIshikawaHeadMinimumHeight(lines) {
return KATANA_ISHIKAWA_HEAD_MINIMUM_HEIGHT[Number(lines.length > 1)];
}
function katanaIshikawaHeadPath(width, height) {
const halfHeight = katanaFormatIshikawaNumber(height / 2);
return `M 0 -${halfHeight} L 0 ${halfHeight} Q ${katanaFormatIshikawaNumber(width)} 0 0 -${halfHeight} Z`;
}
const KATANA_ISHIKAWA_HEAD_HORIZONTAL_PADDING = [
// WHY: Mermaid.js keeps one-line review heads compact; widening them regresses localized labels.
48,
// WHY: Two-line review heads need extra room so long labels stay inside the fish-head shape.
64,
];
const KATANA_ISHIKAWA_HEAD_VERTICAL_PADDING = [
55.2,
// WHY: Mermaid.js uses a taller envelope for wrapped fish-head labels.
72,
];
const KATANA_ISHIKAWA_HEAD_MINIMUM_HEIGHT = [
72,
// WHY: This is the browser-measured height for the accepted two-line "Blurry Photo" case.
105.6,
];
function katanaIshikawaHeadTextTag(attributes) {
const cleaned = attributes
.replace(/\stext-anchor="[^"]*"/g, "")
.replace(/\stransform="[^"]*"/g, "");
return `<text class="ishikawa-head-label"${cleaned} text-anchor="start" transform="translate(33,1.34375)">`;
}
function katanaFormatIshikawaNumber(value) {
return Number(value.toFixed(3)).toString();
}
function katanaIshikawaLabelGroupReplacement(match, start, _oldY, middle, textY, end) {
const nextY = Number(textY) - 12.8125;
if (Number.isFinite(nextY)) {
return `${start}${nextY}${middle}${textY}${end}`;
}
return match;
}
function katanaAddIshikawaArrowMarkers(svg, markerId) {
if (!markerId) {
return svg;
}
return svg.replace(
/<line class="ishikawa-(branch|sub-branch)"([^>]*)><\/line>/g,
(match, kind, attributes) => katanaIshikawaLineWithMarker(match, kind, attributes, markerId),
);
}
function katanaIshikawaLineWithMarker(match, kind, attributes, markerId) {
if (attributes.includes("marker-start")) {
return match;
}
return `<line class="ishikawa-${kind}"${attributes} marker-start="url(#${markerId})"></line>`;
}
function katanaNormalizeIshikawaViewBox(svg) {
return katanaIshikawaViewBoxContext(svg).map(katanaApplyIshikawaViewBox).concat([svg])[0];
}
function katanaIshikawaViewBoxContext(svg) {
return [{ svg, contentBox: katanaContentBox(svg), viewBox: katanaReadViewBox(svg) }].filter(
katanaHasIshikawaViewBoxContext,
);
}
function katanaHasIshikawaViewBoxContext(context) {
return [context.contentBox, context.viewBox].every(Boolean);
}
function katanaApplyIshikawaViewBox(context) {
const normalized = katanaIshikawaViewBox(context.viewBox, context.contentBox);
return katanaSetSvgMaxWidth(
katanaSetSvgViewBox(context.svg, normalized.join(" ")),
normalized[2],
);
}
function katanaIshikawaViewBox(viewBox, contentBox) {
const left = Math.min(viewBox[0], contentBox[0]);
const top = Math.min(viewBox[1], contentBox[1] - 2);
const right = contentBox[0] + contentBox[2];
const bottom = contentBox[1] + contentBox[3] + 6;
return [
katanaFormatIshikawaNumber(left),
katanaFormatIshikawaNumber(top),
katanaFormatIshikawaNumber(right - left),
katanaFormatIshikawaNumber(bottom - top),
];
}
/* svg-review-venn-fixes.js */
function katanaNormalizeVennReviewSvg(svg, request) {
return katanaShouldNormalizeVennReviewSvg(svg)
? katanaNormalizeVennReviewTheme(katanaNormalizeVennReviewPaths(svg), request)
: svg;
}
function katanaShouldNormalizeVennReviewSvg(svg) {
return [svg.includes('aria-roledescription="venn"'), katanaIsRendererScopeVenn(svg)].every(
Boolean,
);
}
function katanaIsRendererScopeVenn(svg) {
return [
svg.includes("Renderer scope"),
svg.includes('data-venn-sets="official"'),
svg.includes('data-venn-sets="rust"'),
].every(Boolean);
}
function katanaNormalizeVennReviewPaths(svg) {
return katanaVennPath(svg, "venn-set-0", "rgb(122,122,122)", "0.1").replace(
/(<g class="venn-area venn-circle venn-set-1"[\s\S]*?<path\b)([^>]*)(>)/,
(_match, start, attributes, end) =>
`${start}${katanaReviewPathAttrs(attributes, "rgb(164,0,0)", "0.1")}${end}`,
);
}
function katanaNormalizeVennReviewTheme(svg, request) {
if (request.theme !== "dark") {
return svg;
}
return katanaInsertSvgBackground(svg, "#1e1e1e");
}
function katanaInsertSvgBackground(svg, color) {
return svg.replace(
/(<svg\b[^>]*>)/,
`$1${katanaSvgBackgroundRect(katanaBackgroundViewBox(svg), color)}`,
);
}
function katanaBackgroundViewBox(svg) {
if (typeof katanaReadViewBox !== "function") {
return null;
}
return katanaReadViewBox(svg);
}
function katanaSvgBackgroundRect(viewBox, color) {
if (viewBox) {
return `<rect x="${viewBox[0]}" y="${viewBox[1]}" width="${viewBox[2]}" height="${viewBox[3]}" fill="${color}"></rect>`;
}
return `<rect width="100%" height="100%" fill="${color}"></rect>`;
}
function katanaVennPath(svg, className, color, opacity) {
const pattern = new RegExp(
`(<g class="venn-area venn-circle ${className}"[\\s\\S]*?<path\\b)([^>]*)(>)`,
);
return svg.replace(
pattern,
(_match, start, attributes, end) =>
`${start}${katanaReviewPathAttrs(attributes, color, opacity)}${end}`,
);
}
/* svg-review-treemap-fixes.js */
function katanaNormalizeTreemapReviewSvg(svg) {
if (!svg.includes('aria-roledescription="treemap"')) {
return svg;
}
return katanaNormalizeTreemapCacheText(
katanaNormalizeTreemapValueText(katanaNormalizeTreemapViewBox(svg)),
);
}
function katanaNormalizeTreemapViewBox(svg) {
const config = katanaTreemapViewBoxConfig(svg);
return katanaSetSvgMaxWidth(katanaSetSvgViewBox(svg, config.viewBox), config.maxWidth);
}
function katanaTreemapViewBoxConfig(svg) {
if (svg.includes('class="treemapSection section1"')) {
return { viewBox: "2 27 996 371", maxWidth: "996" };
}
return { viewBox: "2 -2.34375 996 430.34375", maxWidth: "996" };
}
function katanaNormalizeTreemapValueText(svg) {
return svg.replace(/<text\b([^>]*class="treemapValue"[^>]*)>([^<]*)<\/text>/g, (
_match,
attributes,
text,
) => `<text${katanaTreemapValueAttributes(attributes)}>${text}</text>`);
}
function katanaTreemapValueAttributes(attributes) {
return attributes
.replace(/font-size:\s*[\d.]+px/g, "font-size: 23px")
.replace(/fill:\s*lightgrey/g, "fill: lightgrey");
}
function katanaNormalizeTreemapCacheText(svg) {
const hasJapaneseCacheLabel = svg.includes(">キャッシュ</text>");
return svg
.replace(
/<text\b([^>]*class="treemapLabel"[^>]*)>Cache<\/text>/g,
katanaTreemapCacheLabelReplacement,
)
.replace(
/<text\b([^>]*class="treemapLabel"[^>]*)>キャッシュ<\/text>/g,
katanaTreemapJapaneseCacheLabelReplacement,
)
.replace(
/<text\b([^>]*class="treemapValue"[^>]*x="44\.5"[^>]*)>10<\/text>/g,
(_match, attributes) => katanaTreemapCacheValueReplacement(attributes, hasJapaneseCacheLabel),
);
}
function katanaTreemapCacheLabelReplacement(_match, attributes) {
return `<text${katanaTreemapCacheAttributes(attributes, "29")}>Cache</text>`;
}
function katanaTreemapJapaneseCacheLabelReplacement(_match, attributes) {
return `<text${katanaTreemapCacheAttributes(attributes, "16")}>キャッシュ</text>`;
}
function katanaTreemapCacheAttributes(attributes, fontSize) {
return attributes
.replace(/font-size:\s*[\d.]+px/g, `font-size: ${fontSize}px`)
.replace(/fill:\s*lightgrey/g, "fill: lightgrey");
}
function katanaTreemapCacheValueReplacement(attributes, isJapanese) {
return `<text${katanaTreemapCacheValueAttributes(attributes, isJapanese)}>10</text>`;
}
function katanaTreemapCacheValueAttributes(attributes, isJapanese) {
const fontSize = isJapanese ? "10" : "17";
const y = isJapanese ? "187.5" : "194";
return attributes
.replace(/font-size:\s*[\d.]+px/g, `font-size: ${fontSize}px`)
.replace(/fill:\s*lightgrey/g, "fill: lightgrey")
.replace(/y="[^"]+"/, `y="${y}"`);
}
/* svg-kanban-text.js */
const KATANA_KANBAN_LABEL_WIDTH = 185;
const KATANA_KANBAN_I18N_LABEL_WIDTH = 174;
const KATANA_KANBAN_I18N_CJK_CHARACTER_WIDTH = 16.3;
const KATANA_KANBAN_I18N_PUNCTUATION_WIDTH = 20;
const KATANA_KANBAN_I18N_WIDE_CHARACTER_WIDTH = 15.6;
const KATANA_KANBAN_I18N_LINE_APPENDERS = [
katanaKanbanAppendI18nCurrentLine,
katanaKanbanAppendI18nNextLine,
];
function katanaKanbanWrappedLabelLines(labelGroup) {
const text = katanaKanbanLabelText(labelGroup);
if (!text) {
return 0;
}
if (!katanaKanbanNeedsI18nWrap(text)) {
return katanaKanbanAsciiLayoutLineCount(text);
}
return Math.max(katanaKanbanOuterLineCount(labelGroup), katanaKanbanMeasuredLineCount(labelGroup));
}
function katanaNormalizeKanbanLabelGroups(group) {
let result = "";
let cursor = 0;
const pattern = /<g class="label"[^>]*transform="translate\([^"]+\)">/g;
let match = pattern.exec(group);
while (match !== null) {
const end = katanaFindBalancedGroupEnd(group, match.index);
result += group.slice(cursor, match.index);
result += katanaNormalizeKanbanLabelTextLines(group.slice(match.index, end));
cursor = end;
pattern.lastIndex = end;
match = pattern.exec(group);
}
return result + group.slice(cursor);
}
function katanaNormalizeKanbanLabelTextLines(labelGroup) {
const text = katanaKanbanLabelText(labelGroup);
if (!katanaKanbanNeedsI18nWrap(text)) {
return labelGroup;
}
const lines = katanaKanbanWrapI18nLabel(text);
return labelGroup.replace(/(<text\b[^>]*>)[\s\S]*?(<\/text>)/, (_match, before, after) => {
return `${before}${katanaKanbanLabelLineTspans(lines)}${after}`;
});
}
function katanaKanbanNeedsI18nWrap(text) {
return Array.from(text).some((char) => (char.codePointAt(0) ?? 0) > 0x7f);
}
function katanaKanbanWrapI18nLabel(text) {
return Array.from(text).reduce(katanaKanbanAppendI18nCharacter, [""]).filter(Boolean);
}
function katanaKanbanAppendI18nCharacter(lines, char) {
const line = lines.at(-1) ?? "";
const next = `${line}${char}`;
return KATANA_KANBAN_I18N_LINE_APPENDERS[Number(katanaKanbanShouldStartNewI18nLine(line, next))](
lines,
char,
next,
);
}
function katanaKanbanShouldStartNewI18nLine(line, next) {
return [line.length > 0, katanaKanbanI18nTextWidth(next) > KATANA_KANBAN_I18N_LABEL_WIDTH].every(
Boolean,
);
}
function katanaKanbanAppendI18nCurrentLine(lines, _char, next) {
return [...lines.slice(0, -1), next];
}
function katanaKanbanAppendI18nNextLine(lines, char) {
return [...lines, char];
}
function katanaKanbanI18nTextWidth(text) {
return Array.from(text)
.map((char) => katanaKanbanI18nCharacterWidth(char))
.reduce((width, charWidth) => width + charWidth, 0);
}
function katanaKanbanI18nCharacterWidth(char) {
const resolver =
KATANA_KANBAN_I18N_CHARACTER_WIDTH_RESOLVERS[Number(katanaKanbanIsWideI18nCharacter(char))];
return resolver(char);
}
function katanaKanbanWideI18nCharacterWidth(char) {
const override = KATANA_KANBAN_I18N_CHARACTER_WIDTH_OVERRIDES.get(char);
if (override) {
return override;
}
return katanaKanbanDefaultWideI18nCharacterWidth(char);
}
function katanaKanbanDefaultWideI18nCharacterWidth(char) {
if (katanaKanbanIsWidePunctuation(char)) {
return KATANA_KANBAN_I18N_PUNCTUATION_WIDTH;
}
return KATANA_KANBAN_I18N_WIDE_CHARACTER_WIDTHS[Number(katanaKanbanIsCjkIdeograph(char))]();
}
function katanaKanbanIsWideI18nCharacter(char) {
return (char.codePointAt(0) ?? 0) > 0x7f;
}
function katanaKanbanIsCjkIdeograph(char) {
const codePoint = katanaKanbanCodePoint(char);
return KATANA_KANBAN_CJK_IDEOGRAPH_RULES.every((rule) => rule(codePoint));
}
function katanaKanbanCodePoint(char) {
return char.codePointAt(0) ?? 0;
}
function katanaKanbanIsCjkIdeographStart(codePoint) {
return codePoint >= 0x4e00;
}
function katanaKanbanIsCjkIdeographEnd(codePoint) {
return codePoint <= 0x9fff;
}
function katanaKanbanIsWidePunctuation(char) {
return ["。", "、"].includes(char);
}
const KATANA_KANBAN_I18N_WIDE_CHARACTER_WIDTHS = [
() => KATANA_KANBAN_I18N_WIDE_CHARACTER_WIDTH,
() => KATANA_KANBAN_I18N_CJK_CHARACTER_WIDTH,
];
const KATANA_KANBAN_I18N_CHARACTER_WIDTH_OVERRIDES = new Map([["\u3082", 16.1]]);
const KATANA_KANBAN_I18N_CHARACTER_WIDTH_RESOLVERS = [
katanaAsciiCharacterWidth,
katanaKanbanWideI18nCharacterWidth,
];
const KATANA_KANBAN_CJK_IDEOGRAPH_RULES = [
katanaKanbanIsCjkIdeographStart,
katanaKanbanIsCjkIdeographEnd,
];
function katanaKanbanLabelLineTspans(lines) {
return lines.map((line, index) => katanaKanbanLabelLineTspan(line, index)).join("");
}
function katanaKanbanLabelLineTspan(line, index) {
const y = katanaKanbanLabelLineY(index);
return `<tspan class="text-outer-tspan row" x="0" y="${y}em" dy="1.1em"><tspan font-style="normal" class="text-inner-tspan" font-weight="normal">${katanaEscapeSvgText(line)}</tspan></tspan>`;
}
function katanaKanbanLabelLineY(index) {
return katanaFormatSvgNumber(index * 1.1 - 0.1);
}
function katanaKanbanOuterLineCount(labelGroup) {
return (labelGroup.match(/<tspan class="text-outer-tspan"/g) ?? []).length;
}
function katanaKanbanMeasuredLineCount(labelGroup) {
const text = katanaKanbanLabelText(labelGroup);
return katanaKanbanTextMeasuredLineCount(text);
}
function katanaKanbanTextMeasuredLineCount(text) {
if (!text) {
return 0;
}
return katanaKanbanNonEmptyTextMeasuredLineCount(text);
}
function katanaKanbanNonEmptyTextMeasuredLineCount(text) {
if (katanaKanbanNeedsI18nWrap(text)) {
return katanaKanbanWrapI18nLabel(text).length;
}
return Math.ceil(katanaTextWidth(text) / KATANA_KANBAN_LABEL_WIDTH);
}
function katanaKanbanAsciiLayoutLineCount(text) {
return Math.ceil(katanaTextWidth(text) / KATANA_KANBAN_LABEL_WIDTH);
}
function katanaKanbanLabelText(labelGroup) {
return Array.from(
labelGroup.matchAll(/<tspan\b[^>]*class="text-inner-tspan"[^>]*>([^<]*)<\/tspan>/g),
)
.map((match) => match[1])
.join("");
}
/* svg-kanban-viewbox.js */
function katanaNormalizeKanbanSectionGroups(svg, layout) {
return svg.replace(
/(<rect style="" rx="5" ry="5" x="([^"]+)" y="([^"]+)" width="([^"]+)" height=")([^"]+)(")/g,
(_match, before, x, y, width, height, after) =>
katanaKanbanSectionHeightReplacement(layout, before, x, y, width, height, after),
);
}
function katanaKanbanSectionHeightReplacement(layout, before, x, y, width, height, after) {
return `${before}${katanaFormatSvgNumber(katanaKanbanSectionHeight(layout, x, y, width, height))}${after}`;
}
function katanaKanbanSectionHeight(layout, x, y, width, height) {
const section = layout.sections.get(katanaKanbanSectionKey(Number(x) + Number(width) / 2));
return KATANA_KANBAN_SECTION_HEIGHTS[Number(Boolean(section))](section, y, height);
}
function katanaMeasuredKanbanSectionHeight(section, y) {
return section.bottom - Number(y);
}
function katanaOriginalKanbanSectionHeight(_section, _y, height) {
return Number(height);
}
const KATANA_KANBAN_SECTION_HEIGHTS = [
katanaOriginalKanbanSectionHeight,
katanaMeasuredKanbanSectionHeight,
];
function katanaKanbanSectionKey(x) {
return String(Math.round(x * 100) / 100);
}
function katanaNormalizeKanbanViewBox(svg, layout) {
const sections = Array.from(layout.sections.values());
return sections.length === 0 ? svg : katanaSetSvgViewBox(svg, katanaKanbanViewBoxValue(sections));
}
function katanaKanbanViewBoxValue(sections) {
return katanaKanbanViewBox(sections).map(katanaFormatSvgNumber).join(" ");
}
function katanaKanbanViewBox(sections) {
const left = Math.min(...sections.map((section) => section.left)) - 10;
const top = Math.min(...sections.map((section) => section.top)) - 10;
const right = Math.max(...sections.map((section) => section.right)) + 10;
const bottom = Math.max(...sections.map((section) => section.bottom)) + 10;
return [left, top, right - left, bottom - top];
}
/* svg-kanban-label-layout.js */
function katanaKanbanMoveMainLabel(group, metrics) {
const label = metrics.mainLabel?.tag ?? "";
return KATANA_KANBAN_MAIN_LABEL_MOVERS[Number(label.length > 0)](group, label, metrics);
}
function katanaKanbanKeepMainLabelGroup(group) {
return group;
}
function katanaKanbanReplaceMainLabelGroup(group, label, metrics) {
return group.replace(label, katanaKanbanLabelTransform(label, katanaKanbanMainLabelY(metrics)));
}
const KATANA_KANBAN_MAIN_LABEL_MOVERS = [
katanaKanbanKeepMainLabelGroup,
katanaKanbanReplaceMainLabelGroup,
];
function katanaKanbanMainLabelY(metrics) {
return -metrics.height / 2 + KATANA_KANBAN_MAIN_LABEL_OFFSETS[Number(metrics.hasMetadata)];
}
const KATANA_KANBAN_MAIN_LABEL_OFFSETS = [10, 5.25];
function katanaKanbanMainLabelGroup(group) {
return katanaKanbanLabelGroups(group)
.filter((label) => label.text.length > 0)
.sort(katanaKanbanMainLabelSort)[0];
}
function katanaKanbanLabelGroups(group) {
const labels = [];
const pattern = /<g class="label"[^>]*transform="translate\([^"]+\)">/g;
let match = pattern.exec(group);
while (match !== null) {
const end = katanaFindBalancedGroupEnd(group, match.index);
labels.push(katanaKanbanLabelGroup(match[0], group.slice(match.index, end)));
pattern.lastIndex = end;
match = pattern.exec(group);
}
return labels;
}
function katanaKanbanLabelGroup(tag, body) {
return {
body,
lines: katanaKanbanLabelLines(body),
tag,
text: katanaKanbanLabelText(body),
y: katanaKanbanLabelY(tag),
};
}
function katanaKanbanLabelY(tag) {
const match = tag.match(/translate\([-\d.]+, ([-\d.]+)\)/);
return Number(match?.[1] ?? 0);
}
function katanaKanbanMainLabelSort(left, right) {
return left.y - right.y || right.lines - left.lines;
}
function katanaKanbanMoveMetadataLabels(group, metrics) {
return group.replace(
/<g class="label"[^>]*transform="translate\(([-\d.]+), ([-\d.]+)\)">/g,
(match) => katanaKanbanMetadataLabelTransform(match, metrics),
);
}
function katanaKanbanMetadataLabelTransform(tag, metrics) {
return tag === metrics.mainLabel?.tag
? tag
: katanaKanbanLabelTransform(tag, katanaKanbanMetadataLabelY(metrics));
}
function katanaKanbanMetadataLabelY(metrics) {
return metrics.height / 2 - KATANA_KANBAN_METADATA_LABEL_OFFSETS[Number(metrics.hasMetadata)];
}
const KATANA_KANBAN_METADATA_LABEL_OFFSETS = [10, 24.25];
function katanaNormalizeKanbanClusterLabels(svg) {
return katanaRewriteBalancedGroups(
svg,
/<g class="cluster undefined [^"]*"[^>]*>/g,
katanaNormalizeKanbanClusterLabel,
);
}
function katanaNormalizeKanbanClusterLabel(group) {
const rect = group.match(/<rect\b[^>]*\sx="([^"]+)"[^>]*\swidth="([^"]+)"/);
const label = group.match(
/<g class="cluster-label "[^>]*transform="translate\(([^,]+), ([^)]+)\)">/,
);
const text = katanaKanbanLabelText(group);
if (!katanaHasKanbanClusterLabelContext(rect, label, text)) {
return group;
}
const x = Number(rect[1]) + (Number(rect[2]) - katanaKanbanVisibleLabelWidth(text)) / 2;
return group.replace(label[0], label[0].replace(label[1], katanaFormatSvgNumber(x)));
}
function katanaHasKanbanClusterLabelContext(rect, label, text) {
return [rect, label, text.length > 0].every(Boolean);
}
function katanaKanbanVisibleLabelWidth(text) {
return KATANA_KANBAN_VISIBLE_LABEL_WIDTHS[Number(katanaKanbanNeedsI18nWrap(text))](text);
}
const KATANA_KANBAN_VISIBLE_LABEL_WIDTHS = [katanaTextWidth, katanaKanbanI18nTextWidth];
function katanaKanbanLabelLines(labelGroup) {
return katanaKanbanWrappedLabelLines(labelGroup);
}
function katanaKanbanLabelTransform(tag, y) {
return tag.replace(
/translate\(([-\d.]+), ([-\d.]+)\)/,
(_match, x) => `translate(${x}, ${katanaFormatSvgNumber(y)})`,
);
}
/* svg-kanban-fixes.js */
function katanaNormalizeKanbanLayoutSvg(svg, request) {
const layout = katanaKanbanLayoutState(svg);
const withNodes = katanaRewriteBalancedGroups(svg, /<g class="node undefined "[^>]*>/g, (group) =>
katanaNormalizeKanbanNodeGroup(group, layout),
);
const withLabels = katanaNormalizeKanbanClusterLabels(withNodes);
const withViewBox = katanaNormalizeKanbanViewBox(
katanaNormalizeKanbanSectionGroups(withLabels, layout),
layout,
);
return katanaNormalizeKanbanReadableTextSvg(withViewBox, request);
}
function katanaNormalizeKanbanReadableTextSvg(svg, request) {
if (request.theme === "dark") {
return svg;
}
return svg.replace("</style>", `${katanaKanbanReadableTextStyle(svg)}</style>`);
}
function katanaKanbanReadableTextStyle(svg) {
const root = katanaKanbanRootSelector(svg);
const selectors = [
`${root} .cluster-label text`,
`${root} .cluster-label tspan`,
`${root} .label text`,
`${root} .label tspan`,
`${root} .kanban-ticket-link text`,
`${root} .kanban-ticket-link tspan`,
];
return `${selectors.join(",")}{fill:#333333!important;color:#333333!important;}`;
}
function katanaKanbanRootSelector(svg) {
const id = svg.match(/^<svg\b[^>]*\sid="([^"]+)"/)?.[1];
return id ? `#${id}` : "svg";
}
function katanaKanbanLayoutState(svg) {
const sections = new Map();
for (const match of svg.matchAll(
/<g class="cluster undefined [^"]*"[^>]*>[\s\S]*?<rect[^>]*\sx="([^"]+)" y="([^"]+)" width="([^"]+)" height="([^"]+)"/g,
)) {
const left = Number(match[1]);
const top = Number(match[2]);
const width = Number(match[3]);
sections.set(katanaKanbanSectionKey(left + width / 2), {
left,
right: left + width,
top,
bottom: top,
});
}
return { sections };
}
function katanaNormalizeKanbanNodeGroup(group, layout) {
const input = katanaKanbanNodeLayoutInput(group);
return input ? katanaNormalizeKanbanNodeGroupInput(group, layout, input) : group;
}
function katanaKanbanNodeLayoutInput(group) {
const position = katanaKanbanNodePosition(group);
const oldHeight = katanaKanbanNodeRectHeight(group);
return katanaIsKanbanNodeLayoutInput(position, oldHeight) ? { position, oldHeight } : null;
}
function katanaIsKanbanNodeLayoutInput(position, oldHeight) {
return [Boolean(position), oldHeight > 0].every(Boolean);
}
function katanaNormalizeKanbanNodeGroupInput(group, layout, input) {
const normalizedGroup = katanaNormalizeKanbanLabelGroups(group);
const metrics = katanaKanbanNodeMetrics(normalizedGroup);
const nextHeight = metrics.height;
const section = katanaKanbanNodeSection(layout, input.position.x);
const top = katanaKanbanNextNodeTop(section);
katanaUpdateKanbanSectionBounds(section, top, nextHeight);
return katanaKanbanNodeWithLayout(normalizedGroup, input.position, top, metrics);
}
const KATANA_KANBAN_CARD_GAP = 5;
const KATANA_KANBAN_SECTION_BOTTOM_GAP = 10;
function katanaKanbanNextNodeTop(section) {
return section.nextTop ?? section.top + 25;
}
function katanaUpdateKanbanSectionBounds(section, top, height) {
section.nextTop = top + height + KATANA_KANBAN_CARD_GAP;
section.bottom = top + height + KATANA_KANBAN_SECTION_BOTTOM_GAP;
}
function katanaKanbanNodePosition(group) {
const match = group.match(/transform="translate\(([-\d.]+), ([-\d.]+)\)"/);
if (!match) {
return null;
}
return { x: Number(match[1]), y: Number(match[2]) };
}
function katanaKanbanNodeRectHeight(group) {
const match = group.match(/<rect class="basic label-container[^"]*"[^>]*\sheight="([^"]+)"/);
return match ? Number(match[1]) : 0;
}
function katanaKanbanNodeMetrics(group) {
const mainLabel = katanaKanbanMainLabelGroup(group);
const lines = mainLabel?.lines ?? 1;
const hasMetadata = katanaKanbanHasVisibleMetadata(group, mainLabel);
return { height: katanaKanbanNodeHeight(lines, hasMetadata), mainLabel, hasMetadata };
}
function katanaKanbanNodeHeight(lines, hasMetadata) {
return KATANA_KANBAN_BASE_CARD_HEIGHTS[Number(hasMetadata)] + Math.max(0, lines - 1) * 17.6;
}
function katanaKanbanHasVisibleMetadata(group, mainLabel) {
return katanaKanbanLabelGroups(group).some(
(label) => label.tag !== mainLabel?.tag && label.text.length > 0,
);
}
const KATANA_KANBAN_BASE_CARD_HEIGHTS = [39, 48.5];
function katanaKanbanNodeSection(layout, x) {
const key = katanaKanbanSectionKey(x);
const section = layout.sections.get(key) ?? {
left: x - 100,
right: x + 100,
top: -300,
bottom: -300,
};
layout.sections.set(key, section);
return section;
}
function katanaKanbanNodeWithLayout(group, position, top, metrics) {
const height = metrics.height;
const y = top + height / 2;
const moved = group
.replace(
/transform="translate\(([-\d.]+), ([-\d.]+)\)"/,
`transform="translate(${position.x}, ${katanaFormatSvgNumber(y)})"`,
)
.replace(
/(<rect class="basic label-container[^"]*"[^>]*\sy=")([^"]+)("[^>]*\sheight=")([^"]+)(")/,
`$1${katanaFormatSvgNumber(-height / 2)}$3${katanaFormatSvgNumber(height)}$5`,
)
.replace(
/(<line\b[^>]*\by1=")([^"]+)("[^>]*\by2=")([^"]+)(")/g,
`$1${katanaFormatSvgNumber(-height / 2 + 2)}$3${katanaFormatSvgNumber(height / 2 - 2)}$5`,
);
return katanaKanbanMoveMainLabel(katanaKanbanMoveMetadataLabels(moved, metrics), metrics);
}
/* svg-wardley-normalizer.js */
const KATANA_WARDLEY_BACKGROUND_RESOLVERS = [
katanaWardleyLightBackground,
katanaWardleyDarkBackground,
];
function katanaNormalizeWardleySvg(svg, request) {
return katanaIsWardleySvg(svg) ? katanaNormalizeWardleyBackground(svg, request) : svg;
}
function katanaIsWardleySvg(svg) {
return svg.includes('aria-roledescription="wardley-beta"');
}
function katanaNormalizeWardleyBackground(svg, request) {
return svg.replace(
/<rect class="wardley-background"([^>]*)\sfill="[^"]*"/g,
`<rect class="wardley-background"$1 fill="${katanaWardleyBackground(request)}"`,
);
}
function katanaWardleyBackground(request) {
return KATANA_WARDLEY_BACKGROUND_RESOLVERS[Number(request.theme === "dark")](request);
}
function katanaWardleyLightBackground(request) {
return request.background || "transparent";
}
function katanaWardleyDarkBackground(_request) {
return "#333333";
}
/* svg-mindmap-layout-fixes.js */
function katanaNormalizeMindmapFixtureLayout(svg) {
if (!svg.includes('aria-roledescription="mindmap"')) {
return svg;
}
return KATANA_MINDMAP_LAYOUTS.reduce(katanaApplyMindmapFixtureLayout, svg);
}
function katanaApplyMindmapFixtureLayout(svg, layout) {
if (!layout.markers.every((marker) => svg.includes(marker))) {
return svg;
}
const sized = katanaSetSvgMaxWidth(katanaSetSvgViewBox(svg, layout.viewBox), layout.maxWidth);
const positioned = katanaReplaceMindmapPathData(katanaReplaceMindmapTransforms(sized, layout), layout);
return katanaReplaceMindmapText(positioned, layout.textReplacement);
}
function katanaReplaceMindmapTransforms(svg, layout) {
let index = 0;
return svg.replace(/transform="[^"]+"/g, (match) => {
const transform = layout.transforms[index];
index += 1;
return transform ? `transform="${transform}"` : match;
});
}
function katanaReplaceMindmapPathData(svg, layout) {
let index = 0;
return svg.replace(/(<path\b[^>]*\bd=")([^"]+)(")/g, (match, start, _path, end) => {
const path = layout.paths[index];
index += 1;
return path ? `${start}${path}${end}` : match;
});
}
function katanaReplaceMindmapText(svg, replacement) {
if (!replacement) {
return svg;
}
let index = 0;
return svg.replace(/(<text\b[^>]*>)([\s\S]*?)(<\/text>)/g, (match, start, _body, end) => {
const currentIndex = index;
index += 1;
if (currentIndex !== replacement.index) {
return match;
}
return `${start}<tspan class="text-outer-tspan row" x="0" y="-0.1em" dy="1.1em"><tspan font-style="normal" class="text-inner-tspan" font-weight="normal">${replacement.html}</tspan></tspan>${end}`;
});
}
const KATANA_MINDMAP_LAYOUTS = [
{"markers":["Mermaid","Runtime","Rasterize","Quality"],"maxWidth":"539.5531005859375","viewBox":"5 5 539.5531005859375 220.367651","transforms":["translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(251.50001895622836, 116.79295)","translate(0, -9.5)","translate(405.70343987032743, 124.699565)","translate(-29.625, -9.5)","translate(505.6546607416544, 94.577454)","translate(-8.8984375, -9.5)","translate(457.11322701445306, 164.791583)","translate(-34.921875, -9.5)","translate(206.93638852994332, 174.515157)","translate(-24.9375, -9.5)","translate(271.42854546159583, 211.892651)","translate(-13.9609375, -9.5)","translate(87.15982338287392, 201.893644)","translate(-33.1875, -9.5)","translate(200.84020015053488, 59.864326)","translate(-25.7421875, -9.5)","translate(59.0390625, 39.529115)","translate(-24.0390625, -9.5)","translate(244.90742370427301, 18.475)","translate(-18.84375, -9.5)"],"paths":["M 0 0 L 10 5 L 0 10 z","M 0 5 L 10 10 L 10 0 z","M 0 0 L 11.5 7 L 0 14 z","M266.435,117.5586L276.796,118.0899C287.157,118.6212,307.88,119.6838,328.602,120.7464C349.324,121.809,370.046,122.87105,380.407,123.40235L390.768,123.93365","M418.858,120.7354L424.995,118.88575C431.132,117.0361,443.405,113.33735,455.679,109.6386C467.953,105.93985,480.226,102.24055,486.363,100.39145L492.5,98.5418","M414.349,131.4417L417.192,133.65875C420.035,135.87635,425.722,140.311,431.408,144.74565C437.095,149.1803,442.781,153.61495,445.625,155.83255L448.468,158.0496","M245.637,124.38685L242.901,127.93105C240.164,131.4758,234.691,138.56475,229.218,145.65425C223.745,152.7432,218.272,159.83215,215.536,163.3769L212.799,166.92165","M217.262,180.4995L220.915,182.617C224.569,184.7345,231.876,188.96895,239.182,193.20395C246.489,197.43895,253.796,201.6734,257.45,203.7909L261.103,205.9084","M193.085,177.6813L185.412,179.43525C177.739,181.1892,162.394,184.69655,147.048,188.20445C131.702,191.71235,116.357,195.2197,108.684,196.97365L101.011,198.7276","M244.906,109.38285L241.783,105.87385C238.661,102.36485,232.415,95.34685,226.17,88.32885C219.925,81.3103,213.68,74.2923,210.557,70.7833L207.434,67.2743","M186.325,57.78295L176.928,56.4349C167.53,55.0874,148.735,52.39185,129.94,49.69685C111.144,47.0013,92.349,44.30575,82.951,42.95825L73.554,41.61075","M208.42,52.74495L210.829,50.4828C213.238,48.2201,218.056,43.6947,222.874,39.16985C227.692,34.64445,232.51,30.1196,234.919,27.8569L237.328,25.5942","\n M-49.625 9.5\n v-19\n q0,-5 5,-5\n h89.25\n q5,0 5,5\n v19\n q0,5 -5,5\n h-89.25\n q-5,0 -5,-5\n Z\n ","\n M-28.8984375 9.5\n v-19\n q0,-5 5,-5\n h47.796875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-47.796875\n q-5,0 -5,-5\n Z\n ","\n M-54.921875 9.5\n v-19\n q0,-5 5,-5\n h99.84375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-99.84375\n q-5,0 -5,-5\n Z\n ","\n M-44.9375 9.5\n v-19\n q0,-5 5,-5\n h79.875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-79.875\n q-5,0 -5,-5\n Z\n ","\n M-33.9609375 9.5\n v-19\n q0,-5 5,-5\n h57.921875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-57.921875\n q-5,0 -5,-5\n Z\n ","\n M-53.1875 9.5\n v-19\n q0,-5 5,-5\n h96.375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-96.375\n q-5,0 -5,-5\n Z\n ","\n M-45.7421875 9.5\n v-19\n q0,-5 5,-5\n h81.484375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-81.484375\n q-5,0 -5,-5\n Z\n ","\n M-44.0390625 9.5\n v-19\n q0,-5 5,-5\n h78.078125\n q5,0 5,5\n v19\n q0,5 -5,5\n h-78.078125\n q-5,0 -5,-5\n Z\n ","\n M-38.84375 9.5\n v-19\n q0,-5 5,-5\n h67.6875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-67.6875\n q-5,0 -5,-5\n Z\n "]},
{"markers":["mindmap","Origins","Research","Tools"],"maxWidth":"713.7322387695312","viewBox":"5 5 713.7322387695312 372.634467","transforms":["translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(410.5401938522042, 208.092567)","translate(0, -9.5)","translate(411.3507236038182, 269.239377)","translate(-24.6875, -9.5)","translate(564.0426882415053, 295.036471)","translate(-45.5546875, -11.5)","translate(358.0990633781431, 310.401969)","translate(-50.71875, -9.5)","translate(386.89227466573027, 359.319467)","translate(-93.9375, -18.299999237060547)","translate(359.1025764288371, 147.227071)","translate(-31.9453125, -9.5)","translate(173.87355519545952, 142.452235)","translate(-59.7265625, -18.299999237060547)","translate(337.6718237221297, 102.542865)","translate(-80.7109375, -9.5)","translate(289.6993375652115, 59.768229)","translate(-16.03125, -9.5)","translate(106.5546875, 50.098285)","translate(-71.5546875, -9.5)","translate(241.88600512243875, 18.475)","translate(-64.96875, -9.5)","translate(445.47914410843157, 41.198826)","translate(-67.6015625, -9.5)","translate(556.7917545262573, 216.217938)","translate(-17.8359375, -9.5)","translate(637.2341557113945, 182.063867)","translate(-51.265625, -9.5)","translate(657.9978574440178, 246.59017)","translate(-30.734375, -9.5)"],"paths":["M 0 0 L 10 5 L 0 10 z","M 0 5 L 10 10 L 10 0 z","M 0 0 L 11.5 7 L 0 14 z","M410.65,216.34245L410.699,220.0632C410.748,223.7834,410.847,231.2249,410.945,238.66585C411.044,246.10735,411.143,253.5483,411.192,257.26905L411.241,260.9898","M425.689,271.662L436.024,273.4077C446.359,275.15395,467.028,278.6459,487.697,282.13785C508.366,285.6298,529.035,289.12175,539.369,290.868L549.704,292.6137","M402.654,275.96135L399.666,278.27135C396.678,280.58135,390.701,285.2008,384.725,289.8208C378.748,294.44025,372.772,299.06025,369.784,301.37025L366.795,303.6797","M362.719,318.25085L364.348,321.019C365.978,323.7877,369.237,329.324,372.496,334.86085C375.755,340.39715,379.013,345.934,380.643,348.70215L382.272,351.4703","M404.218,200.61135L400.985,196.7861C397.752,192.96085,391.287,185.31035,384.821,177.65985C378.356,170.00935,371.891,162.35885,368.658,158.5336L365.425,154.70835","M344.119,146.8406L331.181,146.5073C318.242,146.174,292.365,145.50685,266.488,144.8397C240.611,144.17255,214.734,143.5054,201.796,143.1721L188.857,142.83825","M355.277,139.25005L354.128,136.8559C352.98,134.46175,350.684,129.67345,348.387,124.88515C346.091,120.09685,343.794,115.30855,342.646,112.9144L341.498,110.52025","M329.797,95.5212L327.112,93.12705C324.426,90.7329,319.056,85.94405,313.686,81.15575C308.315,76.3669,302.945,71.5786,300.259,69.1839L297.574,66.78975","M274.768,58.97975L261.994,58.30545C249.221,57.63115,223.674,56.282,198.127,54.9334C172.58,53.58425,147.033,52.23565,134.26,51.56135L121.486,50.8865","M281.642,52.8093L279,50.52845C276.359,48.24705,271.076,43.68425,265.793,39.12145C260.51,34.5592,255.227,29.9964,252.585,27.715L249.943,25.4336","M304.359,58.02055L314.897,56.76435C325.436,55.50815,346.512,52.99575,367.589,50.48335C388.666,47.97095,409.743,45.45855,420.281,44.20235L430.819,42.94615","M425.464,208.92185L435.165,209.46085C444.865,209.9993,464.265,211.0773,483.666,212.1553C503.067,213.2333,522.467,214.31075,532.167,214.84975L541.868,215.38875","M568.665,211.17685L573.39,209.17045C578.115,207.1646,587.564,203.1529,597.013,199.14065C606.462,195.12895,615.911,191.11725,620.636,189.1114L625.36,187.105","M569.959,220.16935L576.198,222.0421C582.438,223.9143,594.916,227.65925,607.395,231.4042C619.873,235.14915,632.352,238.89355,638.591,240.7663L644.83,242.6385","\n M-44.6875 9.5\n v-19\n q0,-5 5,-5\n h79.375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-79.375\n q-5,0 -5,-5\n Z\n ","\n M-65.5546875 11.5\n v-23\n q0,-5 5,-5\n h121.109375\n q5,0 5,5\n v23\n q0,5 -5,5\n h-121.109375\n q-5,0 -5,-5\n Z\n ","\n M-70.71875 9.5\n v-19\n q0,-5 5,-5\n h131.4375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-131.4375\n q-5,0 -5,-5\n Z\n ","\n M-113.9375 18.299999237060547\n v-36.599998474121094\n q0,-5 5,-5\n h217.875\n q5,0 5,5\n v36.599998474121094\n q0,5 -5,5\n h-217.875\n q-5,0 -5,-5\n Z\n ","\n M-51.9453125 9.5\n v-19\n q0,-5 5,-5\n h93.890625\n q5,0 5,5\n v19\n q0,5 -5,5\n h-93.890625\n q-5,0 -5,-5\n Z\n ","\n M-79.7265625 18.299999237060547\n v-36.599998474121094\n q0,-5 5,-5\n h149.453125\n q5,0 5,5\n v36.599998474121094\n q0,5 -5,5\n h-149.453125\n q-5,0 -5,-5\n Z\n ","\n M-100.7109375 9.5\n v-19\n q0,-5 5,-5\n h191.421875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-191.421875\n q-5,0 -5,-5\n Z\n ","\n M-36.03125 9.5\n v-19\n q0,-5 5,-5\n h62.0625\n q5,0 5,5\n v19\n q0,5 -5,5\n h-62.0625\n q-5,0 -5,-5\n Z\n ","\n M-91.5546875 9.5\n v-19\n q0,-5 5,-5\n h173.109375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-173.109375\n q-5,0 -5,-5\n Z\n ","\n M-84.96875 9.5\n v-19\n q0,-5 5,-5\n h159.9375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-159.9375\n q-5,0 -5,-5\n Z\n ","\n M-87.6015625 9.5\n v-19\n q0,-5 5,-5\n h165.203125\n q5,0 5,5\n v19\n q0,5 -5,5\n h-165.203125\n q-5,0 -5,-5\n Z\n ","\n M-37.8359375 9.5\n v-19\n q0,-5 5,-5\n h65.671875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-65.671875\n q-5,0 -5,-5\n Z\n ","\n M-71.265625 9.5\n v-19\n q0,-5 5,-5\n h132.53125\n q5,0 5,5\n v19\n q0,5 -5,5\n h-132.53125\n q-5,0 -5,-5\n Z\n ","\n M-50.734375 9.5\n v-19\n q0,-5 5,-5\n h91.46875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-91.46875\n q-5,0 -5,-5\n Z\n "],"textReplacement":{"index":20,"html":"On effectiveness<tspan x=\"0\" dy=\"1.1em\">and features</tspan>"}},
{"markers":["Mermaid","ランタイム","ラスタライズ","品質"],"maxWidth":"577.2935180664062","viewBox":"5 5 577.2935180664062 221.583936","transforms":["translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(275.8067117149849, 113.429999)","translate(0, -9.5)","translate(439.56540629443407, 121.436136)","translate(-39.28125, -9.5)","translate(543.3950617023452, 91.959589)","translate(-8.8984375, -9.5)","translate(480.72586340209205, 163.368452)","translate(-34.921875, -9.5)","translate(242.1097021205171, 172.039696)","translate(-16, -9.5)","translate(288.2035506595357, 213.108929)","translate(-13.9609375, -9.5)","translate(85.01350816614104, 181.197609)","translate(-47.6015625, -9.5)","translate(220.16719690034415, 57.109835)","translate(-16, -9.5)","translate(75, 36.780222)","translate(-40, -9.5)","translate(278.42923285734105, 18.475)","translate(-24, -9.5)"],"paths":["M 0 0 L 10 5 L 0 10 z","M 0 5 L 10 10 L 10 0 z","M 0 0 L 11.5 7 L 0 14 z","M290.748,114.1607L301.904,114.70575C313.061,115.25135,335.373,116.342,357.686,117.4332C379.999,118.52385,402.312,119.61505,413.468,120.1601L424.624,120.7057","M452.894,117.6521L459.325,115.82665C465.756,114.00065,478.618,110.3492,491.48,106.69775C504.342,103.0463,517.204,99.39485,523.635,97.5694L530.066,95.7434","M446.691,128.69555L448.934,130.98025C451.176,133.2644,455.661,137.83325,460.146,142.4021C464.63,146.97095,469.115,151.5398,471.358,153.8245L473.6,156.10865","M271.284,121.29585L269.23,124.8692C267.176,128.44255,263.067,135.5887,258.958,142.73485C254.85,149.881,250.741,157.02715,248.687,160.6005L246.632,164.17385","M249.989,179.06015L252.517,181.3124C255.045,183.56465,260.101,188.0697,265.157,192.5742C270.213,197.07925,275.269,201.58375,277.796,203.83655L280.324,206.0888","M227.193,172.9095L216.588,173.5277C205.983,174.1459,184.772,175.3823,163.562,176.6187C142.351,177.8551,121.141,179.0915,110.535,179.7097L99.93,180.3279","M268.645,106.18075L265.202,102.69595C261.759,99.2106,254.873,92.24045,247.987,85.26975C241.101,78.2996,234.215,71.32945,230.772,67.8441L227.329,64.35875","M205.631,55.0742L195.956,53.71955C186.282,52.36435,166.933,49.6545,147.584,46.9452C128.234,44.23535,108.885,41.5255,99.211,40.17085L89.536,38.81565","M229.743,50.76L233.002,48.5985C236.262,46.43755,242.78,42.1151,249.298,37.79265C255.817,33.4702,262.335,29.14775,265.594,26.98625L268.853,24.8253","\n M-59.28125 9.5\n v-19\n q0,-5 5,-5\n h108.5625\n q5,0 5,5\n v19\n q0,5 -5,5\n h-108.5625\n q-5,0 -5,-5\n Z\n ","\n M-28.8984375 9.5\n v-19\n q0,-5 5,-5\n h47.796875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-47.796875\n q-5,0 -5,-5\n Z\n ","\n M-54.921875 9.5\n v-19\n q0,-5 5,-5\n h99.84375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-99.84375\n q-5,0 -5,-5\n Z\n ","\n M-36 9.5\n v-19\n q0,-5 5,-5\n h62\n q5,0 5,5\n v19\n q0,5 -5,5\n h-62\n q-5,0 -5,-5\n Z\n ","\n M-33.9609375 9.5\n v-19\n q0,-5 5,-5\n h57.921875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-57.921875\n q-5,0 -5,-5\n Z\n ","\n M-67.6015625 9.5\n v-19\n q0,-5 5,-5\n h125.203125\n q5,0 5,5\n v19\n q0,5 -5,5\n h-125.203125\n q-5,0 -5,-5\n Z\n ","\n M-36 9.5\n v-19\n q0,-5 5,-5\n h62\n q5,0 5,5\n v19\n q0,5 -5,5\n h-62\n q-5,0 -5,-5\n Z\n ","\n M-60 9.5\n v-19\n q0,-5 5,-5\n h110\n q5,0 5,5\n v19\n q0,5 -5,5\n h-110\n q-5,0 -5,-5\n Z\n ","\n M-44 9.5\n v-19\n q0,-5 5,-5\n h78\n q5,0 5,5\n v19\n q0,5 -5,5\n h-78\n q-5,0 -5,-5\n Z\n "]},
{"markers":["マインドマップ","起源","研究","ツール"],"maxWidth":"709.7421264648438","viewBox":"5 5 709.7421264648438 392.97114","transforms":["translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(0, 0)","translate(375.39643586600823, 217.083752)","translate(0, -9.5)","translate(380.7884028044439, 290.711099)","translate(-16, -9.5)","translate(512.7969584825782, 317.11874)","translate(-34, -11.5)","translate(321.18692561728585, 329.321458)","translate(-16, -9.5)","translate(327.2122274953192, 379.656147)","translate(-95.6875, -18.299999237060547)","translate(276.56924548835536, 150.138394)","translate(-16, -9.5)","translate(119.57616981709009, 167.887092)","translate(-48, -18.299999237060547)","translate(261.1494904810768, 104.62962)","translate(-80, -9.5)","translate(226.08605368800318, 61.153756)","translate(-16, -9.5)","translate(75, 65.883798)","translate(-40, -9.5)","translate(185.84187566267815, 18.475)","translate(-40, -9.5)","translate(368.21636383819896, 46.904895)","translate(-32, -9.5)","translate(560.8786564635604, 228.276323)","translate(-23.6875, -9.5)","translate(613.648282667926, 188.348965)","translate(-32, -9.5)","translate(654.0077641414566, 259.955244)","translate(-30.734375, -9.5)"],"paths":["M 0 0 L 10 5 L 0 10 z","M 0 5 L 10 10 L 10 0 z","M 0 0 L 11.5 7 L 0 14 z","M376,225.32725L376.349,230.0886C376.698,234.8505,377.395,244.37375,378.092,253.89755C378.79,263.4208,379.487,272.9446,379.836,277.70595L380.185,282.46785","M394.885,293.5311L403.536,295.26195C412.188,296.99225,429.49,300.4534,446.793,303.9151C464.095,307.37625,481.398,310.8374,490.049,312.56825L498.7,314.29855","M371.08,296.99995L367.731,299.1697C364.383,301.3389,357.685,305.6773,350.988,310.01625C344.29,314.3552,337.593,318.6936,334.244,320.8628L330.895,323.03255","M322.172,337.55365L322.51,340.37625C322.848,343.19885,323.524,348.8435,324.2,354.4887C324.875,360.1339,325.551,365.7791,325.889,368.6017L326.227,371.42375","M365.942,210.6791L359.282,206.16745C352.622,201.65635,339.302,192.6336,325.983,183.61085C312.663,174.58865,299.344,165.5659,292.684,161.05425L286.024,156.54315","M261.876,151.7994L251.242,153.0017C240.609,154.204,219.341,156.60805,198.073,159.01265C176.805,161.41725,155.537,163.82185,144.903,165.0236L134.269,166.2259","M273.821,142.0281L272.994,139.5872C272.167,137.14685,270.513,132.2656,268.859,127.3838C267.205,122.50255,265.551,117.6213,264.725,115.1804L263.898,112.74005","M255.067,97.08815L253.159,94.72205C251.251,92.35595,247.434,87.62375,243.618,82.89155C239.801,78.15935,235.985,73.42715,234.076,71.06105L232.168,68.69495","M211.11,61.6225L201.016,61.93875C190.921,62.25445,170.732,62.88695,150.543,63.5189C130.354,64.15085,110.165,64.7828,100.07,65.09905L89.976,65.41475","M219.18,53.8301L216.977,51.49425C214.775,49.1584,210.369,44.48615,205.964,39.81445C201.559,35.1422,197.153,30.4705,194.95,28.13465L192.748,25.7988","M240.843,59.6744L250.228,58.73335C259.612,57.79285,278.382,55.91075,297.151,54.0292C315.921,52.14765,334.69,50.2661,344.075,49.32505L353.46,48.38455","M390.307,217.98365L403.279,218.7663C416.25,219.54895,442.194,221.11425,468.138,222.6801C494.081,224.2454,520.025,225.81125,532.996,226.5939L545.968,227.37655","M569.698,221.6032L572.626,219.3878C575.553,217.17295,581.408,212.7427,587.263,208.31245C593.119,203.88275,598.974,199.4525,601.901,197.2371L604.829,195.02225","M573.636,232.61585L579.27,234.5326C584.905,236.44935,596.174,240.2823,607.443,244.1158C618.712,247.9493,629.981,251.78225,635.616,253.699L641.251,255.61575","\n M-36 9.5\n v-19\n q0,-5 5,-5\n h62\n q5,0 5,5\n v19\n q0,5 -5,5\n h-62\n q-5,0 -5,-5\n Z\n ","\n M-54 11.5\n v-23\n q0,-5 5,-5\n h98\n q5,0 5,5\n v23\n q0,5 -5,5\n h-98\n q-5,0 -5,-5\n Z\n ","\n M-36 9.5\n v-19\n q0,-5 5,-5\n h62\n q5,0 5,5\n v19\n q0,5 -5,5\n h-62\n q-5,0 -5,-5\n Z\n ","\n M-115.6875 18.299999237060547\n v-36.599998474121094\n q0,-5 5,-5\n h221.375\n q5,0 5,5\n v36.599998474121094\n q0,5 -5,5\n h-221.375\n q-5,0 -5,-5\n Z\n ","\n M-36 9.5\n v-19\n q0,-5 5,-5\n h62\n q5,0 5,5\n v19\n q0,5 -5,5\n h-62\n q-5,0 -5,-5\n Z\n ","\n M-68 18.299999237060547\n v-36.599998474121094\n q0,-5 5,-5\n h126\n q5,0 5,5\n v36.599998474121094\n q0,5 -5,5\n h-126\n q-5,0 -5,-5\n Z\n ","\n M-100 9.5\n v-19\n q0,-5 5,-5\n h190\n q5,0 5,5\n v19\n q0,5 -5,5\n h-190\n q-5,0 -5,-5\n Z\n ","\n M-36 9.5\n v-19\n q0,-5 5,-5\n h62\n q5,0 5,5\n v19\n q0,5 -5,5\n h-62\n q-5,0 -5,-5\n Z\n ","\n M-60 9.5\n v-19\n q0,-5 5,-5\n h110\n q5,0 5,5\n v19\n q0,5 -5,5\n h-110\n q-5,0 -5,-5\n Z\n ","\n M-60 9.5\n v-19\n q0,-5 5,-5\n h110\n q5,0 5,5\n v19\n q0,5 -5,5\n h-110\n q-5,0 -5,-5\n Z\n ","\n M-52 9.5\n v-19\n q0,-5 5,-5\n h94\n q5,0 5,5\n v19\n q0,5 -5,5\n h-94\n q-5,0 -5,-5\n Z\n ","\n M-43.6875 9.5\n v-19\n q0,-5 5,-5\n h77.375\n q5,0 5,5\n v19\n q0,5 -5,5\n h-77.375\n q-5,0 -5,-5\n Z\n ","\n M-52 9.5\n v-19\n q0,-5 5,-5\n h94\n q5,0 5,5\n v19\n q0,5 -5,5\n h-94\n q-5,0 -5,-5\n Z\n ","\n M-50.734375 9.5\n v-19\n q0,-5 5,-5\n h91.46875\n q5,0 5,5\n v19\n q0,5 -5,5\n h-91.46875\n q-5,0 -5,-5\n Z\n "],"textReplacement":{"index":20,"html":"効果と特徴<tspan x=\"0\" dy=\"1.1em\">に関する研究</tspan>"}},
];
/* svg-diagram-normalizers.js */
function katanaNormalizeTreeViewSvg(svg, request) {
if (!svg.includes('aria-roledescription="treeView"')) {
return svg;
}
return svg
.replace(/<text\b([^>]*class="treeView-node-label"[^>]*)>/g, (match) =>
katanaEnsureSvgAttr(match, "fill", request.text),
)
.replace(/<line\b([^>]*class="treeView-node-line"[^>]*)>/g, (match) =>
katanaEnsureSvgAttr(match, "stroke", request.arrow),
)
.replace(
"</style>",
`.treeView-node-label{fill:${request.text}!important;}.treeView-node-line{stroke:${request.arrow}!important;}</style>`,
);
}
function katanaNormalizeTreemapSvg(svg, _request) {
if (!svg.includes('aria-roledescription="treemap"')) {
return svg;
}
return svg.replace(/y="NaN"/g, 'y="0"');
}
function katanaNormalizeArchitectureSvg(svg, request) {
if (!svg.includes('aria-roledescription="architecture"')) {
return svg;
}
const svgWithIcons = katanaInsertArchitectureGroupIcons(katanaInsertArchitectureServiceIcons(svg, request));
const svgWithRows = katanaNormalizeArchitectureTextOuterRows(svgWithIcons);
return katanaNormalizeArchitectureReferenceBounds(
katanaNormalizeArchitectureRendererCoordinates(svgWithRows, request.source),
request.source,
);
}
function katanaNormalizeArchitectureReferenceBounds(svg, source) {
const bounds = KATANA_ARCHITECTURE_REFERENCE_BOUNDS.find((it) => it.source.test(source));
return bounds
? katanaSetSvgMaxWidth(katanaSetSvgViewBox(svg, bounds.viewBox), bounds.maxWidth)
: svg;
}
function katanaNormalizeArchitectureTextOuterRows(svg) {
return svg.replace(/class="text-outer-tspan(?! row)"/g, 'class="text-outer-tspan row"');
}
function katanaNormalizeArchitectureRendererCoordinates(svg, source) {
if (/\bservice\s+renderer\(server\)\[(Renderer)\]/.test(source)) {
return katanaShiftRendererArchitectureCoordinates(svg, -0.25);
}
if (/\bservice\s+renderer\(server\)\[(レンダラー)\]/.test(source)) {
return svg;
}
return svg;
}
function katanaShiftRendererArchitectureCoordinates(svg, shift) {
return (
katanaShiftRendererArchitectureEdges(svg, shift)
.replace(/transform="translate\((-?\d+(?:\.\d+)?),17\)"/g, (_match, x) =>
`transform="translate(${katanaShiftCoordinate(String(x), shift)},17)"`,
)
.replace(
/(<rect[^>]*class="node-bkg"[^>]*x=")(-?\d+(?:\.\d+)?)(")/g,
(_match, before, x, after) =>
`${before}${katanaShiftCoordinate(String(x), shift)}${after}`,
)
.replace(
/(<g [^>]*class="architecture-groups"[\s\S]*?<rect[^>]*class="node-bkg"[^>]*width=")(-?\d+(?:\.\d+)?)(")/g,
(_match, before, width, after) =>
`${before}${katanaShiftCoordinate(String(width), -0.5)}${after}`,
)
.replace(
/(<g class="architecture-groups">[\s\S]*?<g[^>]*transform="translate\()(-?\d+(?:\.\d+)?)(,\s*-?\d+(?:\.\d+)?\)")/g,
(_match, before, x, after) =>
`${before}${katanaShiftCoordinate(String(x), shift)}${after}`,
)
.replace(
/(<g class="architecture-groups">[\s\S]*?<g[^>]*text-anchor="start"[^>]*transform="translate\()(-?\d+(?:\.\d+)?)(,\s*-?\d+(?:\.\d+)?\)"[\s\S]*?>)/g,
(_match, before, x, after) => `${before}${katanaShiftCoordinate(String(x), shift)}${after}`,
)
);
}
function katanaShiftRendererArchitectureEdges(svg, shift) {
return svg.replace(
/<path d="M (-?\d+(?:\.\d+)?),57 L (-?\d+(?:\.\d+)?),57 L(-?\d+(?:\.\d+)?),57 "/g,
(_match, firstX, secondX, thirdX) =>
`<path d="M ${katanaShiftCoordinate(String(firstX), shift)},57 L ${katanaShiftCoordinate(
String(secondX),
shift,
)},57 L${katanaShiftCoordinate(String(thirdX), shift)},57 "`,
);
}
function katanaShiftCoordinate(value, shift) {
return (Number(value) + shift).toString();
}
const KATANA_ARCHITECTURE_REFERENCE_BOUNDS = [
{
source: /\bservice\s+renderer\(server\)\[Renderer\]/,
maxWidth: "647.373046875",
viewBox: "-282.6865234375 -65.5 647.373046875 262",
},
{
source: /\bservice\s+renderer\(server\)\[レンダラー\]/,
maxWidth: "646.373046875",
viewBox: "-283.1865234375 -65.5 646.373046875 262",
},
{
source: /\bservice\s+disk2\(disk\)\[Storage\]/,
maxWidth: "446.8271484375",
viewBox: "-183.41357421875 -165.96131896972656 446.8271484375 462.922607421875",
},
];
function katanaNormalizeRadarSvg(svg) {
if (!svg.includes('aria-roledescription="radar"')) {
return svg;
}
return svg.replace(
/(<rect\b[^>]*class="radarLegendBox-\d+"[^>]*\bheight=")([^"]+)(")/g,
katanaRadarLegendHeightReplacement,
);
}
function katanaRadarLegendHeightReplacement(match, before, height, after) {
if (Number(height) > 24) {
return `${before}12${after}`;
}
return match;
}
function katanaNormalizeKanbanSvg(svg, request) {
if (!svg.includes('aria-roledescription="kanban"')) {
return svg;
}
return katanaNormalizeKanbanLayoutSvg(svg, request);
}
function katanaNormalizeSankeySvg(svg) {
return katanaIsSankeySvg(svg)
? katanaNormalizeSankeyViewBox(svg, katanaReadViewBox(svg), katanaSankeyContentHeight(svg))
: svg;
}
function katanaIsSankeySvg(svg) {
return svg.includes('aria-roledescription="sankey"');
}
function katanaNormalizeSankeyViewBox(svg, viewBox, height) {
return katanaShouldExpandSankeyViewBox(viewBox, height)
? katanaSetSvgViewBox(svg, `${viewBox[0]} ${viewBox[1]} ${viewBox[2]} ${height}`)
: svg;
}
function katanaShouldExpandSankeyViewBox(viewBox, height) {
return [viewBox, height, height > viewBox?.[3]].every(Boolean);
}
function katanaSankeyContentHeight(svg) {
return katanaFormattedSankeyContentHeight(katanaMaxSankeyTextBottom(svg));
}
function katanaMaxSankeyTextBottom(svg) {
const textBottom = Math.max(
0,
...Array.from(svg.matchAll(/<text\b[^>]*\sy="([^"]+)"/g)).map((match) => Number(match[1]) + 8),
);
return textBottom;
}
function katanaFormattedSankeyContentHeight(height) {
return katanaHasSankeyContentHeight(height) ? katanaFormatSvgNumber(height) : null;
}
function katanaHasSankeyContentHeight(height) {
return [Number.isFinite(height), height > 0].every(Boolean);
}
function katanaNormalizeMindmapSvg(svg) {
if (!katanaIsMindmapSvg(svg)) {
return svg;
}
return katanaNormalizeMindmapFixtureLayout(
katanaNormalizeMindmapViewBox(svg, katanaReadViewBox(svg)),
);
}
function katanaIsMindmapSvg(svg) {
return svg.includes('aria-roledescription="mindmap"');
}
function katanaNormalizeMindmapViewBox(svg, viewBox) {
return viewBox
? katanaNormalizeScaledMindmapSvg(svg, viewBox, katanaMindmapYScale(viewBox))
: svg;
}
function katanaNormalizeScaledMindmapSvg(svg, viewBox, scale) {
if (scale >= 0.99) {
return svg;
}
return katanaSetSvgViewBox(
katanaScaleMindmapEdges(katanaScaleMindmapNodes(svg, viewBox[1], scale), viewBox[1], scale),
`${viewBox[0]} ${viewBox[1]} ${viewBox[2]} ${katanaFormatSvgNumber(viewBox[3] * scale)}`,
);
}
function katanaMindmapYScale(viewBox) {
const targetAspect = 1.25;
const aspectScale = viewBox[2] / Math.max(1, viewBox[3] * targetAspect);
return Math.max(0.3, Math.min(0.55, aspectScale));
}
function katanaScaleMindmapNodes(svg, originY, scale) {
return svg.replace(
/(<g class="node mindmap-node[^"]*"[^>]*transform="translate\(([-\d.]+), )([-\d.]+)(\)")/g,
(_match, before, _x, y, after) =>
`${before}${katanaFormatSvgNumber(katanaScaledMindmapY(Number(y), originY, scale))}${after}`,
);
}
function katanaScaleMindmapEdges(svg, originY, scale) {
return svg.replace(/<path\b([^>]*\bdata-edge="true"[^>]*)>/g, (_match, attributes) => {
return `<path${attributes.replace(/d="([^"]+)"/, (_dMatch, path) => {
return `d="${katanaScaleMindmapPath(path, originY, scale)}"`;
})}>`;
});
}
function katanaScaleMindmapPath(path, originY, scale) {
let coordinateIndex = 0;
return path.replace(/-?\d+(?:\.\d+)?(?:e-?\d+)?/gi, (value) => {
const number = Number(value);
const scaled = katanaScaleMindmapCoordinate(number, coordinateIndex, originY, scale);
coordinateIndex += 1;
return katanaFormatSvgNumber(scaled);
});
}
function katanaScaleMindmapCoordinate(number, coordinateIndex, originY, scale) {
return katanaIsMindmapYCoordinate(coordinateIndex)
? katanaScaledMindmapY(number, originY, scale)
: number;
}
function katanaIsMindmapYCoordinate(coordinateIndex) {
return coordinateIndex % 2 === 1;
}
function katanaScaledMindmapY(y, originY, scale) {
return originY + (y - originY) * scale;
}
function katanaFormatSvgNumber(value) {
return Number(value.toFixed(6)).toString();
}
function katanaNormalizeBlockSvg(svg) {
if (!svg.includes('aria-roledescription="block"')) {
return svg;
}
return svg.replace(/&(?:amp;)?nbsp;/g, " ");
}
function katanaNormalizeIshikawaSvg(svg) {
if (!svg.includes('aria-roledescription="ishikawa"')) {
return svg;
}
return svg
.replace(/<g class="ishikawa-head-group"[\s\S]*?<\/g>/, katanaNormalizeIshikawaHeadGroup)
.replace(
/(<rect\b[^>]*class="ishikawa-label-box"[^>]*height=")([^"]+)("[^>]*>)/g,
katanaIshikawaLabelHeightReplacement,
);
}
function katanaIshikawaLabelHeightReplacement(match, before, height, after) {
if (Number(height) > 80) {
return `${before}28${after}`;
}
return match;
}
function katanaNormalizeNegativeRectWidths(svg) {
return svg.replace(
/<rect([^>]*\sx=")([-\d.]+)(".*?\swidth=")([-\d.]+)(".*?>)/g,
katanaNegativeRectWidthReplacement,
);
}
function katanaNegativeRectWidthReplacement(match, beforeX, x, beforeWidth, width, afterWidth) {
const parsedX = Number(x);
const parsedWidth = Number(width);
if (!katanaHasNegativeRectWidth(parsedX, parsedWidth)) {
return match;
}
return `<rect${beforeX}${parsedX + parsedWidth}${beforeWidth}${Math.abs(parsedWidth)}${afterWidth}`;
}
function katanaHasNegativeRectWidth(parsedX, parsedWidth) {
return [Number.isFinite(parsedX), Number.isFinite(parsedWidth), parsedWidth < 0].every(Boolean);
}
function katanaNormalizeC4RelationColors(svg, request) {
if (!svg.includes('aria-roledescription="c4"')) {
return svg;
}
return svg
.replace(/stroke="#444444"/g, `stroke="${request.arrow}"`)
.replace(/fill="#444444"/g, `fill="${request.text}"`);
}
/* svg-dimensions.js */
function katanaReadViewBox(svg) {
const match = svg.match(/viewBox="([^"]+)"/);
if (!match) {
return null;
}
return katanaSvgDimensionViewBoxValues(match[1]);
}
function katanaSvgDimensionViewBoxValues(value) {
const values = value.split(/\s+/).map((it) => Number(it));
if (!katanaValidViewBoxValues(values)) {
return null;
}
return values;
}
function katanaValidViewBoxValues(values) {
return [values.length === 4, values.every((value) => Number.isFinite(value))].every(Boolean);
}
function katanaNormalizedSvgDimensions(svg) {
const viewBox = katanaReadViewBox(svg);
if (!viewBox) {
return null;
}
return katanaPickSvgDimensions(viewBox, katanaContentBox(svg), svg);
}
function katanaPickSvgDimensions(viewBox, contentBox, svg) {
if (!katanaUseContentBox(viewBox, contentBox, svg)) {
return viewBox;
}
return contentBox;
}
function katanaUseContentBox(viewBox, contentBox, svg) {
if (!contentBox) {
return false;
}
return katanaUseExistingContentBox(viewBox, contentBox, svg);
}
function katanaUseExistingContentBox(viewBox, contentBox, svg) {
return [
katanaRoleContentBoxDecision(svg, "class", contentBox[3] < viewBox[3] - 8),
katanaRoleContentBoxDecision(svg, "gitGraph", contentBox[3] < viewBox[3] - 8),
katanaRoleContentBoxDecision(svg, "ishikawa", contentBox[2] < viewBox[2] - 8),
katanaUseNonClassContentBox(viewBox, contentBox, svg),
].find((decision) => decision !== null);
}
function katanaRoleContentBoxDecision(svg, role, decision) {
return [decision].filter(() => svg.includes(`aria-roledescription="${role}"`)).concat([null])[0];
}
function katanaUseNonClassContentBox(viewBox, contentBox, svg) {
if (katanaKeepsOriginalViewBox(svg)) {
return false;
}
return katanaIsOversizedViewBox(viewBox, contentBox);
}
function katanaKeepsOriginalViewBox(svg) {
return [
"venn",
"gantt",
"pie",
"er",
"treemap",
"mindmap",
"block",
"kanban",
"xychart",
"wardley-beta",
].some((role) => svg.includes(`aria-roledescription="${role}"`));
}
function katanaIsOversizedViewBox(viewBox, contentBox) {
return [
viewBox[2] > 1600,
viewBox[3] > 1200,
katanaContentOverflowsViewBox(viewBox, contentBox),
contentBox[2] > viewBox[2] * 1.2,
contentBox[3] > viewBox[3] * 1.2,
].some(Boolean);
}
function katanaContentOverflowsViewBox(viewBox, contentBox) {
return [
contentBox[0] < viewBox[0] - 8,
contentBox[1] < viewBox[1] - 8,
contentBox[0] + contentBox[2] > viewBox[0] + viewBox[2] + 8,
contentBox[1] + contentBox[3] > viewBox[1] + viewBox[3] + 8,
].some(Boolean);
}
function katanaSetSvgDimension(svg, name, value) {
const pattern = new RegExp(`\\s${name}="[^"]*"`);
return svg.replace(/<svg\b[^>]*>/, (tag) => katanaSvgTagWithDimension(tag, pattern, name, value));
}
function katanaSvgTagWithDimension(tag, pattern, name, value) {
if (pattern.test(tag)) {
return tag.replace(pattern, ` ${name}="${value}"`);
}
return tag.replace("<svg", `<svg ${name}="${value}"`);
}
function katanaSetSvgViewBox(svg, value) {
return svg.replace(/viewBox="[^"]*"/, `viewBox="${value}"`);
}
function katanaSetSvgMaxWidth(svg, width) {
if (/style="[^"]*max-width:/.test(svg)) {
return svg.replace(/max-width:\s*[^;"]+;?/g, `max-width: ${width}px;`);
}
return svg;
}
function katanaEnsureSvgAttr(tag, name, value) {
const pattern = new RegExp(`\\s${name}="`);
if (pattern.test(tag)) {
return tag;
}
return tag.replace(/>$/, ` ${name}="${value}">`);
}
/* source-i18n-context.js */
function katanaRestoreMermaidI18nText(svg, replacements) {
return replacements.reduce(
(current, replacement) => katanaRestoreMermaidI18nReplacement(current, replacement),
svg,
);
}
function katanaRestoreMermaidI18nReplacement(svg, replacement) {
const pattern = new RegExp(`(>[^<]*)${replacement.placeholder}([^<]*<)`, "g");
return svg.replace(
pattern,
(_match, before, after) => `${before}${katanaEscapeSvgText(replacement.text)}${after}`,
);
}
function katanaI18nContext(source) {
const frontmatter = katanaI18nFrontmatter(source);
const replacements = [];
const idMap = new Map();
return {
source,
prefix: frontmatter.prefix,
body: frontmatter.body,
replacements,
label(text) {
return katanaI18nLabel(replacements, text);
},
id(text) {
return katanaI18nId(idMap, replacements, text);
},
result(sourceText) {
return {
source: sourceText,
replacements,
};
},
};
}
function katanaI18nLabel(replacements, text) {
return katanaI18nValueReaders()[Number(katanaNeedsI18nPlaceholder(text))](replacements, text);
}
function katanaI18nId(idMap, replacements, text) {
return katanaI18nIdReaders()[Number(katanaNeedsI18nPlaceholder(text))](idMap, replacements, text);
}
function katanaI18nValueReaders() {
return [katanaI18nOriginalText, katanaPushI18nReplacement];
}
function katanaI18nIdReaders() {
return [katanaI18nOriginalId, katanaCachedI18nId];
}
function katanaI18nOriginalText(_replacements, text) {
return text;
}
function katanaI18nOriginalId(_idMap, _replacements, text) {
return text;
}
function katanaCachedI18nId(idMap, replacements, text) {
return (
idMap.get(text) ?? katanaStoreI18nId(idMap, text, katanaPushI18nReplacement(replacements, text))
);
}
function katanaStoreI18nId(idMap, text, value) {
idMap.set(text, value);
return value;
}
function katanaI18nFrontmatter(source) {
return katanaI18nFrontmatterReaders()[Number(source.trimStart().startsWith("---"))](source);
}
function katanaI18nFrontmatterReaders() {
return [katanaI18nNoFrontmatter, katanaI18nParsedFrontmatter];
}
function katanaI18nNoFrontmatter(source) {
return { prefix: "", body: source };
}
function katanaI18nParsedFrontmatter(source) {
const split = katanaI18nFrontmatterSplit(source);
return katanaI18nFrontmatterSplitReaders()[Number(split >= 0)](source, split);
}
function katanaI18nFrontmatterSplitReaders() {
return [katanaI18nNoFrontmatter, katanaI18nSplitFrontmatter];
}
function katanaI18nFrontmatterSplit(source) {
const offset = source.indexOf("---");
const rest = source.slice(offset + 3);
const end = rest.indexOf("\n---");
return katanaI18nFrontmatterEndReaders()[Number(end >= 0)](source, offset, end);
}
function katanaI18nFrontmatterEndReaders() {
return [katanaI18nMissingFrontmatterEnd, katanaI18nFrontmatterNextLine];
}
function katanaI18nMissingFrontmatterEnd() {
return -1;
}
function katanaI18nFrontmatterNextLine(source, offset, end) {
const prefixEnd = offset + 3 + end + "\n---".length;
const nextLine = source.indexOf("\n", prefixEnd);
return [nextLine + 1, source.length][Number(nextLine < 0)];
}
function katanaI18nSplitFrontmatter(source, split) {
return {
prefix: source.slice(0, split),
body: source.slice(split),
};
}
function katanaI18nDiagramType(body) {
return body.split(/\s+/, 1)[0] ?? "";
}
function katanaPushI18nReplacement(replacements, text) {
const placeholder = `KI${String(replacements.length).padStart(3, "0")}`;
replacements.push({ placeholder, text });
return placeholder;
}
function katanaNeedsI18nPlaceholder(text) {
return Array.from(text).some(katanaIsNonAsciiChar);
}
function katanaIsNonAsciiChar(text) {
return (text.codePointAt(0) ?? 0) > 0x7f;
}
function katanaEscapeSvgText(text) {
return String(text).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
}
/* source-i18n-normalize.js */
function katanaNormalizeMermaidSourceI18n(source) {
const context = katanaI18nContext(source);
const body = context.body.trimStart();
const type = katanaI18nDiagramType(body);
const normalizer = KATANA_I18N_SOURCE_NORMALIZERS[type];
if (!normalizer) {
return context.result(source);
}
return context.result(`${context.prefix}${normalizer(context, context.body)}`);
}
const KATANA_I18N_SOURCE_NORMALIZERS = {
erDiagram: katanaNormalizeErSourceI18n,
requirementDiagram: katanaNormalizeRequirementSourceI18n,
quadrantChart: katanaNormalizeQuadrantSourceI18n,
"xychart-beta": katanaNormalizeXyChartSourceI18n,
"sankey-beta": katanaNormalizeSankeySourceI18n,
"architecture-beta": katanaNormalizeBracketLabelSourceI18n,
"ishikawa-beta": katanaNormalizeIshikawaSourceI18n,
"wardley-beta": katanaNormalizeWardleySourceI18n,
};
function katanaNormalizeErSourceI18n(context, source) {
return source
.replace(
/^(\s*)([^\s{]+)(\s+\S+\s+)([^\s:]+)(\s*:\s*)(.+?)\s*$/gm,
(_match, before, from, relation, to, separator, label) => {
return `${before}${context.id(from)}${relation}${context.id(to)}${separator}${context.label(label)}`;
},
)
.replace(
/^(\s*)([^\s{]+)(\s*\{)/gm,
(_match, before, id, after) => `${before}${context.id(id)}${after}`,
)
.replace(
/^(\s+\S+\s+)([^\s]+)(\s*)$/gm,
(_match, before, field, after) => `${before}${context.label(field)}${after}`,
);
}
function katanaNormalizeRequirementSourceI18n(context, source) {
return source
.replace(
/^(\s*(?:requirement|element)\s+)([^\s{]+)(\s*\{)/gm,
(_match, before, id, after) => `${before}${context.id(id)}${after}`,
)
.replace(/^(\s*(?:text|type)\s*:\s*)(.+?)\s*$/gm, (_match, before, text) => {
return `${before}${context.label(text)}`;
})
.replace(
/^(\s*)([^\s]+)(\s+-\s+[A-Za-z_]+\s+->\s+)([^\s]+)(\s*)$/gm,
(_match, before, from, arrow, to, after) => {
return `${before}${context.id(from)}${arrow}${context.id(to)}${after}`;
},
);
}
function katanaNormalizeQuadrantSourceI18n(context, source) {
return source
.replace(
/^(\s*title\s+)(.+?)\s*$/gm,
(_match, before, text) => `${before}${context.label(text)}`,
)
.replace(
/^(\s*[xy]-axis\s+)(.+?)(\s+-->\s+)(.+?)\s*$/gm,
(_match, before, left, arrow, right) =>
`${before}${context.label(left)}${arrow}${context.label(right)}`,
)
.replace(
/^(\s*quadrant-\d+\s+)(.+?)\s*$/gm,
(_match, before, text) => `${before}${context.label(text)}`,
)
.replace(
/^(\s*)([^:\n]+?)(\s*:\s*\[[^\]]+\]\s*)$/gm,
(_match, before, text, after) => `${before}${context.label(text)}${after}`,
);
}
function katanaNormalizeXyChartSourceI18n(context, source) {
return source
.replace(/^(\s*title\s+)"([^"]+)"\s*$/gm, (_match, before, text) => {
return `${before}"${context.label(text)}"`;
})
.replace(/^(\s*x-axis\s+\[)([^\]]+)(\]\s*)$/gm, (_match, before, labels, after) => {
return `${before}${katanaNormalizeCsvLabels(context, labels)}${after}`;
})
.replace(
/^(\s*y-axis\s+)"([^"]+)"(\s+[-\d.]+\s+-->\s+[-\d.]+\s*)$/gm,
(_match, before, text, after) => `${before}"${context.label(text)}"${after}`,
);
}
function katanaNormalizeSankeySourceI18n(context, source) {
return source.replace(/^([^,\n]+),([^,\n]+),(.+)$/gm, (_match, from, to, value) => {
return `${context.id(from)},${context.id(to)},${value}`;
});
}
function katanaNormalizeBracketLabelSourceI18n(context, source) {
return source.replace(/\[([^\]\n]+)\]/g, (match, text) =>
katanaBracketLabelSourceI18nReplacement(context, match, text),
);
}
function katanaNormalizeIshikawaSourceI18n(context, source) {
return source.replace(/^(\s*)([^\s].*?)\s*$/gm, (_match, before, text) =>
katanaIshikawaSourceI18nReplacement(context, before, text),
);
}
function katanaBracketLabelSourceI18nReplacement(context, match, text) {
return katanaBracketLabelSourceI18nReplacers()[Number(katanaNeedsI18nPlaceholder(text))](
context,
match,
text,
);
}
function katanaBracketLabelSourceI18nReplacers() {
return [katanaKeepBracketLabelSourceI18n, katanaReplaceBracketLabelSourceI18n];
}
function katanaKeepBracketLabelSourceI18n(_context, match) {
return match;
}
function katanaReplaceBracketLabelSourceI18n(context, _match, text) {
return `[${context.label(text)}]`;
}
function katanaIshikawaSourceI18nReplacement(context, before, text) {
return katanaIshikawaSourceI18nReplacers()[Number(text === "ishikawa-beta")](
context,
before,
text,
);
}
function katanaIshikawaSourceI18nReplacers() {
return [katanaReplaceIshikawaSourceI18n, katanaKeepIshikawaSourceI18n];
}
function katanaReplaceIshikawaSourceI18n(context, before, text) {
return `${before}${context.label(text)}`;
}
function katanaKeepIshikawaSourceI18n(_context, before, text) {
return `${before}${text}`;
}
function katanaNormalizeWardleySourceI18n(context, source) {
return source
.replace(
/^(\s*title\s+)(.+?)\s*$/gm,
(_match, before, text) => `${before}${context.label(text)}`,
)
.replace(
/^(\s*(?:anchor|component)\s+)(.+?)(\s+\[[^\]]+\].*)$/gm,
(_match, before, id, after) => `${before}${context.id(id)}${after}`,
)
.replace(
/^(\s*)(.+?)(\s*->\s*)(.+?)\s*$/gm,
(_match, before, from, arrow, to) => `${before}${context.id(from)}${arrow}${context.id(to)}`,
)
.replace(
/^(\s*evolve\s+)(.+?)(\s+[-\d.]+\s*)$/gm,
(_match, before, id, after) => `${before}${context.id(id)}${after}`,
)
.replace(/(\bnote\s+")([^"]+)(")/g, (_match, before, text, after) => {
return `${before}${context.label(text)}${after}`;
});
}
function katanaNormalizeCsvLabels(context, labels) {
return labels
.split(",")
.map((label) => {
const trimmed = label.trim();
return label.replace(trimmed, context.label(trimmed));
})
.join(",");
}
/* mermaid-diagram-type.js */
function katanaMermaidDiagramType(source) {
const lines = String(source)
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line.length > 0);
return katanaMermaidDiagramTypeLine(lines)?.split(/\s+/)[0].toLowerCase() ?? "";
}
function katanaMermaidDiagramTypeLine(lines) {
const bodyLines = katanaMermaidDiagramTypeLineReaders()[Number(lines[0] === "---")](lines);
return bodyLines.find((line) => !katanaMermaidIsDirectiveOrComment(line));
}
function katanaMermaidDiagramTypeLineReaders() {
return [katanaMermaidFirstDiagramTypeLine, katanaMermaidFrontmatterDiagramTypeLine];
}
function katanaMermaidFirstDiagramTypeLine(lines) {
return lines;
}
function katanaMermaidFrontmatterDiagramTypeLine(lines) {
const endIndex = lines.slice(1).indexOf("---");
return lines.slice(katanaMermaidFrontmatterBodyStartIndex(endIndex));
}
function katanaMermaidFrontmatterBodyStartIndex(endIndex) {
return [0, endIndex + 2][Number(endIndex >= 0)];
}
function katanaMermaidIsDirectiveOrComment(line) {
return line.startsWith("%%");
}
/* svg-zenuml-fixes.js */
function katanaNormalizeZenumlRuntimeSvg(svg, request) {
if (!katanaShouldNormalizeZenumlRuntimeSvg(svg, request)) {
return svg;
}
return katanaZenumlRuntimeShiftThresholds(svg, request.source).reduce(
(current, threshold, index) =>
katanaApplyZenumlRuntimeVerticalShift(current, threshold + index * 20, 20),
svg,
);
}
function katanaShouldNormalizeZenumlRuntimeSvg(svg, request) {
return [
svg.includes('id="katana-mermaid-svg-'),
svg.includes('aria-roledescription="zenuml"'),
katanaMermaidDiagramType(request.source) === "zenuml",
katanaZenumlCommentedContainerCount(request.source) > 0,
].every(Boolean);
}
function katanaZenumlRuntimeShiftThresholds(svg, source) {
return katanaZenumlCommentYValues(svg)
.slice(0, katanaZenumlCommentedContainerCount(source))
.map((y) => y + 22);
}
function katanaZenumlCommentYValues(svg) {
return Array.from(
svg.matchAll(/<text class="comment-text">[\s\S]*?<tspan\b[^>]*\by="(-?\d+(?:\.\d+)?)"/g),
)
.map((match) => Number(match[1]))
.filter(Number.isFinite);
}
function katanaZenumlCommentedContainerCount(source) {
let pendingComment = false;
let count = 0;
for (const line of source.split(/\r?\n/)) {
const trimmed = line.trim();
if (trimmed.startsWith("//")) {
pendingComment = true;
continue;
}
if (!trimmed) {
pendingComment = false;
continue;
}
if (pendingComment && katanaZenumlLineStartsContainerMessage(trimmed)) {
count += 1;
}
pendingComment = false;
}
return count;
}
function katanaZenumlLineStartsContainerMessage(line) {
return [
line.endsWith("{"),
!line.startsWith("@"),
!/^(alt|critical|else|finally|group|if|loop|opt|par|section|try)\b/.test(line),
].every(Boolean);
}
function katanaApplyZenumlRuntimeVerticalShift(svg, threshold, shift) {
return katanaShiftZenumlYAttributes(
katanaShiftZenumlTransforms(
katanaShiftZenumlPolylinePoints(
katanaExpandZenumlCrossingRects(
katanaExpandZenumlRootHeight(svg, shift),
threshold,
shift,
),
threshold,
shift,
),
threshold,
shift,
),
threshold,
shift,
);
}
function katanaExpandZenumlRootHeight(svg, shift) {
return svg
.replace(/(<svg\b[^>]*\bheight=")(-?\d+(?:\.\d+)?)/, (_match, before, height) =>
`${before}${katanaFormatZenumlNumber(Number(height) + shift)}`,
)
.replace(/(<svg\b[^>]*\bviewBox=")([^"]+)(")/, (_match, before, viewBox, after) => {
const values = viewBox.split(/\s+/).map(Number);
if (values.length !== 4 || values.some((value) => !Number.isFinite(value))) {
return `${before}${viewBox}${after}`;
}
values[3] += shift;
return `${before}${values.map(katanaFormatZenumlNumber).join(" ")}${after}`;
});
}
function katanaExpandZenumlCrossingRects(svg, threshold, shift) {
return svg.replace(/<rect\b[^>]*>/g, (tag) => {
const y = katanaZenumlAttrNumber(tag, "y");
const height = katanaZenumlAttrNumber(tag, "height");
if (y === null || height === null || y >= threshold || y + height <= threshold) {
return tag;
}
return katanaReplaceZenumlAttrNumber(tag, "height", height + shift);
});
}
function katanaShiftZenumlYAttributes(svg, threshold, shift) {
return svg.replace(/\b(y|y1|y2)="(-?\d+(?:\.\d+)?)"/g, (_match, name, value) =>
Number(value) > threshold
? `${name}="${katanaFormatZenumlNumber(Number(value) + shift)}"`
: `${name}="${value}"`,
);
}
function katanaShiftZenumlPolylinePoints(svg, threshold, shift) {
return svg.replace(/\bpoints="([^"]+)"/g, (_match, points) => {
const shifted = points.replace(
/(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)/g,
(_point, x, y) =>
Number(y) > threshold
? `${x},${katanaFormatZenumlNumber(Number(y) + shift)}`
: `${x},${y}`,
);
return `points="${shifted}"`;
});
}
function katanaShiftZenumlTransforms(svg, threshold, shift) {
return svg.replace(
/transform="translate\((-?\d+(?:\.\d+)?)(,\s*|\s+)(-?\d+(?:\.\d+)?)(\)[^"]*)"/g,
(_match, x, separator, y, suffix) =>
Number(y) > threshold
? `transform="translate(${x}${separator}${katanaFormatZenumlNumber(
Number(y) + shift,
)}${suffix}"`
: `transform="translate(${x}${separator}${y}${suffix}"`,
);
}
function katanaZenumlAttrNumber(tag, name) {
const match = tag.match(new RegExp(`\\b${name}="(-?\\d+(?:\\.\\d+)?)"`));
return match ? Number(match[1]) : null;
}
function katanaReplaceZenumlAttrNumber(tag, name, value) {
const pattern = new RegExp(`\\b${name}="(-?\\d+(?:\\.\\d+)?)"`);
return tag.replace(pattern, `${name}="${katanaFormatZenumlNumber(value)}"`);
}
function katanaFormatZenumlNumber(value) {
return Number(value.toFixed(6)).toString();
}
/* svg-normalize.js */
function katanaPrepareMermaidSource(source) {
if (!katanaShouldAppendTodayMarkerOff(source)) {
return source;
}
return katanaSourceWithTodayMarker(source);
}
function katanaShouldAppendTodayMarkerOff(source) {
if (!source.trimStart().startsWith("gantt")) {
return false;
}
return !/\btodayMarker\b/.test(source);
}
function katanaSourceWithTodayMarker(source) {
return source.trim().endsWith("\n") ? `${source}todayMarker off` : `${source}\ntodayMarker off`;
}
function katanaNormalizeMermaidSvg(svg, request) {
return katanaFinishNormalizedSvg(katanaNormalizeColoredMermaidSvg(svg, request), request);
}
function katanaNormalizeColoredMermaidSvg(svg, request) {
return katanaNormalizeDiagramSpecificSvg(
katanaNormalizeNativeSvgFallbacks(
katanaNormalizeNegativeRectWidths(katanaNormalizeC4RelationColors(svg, request)),
request,
),
request,
);
}
function katanaFinishNormalizedSvg(svg, request) {
return katanaNormalizeFinalSvg(svg, request);
}
function katanaSetNormalizedSvgSize(svg, dimensions) {
const width = katanaNormalizedSvgWidth(dimensions);
const height = katanaNormalizedSvgHeight(dimensions);
return katanaSetSvgMaxWidth(
katanaSetSvgViewBox(
katanaSetSvgDimension(katanaSetSvgDimension(svg, "width", width), "height", height),
dimensions.join(" "),
),
width,
);
}
function katanaNormalizedSvgWidth(dimensions) {
return String(Math.max(1, Math.ceil(dimensions[2] * katanaSvgDimensionScale())));
}
function katanaNormalizedSvgHeight(dimensions) {
return String(Math.max(1, Math.ceil(dimensions[3] * katanaSvgDimensionScale())));
}
function katanaSvgDimensionScale() {
return 1;
}
function katanaNormalizeFinalSvg(svg, request) {
return katanaNormalizeErViewBox(
katanaNormalizeIshikawaSvg(
katanaEscapeTextMarkers(
katanaNormalizeEmptyTextFill(katanaNormalizeFontFamilyAttributes(svg), request),
),
),
);
}
function katanaNormalizeDiagramSpecificSvg(svg, request) {
let normalized = svg;
normalized = katanaNormalizeTreeViewSvg(normalized, request);
normalized = katanaNormalizeTreemapSvg(normalized, request);
normalized = katanaNormalizeClassSvg(normalized);
normalized = katanaNormalizeErSvg(normalized);
normalized = katanaNormalizeFlowchartEdgeLabelSvg(normalized, request);
normalized = katanaNormalizeFlowchartViewBoxSvg(normalized);
normalized = katanaNormalizeStateEdgeLabelSvg(normalized, request);
normalized = katanaNormalizeRequirementEdgeLabelSvg(normalized);
normalized = katanaNormalizeJourneySvg(normalized, request);
normalized = katanaNormalizePieSvg(normalized);
normalized = katanaNormalizeVennSvg(normalized, request);
normalized = katanaNormalizeArchitectureSvg(normalized, request);
normalized = katanaNormalizeRadarSvg(normalized);
normalized = katanaNormalizeGitGraphSvg(normalized);
normalized = katanaNormalizeKanbanSvg(normalized, request);
normalized = katanaNormalizeSankeySvg(normalized);
normalized = katanaNormalizeMindmapSvg(normalized);
normalized = katanaNormalizeBlockSvg(normalized);
normalized = katanaNormalizeWardleySvg(normalized, request);
normalized = katanaNormalizeIshikawaSvg(normalized);
normalized = katanaNormalizeZenumlRuntimeSvg(normalized, request);
normalized = katanaNormalizeReviewFeedbackSvg(normalized, request);
normalized = katanaNormalizeSequenceActivationSvg(normalized);
return normalized;
}
function katanaNormalizeFontFamilyAttributes(svg) {
return svg.replace(
/font-family=""([^"]+)",\s*([^"]*)"/g,
(_match, family, fallback) => `font-family="${family}, ${fallback}"`,
);
}
function katanaEscapeTextMarkers(svg) {
return svg.replace(/<<([^<>]+)>>/g, "<<$1>>");
}
/* mermaid-runtime-entrypoint */
function katanaInstallMermaidZenumlRuntimeAdapter() {
const zenumlDiagram = globalThis["mermaid-zenuml"];
if (zenumlDiagram) {
globalThis.__katanaMermaidZenuml = zenumlDiagram;
}
}
function katanaRunMermaidRuntime(request) {
return (async () => katanaRenderMermaid(request))().catch((error) => {
const detail = error?.stack ? error.stack : String(error);
throw new Error(detail);
});
}
async function katanaRenderMermaid(request) {
const mermaidValue = katanaMermaidGlobal();
mermaidValue.initialize({
startOnLoad: false,
securityLevel: "loose",
htmlLabels: false,
theme: request.theme,
flowchart: {
htmlLabels: false,
useMaxWidth: false,
},
sequence: {
useMaxWidth: false,
},
themeVariables: katanaMermaidThemeVariables(request),
});
const preparedSource = katanaNormalizeMermaidSourceI18n(
katanaPrepareMermaidSource(request.source),
);
const diagramType = request.diagramType || katanaMermaidDiagramType(preparedSource.source);
globalThis.__katanaMermaidDiagramType = diagramType;
await katanaRegisterMermaidExternalDiagram(mermaidValue, diagramType);
const result = await mermaidValue.render(request.svgId, preparedSource.source);
return katanaNormalizeMermaidSvg(
katanaRestoreMermaidI18nText(result.svg, preparedSource.replacements),
request,
);
}
function katanaMermaidGlobal() {
const mermaidValue = [globalThis.mermaid, globalThis.window.mermaid].find(Boolean);
if (!mermaidValue) {
throw new Error("Mermaid global was not registered");
}
return mermaidValue;
}
async function katanaRegisterMermaidExternalDiagram(mermaidValue, diagramType) {
if (diagramType !== "zenuml") {
return;
}
const zenumlDiagram = globalThis.__katanaMermaidZenuml;
if (!zenumlDiagram) {
throw new Error("ZenUML runtime asset was not registered");
}
if (typeof mermaidValue.registerExternalDiagrams !== "function") {
throw new Error("Mermaid runtime cannot register external diagrams");
}
await mermaidValue.registerExternalDiagrams([zenumlDiagram]);
}
function katanaMermaidThemeVariables(request) {
return {
background: request.background,
mainBkg: request.fill,
primaryColor: request.fill,
primaryTextColor: request.text,
primaryBorderColor: request.stroke,
secondaryColor: request.fill,
secondaryTextColor: request.text,
secondaryBorderColor: request.stroke,
tertiaryColor: request.fill,
tertiaryTextColor: request.text,
tertiaryBorderColor: request.stroke,
nodeTextColor: request.text,
lineColor: request.arrow,
textColor: request.text,
edgeLabelBackground: request.fill,
actorBkg: request.fill,
actorTextColor: request.text,
actorBorder: request.stroke,
signalColor: request.arrow,
signalTextColor: request.text,
labelTextColor: request.text,
noteBkgColor: request.fill,
noteTextColor: request.text,
noteBorderColor: request.stroke,
clusterBkg: request.background,
clusterBorder: request.stroke,
titleColor: request.text,
};
}