mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-25 02:32:47 +00:00
fix(markdown): preserve first definitions across Mermaid segments
This commit is contained in:
@@ -11,10 +11,11 @@ interface Segment {
|
||||
export function splitMermaidFences(markdown: string): Segment[] {
|
||||
if (!/mermaid/i.test(markdown)) return [{ kind: "markdown", id: "0", source: markdown }];
|
||||
const segments: Segment[] = [];
|
||||
const definitions: Definition[] = [];
|
||||
const definitions = new Map<string, Definition>();
|
||||
let cursor = 0;
|
||||
function visit(node: RootContent): void {
|
||||
if (node.type === "definition") definitions.push(node);
|
||||
if (node.type === "definition" && !definitions.has(node.identifier))
|
||||
definitions.set(node.identifier, node);
|
||||
if (node.type === "code" && node.lang?.toLowerCase() === "mermaid" && node.position) {
|
||||
const start = node.position.start.offset!;
|
||||
const end = node.position.end.offset!;
|
||||
@@ -36,9 +37,10 @@ export function splitMermaidFences(markdown: string): Segment[] {
|
||||
id: String(segments.length),
|
||||
source: markdown.slice(cursor),
|
||||
});
|
||||
// Reference links keep their document-wide scope on both sides of a diagram.
|
||||
// Prepend the document's first definitions after splitting, so fragment-local
|
||||
// duplicates cannot override them. Original source slices and fence offsets stay intact.
|
||||
if (segments.some((segment) => segment.kind === "mermaid")) {
|
||||
const referenceSource = definitions
|
||||
const referenceSource = [...definitions.values()]
|
||||
.map((node) => {
|
||||
const label = node.identifier.replace(/[\\[\]]/g, "\\$&");
|
||||
const url = node.url.replace(/[\\<>]/g, "\\$&");
|
||||
@@ -48,7 +50,7 @@ export function splitMermaidFences(markdown: string): Segment[] {
|
||||
.join("\n");
|
||||
if (referenceSource)
|
||||
for (const segment of segments) {
|
||||
if (segment.kind === "markdown") segment.source += `\n\n${referenceSource}`;
|
||||
if (segment.kind === "markdown") segment.source = `${referenceSource}\n\n${segment.source}`;
|
||||
}
|
||||
}
|
||||
return segments;
|
||||
|
||||
@@ -369,3 +369,25 @@ it("retries transient image decoding failures instead of caching an unavailable
|
||||
expect(attempts).toBe(2);
|
||||
client.clear();
|
||||
});
|
||||
|
||||
it("keeps the document's first reference definition across every native Mermaid segment", async () => {
|
||||
const { fromMarkdown } = await import("mdast-util-from-markdown");
|
||||
const { splitMermaidFences } = await import("./fence/mermaid/segments");
|
||||
const before = '[first]: /repo/first.ts "Original"\n\n';
|
||||
const after = '\n\n[open][first]\n\n[first]: /repo/second.ts "Later"';
|
||||
const source = `${before}\`\`\`mermaid\ngraph TD\nA-->B\n\`\`\`${after}`;
|
||||
const firstDefinition = (markdown: string) =>
|
||||
fromMarkdown(markdown).children.find((node) => node.type === "definition");
|
||||
const canonical = firstDefinition(source);
|
||||
const segments = splitMermaidFences(source);
|
||||
for (const segment of segments.filter((candidate) => candidate.kind === "markdown")) {
|
||||
expect(firstDefinition(segment.source)).toMatchObject({
|
||||
identifier: canonical?.identifier,
|
||||
url: canonical?.url,
|
||||
title: canonical?.title,
|
||||
});
|
||||
}
|
||||
expect(segments[0].source.endsWith(before)).toBe(true);
|
||||
expect(segments[2].source.endsWith(after)).toBe(true);
|
||||
expect(segments[1]).toEqual({ kind: "mermaid", id: "1", source: "graph TD\nA-->B" });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user