mirror of
https://github.com/runbear-io/beardrive.git
synced 2026-08-25 08:08:08 +02:00
feat(webapp): mermaid fences render as diagrams, in the viewer and on share pages (BEA-91) (#143)
A ```mermaid fence rendered as a wall of `graph TD` source on both surfaces. It now renders as an SVG in the hub file viewer and on public /s/<token> markdown share pages. Mermaid ships inside the binary (no CDN, so air-gapped self-hosters keep working) and is imported lazily: a document with no fence downloads none of it. A fence that doesn't parse — the common case for hand-written wiki diagrams — keeps today's <pre><code> plus a small note, and one bad fence never stops the good ones beside it. A blocked or offline chunk lands in the same place. The share page is the harder half: it is server-rendered Go HTML with no JavaScript, and its `sandbox allow-scripts` CSP makes the origin opaque, so a module script and every import() it makes arrive with `Origin: null`. The CSP is unchanged and gains no allow-same-origin; instead the real-asset branch of frontend() now sets Access-Control-Allow-Origin, which only ever touches files that are already public and cookie-less. The script tag itself is injected only when the rendered document actually contains a fence. Also fixes an embed bug this change surfaced: `//go:embed static` silently skips names beginning with `_`, and Vite's first shared chunk is `_commonjsHelpers-<hash>.js`. The build passed, the commit looked right, and the served app was blank. It is `all:static` now, with a test that every file on disk is in the binary.
This commit is contained in:
@@ -146,3 +146,29 @@ func TestFrontendSPAFallback(t *testing.T) {
|
||||
t.Fatalf("/api/bogus: want 404, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// Every file the frontend build wrote must actually be IN the binary. A bare
|
||||
// `//go:embed static` skips names starting with `_` or `.`, which is how Vite's
|
||||
// first `_commonjsHelpers-<hash>.js` chunk went missing: the build passes, the
|
||||
// commit looks right, and the running app answers that chunk with index.html
|
||||
// until the browser refuses the whole entry over its MIME type. Nothing about
|
||||
// that is visible without loading the page, so it is asserted here instead.
|
||||
func TestEveryBuiltAssetIsEmbedded(t *testing.T) {
|
||||
built := os.DirFS("static")
|
||||
embedded, err := fs.Sub(staticFiles, "static")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = fs.WalkDir(built, ".", func(p string, d fs.DirEntry, err error) error {
|
||||
if err != nil || d.IsDir() {
|
||||
return err
|
||||
}
|
||||
if _, err := fs.Stat(embedded, p); err != nil {
|
||||
t.Errorf("static/%s is on disk but not in the binary — //go:embed needs the all: prefix for a name like this", p)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,6 +288,13 @@ func seedE2E(t *testing.T, state, prefix, projectID string) {
|
||||
// content, so their rows stay unclickable while every other row is now an
|
||||
// address for its own version.
|
||||
put("scratch.md", "# Scratch\n\nTemporary.\n", 12*time.Hour)
|
||||
// One good fence and one deliberately broken one on the same page: the
|
||||
// point of the fallback is that a diagram nobody can parse doesn't take
|
||||
// the diagrams around it down with it. Appended LAST on purpose — the
|
||||
// mutations above address ops by index, so an insert anywhere earlier
|
||||
// hands one file's author or note to another file.
|
||||
put("diagram.md", "# Diagram\n\n```mermaid\ngraph TD\n A[Agent] --> B[Hub]\n B --> C[Teammate]\n```\n\n"+
|
||||
"Broken one below.\n\n```mermaid\ngraph TD\n A[[[[ --> ???\n```\n", 24*time.Hour)
|
||||
lam++
|
||||
seq++
|
||||
ops = append(ops, journal.Op{
|
||||
|
||||
@@ -1013,3 +1013,51 @@ test("a wide csv scrolls inside its own box at 390px", async ({ page }) => {
|
||||
await page.evaluate(() => document.documentElement.scrollWidth > window.innerWidth + 1),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("mermaid: a good fence renders, a broken one keeps its code block", async ({ page }) => {
|
||||
await login(page);
|
||||
const pid = await wikiId(page);
|
||||
await page.goto(`/${pid}/diagram.md`);
|
||||
// The valid fence became a diagram...
|
||||
const svg = page.locator("#content .mermaid-diagram svg");
|
||||
await expect(svg).toHaveCount(1);
|
||||
await expect(svg).toContainText("Teammate");
|
||||
// ...and the broken one below it kept today's <pre><code> plus a note. One
|
||||
// bad fence must not take the good one on the same page down with it.
|
||||
await expect(page.locator("#content pre code.language-mermaid")).toHaveCount(1);
|
||||
await expect(page.locator("#content .mermaid-err")).toHaveText("Couldn't render this diagram.");
|
||||
});
|
||||
|
||||
test("a file with no mermaid fence fetches no mermaid chunk", async ({ page }) => {
|
||||
await login(page);
|
||||
const pid = await wikiId(page);
|
||||
// mermaid.core is the library; the *Diagram-* chunks are its per-grammar
|
||||
// splits. lib/mermaid.ts itself is a static import of the app entry (a few
|
||||
// KB of gate, no mermaid code in it), which is exactly why the gate is a
|
||||
// plain string check and not something that has to load mermaid to answer.
|
||||
const fetched: string[] = [];
|
||||
page.on("request", (r) => /mermaid\.core|Diagram-/.test(r.url()) && fetched.push(r.url()));
|
||||
await page.goto(`/${pid}/guide.md`);
|
||||
await expect(page.locator("#content")).toContainText("Second version");
|
||||
await page.waitForTimeout(500);
|
||||
expect(fetched).toEqual([]);
|
||||
});
|
||||
|
||||
test("a shared diagram renders on the public page, without one there is no script", async ({
|
||||
page,
|
||||
}) => {
|
||||
await login(page);
|
||||
const pid = await wikiId(page);
|
||||
const mint = async (path: string) =>
|
||||
(await (await page.request.post(`/api/p/${pid}/shares`, { data: { path } })).json()).token;
|
||||
|
||||
// Diagram-free share pages stay the zero-JavaScript document they were.
|
||||
const plain = await page.request.get(`/s/${await mint("index.md")}`);
|
||||
expect(await plain.text()).not.toContain("<script");
|
||||
|
||||
await page.goto(`/s/${await mint("diagram.md")}`);
|
||||
const svg = page.locator(".mermaid-diagram svg");
|
||||
await expect(svg).toHaveCount(1);
|
||||
await expect(svg).toContainText("Teammate");
|
||||
await expect(page.locator(".mermaid-err")).toHaveText("Couldn't render this diagram.");
|
||||
});
|
||||
|
||||
+1095
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
"lucide-react": "^1.25.0",
|
||||
"mermaid": "^11.16.1",
|
||||
"radix-ui": "^1.6.2",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
whoChanged,
|
||||
} from "../util";
|
||||
import { CSV_ROWS, parseDelimited, type Csv } from "../lib/csv";
|
||||
import { hasMermaid, renderMermaid } from "../lib/mermaid";
|
||||
|
||||
export function FileView(props: {
|
||||
apiBase: string;
|
||||
@@ -151,6 +152,25 @@ function MarkdownView(props: Parameters<typeof FileView>[0]) {
|
||||
[doc, path, apiBase],
|
||||
);
|
||||
|
||||
// Diagrams are rendered into a NEW html string and fed back through state,
|
||||
// so the one dangerouslySetInnerHTML below re-mounts with the SVG already
|
||||
// in it — the same reason transformHTML runs before the mount and not after
|
||||
// it. Runs on transformHTML's output, so a diagram's SVG never goes through
|
||||
// the img/link rewriting pass.
|
||||
const [diagrams, setDiagrams] = useState<string | null>(null);
|
||||
useEffect(() => {
|
||||
setDiagrams(null);
|
||||
if (!hasMermaid(html)) return; // no fence: mermaid is never downloaded
|
||||
let cancelled = false;
|
||||
renderMermaid(html).then((out) => {
|
||||
// A slow render of the file we just left must not paint over this one.
|
||||
if (!cancelled) setDiagrams(out);
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [html]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!doc) return;
|
||||
const parts: string[] = [];
|
||||
@@ -176,7 +196,7 @@ function MarkdownView(props: Parameters<typeof FileView>[0]) {
|
||||
// classic app assigning innerHTML.
|
||||
return (
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
dangerouslySetInnerHTML={{ __html: diagrams ?? html }}
|
||||
onClick={(e) => handleLinkClick(e, path, flatFiles, onOpenFile)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/* Mermaid fences -> SVG, shared by the hub viewer and the /s/ share page.
|
||||
|
||||
HTML string in, HTML string out: it never mutates a live DOM. The viewer
|
||||
feeds the result back through state into its single dangerouslySetInnerHTML
|
||||
(CLAUDE.md: React re-applies that markup on unrelated updates and silently
|
||||
discards post-commit DOM patches), and the share page assigns the result
|
||||
itself.
|
||||
|
||||
Failure is the common path, not the edge case — hand-written diagrams in a
|
||||
wiki fail to parse often. A fence that doesn't parse, a render that throws,
|
||||
and a chunk that never loads all end up at the same place: today's
|
||||
<pre><code> block, plus a small note. One bad fence never stops the good
|
||||
ones beside it. */
|
||||
|
||||
const SEL = "pre > code.language-mermaid";
|
||||
|
||||
// Colours come from the surrounding surface rather than mermaid's stock
|
||||
// palette. The hub app is dark-only; the share page follows the OS.
|
||||
export type Palette = {
|
||||
bg: string; // diagram node fill
|
||||
line: string; // node borders and edges
|
||||
text: string; // labels
|
||||
accent: string; // the one highlight (cluster borders, note edges)
|
||||
};
|
||||
|
||||
export const DARK: Palette = { bg: "#15171b", line: "#9aa0a9", text: "#eef0f3", accent: "#f5a623" };
|
||||
export const LIGHT: Palette = { bg: "#f6f8fa", line: "#57606a", text: "#24292f", accent: "#b26a00" };
|
||||
|
||||
/** True when html contains at least one mermaid fence — cheap enough to gate
|
||||
* the dynamic import on, so a document without one downloads no mermaid. */
|
||||
export function hasMermaid(html: string): boolean {
|
||||
return html.includes('class="language-mermaid"');
|
||||
}
|
||||
|
||||
/** Renders every mermaid fence in html and returns the new HTML. Returns html
|
||||
* unchanged (importing nothing) when there are no fences, or when mermaid
|
||||
* itself fails to load. */
|
||||
export async function renderMermaid(html: string, palette: Palette = DARK): Promise<string> {
|
||||
if (!hasMermaid(html)) return html;
|
||||
const doc = new DOMParser().parseFromString(html, "text/html");
|
||||
const blocks = [...doc.querySelectorAll(SEL)];
|
||||
if (!blocks.length) return html;
|
||||
|
||||
let mermaid;
|
||||
try {
|
||||
mermaid = (await import("mermaid")).default;
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
// The source is teammate-authored content on a page that carries a
|
||||
// signed-in hub session. Don't relax this for htmlLabels.
|
||||
securityLevel: "strict",
|
||||
theme: "base",
|
||||
fontFamily: "inherit",
|
||||
themeVariables: {
|
||||
background: "transparent",
|
||||
primaryColor: palette.bg,
|
||||
primaryTextColor: palette.text,
|
||||
primaryBorderColor: palette.line,
|
||||
secondaryColor: palette.bg,
|
||||
tertiaryColor: palette.bg,
|
||||
lineColor: palette.line,
|
||||
textColor: palette.text,
|
||||
mainBkg: palette.bg,
|
||||
nodeBorder: palette.line,
|
||||
clusterBkg: "transparent",
|
||||
clusterBorder: palette.accent,
|
||||
titleColor: palette.text,
|
||||
edgeLabelBackground: palette.bg,
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
return html; // chunk blocked or offline: today's code blocks, untouched
|
||||
}
|
||||
|
||||
for (const [i, code] of blocks.entries()) {
|
||||
const pre = code.parentElement!;
|
||||
try {
|
||||
// Unique per call as well as per block: two renders of the same
|
||||
// document must not collide on an element id.
|
||||
const id = "mmd-" + Math.random().toString(36).slice(2) + "-" + i;
|
||||
const { svg } = await mermaid.render(id, code.textContent || "");
|
||||
const wrap = doc.createElement("div");
|
||||
wrap.className = "mermaid-diagram";
|
||||
wrap.innerHTML = svg;
|
||||
pre.replaceWith(wrap);
|
||||
} catch {
|
||||
const note = doc.createElement("div");
|
||||
note.className = "mermaid-err";
|
||||
note.textContent = "Couldn't render this diagram.";
|
||||
pre.after(note);
|
||||
}
|
||||
}
|
||||
// mermaid.render measures in a temporary `d<id>` element on the live body
|
||||
// and normally removes it itself; a throw mid-render can leave one behind.
|
||||
// Deliberately `dmmd-` ONLY — sweeping `mmd-` would match the SVGs already
|
||||
// MOUNTED from an earlier file and delete them, which is the post-commit
|
||||
// DOM patch this whole helper exists to avoid.
|
||||
for (const stray of document.querySelectorAll("[id^='dmmd-']")) stray.remove();
|
||||
return doc.body.innerHTML;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/* The share page's only script. Injected by shares.go ONLY when the shared
|
||||
document contains a mermaid fence, so a diagram-free share page still
|
||||
downloads nothing.
|
||||
|
||||
No framework owns this DOM, so the rendered string goes straight back into
|
||||
document.body. The page is served under `sandbox allow-scripts` with an
|
||||
opaque origin — a module script and its import() both need
|
||||
Access-Control-Allow-Origin on the static assets (server.go), which is why
|
||||
this is a module rather than one self-contained classic bundle. */
|
||||
import { renderMermaid, DARK, LIGHT } from "./lib/mermaid";
|
||||
|
||||
// Picked once, at load: the shell's colours come from a prefers-color-scheme
|
||||
// block, and mermaid bakes its palette in at render time.
|
||||
const dark = matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
|
||||
renderMermaid(document.body.innerHTML, dark ? DARK : LIGHT).then((html) => {
|
||||
document.body.innerHTML = html;
|
||||
});
|
||||
@@ -1063,6 +1063,12 @@ a.ai-main:hover { color: var(--accent); }
|
||||
.markdown tr:hover td { background: rgba(255,255,255,.02); }
|
||||
.markdown img { max-width: 100%; border-radius: 8px; border: 1px solid var(--border); }
|
||||
.markdown hr { border: none; border-top: 1px solid var(--border); margin: 2.2em 0; }
|
||||
/* Rendered mermaid. The note is what a fence that doesn't parse gets, sitting
|
||||
under the code block it kept — quiet, since a wiki full of hand-written
|
||||
diagrams would otherwise be a wall of red. */
|
||||
.markdown .mermaid-diagram { margin: 1.3em 0; overflow-x: auto; }
|
||||
.markdown .mermaid-diagram svg { max-width: 100%; height: auto; }
|
||||
.markdown .mermaid-err { margin: -.9em 0 1.3em; font-size: 12px; color: var(--text-faint); }
|
||||
/* Frontmatter key/value table (server-rendered from a doc's YAML header). */
|
||||
.markdown table.frontmatter { margin: 0 0 1.8em; font-size: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; border-collapse: separate; border-spacing: 0; }
|
||||
.markdown table.frontmatter th { text-transform: none; letter-spacing: 0; font-size: 11.5px; color: var(--text-faint); font-weight: 600; text-align: left; white-space: nowrap; vertical-align: top; padding: 6px 14px 6px 12px; border-bottom: 1px solid var(--border); }
|
||||
|
||||
@@ -13,7 +13,27 @@ const target = process.env.BDRIVE_DEV_PROXY || "http://localhost:8080";
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
resolve: { alias: { "@": path.resolve(__dirname, "src") } },
|
||||
build: { outDir: "../static", emptyOutDir: true },
|
||||
build: {
|
||||
outDir: "../static",
|
||||
emptyOutDir: true,
|
||||
rollupOptions: {
|
||||
// Two entries: the SPA, and the one script the server-rendered /s/
|
||||
// share page loads when its document has a mermaid fence.
|
||||
input: {
|
||||
index: path.resolve(__dirname, "index.html"),
|
||||
"share-mermaid": path.resolve(__dirname, "src/share-mermaid.ts"),
|
||||
},
|
||||
output: {
|
||||
// Fixed name OUTSIDE assets/: sharedMarkdownShell is a const string
|
||||
// and can't know a content hash, and server.go marks assets/
|
||||
// immutable for a year — an unhashed file there would pin a stale
|
||||
// bundle in shared caches. At the static root it gets no-cache.
|
||||
// Mermaid's own chunks keep the hashed assets/ names.
|
||||
entryFileNames: (c) =>
|
||||
c.name === "share-mermaid" ? "[name].js" : "assets/[name]-[hash].js",
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
// Everything the Go server owns; the frontend itself only ever uses
|
||||
|
||||
@@ -45,7 +45,14 @@ import (
|
||||
"github.com/runbear-io/beardrive/internal/templates"
|
||||
)
|
||||
|
||||
//go:embed static
|
||||
// all:, not a bare `static` — a bare embed silently skips every file whose
|
||||
// name begins with `_` or `.`, and Vite names shared chunks after the module
|
||||
// they came from (`_commonjsHelpers-<hash>.js` is the first one this build
|
||||
// produces). The miss is invisible at build time and total at runtime: the
|
||||
// chunk 404s, the SPA fallback answers with index.html, and the browser
|
||||
// refuses the whole entry over its MIME type — a blank app, not a degraded one.
|
||||
//
|
||||
//go:embed all:static
|
||||
var staticFiles embed.FS
|
||||
|
||||
// Source supplies the file set and content of one volume. Implementations:
|
||||
@@ -820,6 +827,18 @@ func (s *Server) frontend(static fs.FS) http.HandlerFunc {
|
||||
if strings.HasPrefix(upath, "assets/") {
|
||||
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
|
||||
}
|
||||
// The /s/ share page runs under `sandbox allow-scripts`, so
|
||||
// its origin is opaque: a module script and every import()
|
||||
// it makes are fetched with `Origin: null` and blocked
|
||||
// without this. That is how share-mermaid.js and mermaid's
|
||||
// chunks reach a share page at all.
|
||||
//
|
||||
// On the real asset ONLY, never on the index.html fallback
|
||||
// below: these files are already public, unauthenticated
|
||||
// and cookie-less, and `*` forbids credentialed requests by
|
||||
// definition, so this grants a cross-origin reader nothing
|
||||
// it could not already fetch in no-cors mode.
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
files.ServeHTTP(w, r) // a real asset
|
||||
return
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ func (s *Server) handleShared(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
fmt.Fprintf(cw, sharedMarkdownShell, html.EscapeString(path.Base(sp)), updatedStamp(fi.Time), body)
|
||||
fmt.Fprintf(cw, sharedMarkdownShell, html.EscapeString(path.Base(sp)), mermaidTag(body), updatedStamp(fi.Time), body)
|
||||
case ".html", ".htm":
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
io.Copy(cw, rc)
|
||||
@@ -590,8 +590,25 @@ func updatedStamp(t time.Time) string {
|
||||
html.EscapeString(t.Format(time.RFC3339)), html.EscapeString(t.Format("2 Jan 2006")))
|
||||
}
|
||||
|
||||
// mermaidTag is the share page's only script, and only when the document
|
||||
// actually has a diagram in it — a share page without a mermaid fence must
|
||||
// stay the byte-for-byte zero-JavaScript document it has always been.
|
||||
//
|
||||
// The tag is a module: under this page's sandbox CSP the origin is opaque, so
|
||||
// the asset responses carry Access-Control-Allow-Origin (server.go) and
|
||||
// mermaid keeps its code splitting instead of arriving as one file. The name
|
||||
// is fixed and lives outside assets/ because this template cannot know Vite's
|
||||
// content hash.
|
||||
func mermaidTag(body string) string {
|
||||
if !strings.Contains(body, `class="language-mermaid"`) {
|
||||
return ""
|
||||
}
|
||||
return `<script type="module" src="/share-mermaid.js"></script>`
|
||||
}
|
||||
|
||||
// sharedMarkdownShell wraps rendered markdown in a minimal readable page.
|
||||
// Verbs, in order: title, updated stamp, body.
|
||||
// Verbs, in order: title, mermaid script tag (usually empty), updated stamp,
|
||||
// body.
|
||||
const sharedMarkdownShell = `<!doctype html><html lang="en"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"><title>%s</title>
|
||||
<style>
|
||||
@@ -614,6 +631,9 @@ pre{max-width:100%%}
|
||||
footer.bdrive{margin-top:64px;padding-top:14px;border-top:1px solid #d0d7de;font-size:12.5px;color:#57606a}
|
||||
footer.bdrive a{color:inherit}
|
||||
.updated{font-size:12.5px;color:#57606a;margin-bottom:28px}
|
||||
.mermaid-diagram{margin:20px 0;overflow-x:auto}
|
||||
.mermaid-diagram svg{max-width:100%%;height:auto}
|
||||
.mermaid-err{font-size:12.5px;color:#57606a;margin:-8px 0 20px}
|
||||
/* Dark theme LAST: these rules sit at the same specificity as the light ones
|
||||
above, so source order is the whole fix — a dark block placed earlier loses
|
||||
to every light rule that follows it. Values are the hub's @theme tokens
|
||||
@@ -634,7 +654,8 @@ table.frontmatter{background:#15171b;color:#9aa0a9}
|
||||
table.frontmatter th,table.frontmatter td{border-bottom-color:rgba(255,255,255,.07)}
|
||||
table.frontmatter th{color:#868b93}
|
||||
footer.bdrive{border-top-color:rgba(255,255,255,.07);color:#868b93}
|
||||
.updated{color:#868b93}}
|
||||
</style></head><body>%s%s
|
||||
.updated{color:#868b93}
|
||||
.mermaid-err{color:#868b93}}
|
||||
</style>%s</head><body>%s%s
|
||||
<footer class="bdrive">Shared with <a href="https://github.com/runbear-io/beardrive" rel="noopener">BearDrive</a> — synced files for AI agent teams</footer>
|
||||
</body></html>`
|
||||
|
||||
@@ -486,6 +486,41 @@ func TestShareDarkThemeIsLast(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A share page is a zero-JavaScript document, and it stays one unless the
|
||||
// document it renders actually has a diagram in it. The tag is the whole cost
|
||||
// of the feature for every other share page on the hub, so it is worth a test
|
||||
// that it isn't paid — and that the CSP sandbox that makes the tag work at all
|
||||
// is unchanged.
|
||||
func TestShareMermaidScriptOnlyWhenNeeded(t *testing.T) {
|
||||
srv, p, _, f, h := shareHub(t)
|
||||
f.put("dev1", "wiki/diagram.md", "# D\n\n```mermaid\ngraph TD\n A --> B\n```\n")
|
||||
|
||||
tag := `<script type="module" src="/share-mermaid.js"></script>`
|
||||
|
||||
token, _ := authedShare(t, srv, h, p.ID, "wiki/diagram.md")
|
||||
rec := do(t, h, "GET", "/s/"+token, nil)
|
||||
body := rec.Body.String()
|
||||
if !strings.Contains(body, tag) {
|
||||
t.Errorf("a document with a mermaid fence must load the script: %s", body)
|
||||
}
|
||||
if strings.Contains(body, "%!") {
|
||||
t.Errorf("format verb leaked into the page: %s", body)
|
||||
}
|
||||
// The tag only works because the page is sandboxed with scripts allowed
|
||||
// and its origin is opaque; adding allow-same-origin to make loading
|
||||
// easier would hand shared content the hub's origin.
|
||||
if csp := rec.Header().Get("Content-Security-Policy"); csp != "sandbox allow-scripts allow-popups" {
|
||||
t.Errorf("share CSP = %q, want the unchanged sandbox", csp)
|
||||
}
|
||||
|
||||
// wiki/notes.md has no fence: not one byte of mermaid.
|
||||
plain, _ := authedShare(t, srv, h, p.ID, "wiki/notes.md")
|
||||
if b := do(t, h, "GET", "/s/"+plain, nil).Body.String(); strings.Contains(b, "share-mermaid") ||
|
||||
strings.Contains(b, "<script") {
|
||||
t.Errorf("a share page without a diagram must ship no script: %s", b)
|
||||
}
|
||||
}
|
||||
|
||||
// listShares reads the project's share list as the signed-in sharer.
|
||||
func listShares(t *testing.T, srv *Server, h http.Handler, project string) []map[string]any {
|
||||
t.Helper()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
function e(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}export{e as g};
|
||||
@@ -0,0 +1 @@
|
||||
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-C7qNvbCj.js";import{p as f}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{_ as n,l as o}from"./mermaid.core-B7WVQkyL.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},F={parser:R,db:a,renderer:u,styles:p};export{F as diagram};
|
||||
@@ -0,0 +1 @@
|
||||
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-B7WVQkyL.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{ag as o,ah as n}from"./mermaid.core-B7WVQkyL.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
|
||||
@@ -0,0 +1 @@
|
||||
import{_ as i,d as l,S as d,j as o}from"./mermaid.core-B7WVQkyL.js";var x=i((r,t)=>{const e=r.append("rect");if(e.attr("x",t.x),e.attr("y",t.y),e.attr("fill",t.fill),e.attr("stroke",t.stroke),e.attr("width",t.width),e.attr("height",t.height),t.name&&e.attr("name",t.name),t.rx&&e.attr("rx",t.rx),t.ry&&e.attr("ry",t.ry),t.attrs!==void 0)for(const s in t.attrs)e.attr(s,t.attrs[s]);return t.class&&e.attr("class",t.class),e},"drawRect"),p=i((r,t)=>{const e={x:t.startx,y:t.starty,width:t.stopx-t.startx,height:t.stopy-t.starty,fill:t.fill,stroke:t.stroke,class:"rect"};x(r,e).lower()},"drawBackgroundRect"),y=i((r,t)=>{const e=t.text.replace(d," "),s=r.append("text");s.attr("x",t.x),s.attr("y",t.y),s.attr("class","legend"),s.style("text-anchor",t.anchor),t.class&&s.attr("class",t.class);const a=s.append("tspan");return a.attr("x",t.x+t.textMargin*2),a.text(e),s},"drawText"),m=i((r,t,e,s)=>{const a=r.append("image");a.attr("x",t),a.attr("y",e);const n=o.sanitizeUrl(s);a.attr("xlink:href",n)},"drawImage"),g=i((r,t,e,s)=>{const a=r.append("use");a.attr("x",t),a.attr("y",e);const n=o.sanitizeUrl(s);a.attr("xlink:href",`#${n}`)},"drawEmbeddedImage"),h=i(()=>({x:0,y:0,width:100,height:100,fill:"#EDF2AE",stroke:"#666",anchor:"start",rx:0,ry:0}),"getNoteRect"),f=i(()=>({x:0,y:0,width:100,height:100,"text-anchor":"start",style:"#666",textMargin:0,rx:0,ry:0,tspan:!0}),"getTextObj"),w=i(()=>{let r=l(".mermaidTooltip");return r.empty()&&(r=l("body").append("div").attr("class","mermaidTooltip").style("opacity",0).style("position","absolute").style("text-align","center").style("max-width","200px").style("padding","2px").style("font-size","12px").style("background","#ffffde").style("border","1px solid #333").style("border-radius","2px").style("pointer-events","none").style("z-index","100")),r},"createTooltip");export{p as a,f as b,g as c,x as d,m as e,w as f,h as g,y as h};
|
||||
@@ -0,0 +1 @@
|
||||
import{_ as s}from"./mermaid.core-B7WVQkyL.js";var t,e=(t=class{constructor(i){this.init=i,this.records=this.init()}reset(){this.records=this.init()}},s(t,"ImperativeState"),t);export{e as I};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
|
||||
import{_ as e}from"./mermaid.core-B7WVQkyL.js";var l=e(()=>`
|
||||
/* Font Awesome icon styling - consolidated */
|
||||
.label-icon {
|
||||
display: inline-block;
|
||||
height: 1em;
|
||||
overflow: visible;
|
||||
vertical-align: -0.125em;
|
||||
}
|
||||
|
||||
.node .label-icon path {
|
||||
fill: currentColor;
|
||||
stroke: revert;
|
||||
stroke-width: revert;
|
||||
}
|
||||
`,"getIconStyles");export{l as g};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{_ as i}from"./mermaid.core-B7WVQkyL.js";function t(c,e){c.accDescr&&e.setAccDescription?.(c.accDescr),c.accTitle&&e.setAccTitle?.(c.accTitle),c.title&&e.setDiagramTitle?.(c.title)}i(t,"populateCommonDb");export{t as p};
|
||||
@@ -0,0 +1 @@
|
||||
import{_ as a,e as w,l as x}from"./mermaid.core-B7WVQkyL.js";var d=a((e,t,i,r)=>{e.attr("class",i);const{width:o,height:h,x:n,y:c}=u(e,t);w(e,h,o,r);const s=l(n,c,o,h,t);e.attr("viewBox",s),x.debug(`viewBox configured: ${s} with padding: ${t}`)},"setupViewPortForSVG"),u=a((e,t)=>{const i=e.node()?.getBBox()||{width:0,height:0,x:0,y:0};return{width:i.width+t*2,height:i.height+t*2,x:i.x,y:i.y}},"calculateDimensionsWithPadding"),l=a((e,t,i,r,o)=>`${e-o} ${t-o} ${i} ${r}`,"createViewBox");export{d as s};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{_ as a,d as o}from"./mermaid.core-B7WVQkyL.js";var d=a((t,e)=>{let n;return e==="sandbox"&&(n=o("#i"+t)),(e==="sandbox"?o(n.nodes()[0].contentDocument.body):o("body")).select(`[id="${t}"]`)},"getDiagramElement");export{d as g};
|
||||
@@ -0,0 +1 @@
|
||||
import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-DJ222bgi.js";import{_ as i}from"./mermaid.core-B7WVQkyL.js";import"./chunk-5VM5RSS4-DJhOL3Lj.js";import"./chunk-XXDRQBXY-BXTWinaX.js";import"./chunk-KBJHAD2P-CHI3y1em.js";import"./chunk-2GRJ4B5K-Bng47RDF.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var f={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{f as diagram};
|
||||
@@ -0,0 +1 @@
|
||||
import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-DJ222bgi.js";import{_ as i}from"./mermaid.core-B7WVQkyL.js";import"./chunk-5VM5RSS4-DJhOL3Lj.js";import"./chunk-XXDRQBXY-BXTWinaX.js";import"./chunk-KBJHAD2P-CHI3y1em.js";import"./chunk-2GRJ4B5K-Bng47RDF.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var f={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{f as diagram};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
|
||||
import{c as O,w as I,a as J,f as P,b as E,s as A}from"./chunk-RYQCIY6F-xkrp9DIm.js";import{_ as w,am as v,an as D,ao as H,ap as Y,l,c as _,aq as W,ar as $,ae as j,as as q,af as R,ad as F,at as z,au as K,av as G}from"./mermaid.core-B7WVQkyL.js";import{G as Q}from"./graph-DOmOIIwC.js";import{l as U}from"./layout-D-LzfAck.js";import"./map-DxJ2ADlA.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var C=w((s,t,g)=>Math.max(t,Math.min(g,s)),"clamp"),B=w((s="TB")=>{switch(s){case"BT":return"bottom";case"LR":return"right";case"RL":return"left";default:return"top"}},"getDefaultSelfLoopSide"),V=w(s=>s==="flowchart"||s==="flowchart-v2"||s==="stateDiagram","shouldMergeSelfLoopSegments"),Z=w((s,t,g,m,c)=>{const o=[],r=new Set;if(g.forEach(({start:i,end:n})=>{i!==m&&r.add(i),n!==m&&r.add(n)}),r.forEach(i=>{const n=s.node(i);typeof n?.x=="number"&&typeof n?.y=="number"&&o.push(n)}),o.length===0&&g.forEach(({edge:i})=>{(i.points??[]).forEach(n=>{typeof n?.x=="number"&&typeof n?.y=="number"&&o.push(n)})}),o.length===0)return B(c);const f=o.reduce((i,n)=>({x:i.x+n.x/o.length,y:i.y+n.y/o.length}),{x:0,y:0}),h=f.x-t.x,a=f.y-t.y;return Math.abs(h)>Math.abs(a)?h>0?"right":"left":Math.abs(a)>0?a>0?"bottom":"top":B(c)},"getSelfLoopSide"),ee=w((s,t="top",g=0,m=0)=>{const c=s.x,o=s.y-g,r=s.width/2,f=s.height/2,h=Math.max(36,Math.min(100,s.width*.8)),a=C(Math.max(m,s.width*.35),36,h),i=C(Math.min(s.width,s.height)*.45,24,48);switch(t){case"bottom":{const n=o+f;return[{x:c-a/2,y:n},{x:c-a/2,y:n+i},{x:c+a/2,y:n+i},{x:c+a/2,y:n}]}case"right":{const n=c+r;return[{x:n,y:o-a/2},{x:n+i,y:o-a/2},{x:n+i,y:o+a/2},{x:n,y:o+a/2}]}case"left":{const n=c-r;return[{x:n,y:o-a/2},{x:n-i,y:o-a/2},{x:n-i,y:o+a/2},{x:n,y:o+a/2}]}default:{const n=o-f;return[{x:c-a/2,y:n},{x:c-a/2,y:n-i},{x:c+a/2,y:n-i},{x:c+a/2,y:n}]}}},"getSelfLoopPoints"),te=w((s,t,g="top",m=0,c={})=>{const r=s.x,f=s.y-m,h=c.width??0,a=c.height??0;switch(g){case"bottom":return{x:r,y:Math.max(...t.map(i=>i.y))+a/2+4};case"right":return{x:Math.max(...t.map(i=>i.x))+h/2+4,y:f};case"left":return{x:Math.min(...t.map(i=>i.x))-h/2-4,y:f};default:return{x:r,y:Math.min(...t.map(i=>i.y))-a/2-4}}},"getSelfLoopLabelPosition"),ne=w((s,t=0,{mergeSelfLoops:g=!0}={})=>{const m=new Map,c=[],o=s.graph()?.rankdir;return s.edges().forEach(r=>{const f=s.edge(r);if(g&&f.selfLoop){const h=f.selfLoop.id;m.has(h)||m.set(h,[]),m.get(h).push({edge:f,start:r.v,end:r.w})}else c.push({edge:f,start:r.v,end:r.w})}),m.forEach(r=>{if(r.length!==3){r.forEach(L=>c.push(L));return}r.sort((L,d)=>L.edge.selfLoop.order-d.edge.selfLoop.order);const[f,h,a]=r,i=f.edge.originalEdge??h.edge.originalEdge??a.edge.originalEdge??h.edge,n=s.node(i.start);if(!n){r.forEach(L=>c.push(L));return}const p={width:h.edge.width,height:h.edge.height},y=Z(s,n,r,i.start,o),X=ee(n,y,t,p.width??0),S=te(n,X,y,t,p),b={...h.edge,...i,id:i.id,points:X,start:i.start,end:i.end,x:S.x,y:S.y,width:p.width,height:p.height,labelStyle:h.edge.labelStyle,fromCluster:f.edge.fromCluster??h.edge.fromCluster??a.edge.fromCluster,toCluster:f.edge.toCluster??h.edge.toCluster??a.edge.toCluster};delete b.selfLoop,delete b.originalEdge,c.push({edge:b,start:b.start,end:b.end})}),c},"getEdgesToRender"),T=w(async(s,t,g,m,c,o)=>{l.warn("Graph in recursive render:XAX",I(t),c);const r=t.graph().rankdir;l.trace("Dir in recursive render - dir:",r);const f=s.insert("g").attr("class","root");t.nodes()?l.info("Recursive render XXX",t.nodes()):l.info("No nodes found for",t),t.edges().length>0&&l.info("Recursive edges",t.edge(t.edges()[0]));const h=f.insert("g").attr("class","clusters"),a=f.insert("g").attr("class","edgePaths"),i=f.insert("g").attr("class","edgeLabels"),n=f.insert("g").attr("class","nodes"),p=V(g);await Promise.all(t.nodes().map(async function(d){const e=t.node(d);if(c!==void 0){const u=JSON.parse(JSON.stringify(c.clusterData));l.trace(`Setting data for parent cluster XXX
|
||||
Node.id = `,d,`
|
||||
data=`,u.height,`
|
||||
Parent cluster`,c.height),t.setNode(c.id,u),t.parent(d)||(l.trace("Setting parent",d,c.id),t.setParent(d,c.id,u))}if(l.info("(Insert) Node XXX"+d+": "+JSON.stringify(t.node(d))),e?.clusterNode){l.info("Cluster identified XBX",d,e.width,t.node(d));const{ranksep:u,nodesep:x}=t.graph();e.graph.setGraph({...e.graph.graph(),ranksep:u+25,nodesep:x});const N=await T(n,e.graph,g,m,t.node(d),o),M=N.elem;W(e,M),e.diff=N.diff||0,l.info("New compound node after recursive render XAX",d,"width",e.width,"height",e.height),$(M,e)}else t.children(d).length>0?(l.trace("Cluster - the non recursive path XBX",d,e.id,e,e.width,"Graph:",t),l.trace(P(e.id,t)),E.set(e.id,{id:P(e.id,t),node:e})):(l.trace("Node - the non recursive path XAX",d,n,t.node(d),r),await j(n,t.node(d),{config:o,dir:r}))})),await w(async()=>{const d=t.edges().map(async function(e){const u=t.edge(e.v,e.w,e.name);if(l.info("Edge "+e.v+" -> "+e.w+": "+JSON.stringify(e)),l.info("Edge "+e.v+" -> "+e.w+": ",e," ",JSON.stringify(t.edge(e))),l.info("Fix",E,"ids:",e.v,e.w,"Translating: ",E.get(e.v),E.get(e.w)),p&&u.selfLoop){if(u.selfLoop.order!==1)return;const x=u.id;u.id=u.selfLoop.id,await G(i,u),u.id=x;return}await G(i,u)});await Promise.all(d)},"processEdges")(),l.info("Graph before layout:",JSON.stringify(I(t))),l.info("############################################# XXX"),l.info("### Layout ### XXX"),l.info("############################################# XXX"),U(t),l.info("Graph after layout:",JSON.stringify(I(t)));let X=0,{subGraphTitleTotalMargin:S}=q(o);await Promise.all(A(t).map(async function(d){const e=t.node(d);if(l.info("Position XBX => "+d+": ("+e.x,","+e.y,") width: ",e.width," height: ",e.height),e?.clusterNode)e.y+=S,l.info("A tainted cluster node XBX1",d,e.id,e.width,e.height,e.x,e.y,t.parent(d)),E.get(e.id).node=e,R(e);else if(t.children(d).length>0){l.info("A pure cluster node XBX1",d,e.id,e.x,e.y,e.width,e.height,t.parent(d)),e.height+=S,t.node(e.parentId);const u=e?.padding/2||0,x=e?.labelBBox?.height||0,N=x-u||0;l.debug("OffsetY",N,"labelHeight",x,"halfPadding",u),await F(h,e),E.get(e.id).node=e}else{const u=t.node(e.parentId);e.y+=S/2,l.info("A regular node XBX1 - using the padding",e.id,"parent",e.parentId,e.width,e.height,e.x,e.y,"offsetY",e.offsetY,"parent",u,u?.offsetY,e),R(e)}}));const b=S/2;return ne(t,b,{mergeSelfLoops:p}).forEach(function({edge:d,start:e,end:u}){l.info("Edge "+e+" -> "+u+": "+JSON.stringify(d),d),d.points.forEach(k=>k.y+=b);const x=t.node(e),N=t.node(u),M=z(a,d,E,g,x,N,m);K(d,M)}),t.nodes().forEach(function(d){const e=t.node(d);l.info(d,e.type,e.diff),e.isGroup&&(X=e.diff)}),l.warn("Returning from recursive render XAX",f,X),{elem:f,diff:X}},"recursiveRender"),le=w(async(s,t)=>{const g=new Q({multigraph:!0,compound:!0}).setGraph({rankdir:s.direction,nodesep:s.config?.nodeSpacing||s.config?.flowchart?.nodeSpacing||s.nodeSpacing,ranksep:s.config?.rankSpacing||s.config?.flowchart?.rankSpacing||s.rankSpacing,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}}),m=t.select("g");v(m,s.markers,s.type,s.diagramId),D(),H(),Y(),O(),s.nodes.forEach(o=>{g.setNode(o.id,{...o}),o.parentId&&g.setParent(o.id,o.parentId)}),l.debug("Edges:",s.edges),s.edges.forEach(o=>{if(o.start===o.end){const r=o.start,f=r+"---"+r+"---1",h=r+"---"+r+"---2",a=g.node(r);g.setNode(f,{domId:f,id:f,parentId:a.parentId,labelStyle:"",label:"",padding:0,shape:"labelRect",style:"",width:10,height:10}),g.setParent(f,a.parentId),g.setNode(h,{domId:h,id:h,parentId:a.parentId,labelStyle:"",padding:0,shape:"labelRect",label:"",style:"",width:10,height:10}),g.setParent(h,a.parentId);const i=structuredClone(o),n=structuredClone(o),p=structuredClone(o),y=structuredClone(o);n.originalEdge=i,n.selfLoop={id:i.id,order:0},p.originalEdge=i,p.selfLoop={id:i.id,order:1},y.originalEdge=i,y.selfLoop={id:i.id,order:2},n.label="",n.arrowTypeEnd="none",n.endLabelLeft="",n.endLabelRight="",n.startLabelLeft="",n.id=r+"-cyclic-special-1",p.startLabelRight="",p.startLabelLeft="",p.endLabelLeft="",p.endLabelRight="",p.arrowTypeStart="none",p.arrowTypeEnd="none",p.id=r+"-cyclic-special-mid",y.label="",y.startLabelRight="",y.startLabelLeft="",y.arrowTypeStart="none",a.isGroup&&(n.fromCluster=r,y.toCluster=r),y.id=r+"-cyclic-special-2",y.arrowTypeStart="none",g.setEdge(r,f,n,r+"-cyclic-special-0"),g.setEdge(f,h,p,r+"-cyclic-special-1"),g.setEdge(h,r,y,r+"-cyclic-special-2")}else g.setEdge(o.start,o.end,{...o},o.id)}),l.warn("Graph at first:",JSON.stringify(I(g))),J(g),l.warn("Graph after XAX:",JSON.stringify(I(g)));const c=_();await T(m,g,s.type,s.diagramId,void 0,c)},"render");export{ne as getEdgesToRender,le as render};
|
||||
@@ -0,0 +1 @@
|
||||
function J(n){return Math.abs(n=Math.round(n))>=1e21?n.toLocaleString("en").replace(/,/g,""):n.toString(10)}function j(n,t){if(!isFinite(n)||n===0)return null;var e=(n=t?n.toExponential(t-1):n.toExponential()).indexOf("e"),i=n.slice(0,e);return[i.length>1?i[0]+i.slice(2):i,+n.slice(e+1)]}function K(n){return n=j(Math.abs(n)),n?n[1]:NaN}function Q(n,t){return function(e,i){for(var o=e.length,a=[],c=0,h=n[0],M=0;o>0&&h>0&&(M+h+1>i&&(h=Math.max(1,i-M)),a.push(e.substring(o-=h,o+h)),!((M+=h+1)>i));)h=n[c=(c+1)%n.length];return a.reverse().join(t)}}function V(n){return function(t){return t.replace(/[0-9]/g,function(e){return n[+e]})}}var W=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function $(n){if(!(t=W.exec(n)))throw new Error("invalid format: "+n);var t;return new L({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}$.prototype=L.prototype;function L(n){this.fill=n.fill===void 0?" ":n.fill+"",this.align=n.align===void 0?">":n.align+"",this.sign=n.sign===void 0?"-":n.sign+"",this.symbol=n.symbol===void 0?"":n.symbol+"",this.zero=!!n.zero,this.width=n.width===void 0?void 0:+n.width,this.comma=!!n.comma,this.precision=n.precision===void 0?void 0:+n.precision,this.trim=!!n.trim,this.type=n.type===void 0?"":n.type+""}L.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function _(n){n:for(var t=n.length,e=1,i=-1,o;e<t;++e)switch(n[e]){case".":i=o=e;break;case"0":i===0&&(i=e),o=e;break;default:if(!+n[e])break n;i>0&&(i=0);break}return i>0?n.slice(0,i)+n.slice(o+1):n}var N;function v(n,t){var e=j(n,t);if(!e)return N=void 0,n.toPrecision(t);var i=e[0],o=e[1],a=o-(N=Math.max(-8,Math.min(8,Math.floor(o/3)))*3)+1,c=i.length;return a===c?i:a>c?i+new Array(a-c+1).join("0"):a>0?i.slice(0,a)+"."+i.slice(a):"0."+new Array(1-a).join("0")+j(n,Math.max(0,t+a-1))[0]}function X(n,t){var e=j(n,t);if(!e)return n+"";var i=e[0],o=e[1];return o<0?"0."+new Array(-o).join("0")+i:i.length>o+1?i.slice(0,o+1)+"."+i.slice(o+1):i+new Array(o-i.length+2).join("0")}const O={"%":(n,t)=>(n*100).toFixed(t),b:n=>Math.round(n).toString(2),c:n=>n+"",d:J,e:(n,t)=>n.toExponential(t),f:(n,t)=>n.toFixed(t),g:(n,t)=>n.toPrecision(t),o:n=>Math.round(n).toString(8),p:(n,t)=>X(n*100,t),r:X,s:v,X:n=>Math.round(n).toString(16).toUpperCase(),x:n=>Math.round(n).toString(16)};function R(n){return n}var U=Array.prototype.map,Y=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function nn(n){var t=n.grouping===void 0||n.thousands===void 0?R:Q(U.call(n.grouping,Number),n.thousands+""),e=n.currency===void 0?"":n.currency[0]+"",i=n.currency===void 0?"":n.currency[1]+"",o=n.decimal===void 0?".":n.decimal+"",a=n.numerals===void 0?R:V(U.call(n.numerals,String)),c=n.percent===void 0?"%":n.percent+"",h=n.minus===void 0?"−":n.minus+"",M=n.nan===void 0?"NaN":n.nan+"";function T(f,g){f=$(f);var b=f.fill,p=f.align,m=f.sign,w=f.symbol,S=f.zero,E=f.width,F=f.comma,y=f.precision,C=f.trim,d=f.type;d==="n"?(F=!0,d="g"):O[d]||(y===void 0&&(y=12),C=!0,d="g"),(S||b==="0"&&p==="=")&&(S=!0,b="0",p="=");var q=(g&&g.prefix!==void 0?g.prefix:"")+(w==="$"?e:w==="#"&&/[boxX]/.test(d)?"0"+d.toLowerCase():""),B=(w==="$"?i:/[%p]/.test(d)?c:"")+(g&&g.suffix!==void 0?g.suffix:""),D=O[d],H=/[defgprs%]/.test(d);y=y===void 0?6:/[gprs]/.test(d)?Math.max(1,Math.min(21,y)):Math.max(0,Math.min(20,y));function G(r){var l=q,u=B,x,I,k;if(d==="c")u=D(r)+u,r="";else{r=+r;var P=r<0||1/r<0;if(r=isNaN(r)?M:D(Math.abs(r),y),C&&(r=_(r)),P&&+r==0&&m!=="+"&&(P=!1),l=(P?m==="("?m:h:m==="-"||m==="("?"":m)+l,u=(d==="s"&&!isNaN(r)&&N!==void 0?Y[8+N/3]:"")+u+(P&&m==="("?")":""),H){for(x=-1,I=r.length;++x<I;)if(k=r.charCodeAt(x),48>k||k>57){u=(k===46?o+r.slice(x+1):r.slice(x))+u,r=r.slice(0,x);break}}}F&&!S&&(r=t(r,1/0));var z=l.length+r.length+u.length,s=z<E?new Array(E-z+1).join(b):"";switch(F&&S&&(r=t(s+r,s.length?E-u.length:1/0),s=""),p){case"<":r=l+r+u+s;break;case"=":r=l+s+r+u;break;case"^":r=s.slice(0,z=s.length>>1)+l+r+u+s.slice(z);break;default:r=s+l+r+u;break}return a(r)}return G.toString=function(){return f+""},G}function Z(f,g){var b=Math.max(-8,Math.min(8,Math.floor(K(g)/3)))*3,p=Math.pow(10,-b),m=T((f=$(f),f.type="f",f),{suffix:Y[8+b/3]});return function(w){return m(p*w)}}return{format:T,formatPrefix:Z}}var A,tn,rn;en({thousands:",",grouping:[3],currency:["$",""]});function en(n){return A=nn(n),tn=A.format,rn=A.formatPrefix,A}export{rn as a,tn as b,K as e,$ as f};
|
||||
@@ -0,0 +1,30 @@
|
||||
import{I as X}from"./chunk-2Q5K7J3B-Krb_H4ce.js";import{p as O}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{n as G,b as Y,s as P,o as j,g as F,a as Z,_ as f,A,l as D,D as q,e as U,y as N,p as J,i as K,ai as Q,B as ee,aj as te}from"./mermaid.core-B7WVQkyL.js";import{p as ne}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var E=/[─━│┃└┗├┣]/,S=/[└┗├┣]/,re=/[─━]/,V=/^[\s│┃]+$/,$=/^\s*(title[\t ]|accTitle[\t ]*:|accDescr[\t ]*[:{])/,k=/^\s*%%/,ie=" ";function L(n){return n.some(e=>E.test(e))}f(L,"isBoxDrawingFormat");function _(n){for(const e of n){const t=S.exec(e);if(t?.index&&t.index>0)return t.index}return 4}f(_,"inferSegmentWidth");function M(n,e){return n.replace(/\bline\s+(\d+)\b/gi,(t,r)=>{const i=parseInt(r,10),a=e.get(i);return a?`line ${a}`:t})}f(M,"remapErrorLines");function R(n){const e=n.split(`
|
||||
`),t=new Map;let r=-1;for(const[s,o]of e.entries())if(o.trim()==="treeView-beta"){r=s;break}if(r===-1)return{text:n,lineMap:t};const i=[];for(let s=r+1;s<e.length;s++){const o=e[s];o.trim()===""||k.test(o)||$.test(o)||V.test(o)||i.push(o.replace(/\t/g," "))}if(!L(i))return{text:n,lineMap:t};const a=_(i),c=[];let l=0;for(let s=0;s<=r;s++)c.push(e[s]),l++,t.set(l,s+1);for(let s=r+1;s<e.length;s++){const o=e[s],h=o.trim(),p=s+1;if(h===""){c.push(o),l++,t.set(l,p);continue}if(k.test(o)){c.push(o),l++,t.set(l,p);continue}if($.test(o)){c.push(o),l++,t.set(l,p);continue}if(V.test(o))continue;const d=o.replace(/\t/g," "),w=S.exec(d);if(w?.index!==void 0){const g=w.index,m=Math.round(g/a)+1;let u=g+1;for(;u<d.length&&re.test(d[u]);)u++;for(;u<d.length&&d[u]===" ";)u++;const v=d.slice(u).trimEnd();if(!v)throw new Error(`Line ${p}: Empty node — expected a filename or directory name after the box-drawing prefix`);const W=ie.repeat(m);c.push(W+v),l++,t.set(l,p)}else{if(/^[\s─━│┃└┗├┣]+$/.test(d))continue;if(E.test(d))c.push(o),l++,t.set(l,p);else{if(/^\s+/.test(d))throw new Error(`Line ${p}: Unexpected indentation without box-drawing characters. In box-drawing format, use ├── or └── prefixes for indented nodes.`);c.push(o),l++,t.set(l,p)}}}return{text:c.join(`
|
||||
`),lineMap:t}}f(R,"preprocessBoxDrawing");var x=new X(()=>({cnt:1,stack:[{id:0,level:-1,name:"/",nodeType:"directory",children:[]}]})),oe=f(()=>{x.reset(),J()},"clear"),se=f(()=>x.records.stack[0],"getRoot"),ae=f(()=>x.records.cnt,"getCount"),ce=ee.treeView,le=f(()=>A(ce,N().treeView),"getConfig"),de=f((n,e,t,r,i,a)=>{for(;n<=x.records.stack[x.records.stack.length-1].level;)x.records.stack.pop();const c={id:x.records.cnt++,level:n,name:e,nodeType:t,icon:i,cssClass:r,description:a,children:[]};x.records.stack[x.records.stack.length-1].children.push(c),x.records.stack.push(c)},"addNode"),he={clear:oe,addNode:de,getRoot:se,getCount:ae,getConfig:le,getAccTitle:Z,getAccDescription:F,getDiagramTitle:j,setAccDescription:P,setAccTitle:Y,setDiagramTitle:G},I=he,pe=f(n=>{O(n,I);for(const e of n.nodes){const t=typeof e.indent=="number"?e.indent:0;let r=e.name;const i=r.endsWith("/");i&&(r=r.slice(0,-1));const a=i?"directory":"file",c=e.classAnnotation||void 0,l=e.iconAnnotation,s=l!==void 0?l||"none":void 0,o=e.descAnnotation||void 0,h=o?K(o,N()):void 0;I.addNode(t,r,a,c,s,h)}},"populate"),fe={parse:f(async n=>{const{text:e,lineMap:t}=R(n);try{const r=await ne("treeView",e);D.debug(r),pe(r)}catch(r){throw t.size>0&&r instanceof Error&&(r.message=M(r.message,t)),r}},"parse")},b={prefix:"mermaid-treeview",height:24,width:24,icons:{folder:{body:'<path fill="currentColor" d="M10.59 4.59A2 2 0 0 0 9.17 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.17z"/>'},file:{body:'<path fill="currentColor" fill-rule="evenodd" d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8.83a2 2 0 0 0-.59-1.42l-4.82-4.82A2 2 0 0 0 13.17 2H6Zm7.5 1.9l4.6 4.6h-3.6a1 1 0 0 1-1-1V3.9Z" clip-rule="evenodd"/>'}}};function H(n,e){const t=e?.filenameIcons?.[n];if(t)return t;const r=n.lastIndexOf(".");if(r>0){const i=n.substring(r).toLowerCase(),a=e?.extensionIcons;return a?.[i]??a?.[i.slice(1)]}}f(H,"detectIcon");function C(n,e){return n.includes(":")?n:n in b.icons||!e?`${b.prefix}:${n}`:`${e}:${n}`}f(C,"qualifyIcon");function B(n,e){if(n.icon!=="none"){if(n.icon)return C(n.icon,e.defaultIconPack);if(e.showIcons){if(n.nodeType==="file"){const t=H(n.name,e);if(t==="none")return;if(t)return C(t,e.defaultIconPack)}return`${b.prefix}:${n.nodeType==="directory"?"folder":"file"}`}}}f(B,"getNodeIcon");te([{name:b.prefix,icons:b}]);var y=14,ge=4,ue=16,z=f((n,e)=>`tv-icon-${n}-${e.replace(/[^\w-]/g,"-")}`,"iconSymbolId"),we=f(async(n,e,t,r)=>{const i=new Set,a=f(s=>{const o=B(s,t);o&&i.add(o),s.children.forEach(a)},"collect");if(a(e),i.size===0)return;const c=await Promise.all([...i].map(async s=>({icon:s,svg:await Q(s,{height:y,width:y})}))),l=n.append("defs");for(const{icon:s,svg:o}of c)l.append("g").attr("id",z(r,s)).html(o)},"injectIconDefs"),me=f((n,e,t,r,i,a)=>{const c=r.append("g");let l="treeView-node-label";t.nodeType==="directory"&&(l+=" treeView-node-dir"),t.cssClass&&(l+=` ${t.cssClass}`);const s=y+ge,o=B(t,i),h=o!==void 0;o&&c.append("use").attr("xlink:href",`#${z(a,o)}`).attr("x",n+i.paddingX).attr("y",e+i.paddingY).attr("class","treeView-node-icon");const p=c.append("text").text(t.name).attr("dominant-baseline","middle").attr("class",l),{height:d,width:w}=p.node().getBBox(),g=d+i.paddingY*2,m=n+i.paddingX+(h?s:0);p.attr("x",m),p.attr("y",e+g/2);const u=m+w,v=w+i.paddingX*2+(h?s:0);return t.BBox={x:n,y:e,width:v,height:g},t.cssClass?.split(/\s+/).includes("highlight")&&c.insert("rect",":first-child").attr("x",n).attr("y",e+1).attr("width",0).attr("height",g-2).attr("rx",3).attr("class","treeView-highlight-bg"),{node:t,nodeGroup:c,labelRightEdge:u,centerY:e+g/2}},"positionLabel"),T=f((n,e,t,r,i,a)=>n.append("line").attr("x1",e).attr("y1",t).attr("x2",r).attr("y2",i).attr("stroke-width",a).attr("class","treeView-node-line"),"positionLine"),xe=f((n,e,t,r)=>{let i=0,a=0;const c=[],l=f((h,p,d,w)=>{const g=w*(d.rowIndent+d.paddingX),m=me(g,i,p,h,d,r);c.push(m);const{height:u,width:v}=p.BBox;T(h,g-d.rowIndent,i+u/2,g,i+u/2,d.lineThickness),a=Math.max(a,g+v),i+=u},"drawNode"),s=f((h,p=0)=>{l(n,h,t,p),h.children.forEach(m=>{s(m,p+1)});const{x:d,y:w,height:g}=h.BBox;if(h.children.length){const{y:m,height:u}=h.children[h.children.length-1].BBox;T(n,d+t.paddingX,w+g,d+t.paddingX,m+u/2+t.lineThickness/2,t.lineThickness)}},"processNode");s(e);const o=c.filter(h=>h.node.description);if(o.length>0){const p=Math.max(...c.map(d=>d.labelRightEdge))+ue;for(const d of o){const g=d.nodeGroup.append("text").text(d.node.description).attr("dominant-baseline","middle").attr("class","treeView-node-description").attr("x",p).attr("y",d.centerY).node().getBBox();a=Math.max(a,p+g.width+t.paddingX)}}for(const h of c)if(h.node.cssClass?.split(/\s+/).includes("highlight")){const p=h.nodeGroup.select(".treeView-highlight-bg");if(!p.empty()){const d=a-h.node.BBox.x+8;p.attr("width",d),a=Math.max(a,h.node.BBox.x+d+2)}}return{totalHeight:i,totalWidth:a}},"drawTree"),ve=f(async(n,e,t,r)=>{D.debug(`Rendering treeView diagram
|
||||
`+n);const i=r.db,a=i.getRoot(),c=i.getConfig(),l=q(e);await we(l,a,c,e);const s=l.append("g");s.attr("class","tree-view");const{totalHeight:o,totalWidth:h}=xe(s,a,c,e);l.attr("viewBox",`-${c.lineThickness/2} 0 ${h} ${o}`),U(l,o,h,c.useMaxWidth)},"draw"),be={draw:ve},Ie=be,Ce={labelFontSize:"16px",labelColor:"black",lineColor:"black",iconColor:"#546e7a",descriptionColor:"#6a9955",highlightBg:"rgba(255, 193, 7, 0.15)",highlightStroke:"#ffc107"},ye=f(({treeView:n})=>{const{labelFontSize:e,labelColor:t,lineColor:r,iconColor:i,descriptionColor:a,highlightBg:c,highlightStroke:l}=A(Ce,n);return`
|
||||
.treeView-node-label {
|
||||
font-size: ${e};
|
||||
fill: ${t};
|
||||
white-space: pre;
|
||||
}
|
||||
.treeView-node-dir {
|
||||
font-weight: bold;
|
||||
}
|
||||
.treeView-node-line {
|
||||
stroke: ${r};
|
||||
}
|
||||
.treeView-node-icon {
|
||||
color: ${i};
|
||||
}
|
||||
.treeView-node-description {
|
||||
font-size: ${e};
|
||||
fill: ${a};
|
||||
font-style: italic;
|
||||
white-space: pre;
|
||||
}
|
||||
.treeView-highlight-bg {
|
||||
fill: ${c};
|
||||
stroke: ${l};
|
||||
stroke-width: 1;
|
||||
}
|
||||
`},"styles"),Be=ye,Ne={db:I,renderer:Ie,parser:fe,styles:Be};export{Ne as diagram};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,24 @@
|
||||
import{p as $}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{_ as b,A as m,D as C,e as S,l as w,b as D,a as T,n as P,o as z,g as A,s as E,y as F,B as W,p as _}from"./mermaid.core-B7WVQkyL.js";import{p as N}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var L=W.packet,u,v=(u=class{constructor(){this.packet=[],this.setAccTitle=D,this.getAccTitle=T,this.setDiagramTitle=P,this.getDiagramTitle=z,this.getAccDescription=A,this.setAccDescription=E}getConfig(){const t=m({...L,...F().packet});return t.showBits&&(t.paddingY+=10),t}getPacket(){return this.packet}pushWord(t){t.length>0&&this.packet.push(t)}clear(){_(),this.packet=[]}},b(u,"PacketDB"),u),M=1e4,Y=b((e,t)=>{$(e,t);let r=-1,o=[],n=1;const{bitsPerRow:l}=t.getConfig();for(let{start:a,end:i,bits:d,label:c}of e.blocks){if(a!==void 0&&i!==void 0&&i<a)throw new Error(`Packet block ${a} - ${i} is invalid. End must be greater than start.`);if(a??=r+1,a!==r+1)throw new Error(`Packet block ${a} - ${i??a} is not contiguous. It should start from ${r+1}.`);if(d===0)throw new Error(`Packet block ${a} is invalid. Cannot have a zero bit field.`);for(i??=a+(d??1)-1,d??=i-a+1,r=i,w.debug(`Packet block ${a} - ${r} with label ${c}`);o.length<=l+1&&t.getPacket().length<M;){const[p,s]=I({start:a,end:i,bits:d,label:c},n,l);if(o.push(p),p.end+1===n*l&&(t.pushWord(o),o=[],n++),!s)break;({start:a,end:i,bits:d,label:c}=s)}}t.pushWord(o)},"populate"),I=b((e,t,r)=>{if(e.start===void 0)throw new Error("start should have been set during first phase");if(e.end===void 0)throw new Error("end should have been set during first phase");if(e.start>e.end)throw new Error(`Block start ${e.start} is greater than block end ${e.end}.`);if(e.end+1<=t*r)return[e,void 0];const o=t*r-1,n=t*r;return[{start:e.start,end:o,label:e.label,bits:o-e.start},{start:n,end:e.end,label:e.label,bits:e.end-n}]},"getNextFittingBlock"),x={parser:{yy:void 0},parse:b(async e=>{const t=await N("packet",e),r=x.parser?.yy;if(!(r instanceof v))throw new Error("parser.parser?.yy was not a PacketDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues.");w.debug(t),Y(t,r)},"parse")},O=b((e,t,r,o)=>{const n=o.db,l=n.getConfig(),{rowHeight:a,paddingY:i,bitWidth:d,bitsPerRow:c}=l,p=n.getPacket(),s=n.getDiagramTitle(),h=a+i,g=h*(p.length+1)-(s?0:a),k=d*c+2,f=C(t);f.attr("viewBox",`0 0 ${k} ${g}`),S(f,g,k,l.useMaxWidth);for(const[y,B]of p.entries())j(f,B,y,l);f.append("text").text(s).attr("x",k/2).attr("y",g-h/2).attr("dominant-baseline","middle").attr("text-anchor","middle").attr("class","packetTitle")},"draw"),j=b((e,t,r,{rowHeight:o,paddingX:n,paddingY:l,bitWidth:a,bitsPerRow:i,showBits:d})=>{const c=e.append("g"),p=r*(o+l)+l;for(const s of t){const h=s.start%i*a+1,g=(s.end-s.start+1)*a-n;if(c.append("rect").attr("x",h).attr("y",p).attr("width",g).attr("height",o).attr("class","packetBlock"),c.append("text").attr("x",h+g/2).attr("y",p+o/2).attr("class","packetLabel").attr("dominant-baseline","middle").attr("text-anchor","middle").text(s.label),!d)continue;const k=s.end===s.start,f=p-2;c.append("text").attr("x",h+(k?g/2:0)).attr("y",f).attr("class","packetByte start").attr("dominant-baseline","auto").attr("text-anchor",k?"middle":"start").text(s.start),k||c.append("text").attr("x",h+g).attr("y",f).attr("class","packetByte end").attr("dominant-baseline","auto").attr("text-anchor","end").text(s.end)}},"drawWord"),G={draw:O},H={byteFontSize:"10px",startByteColor:"black",endByteColor:"black",labelColor:"black",labelFontSize:"12px",titleColor:"black",titleFontSize:"14px",blockStrokeColor:"black",blockStrokeWidth:"1",blockFillColor:"#efefef"},K=b(({packet:e}={})=>{const t=m(H,e);return`
|
||||
.packetByte {
|
||||
font-size: ${t.byteFontSize};
|
||||
}
|
||||
.packetByte.start {
|
||||
fill: ${t.startByteColor};
|
||||
}
|
||||
.packetByte.end {
|
||||
fill: ${t.endByteColor};
|
||||
}
|
||||
.packetLabel {
|
||||
fill: ${t.labelColor};
|
||||
font-size: ${t.labelFontSize};
|
||||
}
|
||||
.packetTitle {
|
||||
fill: ${t.titleColor};
|
||||
font-size: ${t.titleFontSize};
|
||||
}
|
||||
.packetBlock {
|
||||
stroke: ${t.blockStrokeColor};
|
||||
stroke-width: ${t.blockStrokeWidth};
|
||||
fill: ${t.blockFillColor};
|
||||
}
|
||||
`},"styles"),Q={parser:x,get db(){return new v},renderer:G,styles:K};export{Q as diagram};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,41 @@
|
||||
import{p as I}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{s as _,g as E,o as D,n as F,a as P,b as z,_ as c,D as G,p as B,A as w,y as C,B as W,l as b,E as V,e as H}from"./mermaid.core-B7WVQkyL.js";import{p as j}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var x={showLegend:!0,ticks:5,max:null,min:0,graticule:"circle"},y=32,A={axes:[],curves:[],options:x},m=structuredClone(A),U=W.radar,X=c(()=>w({...U,...C().radar}),"getConfig"),M=c(()=>m.axes,"getAxes"),K=c(()=>m.curves,"getCurves"),N=c(()=>m.options,"getOptions"),Y=c(a=>{m.axes=a.map(t=>({name:t.name,label:t.label??t.name}))},"setAxes"),Z=c(a=>{m.curves=a.map(t=>({name:t.name,label:t.label??t.name,entries:q(t.entries)}))},"setCurves"),q=c(a=>{if(a[0].axis==null)return a.map(e=>e.value);const t=M();if(t.length===0)throw new Error("Axes must be populated before curves for reference entries");return t.map(e=>{const r=a.find(s=>s.axis?.$refText===e.name);if(r===void 0)throw new Error("Missing entry for axis "+e.label);return r.value})},"computeCurveEntries"),J=c(a=>{const t=a.reduce((e,r)=>(e[r.name]=r,e),{});m.options={showLegend:t.showLegend?.value??x.showLegend,ticks:t.ticks?.value??x.ticks,max:t.max?.value??x.max,min:t.min?.value??x.min,graticule:t.graticule?.value??x.graticule},m.options.ticks>y&&(b.warn(`Radar diagram ticks (${m.options.ticks}) exceeds maximum allowed (${y}). Using ${y} instead.`),m.options.ticks=y)},"setOptions"),Q=c(()=>{B(),m=structuredClone(A)},"clear"),$={getAxes:M,getCurves:K,getOptions:N,setAxes:Y,setCurves:Z,setOptions:J,getConfig:X,clear:Q,setAccTitle:z,getAccTitle:P,setDiagramTitle:F,getDiagramTitle:D,getAccDescription:E,setAccDescription:_},tt=c(a=>{I(a,$);const{axes:t,curves:e,options:r}=a;$.setAxes(t),$.setCurves(e),$.setOptions(r)},"populate"),et={parse:c(async a=>{const t=await j("radar",a);b.debug(t),tt(t)},"parse")},at=c((a,t,e,r)=>{const s=r.db,i=s.getAxes(),l=s.getCurves(),n=s.getOptions(),o=s.getConfig(),d=s.getDiagramTitle(),p=G(t),u=rt(p,o),g=n.max??Math.max(...l.map(f=>Math.max(...f.entries))),h=n.min,v=Math.min(o.width,o.height)/2;st(u,i,v,n.ticks,n.graticule),nt(u,i,v,o),L(u,i,l,h,g,n.graticule,o),k(u,l,n.showLegend,o),u.append("text").attr("class","radarTitle").text(d).attr("x",0).attr("y",-o.height/2-o.marginTop)},"draw"),rt=c((a,t)=>{const e=t.width+t.marginLeft+t.marginRight,r=t.height+t.marginTop+t.marginBottom,s={x:t.marginLeft+t.width/2,y:t.marginTop+t.height/2};return H(a,r,e,t.useMaxWidth??!0),a.attr("viewBox",`0 0 ${e} ${r}`).attr("overflow","visible"),a.append("g").attr("transform",`translate(${s.x}, ${s.y})`)},"drawFrame"),st=c((a,t,e,r,s)=>{if(s==="circle")for(let i=0;i<r;i++){const l=e*(i+1)/r;a.append("circle").attr("r",l).attr("class","radarGraticule")}else if(s==="polygon"){const i=t.length;for(let l=0;l<r;l++){const n=e*(l+1)/r,o=t.map((d,p)=>{const u=2*p*Math.PI/i-Math.PI/2,g=n*Math.cos(u),h=n*Math.sin(u);return`${g},${h}`}).join(" ");a.append("polygon").attr("points",o).attr("class","radarGraticule")}}},"drawGraticule"),nt=c((a,t,e,r)=>{const s=t.length;for(let i=0;i<s;i++){const l=t[i].label,n=2*i*Math.PI/s-Math.PI/2,o=Math.cos(n),d=Math.sin(n);a.append("line").attr("x1",0).attr("y1",0).attr("x2",e*r.axisScaleFactor*o).attr("y2",e*r.axisScaleFactor*d).attr("class","radarAxisLine");const p=o>.01?"start":o<-.01?"end":"middle",u=d>.01?"hanging":d<-.01?"auto":"central",g=4;a.append("text").text(l).attr("x",e*r.axisLabelFactor*o+g*o).attr("y",e*r.axisLabelFactor*d+g*d).attr("text-anchor",p).attr("dominant-baseline",u).attr("class","radarAxisLabel")}},"drawAxes");function L(a,t,e,r,s,i,l){const n=t.length,o=Math.min(l.width,l.height)/2;e.forEach((d,p)=>{if(d.entries.length!==n)return;const u=d.entries.map((g,h)=>{const v=2*Math.PI*h/n-Math.PI/2,f=T(g,r,s,o),O=f*Math.cos(v),R=f*Math.sin(v);return{x:O,y:R}});i==="circle"?a.append("path").attr("d",S(u,l.curveTension)).attr("class",`radarCurve-${p}`):i==="polygon"&&a.append("polygon").attr("points",u.map(g=>`${g.x},${g.y}`).join(" ")).attr("class",`radarCurve-${p}`)})}c(L,"drawCurves");function T(a,t,e,r){const s=Math.min(Math.max(a,t),e);return r*(s-t)/(e-t)}c(T,"relativeRadius");function S(a,t){const e=a.length;let r=`M${a[0].x},${a[0].y}`;for(let s=0;s<e;s++){const i=a[(s-1+e)%e],l=a[s],n=a[(s+1)%e],o=a[(s+2)%e],d={x:l.x+(n.x-i.x)*t,y:l.y+(n.y-i.y)*t},p={x:n.x-(o.x-l.x)*t,y:n.y-(o.y-l.y)*t};r+=` C${d.x},${d.y} ${p.x},${p.y} ${n.x},${n.y}`}return`${r} Z`}c(S,"closedRoundCurve");function k(a,t,e,r){if(!e)return;const s=(r.width/2+r.marginRight)*3/4,i=-(r.height/2+r.marginTop)*3/4,l=20;t.forEach((n,o)=>{const d=a.append("g").attr("transform",`translate(${s}, ${i+o*l})`);d.append("rect").attr("width",12).attr("height",12).attr("class",`radarLegendBox-${o}`),d.append("text").attr("x",16).attr("y",0).attr("class","radarLegendText").text(n.label)})}c(k,"drawLegend");var ot={draw:at},it=c((a,t)=>{let e="";for(let r=0;r<a.THEME_COLOR_LIMIT;r++){const s=a[`cScale${r}`];e+=`
|
||||
.radarCurve-${r} {
|
||||
color: ${s};
|
||||
fill: ${s};
|
||||
fill-opacity: ${t.curveOpacity};
|
||||
stroke: ${s};
|
||||
stroke-width: ${t.curveStrokeWidth};
|
||||
}
|
||||
.radarLegendBox-${r} {
|
||||
fill: ${s};
|
||||
fill-opacity: ${t.curveOpacity};
|
||||
stroke: ${s};
|
||||
}
|
||||
`}return e},"genIndexStyles"),lt=c(a=>{const t=V(),e=C(),r=w(t,e.themeVariables),s=w(r.radar,a);return{themeVariables:r,radarOptions:s}},"buildRadarStyleOptions"),ct=c(({radar:a}={})=>{const{themeVariables:t,radarOptions:e}=lt(a);return`
|
||||
.radarTitle {
|
||||
font-size: ${t.fontSize};
|
||||
color: ${t.titleColor};
|
||||
dominant-baseline: hanging;
|
||||
text-anchor: middle;
|
||||
}
|
||||
.radarAxisLine {
|
||||
stroke: ${e.axisColor};
|
||||
stroke-width: ${e.axisStrokeWidth};
|
||||
}
|
||||
.radarAxisLabel {
|
||||
font-size: ${e.axisLabelFontSize}px;
|
||||
color: ${e.axisColor};
|
||||
}
|
||||
.radarGraticule {
|
||||
fill: ${e.graticuleColor};
|
||||
fill-opacity: ${e.graticuleOpacity};
|
||||
stroke: ${e.graticuleColor};
|
||||
stroke-width: ${e.graticuleStrokeWidth};
|
||||
}
|
||||
.radarLegendText {
|
||||
text-anchor: start;
|
||||
font-size: ${e.legendFontSize}px;
|
||||
dominant-baseline: hanging;
|
||||
}
|
||||
${it(t,e)}
|
||||
`},"styles"),xt={parser:et,db:$,renderer:ot,styles:ct};export{xt as diagram};
|
||||
@@ -0,0 +1 @@
|
||||
import{g as l,r as m,d as n}from"./chunk-6Q2QTUOP-C7qNvbCj.js";import{p}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{_ as t,l as o}from"./mermaid.core-B7WVQkyL.js";import{M as u,a as f}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var c=f().RailroadEbnf.parser.LangiumParser,s=t(e=>{const r=e.alternatives.map(E);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformChoice"),E=t(e=>{const r=e.elements.map(d);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformSequence"),i=t(e=>{switch(e.$type){case"EbnfTerminal":return{type:"terminal",value:e.value};case"EbnfNonTerminal":return{type:"nonterminal",name:e.name};case"EbnfSpecial":return{type:"special",text:e.text};case"EbnfGroup":return s(e.element);case"EbnfOptional":return{type:"optional",element:s(e.element)};case"EbnfRepetition":return{type:"repetition",element:s(e.element),min:0,max:1/0};default:throw new Error(`Unsupported EBNF primary node: ${e.$type}`)}},"transformPrimary"),b=t((e,r)=>{switch(r.$type){case"EbnfOptionalPostfix":return{type:"optional",element:e};case"EbnfZeroOrMorePostfix":return{type:"repetition",element:e,min:0,max:1/0};case"EbnfOneOrMorePostfix":return{type:"repetition",element:e,min:1,max:1/0};case"EbnfExceptionPostfix":return{type:"sequence",elements:[e,{type:"terminal",value:"-"},i(r.except)]};default:throw new Error(`Unsupported EBNF postfix node: ${r.$type}`)}},"transformPostfix"),d=t(e=>e.postfixes.reduce((r,a)=>b(r,a),i(e.base)),"transformTerm"),y=t(e=>({name:e.name,definition:s(e.definition)}),"transformRule"),v=t(e=>{p(e,n),e.title&&n.setTitle(e.title),e.rules.map(r=>n.addRule(y(r)))},"populateDb"),g={parse:t(e=>{n.clear(),o.debug("[EBNF Parser] Starting Langium parse");const r=c.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new u(r);const a=r.value;o.debug("[EBNF Parser] Parsed rules:",a.rules.length),v(a),o.debug("[EBNF Parser] Parse complete")},"parse"),parser:{yy:n}},S={parser:g,db:n,renderer:m,styles:l};export{S as diagram};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+15
-15
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
import{_ as a,l as s,D as n,e as i}from"./mermaid.core-B7WVQkyL.js";import{p}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var g={parse:a(async r=>{const e=await p("info",r);s.debug(e)},"parse")},v={version:"11.16.1"},d=a(()=>v.version,"getVersion"),m={getVersion:d},c=a((r,e,o)=>{s.debug(`rendering info diagram
|
||||
`+r);const t=n(e);i(t,100,400,!0),t.append("g").append("text").attr("x",100).attr("y",40).attr("class","version").attr("font-size",32).style("text-anchor","middle").text(`v${o}`)},"draw"),l={draw:c},w={parser:g,db:m,renderer:l};export{w as diagram};
|
||||
@@ -0,0 +1 @@
|
||||
function t(e,a){switch(arguments.length){case 0:break;case 1:this.range(e);break;default:this.range(a).domain(e);break}return this}export{t as i};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/mermaid.core-B7WVQkyL.js","assets/_commonjsHelpers-CqkleIqs.js"])))=>i.map(i=>d[i]);
|
||||
const y="modulepreload",b=function(o){return"/"+o},f={},v=function(e,s,m){let d=Promise.resolve();if(s&&s.length>0){let l=function(n){return Promise.all(n.map(a=>Promise.resolve(a).then(u=>({status:"fulfilled",value:u}),u=>({status:"rejected",reason:u}))))};document.getElementsByTagName("link");const r=document.querySelector("meta[property=csp-nonce]"),t=r?.nonce||r?.getAttribute("nonce");d=l(s.map(n=>{if(n=b(n),n in f)return;f[n]=!0;const a=n.endsWith(".css"),u=a?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${n}"]${u}`))return;const c=document.createElement("link");if(c.rel=a?"stylesheet":y,a||(c.as="script"),c.crossOrigin="",c.href=n,t&&c.setAttribute("nonce",t),document.head.appendChild(c),a)return new Promise((g,h)=>{c.addEventListener("load",g),c.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${n}`)))})}))}function i(r){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=r,window.dispatchEvent(t),!t.defaultPrevented)throw r}return d.then(r=>{for(const t of r||[])t.status==="rejected"&&i(t.reason);return e().catch(i)})},E="pre > code.language-mermaid",C={bg:"#15171b",line:"#9aa0a9",text:"#eef0f3",accent:"#f5a623"},_={bg:"#f6f8fa",line:"#57606a",text:"#24292f",accent:"#b26a00"};function p(o){return o.includes('class="language-mermaid"')}async function L(o,e=C){if(!p(o))return o;const s=new DOMParser().parseFromString(o,"text/html"),m=[...s.querySelectorAll(E)];if(!m.length)return o;let d;try{d=(await v(async()=>{const{default:i}=await import("./mermaid.core-B7WVQkyL.js").then(r=>r.bp);return{default:i}},__vite__mapDeps([0,1]))).default,d.initialize({startOnLoad:!1,securityLevel:"strict",theme:"base",fontFamily:"inherit",themeVariables:{background:"transparent",primaryColor:e.bg,primaryTextColor:e.text,primaryBorderColor:e.line,secondaryColor:e.bg,tertiaryColor:e.bg,lineColor:e.line,textColor:e.text,mainBkg:e.bg,nodeBorder:e.line,clusterBkg:"transparent",clusterBorder:e.accent,titleColor:e.text,edgeLabelBackground:e.bg}})}catch{return o}for(const[i,r]of m.entries()){const t=r.parentElement;try{const l="mmd-"+Math.random().toString(36).slice(2)+"-"+i,{svg:n}=await d.render(l,r.textContent||""),a=s.createElement("div");a.className="mermaid-diagram",a.innerHTML=n,t.replaceWith(a)}catch{const l=s.createElement("div");l.className="mermaid-err",l.textContent="Couldn't render this diagram.",t.after(l)}}for(const i of document.querySelectorAll("[id^='dmmd-']"))i.remove();return s.body.innerHTML}export{C as D,_ as L,v as _,p as h,L as r};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{i as a}from"./init-Gi6I4Gst.js";class o extends Map{constructor(n,t=g){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:t}}),n!=null)for(const[r,s]of n)this.set(r,s)}get(n){return super.get(c(this,n))}has(n){return super.has(c(this,n))}set(n,t){return super.set(l(this,n),t)}delete(n){return super.delete(p(this,n))}}function c({_intern:e,_key:n},t){const r=n(t);return e.has(r)?e.get(r):t}function l({_intern:e,_key:n},t){const r=n(t);return e.has(r)?e.get(r):(e.set(r,t),t)}function p({_intern:e,_key:n},t){const r=n(t);return e.has(r)&&(t=e.get(r),e.delete(r)),t}function g(e){return e!==null&&typeof e=="object"?e.valueOf():e}const f=Symbol("implicit");function h(){var e=new o,n=[],t=[],r=f;function s(u){let i=e.get(u);if(i===void 0){if(r!==f)return r;e.set(u,i=n.push(u)-1)}return t[i%t.length]}return s.domain=function(u){if(!arguments.length)return n.slice();n=[],e=new o;for(const i of u)e.has(i)||e.set(i,n.push(i)-1);return s},s.range=function(u){return arguments.length?(t=Array.from(u),s):t.slice()},s.unknown=function(u){return arguments.length?(r=u,s):r},s.copy=function(){return h(n,t).unknown(r)},a.apply(s,arguments),s}export{h as o};
|
||||
@@ -0,0 +1 @@
|
||||
import{g as l,r as m,d as a}from"./chunk-6Q2QTUOP-C7qNvbCj.js";import{p}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{_ as t,l as o}from"./mermaid.core-B7WVQkyL.js";import{M as u,d as c}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var f=c().RailroadPeg.parser.LangiumParser,i=t(e=>{const r=e.alternatives.map(d);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformOrderedChoice"),d=t(e=>{const r=e.elements.map(P);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformSequence"),P=t(e=>{const r=g(e.suffix);return e.operator?{type:"special",text:e.operator==="&"?`&${s(r)}`:`!${s(r)}`}:r},"transformPrefix"),s=t(e=>{switch(e.type){case"terminal":return`"${e.value}"`;case"nonterminal":return e.name;case"special":return e.text;default:return"(...)"}},"nodeToLabel"),g=t(e=>{const r=v(e.primary);if(!e.operator)return r;switch(e.operator){case"?":return{type:"optional",element:r};case"*":return{type:"repetition",element:r,min:0,max:1/0};case"+":return{type:"repetition",element:r,min:1,max:1/0};default:throw new Error(`Unsupported PEG suffix operator: ${e.operator}`)}},"transformSuffix"),v=t(e=>{switch(e.$type){case"PegLiteral":return{type:"terminal",value:e.value};case"PegIdentifier":return{type:"nonterminal",name:e.name};case"PegGroup":return i(e.element);case"PegAny":return{type:"special",text:e.dot};default:throw new Error(`Unsupported PEG primary node: ${e.$type}`)}},"transformPrimary"),y=t(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=t(e=>{p(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(y(r)))},"populateDb"),b={parse:t(e=>{a.clear(),o.debug("[PEG Parser] Starting Langium parse");const r=f.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new u(r);const n=r.value;o.debug("[PEG Parser] Parsed rules:",n.rules.length),h(n),o.debug("[PEG Parser] Parse complete")},"parse"),parser:{yy:a}},L={parser:b,db:a,renderer:m,styles:l};export{L as diagram};
|
||||
@@ -0,0 +1,39 @@
|
||||
import{p as at}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{a2 as T,a5 as B,b5 as rt,g as nt,s as it,a as ot,b as st,o as lt,n as ct,_ as g,l as G,c as ut,A as dt,D as gt,K as pt,e as ht,p as ft,B as mt}from"./mermaid.core-B7WVQkyL.js";import{p as vt}from"./cynefin-VYW2F7L2-CdOzebfq.js";import{d as Z}from"./arc-DQmUyXqg.js";import{o as xt}from"./ordinal-Cboi1Yqb.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";import"./init-Gi6I4Gst.js";function St(t,n){return n<t?-1:n>t?1:n>=t?0:NaN}function yt(t){return t}function wt(){var t=yt,n=St,y=null,b=T(0),l=T(B),p=T(0);function i(e){var r,s=(e=rt(e)).length,h,w,$=0,f=new Array(s),o=new Array(s),D=+b.apply(this,arguments),E=Math.min(B,Math.max(-B,l.apply(this,arguments)-D)),k,L=Math.min(Math.abs(E)/s,p.apply(this,arguments)),u=L*(E<0?-1:1),A;for(r=0;r<s;++r)(A=o[f[r]=r]=+t(e[r],r,e))>0&&($+=A);for(n!=null?f.sort(function(M,m){return n(o[M],o[m])}):y!=null&&f.sort(function(M,m){return y(e[M],e[m])}),r=0,w=$?(E-s*u)/$:0;r<s;++r,D=k)h=f[r],A=o[h],k=D+(A>0?A*w:0)+u,o[h]={data:e[h],index:r,value:A,startAngle:D,endAngle:k,padAngle:L};return o}return i.value=function(e){return arguments.length?(t=typeof e=="function"?e:T(+e),i):t},i.sortValues=function(e){return arguments.length?(n=e,y=null,i):n},i.sort=function(e){return arguments.length?(y=e,n=null,i):y},i.startAngle=function(e){return arguments.length?(b=typeof e=="function"?e:T(+e),i):b},i.endAngle=function(e){return arguments.length?(l=typeof e=="function"?e:T(+e),i):l},i.padAngle=function(e){return arguments.length?(p=typeof e=="function"?e:T(+e),i):p},i}var At=mt.pie,I={sections:new Map,showData:!1},F=I.sections,V=I.showData,Ct=structuredClone(At),$t=g(()=>structuredClone(Ct),"getConfig"),Dt=g(()=>{F=new Map,V=I.showData,ft()},"clear"),Tt=g(({label:t,value:n})=>{if(n<0)throw new Error(`"${t}" has invalid value: ${n}. Negative values are not allowed in pie charts. All slice values must be >= 0.`);F.has(t)||(F.set(t,n),G.debug(`added new section: ${t}, with value: ${n}`))},"addSection"),bt=g(()=>F,"getSections"),kt=g(t=>{V=t},"setShowData"),zt=g(()=>V,"getShowData"),q={getConfig:$t,clear:Dt,setDiagramTitle:ct,getDiagramTitle:lt,setAccTitle:st,getAccTitle:ot,setAccDescription:it,getAccDescription:nt,addSection:Tt,getSections:bt,setShowData:kt,getShowData:zt},Et=g((t,n)=>{at(t,n),n.setShowData(t.showData),t.sections.map(n.addSection)},"populateDb"),Mt={parse:g(async t=>{const n=await vt("pie",t);G.debug(n),Et(n,q)},"parse")},Rt=g(t=>`
|
||||
.pieCircle{
|
||||
stroke: ${t.pieStrokeColor};
|
||||
stroke-width : ${t.pieStrokeWidth};
|
||||
opacity : ${t.pieOpacity};
|
||||
}
|
||||
.pieCircle.highlighted{
|
||||
scale: 1.05;
|
||||
opacity: 1;
|
||||
}
|
||||
.pieCircle.highlightedOnHover:hover{
|
||||
transition-duration: 250ms;
|
||||
scale: 1.05;
|
||||
opacity: 1;
|
||||
}
|
||||
.pieOuterCircle{
|
||||
stroke: ${t.pieOuterStrokeColor};
|
||||
stroke-width: ${t.pieOuterStrokeWidth};
|
||||
fill: none;
|
||||
}
|
||||
.pieTitleText {
|
||||
text-anchor: middle;
|
||||
font-size: ${t.pieTitleTextSize};
|
||||
fill: ${t.pieTitleTextColor};
|
||||
font-family: ${t.fontFamily};
|
||||
}
|
||||
.slice {
|
||||
font-family: ${t.fontFamily};
|
||||
fill: ${t.pieSectionTextColor};
|
||||
font-size:${t.pieSectionTextSize};
|
||||
// fill: white;
|
||||
}
|
||||
.legend text {
|
||||
fill: ${t.pieLegendTextColor};
|
||||
font-family: ${t.fontFamily};
|
||||
font-size: ${t.pieLegendTextSize};
|
||||
}
|
||||
`,"getStyles"),Lt=Rt,Wt=g(t=>{const n=[...t.values()].reduce((l,p)=>l+p,0),y=[...t.entries()].map(([l,p])=>({label:l,value:p})).filter(l=>l.value/n*100>=1);return wt().value(l=>l.value).sort(null)(y)},"createPieArcs"),_t=g((t,n,y,b)=>{G.debug(`rendering pie chart
|
||||
`+t);const l=b.db,p=ut(),i=dt(l.getConfig(),p.pie),e=40,r=18,s=4,h=450,w=h,$=gt(n),f=$.append("g");f.attr("transform","translate("+w/2+","+h/2+")");const{themeVariables:o}=p;let[D]=pt(o.pieOuterStrokeWidth);D??=2;const E=i.legendPosition,k=i.textPosition,L=i.donutHole>0&&i.donutHole<=.9?i.donutHole:0,u=Math.min(w,h)/2-e,A=Z().innerRadius(L*u).outerRadius(u),M=Z().innerRadius(u*k).outerRadius(u*k),m=f.append("g");m.append("circle").attr("cx",0).attr("cy",0).attr("r",u+D/2).attr("class","pieOuterCircle");const W=l.getSections(),J=Wt(W),Q=[o.pie1,o.pie2,o.pie3,o.pie4,o.pie5,o.pie6,o.pie7,o.pie8,o.pie9,o.pie10,o.pie11,o.pie12];let H=0;W.forEach(a=>{H+=a});const U=J.filter(a=>(a.data.value/H*100).toFixed(0)!=="0"),N=xt(Q).domain([...W.keys()]);m.selectAll("mySlices").data(U).enter().append("path").attr("d",A).attr("fill",a=>N(a.data.label)).attr("class",a=>{let c="pieCircle";return i.highlightSlice==="hover"?c+=" highlightedOnHover":i.highlightSlice===a.data.label&&(c+=" highlighted"),c}),m.selectAll("mySlices").data(U).enter().append("text").text(a=>(a.data.value/H*100).toFixed(0)+"%").attr("transform",a=>"translate("+M.centroid(a)+")").style("text-anchor","middle").attr("class","slice");const Y=f.append("text").text(l.getDiagramTitle()).attr("x",0).attr("y",-400/2).attr("class","pieTitleText"),R=[...W.entries()].map(([a,c])=>({label:a,value:c})),C=f.selectAll(".legend").data(R).enter().append("g").attr("class","legend");C.append("rect").attr("width",r).attr("height",r).style("fill",a=>N(a.label)).style("stroke",a=>N(a.label)),C.append("text").attr("x",r+s).attr("y",r-s).text(a=>l.getShowData()?`${a.label} [${a.value}]`:a.label);const z=Math.max(...C.selectAll("text").nodes().map(a=>a?.getBoundingClientRect().width??0));let _=h,O=w+e;const d=r+s,P=R.length*d;switch(E){case"center":C.attr("transform",(a,c)=>{const v=d*R.length/2,x=-z/2-(r+s),S=c*d-v;return"translate("+x+","+S+")"});break;case"top":_+=P,C.attr("transform",(a,c)=>{const v=u,x=-z/2-(r+s),S=c*d-v;return`translate(${x}, ${S})`}),m.attr("transform",()=>`translate(0, ${P+d})`);break;case"bottom":_+=P,C.attr("transform",(a,c)=>{const v=-u-d,x=-z/2-(r+s),S=c*d-v;return"translate("+x+","+S+")"});break;case"left":O+=r+s+z,C.attr("transform",(a,c)=>{const v=d*R.length/2,x=-u-(r+s),S=c*d-v;return"translate("+x+","+S+")"}),m.attr("transform",()=>`translate(${z+r+s}, 0)`);break;default:O+=r+s+z,C.attr("transform",(a,c)=>{const v=d*R.length/2,x=12*r,S=c*d-v;return"translate("+x+","+S+")"});break}const j=Y.node()?.getBoundingClientRect().width??0,tt=w/2-j/2,et=w/2+j/2,K=Math.min(0,tt),X=Math.max(O,et)-K;$.attr("viewBox",`${K} 0 ${X} ${_}`),ht($,_,X,i.useMaxWidth)},"draw"),Ft={draw:_t},jt={parser:Mt,db:q,renderer:Ft,styles:Lt};export{jt as diagram};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{g as s,r as l,d as t}from"./chunk-6Q2QTUOP-C7qNvbCj.js";import{p as m}from"./chunk-JWPE2WC7-Czg53Rx5.js";import{_ as n,l as i}from"./mermaid.core-B7WVQkyL.js";import{M as p,c as u}from"./cynefin-VYW2F7L2-CdOzebfq.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var d=u().Railroad.parser.LangiumParser,a=n(e=>{switch(e.$type){case"RailroadTerminalExpr":return{type:"terminal",value:e.value};case"RailroadNonTerminalExpr":return{type:"nonterminal",name:e.name};case"RailroadSpecialExpr":return{type:"special",text:e.text};case"RailroadSequenceExpr":{const r=e.elements.map(a);return r.length===1?r[0]:{type:"sequence",elements:r}}case"RailroadChoiceExpr":{const r=e.alternatives.map(a);return r.length===1?r[0]:{type:"choice",alternatives:r}}case"RailroadOptionalExpr":return{type:"optional",element:a(e.element)};case"RailroadOneOrMoreExpr":return{type:"repetition",element:a(e.element),min:1,max:1/0};case"RailroadZeroOrMoreExpr":return{type:"repetition",element:a(e.element),min:0,max:1/0};default:throw new Error(`Unsupported railroad expression: ${e.$type}`)}},"transformExpression"),c=n(e=>({name:e.name,definition:a(e.definition)}),"transformRule"),g=n(e=>{m(e,t),e.title&&t.setTitle(e.title),e.rules.map(r=>t.addRule(c(r)))},"populateDb"),y={parse:n(e=>{t.clear(),i.debug("[Railroad Parser] Starting Langium parse");const r=d.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new p(r);const o=r.value;i.debug("[Railroad Parser] Parsed rules:",o.rules.length),g(o),i.debug("[Railroad Parser] Parse complete")},"parse"),parser:{yy:t}},P={parser:y,db:t,renderer:l,styles:s};export{P as diagram};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{_ as o}from"./mermaid.core-B7WVQkyL.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var p=1;function i(){if(!(typeof globalThis>"u"))return globalThis}o(i,"getCaptureGlobal");function c(){return!!i()?.mermaidCaptureSizes}o(c,"shouldCaptureSizes");function u(){return typeof location>"u"?"browser-dev":`${location.pathname}${location.search}`}o(u,"capturedFromLocation");function d(n,r){const t=i();if(!t)return;const e=r.node(),s=((e&&"ownerSVGElement"in e?e.ownerSVGElement:null)??e)?.id??"(unknown)";t.mermaidCapturedSizes??=[];const a={svgId:s,sizes:n};t.mermaidCapturedSizes.push(a),t.mermaidLastCapturedSizes=a}o(d,"emitCapturedSizes");function m(n,r){const t=[];for(const e of r.nodes)e.isGroup||t.push({id:e.id,width:e.width??0,height:e.height??0});t.length!==0&&d({metadata:{captureVersion:p,capturedAt:new Date().toISOString(),capturedFrom:u()},nodes:t},n)}o(m,"captureNodeSizes");export{m as captureNodeSizes,c as shouldCaptureSizes};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{s as r,b as e,a,S as s}from"./chunk-5RXB4S5H-D-7tWSyr.js";import{_ as i}from"./mermaid.core-B7WVQkyL.js";import"./chunk-XXDRQBXY-BXTWinaX.js";import"./chunk-KBJHAD2P-CHI3y1em.js";import"./chunk-2GRJ4B5K-Bng47RDF.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var n={parser:a,get db(){return new s(2)},renderer:e,styles:r,init:i(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{n as diagram};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
import{c as r,s as e}from"./flowDiagram-UKHOOZJN-XwdembEj.js";import{_ as a}from"./mermaid.core-B7WVQkyL.js";import"./chunk-5VM5RSS4-DJhOL3Lj.js";import"./chunk-XXDRQBXY-BXTWinaX.js";import"./chunk-KBJHAD2P-CHI3y1em.js";import"./chunk-2GRJ4B5K-Bng47RDF.js";import"./channel-BphRH4Sr.js";import"./mermaid-CP2pUOT9.js";import"./_commonjsHelpers-CqkleIqs.js";var o=a(t=>`${e(t)}
|
||||
.swimlane.cluster rect {
|
||||
stroke: ${t.clusterBorder} !important;
|
||||
}
|
||||
[data-look="neo"].cluster rect {
|
||||
filter: none;
|
||||
}
|
||||
`,"getStyles"),m=o,y=r({defaultLayout:"swimlane",styles:m});export{y as diagram};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,8 +5,10 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>BearDrive</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='%23f5a623'><rect x='4' y='4' width='5.6' height='24'/><rect x='11.2' y='4' width='14.4' height='11.2'/><rect x='11.2' y='16.8' width='16.8' height='11.2'/></svg>">
|
||||
<script type="module" crossorigin src="/assets/index-Q_8ZOeQ7.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Do25j1to.css">
|
||||
<script type="module" crossorigin src="/assets/index-D7MxmRut.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/_commonjsHelpers-CqkleIqs.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/mermaid-CP2pUOT9.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Bhy4rJG7.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import{r,D as a,L as d}from"./assets/mermaid-CP2pUOT9.js";const n=matchMedia("(prefers-color-scheme: dark)").matches;r(document.body.innerHTML,n?a:d).then(e=>{document.body.innerHTML=e});
|
||||
Reference in New Issue
Block a user