libpetri 2.7.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/chunk-E3ZWB645.js +27 -0
- package/dist/chunk-E3ZWB645.js.map +1 -0
- package/dist/{chunk-ULX3OG6H.js → chunk-JVI5HFRX.js} +12 -6
- package/dist/chunk-JVI5HFRX.js.map +1 -0
- package/dist/chunk-M3KT7BFO.js +2773 -0
- package/dist/chunk-M3KT7BFO.js.map +1 -0
- package/dist/debug/index.d.ts +2 -2
- package/dist/debug/index.js +2 -1
- package/dist/debug/index.js.map +1 -1
- package/dist/doclet/index.d.ts +1 -1
- package/dist/doclet/index.js +3 -2
- package/dist/doclet/index.js.map +1 -1
- package/dist/dot-exporter-SHBYMMJ3.js +9 -0
- package/dist/{event-store-8XkpYUeU.d.ts → event-store-CAkN_ayv.d.ts} +1 -1
- package/dist/export/index.d.ts +1 -1
- package/dist/export/index.js +2 -1
- package/dist/index.d.ts +67 -4
- package/dist/index.js +632 -12
- package/dist/index.js.map +1 -1
- package/dist/{petri-net-D73-PO6d.d.ts → petri-net-B4wQwsUj.d.ts} +140 -3
- package/dist/verification/index.d.ts +40 -2
- package/dist/verification/index.js +9 -508
- package/dist/verification/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-ETNHEAS6.js +0 -1458
- package/dist/chunk-ETNHEAS6.js.map +0 -1
- package/dist/chunk-ULX3OG6H.js.map +0 -1
- package/dist/dot-exporter-TYC6FUAD.js +0 -8
- /package/dist/{dot-exporter-TYC6FUAD.js.map → dot-exporter-SHBYMMJ3.js.map} +0 -0
package/dist/doclet/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Application } from 'typedoc';
|
|
2
|
-
import { P as PetriNet, S as SubnetDef, o as Instance } from '../petri-net-
|
|
2
|
+
import { P as PetriNet, S as SubnetDef, o as Instance } from '../petri-net-B4wQwsUj.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* TypeDoc plugin for `@petrinet` and `@subnet` tags — auto-generates
|
package/dist/doclet/index.js
CHANGED
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
dotExport,
|
|
4
4
|
nodeStyle,
|
|
5
5
|
sanitize
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-JVI5HFRX.js";
|
|
7
|
+
import "../chunk-E3ZWB645.js";
|
|
7
8
|
import "../chunk-ATT7U5H5.js";
|
|
8
9
|
|
|
9
10
|
// src/doclet/petri-net-plugin.ts
|
|
@@ -446,7 +447,7 @@ function escapeLabel(s) {
|
|
|
446
447
|
|
|
447
448
|
// src/doclet/petri-net-plugin.ts
|
|
448
449
|
async function getDotExport() {
|
|
449
|
-
const mod = await import("../dot-exporter-
|
|
450
|
+
const mod = await import("../dot-exporter-SHBYMMJ3.js");
|
|
450
451
|
return mod.dotExport;
|
|
451
452
|
}
|
|
452
453
|
var TAG_PETRINET = "@petrinet";
|
package/dist/doclet/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/doclet/petri-net-plugin.ts","../../src/doclet/net-resolver.ts","../../src/doclet/diagram-renderer.ts","../../src/doclet/subnet-header.ts","../../src/doclet/subnet-dot-export.ts","../../src/doclet/svg-renderer.ts"],"sourcesContent":["/**\n * TypeDoc plugin for `@petrinet` and `@subnet` tags — auto-generates\n * interactive SVG diagrams from PetriNet / SubnetDef / Instance definitions\n * and embeds them in TypeDoc output.\n *\n * Mirrors: `org.libpetri.doclet.PetriNetTaglet` + `SubnetTaglet`\n *\n * Plugin lifecycle (TypeDoc hooks):\n * 1. `bootstrapEnd` → register `@petrinet` and `@subnet` as known block tags.\n * 2. `preRenderAsyncJobs` → walk reflections, resolve references, generate\n * SVGs, cache HTML.\n * 3. `comment.beforeTags` → inject cached HTML via `JSX.Raw`, skip default\n * rendering for the recognised tags.\n *\n * @module doclet/petri-net-plugin\n */\n\nimport {\n type Application,\n type CommentTag,\n type DeclarationReflection,\n type ProjectReflection,\n type Reflection,\n JSX,\n} from 'typedoc';\nimport { resolveNet, type ResolvedNet } from './net-resolver.js';\nimport { renderSvg, renderSubnetSvg, escapeHtml } from './diagram-renderer.js';\nimport { forSubnetDef, forInstance } from './subnet-header.js';\nimport { fullBody as subnetFullBody, interfaceOnly as subnetInterfaceOnly } from './subnet-dot-export.js';\n\n// Lazy import to avoid requiring libpetri/export at module level.\nasync function getDotExport(): Promise<typeof import('../export/dot-exporter.js').dotExport> {\n const mod = await import('../export/dot-exporter.js');\n return mod.dotExport;\n}\n\n/** Block tag for full body diagrams — resolves PetriNet / SubnetDef / Instance. */\nconst TAG_PETRINET = '@petrinet' as `@${string}`;\n/** Block tag for interface-only subnet diagrams. */\nconst TAG_SUBNET = '@subnet' as `@${string}`;\n\n/** Cache: reflection ID → rendered HTML string */\nconst htmlCache = new Map<number, string>();\n\n/**\n * Loads the petri-net plugin into the TypeDoc application.\n *\n * @param app - the TypeDoc Application instance\n */\nexport function load(app: Application): void {\n // 1. Register both tags as known block tags at bootstrap time.\n app.on('bootstrapEnd', () => {\n const blockTags = app.options.getValue('blockTags') as string[];\n const additions: string[] = [];\n if (!blockTags.includes(TAG_PETRINET)) additions.push(TAG_PETRINET);\n if (!blockTags.includes(TAG_SUBNET)) additions.push(TAG_SUBNET);\n if (additions.length > 0) {\n app.options.setValue('blockTags', [...blockTags, ...additions]);\n }\n });\n\n // 2. Resolve references and generate SVG during pre-render async phase.\n app.renderer.preRenderAsyncJobs.push(async (output) => {\n htmlCache.clear();\n await processProject(app, output.project);\n });\n\n // 3. Inject cached HTML into comment output, suppress default tag rendering.\n app.renderer.hooks.on('comment.beforeTags', (_context, comment, reflection) => {\n const cached = htmlCache.get(reflection.id);\n if (!cached) return JSX.createElement(JSX.Raw, { html: '' });\n\n // Mark our tags as skip so TypeDoc doesn't render them as plain text.\n for (const tag of comment.blockTags) {\n if (tag.tag === TAG_PETRINET || tag.tag === TAG_SUBNET) {\n tag.skipRendering = true;\n }\n }\n\n return JSX.createElement(JSX.Raw, { html: cached });\n });\n}\n\n/**\n * Walks all reflections in the project and processes `@petrinet` / `@subnet`\n * tags. Per-reflection HTML accumulates in {@link htmlCache} so multiple tags\n * on one symbol render in declaration order.\n */\nasync function processProject(app: Application, project: ProjectReflection): Promise<void> {\n const reflections = Object.values(project.reflections);\n\n for (const reflection of reflections) {\n const comment = reflection.comment;\n if (!comment) continue;\n\n for (const tag of comment.blockTags) {\n const isPetrinet = tag.tag === TAG_PETRINET;\n const isSubnet = tag.tag === TAG_SUBNET;\n if (!isPetrinet && !isSubnet) continue;\n\n const reference = tagContent(tag);\n try {\n const html = isSubnet\n ? await generateInterfaceOnly(reference, reflection)\n : await generateDiagram(reference, reflection);\n const existing = htmlCache.get(reflection.id) ?? '';\n htmlCache.set(reflection.id, existing + html);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n const tagName = isSubnet ? '@subnet' : '@petrinet';\n app.logger.warn(`${tagName} error for ${reflection.getFriendlyFullName()}: ${msg}`);\n const html = errorHtml(`Error generating diagram for '${reference}': ${msg}`);\n const existing = htmlCache.get(reflection.id) ?? '';\n htmlCache.set(reflection.id, existing + html);\n }\n }\n }\n}\n\n/**\n * Generates a diagram HTML string for a single `@petrinet` reference. Resolves\n * the reference to one of {@link ResolvedNet} variants and dispatches to the\n * matching renderer.\n */\nasync function generateDiagram(\n reference: string,\n reflection: Reflection,\n): Promise<string> {\n const trimmed = reference.trim();\n if (!trimmed) {\n return errorHtml(`Empty @petrinet reference on ${reflection.getFriendlyFullName()}`);\n }\n\n const sourceFile = getSourceFilePath(reflection);\n if (!sourceFile) {\n return errorHtml(`Cannot determine source file for ${reflection.getFriendlyFullName()}`);\n }\n\n const resolved = await resolveNet(trimmed, sourceFile);\n if (!resolved) {\n return errorHtml(`Cannot resolve PetriNet/SubnetDef/Instance: ${trimmed}`);\n }\n\n return await renderResolved(resolved, /* interfaceOnly */ false);\n}\n\n/**\n * Generates an interface-only diagram for a `@subnet` reference. When the\n * resolved reference is not a {@link import('../core/subnet-def.js').SubnetDef},\n * falls back to the regular diagram so the tag still produces useful output.\n */\nasync function generateInterfaceOnly(\n reference: string,\n reflection: Reflection,\n): Promise<string> {\n const trimmed = reference.trim();\n if (!trimmed) {\n return errorHtml(`Empty @subnet reference on ${reflection.getFriendlyFullName()}`);\n }\n\n const sourceFile = getSourceFilePath(reflection);\n if (!sourceFile) {\n return errorHtml(`Cannot determine source file for ${reflection.getFriendlyFullName()}`);\n }\n\n const resolved = await resolveNet(trimmed, sourceFile);\n if (!resolved) {\n return errorHtml(`Cannot resolve SubnetDef: ${trimmed}`);\n }\n\n return await renderResolved(resolved, /* interfaceOnly */ true);\n}\n\n/**\n * Dispatches a {@link ResolvedNet} to the matching renderer. The\n * `interfaceOnly` flag is honoured only when the resolved kind is `subnet` —\n * for `net` and `instance` it is ignored (the body is the whole point of\n * those references).\n */\nasync function renderResolved(\n resolved: ResolvedNet,\n interfaceOnly: boolean,\n): Promise<string> {\n switch (resolved.kind) {\n case 'net': {\n const dotExport = await getDotExport();\n const dot = dotExport(resolved.value);\n return renderDiagramHtml(resolved.title, dot, /* header */ null);\n }\n case 'subnet': {\n const dot = interfaceOnly\n ? subnetInterfaceOnly(resolved.value)\n : subnetFullBody(resolved.value);\n const header = forSubnetDef(resolved.value, interfaceOnly);\n const title = resolved.value.name + (interfaceOnly ? ' (interface)' : '');\n return renderDiagramHtml(title, dot, header);\n }\n case 'instance': {\n const dotExport = await getDotExport();\n const dot = dotExport(resolved.value.renamedBody);\n const header = forInstance(resolved.value);\n return renderDiagramHtml(resolved.title, dot, header);\n }\n }\n}\n\n/**\n * Emits the diagram HTML. The canonical viewer renders DOT to SVG\n * client-side via Graphviz-WASM, so no server-side SVG rendering happens\n * here. Routes through the subnet-aware renderer when `header` is non-null,\n * the plain renderer otherwise.\n */\nfunction renderDiagramHtml(\n title: string,\n dot: string,\n header: string | null,\n): string {\n if (header !== null) {\n return renderSubnetSvg(title, header, dot);\n }\n return renderSvg(title, dot);\n}\n\n/**\n * Extracts text content from a CommentTag.\n */\nfunction tagContent(tag: CommentTag): string {\n return tag.content\n .map((part) => part.text)\n .join('')\n .trim();\n}\n\n/**\n * Gets the source file path from a reflection. Walks parents because\n * comment-bearing reflections sometimes lack their own `sources` (e.g.\n * inherited members).\n */\nfunction getSourceFilePath(reflection: Reflection): string | null {\n const decl = reflection as DeclarationReflection;\n if (decl.sources && decl.sources.length > 0) {\n return decl.sources[0]!.fullFileName;\n }\n if (reflection.parent) {\n return getSourceFilePath(reflection.parent);\n }\n return null;\n}\n\n/**\n * Renders an error message as styled HTML.\n */\nfunction errorHtml(message: string): string {\n return `<div class=\"petrinet-error\" style=\"color: #dc3545; border: 1px solid #dc3545; padding: 10px; border-radius: 4px;\">\n<strong>@petrinet Error:</strong> ${escapeHtml(message)}\n</div>`;\n}\n","/**\n * Dynamic import-based resolver for `@petrinet` / `@subnet` references.\n *\n * Resolves three kinds of static exports per Java's `PetriNetTaglet` design:\n * 1. `PetriNet` — full body diagram (existing behaviour).\n * 2. `SubnetDef<?>` — body diagram with interface ports highlighted, plus a\n * subnet header with port/channel badges.\n * 3. `Instance<?>` — renamed body diagram (already prefix-clustered by the\n * DOT exporter), plus an instance header with prefix, def name, and\n * params summary.\n *\n * TypeScript cannot use reflection like Java — modules must be importable at\n * doc time (typically from `dist/` after `npm run build`).\n *\n * Tag format:\n * ```\n * @petrinet ./path/to/module#exportName — access a static export\n * @petrinet ./path/to/module#functionName() — call a function returning one\n * @petrinet #localExport — resolve from same file\n * ```\n *\n * Mirrors: `org.libpetri.doclet.PetriNetTaglet.resolveReference`\n *\n * @module doclet/net-resolver\n */\n\nimport { resolve, dirname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { PetriNet } from '../core/petri-net.js';\nimport type { SubnetDef } from '../core/subnet-def.js';\nimport type { Instance } from '../core/instance.js';\n\n/**\n * Discriminated-union result from {@link resolveNet}. Each variant carries\n * the resolved value plus a display title.\n */\nexport type ResolvedNet =\n | { readonly kind: 'net'; readonly value: PetriNet; readonly title: string }\n | { readonly kind: 'subnet'; readonly value: SubnetDef<unknown>; readonly title: string }\n | { readonly kind: 'instance'; readonly value: Instance<unknown>; readonly title: string };\n\n/**\n * Parses a `@petrinet` / `@subnet` reference and resolves it via dynamic\n * import. Returns `null` when the reference cannot be parsed or imported, or\n * when the resolved value is none of the three supported kinds.\n *\n * @param reference - the tag content, e.g. `./definition#buildDebugNet()`\n * @param sourceFilePath - absolute path to the source file containing the tag\n */\nexport async function resolveNet(\n reference: string,\n sourceFilePath: string,\n): Promise<ResolvedNet | null> {\n const trimmed = reference.trim().split(/\\s+/)[0] ?? '';\n if (!trimmed) return null;\n\n const hashIndex = trimmed.indexOf('#');\n if (hashIndex === -1) return null;\n\n const modulePath = trimmed.substring(0, hashIndex);\n const exportRef = trimmed.substring(hashIndex + 1);\n if (!exportRef) return null;\n\n const isCall = exportRef.endsWith('()');\n const exportName = isCall ? exportRef.slice(0, -2) : exportRef;\n\n // Resolve module path relative to the source file.\n let absolutePath: string;\n if (modulePath) {\n absolutePath = resolve(dirname(sourceFilePath), modulePath);\n } else {\n // `#localExport` — resolve from same file's compiled output.\n absolutePath = sourceFilePath;\n }\n\n // Try `.js` extension for compiled output, then `.ts` for ts-node scenarios.\n const candidates = [\n absolutePath,\n absolutePath + '.js',\n absolutePath + '.ts',\n absolutePath.replace(/\\.ts$/, '.js'),\n ];\n\n let mod: Record<string, unknown> | undefined;\n for (const candidate of candidates) {\n try {\n mod = await import(pathToFileURL(candidate).href) as Record<string, unknown>;\n break;\n } catch {\n // Try next candidate.\n }\n }\n\n if (!mod) return null;\n\n const exported = mod[exportName];\n if (exported == null) return null;\n\n let value: unknown;\n if (isCall) {\n if (typeof exported !== 'function') return null;\n const result = (exported as (...args: unknown[]) => unknown)();\n // Support functions that return `{ net: PetriNet, ... }` for legacy\n // callers; otherwise pass the result through directly.\n if (\n result !== null && typeof result === 'object' && 'net' in result &&\n isPetriNetLike((result as { net: unknown }).net)\n ) {\n value = (result as { net: unknown }).net;\n } else {\n value = result;\n }\n } else {\n value = exported;\n }\n\n return classify(value);\n}\n\n/**\n * Wraps the resolved value into a {@link ResolvedNet} variant by structural\n * shape — checks {@link Instance} before {@link SubnetDef} before\n * {@link PetriNet} so the most specific match wins (Instance has both `def`\n * and `renamedBody`; SubnetDef has `iface` and `body`; PetriNet has only\n * `transitions` + `name`).\n *\n * Returns `null` when the value matches none of the supported shapes.\n */\nfunction classify(value: unknown): ResolvedNet | null {\n if (value === null || typeof value !== 'object') return null;\n\n if (isInstanceLike(value)) {\n const inst = value as Instance<unknown>;\n return { kind: 'instance', value: inst, title: `${inst.def.name} :: ${inst.prefix}` };\n }\n if (isSubnetDefLike(value)) {\n const def = value as SubnetDef<unknown>;\n return { kind: 'subnet', value: def, title: def.name };\n }\n if (isPetriNetLike(value)) {\n const net = value as PetriNet;\n return { kind: 'net', value: net, title: net.name };\n }\n return null;\n}\n\n/**\n * Structural test for {@link PetriNet}: has a string `name` and a `transitions`\n * Set. Avoids `instanceof` because the imported module may have re-bound the\n * class identity (TypeDoc's bundled output vs `dist/` import path).\n */\nfunction isPetriNetLike(value: unknown): value is PetriNet {\n if (value === null || typeof value !== 'object') return false;\n const candidate = value as { name?: unknown; transitions?: unknown };\n return typeof candidate.name === 'string' && candidate.transitions instanceof Set;\n}\n\n/**\n * Structural test for {@link SubnetDef}: has a string `name`, a {@link\n * PetriNet}-shaped `body`, and an `iface` carrying `ports` + `channels` maps.\n */\nfunction isSubnetDefLike(value: unknown): value is SubnetDef<unknown> {\n if (value === null || typeof value !== 'object') return false;\n const candidate = value as { name?: unknown; body?: unknown; iface?: unknown };\n if (typeof candidate.name !== 'string') return false;\n if (!isPetriNetLike(candidate.body)) return false;\n const iface = candidate.iface as { ports?: unknown; channels?: unknown } | undefined;\n return iface !== undefined && iface !== null\n && iface.ports instanceof Map && iface.channels instanceof Map;\n}\n\n/**\n * Structural test for {@link Instance}: has a string `prefix`, a {@link\n * SubnetDef}-shaped `def`, and a {@link PetriNet}-shaped `renamedBody`.\n */\nfunction isInstanceLike(value: unknown): value is Instance<unknown> {\n if (value === null || typeof value !== 'object') return false;\n const candidate = value as { prefix?: unknown; def?: unknown; renamedBody?: unknown };\n return typeof candidate.prefix === 'string'\n && isSubnetDefLike(candidate.def)\n && isPetriNetLike(candidate.renamedBody);\n}\n","/**\n * Shared HTML renderer for Petri Net diagrams in TypeDoc.\n *\n * Generates consistent HTML markup that mounts the canonical\n * {@link https://libpetri.org | libpetri} viewer client-side. The viewer IIFE\n * bundle (Graphviz WASM inlined, offline-safe) is inlined into the generated\n * HTML, making the plugin fully self-contained with no external file\n * dependencies.\n *\n * Each diagram container carries its DOT source as a `data-dot` attribute. An\n * init snippet reads the attribute and calls\n * `window.LibpetriViewer.mount(dot, container, { chrome: true })` to render the\n * SVG and wire pan/zoom + cluster legend/filter chrome.\n *\n * Mirrors: `org.libpetri.doclet.DiagramRenderer`\n *\n * @module doclet/diagram-renderer\n */\n\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction loadResource(filename: string): string {\n return readFileSync(join(__dirname, 'resources', filename), 'utf-8');\n}\n\nlet inlineCss: string | undefined;\nlet inlineJs: string | undefined;\n\nfunction css(): string {\n return (inlineCss ??= loadResource('petrinet-diagrams.css'));\n}\n\nfunction js(): string {\n return (inlineJs ??= loadResource('petrinet-diagrams.js'));\n}\n\n/**\n * Escapes HTML special characters for safe embedding as text content.\n */\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/**\n * Escapes a string for safe inclusion in an HTML attribute value enclosed in\n * double quotes. Identical to {@link escapeHtml} plus single-quote escaping\n * (defence-in-depth even though we always emit double-quoted attributes).\n */\nfunction escapeAttr(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Renders a diagram from a DOT source string. The viewer renders the SVG\n * client-side via Graphviz-WASM; no server-side SVG is emitted on the\n * embedded path.\n *\n * Inlines CSS and the viewer IIFE from bundled resources. The IIFE is guarded\n * by an idempotency check (`window._libpetriViewerInit`) so it only executes\n * once per page even when multiple `@petrinet` tags appear.\n *\n * @param title - optional title (null/undefined for no title)\n * @param dotSource - the DOT source code; embedded as `data-dot` and shown in\n * the collapsible \"View DOT Source\" block\n * @returns HTML markup with diagram controls\n */\nexport function renderSvg(\n title: string | null | undefined,\n dotSource: string,\n): string {\n return renderInternal(title ?? null, /* headerHtml */ null, dotSource);\n}\n\n/**\n * Renders a subnet- or instance-aware diagram. Identical to {@link renderSvg}\n * apart from an extra {@code headerHtml} block (the port/channel/params\n * badge bar) prepended above the diagram, and the CSS class\n * {@code subnet-diagram} on the wrapper.\n *\n * @param title diagram title (e.g. \"BoundedBuffer :: b1\")\n * @param headerHtml the HTML produced by {@link import('./subnet-header.js')}\n * @param dotSource the DOT source code\n * @returns HTML markup\n */\nexport function renderSubnetSvg(\n title: string | null | undefined,\n headerHtml: string,\n dotSource: string,\n): string {\n return renderInternal(title ?? null, headerHtml, dotSource);\n}\n\nlet diagramIdCounter = 0;\n\nfunction renderInternal(\n title: string | null,\n headerHtml: string | null,\n dotSource: string,\n): string {\n const titleHtml = title !== null ? `<h4>${escapeHtml(title)}</h4>\\n` : '';\n const summaryText = title !== null ? 'View DOT Source' : 'View Source';\n const diagramClass = headerHtml !== null ? 'petrinet-diagram subnet-diagram' : 'petrinet-diagram';\n const headerBlock = headerHtml !== null ? headerHtml : '';\n const dotAttr = escapeAttr(dotSource);\n const containerId = `libpetri-diagram-${++diagramIdCounter}`;\n\n return `<style>${css()}</style>\n<script>if(!window._libpetriViewerInit){window._libpetriViewerInit=true;\n${js()}\n}</script>\n<div class=\"${diagramClass}\">\n${titleHtml}${headerBlock}<div class=\"diagram-container\" id=\"${containerId}\" data-libpetri-diagram=\"true\" data-dot=\"${dotAttr}\"></div>\n<details>\n<summary>${summaryText}</summary>\n<pre><code>${escapeHtml(dotSource)}</code></pre>\n</details>\n</div>\n<script>(function(){function mount(){var el=document.getElementById(${JSON.stringify(containerId)});if(!el)return;if(el.dataset.libpetriMounted)return;if(!window.LibpetriViewer||typeof window.LibpetriViewer.mount!=='function'){return setTimeout(mount,30);}el.dataset.libpetriMounted='1';try{window.LibpetriViewer.mount(el.dataset.dot,el,{chrome:true});}catch(e){console.error('[libpetri] mount failed',e);}}if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',mount);}else{mount();}})();</script>`;\n}\n","/**\n * HTML-fragment generator for the small \"subnet header\" badge bar that the\n * {@link import('./diagram-renderer.js')} layers above subnet diagrams.\n *\n * For a {@link import('../core/subnet-def.js').SubnetDef} the header lists\n * the subnet name, the parameter type (best-effort — TypeScript erases\n * generics at runtime so the slot is shown as a placeholder), and one badge\n * per port and channel — colour-coded by direction\n * (`interface-port-input` / `-output` / `-inout` CSS classes, plus\n * `interface-channel` for sync channels).\n *\n * For an {@link import('../core/instance.js').Instance} the header lists the\n * instance prefix, the originating definition's name, and the {@link\n * import('../core/instance.js').Instance#params} summary.\n *\n * Mirrors: `org.libpetri.doclet.SubnetHeader`\n *\n * @module doclet/subnet-header\n */\n\nimport type { Instance } from '../core/instance.js';\nimport type { Interface, Port } from '../core/interface.js';\nimport type { SubnetDef } from '../core/subnet-def.js';\nimport { escapeHtml } from './diagram-renderer.js';\n\n/**\n * Builds the header HTML for a {@link SubnetDef} field.\n *\n * @param def the subnet definition\n * @param interfaceOnly when `true`, the header carries the \"(interface only)\"\n * badge so the reader knows the body is intentionally\n * omitted\n */\nexport function forSubnetDef(def: SubnetDef<unknown>, interfaceOnly: boolean): string {\n const sb: string[] = [];\n sb.push(`<div class=\"subnet-header\">\\n`);\n sb.push(` <div class=\"subnet-header-row\">\\n`);\n sb.push(` <span class=\"subnet-header-label\">subnet</span>\\n`);\n sb.push(` <span class=\"subnet-header-name\">${escapeHtml(def.name)}</span>\\n`);\n // TypeScript erases generics at runtime, so the parameter-type slot is\n // populated with a placeholder (\"?\"). Java emits the simple class name —\n // the structural HTML is otherwise byte-equivalent.\n sb.push(` <span class=\"subnet-header-param\"><?></span>\\n`);\n if (interfaceOnly) {\n sb.push(` <span class=\"subnet-header-badge subnet-header-badge-interface\">interface only</span>\\n`);\n }\n sb.push(` </div>\\n`);\n sb.push(renderPortChannelBadges(def.iface));\n sb.push(`</div>\\n`);\n return sb.join('');\n}\n\n/**\n * Builds the header HTML for an {@link Instance} field.\n */\nexport function forInstance(instance: Instance<unknown>): string {\n const def = instance.def;\n const sb: string[] = [];\n sb.push(`<div class=\"subnet-header\">\\n`);\n sb.push(` <div class=\"subnet-header-row\">\\n`);\n sb.push(` <span class=\"subnet-header-label\">instance</span>\\n`);\n sb.push(` <span class=\"subnet-header-name\">${escapeHtml(instance.prefix)}</span>\\n`);\n sb.push(` <span class=\"subnet-header-of\">of</span>\\n`);\n sb.push(` <span class=\"subnet-header-name\">${escapeHtml(def.name)}</span>\\n`);\n const params = instance.params;\n if (params !== null && params !== undefined) {\n sb.push(` <span class=\"subnet-header-params\">params=${escapeHtml(String(params))}</span>\\n`);\n }\n sb.push(` </div>\\n`);\n sb.push(renderPortChannelBadges(def.iface));\n sb.push(`</div>\\n`);\n return sb.join('');\n}\n\n/**\n * Renders the per-port and per-channel badge row. Each badge carries a CSS\n * class identifying its kind so the stylesheet can colour-code by direction.\n */\nfunction renderPortChannelBadges(iface: Interface): string {\n if (iface.ports.size === 0 && iface.channels.size === 0) {\n return '';\n }\n const sb: string[] = [];\n sb.push(` <div class=\"subnet-header-badges\">\\n`);\n for (const port of iface.ports.values()) {\n const kind = portKind(port);\n sb.push(` <span class=\"interface-port-badge interface-port-badge-${kind}\">`);\n sb.push(`<span class=\"badge-direction\">${kind}</span>`);\n sb.push(`<span class=\"badge-name\">${escapeHtml(port.name)}</span>`);\n // TypeScript erases generics so we can't print the runtime token type;\n // omit the type-name span rather than emit a bogus value.\n sb.push(`</span>\\n`);\n }\n for (const channel of iface.channels.values()) {\n sb.push(` <span class=\"interface-channel-badge\">`);\n sb.push(`<span class=\"badge-direction\">channel</span>`);\n sb.push(`<span class=\"badge-name\">${escapeHtml(channel.name)}</span>`);\n sb.push(`</span>\\n`);\n }\n sb.push(` </div>\\n`);\n return sb.join('');\n}\n\nfunction portKind(port: Port<unknown>): 'input' | 'output' | 'inout' {\n return port.direction;\n}\n","/**\n * DOT generators for the subnet-aware diagrams the {@link\n * import('./petri-net-plugin.js')} plugin draws.\n *\n * Two flavours:\n * - {@link fullBody} — the subnet's complete body, but with its interface-port\n * places restyled with the `interface-port` category from\n * `petri-net-styles.json` so they read as boundary elements at a glance. A\n * small `subgraph cluster_iface_*` with label `\"interface\"` surrounds the\n * port places and channel transitions to advertise the subnet boundary\n * visually.\n * - {@link interfaceOnly} — a tiny diagram of just the port places, the\n * channel transitions, and a single stub node indicating the body is\n * omitted. Used by the `@subnet` block tag.\n *\n * This module stays in the doclet directory (rather than living in\n * `export/`) because it is a doclet-presentation concern — the production\n * export pipeline never adds the `interface` cluster.\n *\n * Mirrors: `org.libpetri.doclet.SubnetDotExport`\n *\n * @module doclet/subnet-dot-export\n */\n\nimport type { SubnetDef } from '../core/subnet-def.js';\nimport type { Interface, Port, Channel } from '../core/interface.js';\nimport { dotExport } from '../export/dot-exporter.js';\nimport { sanitize } from '../export/petri-net-mapper.js';\nimport { nodeStyle, FONT } from '../export/styles.js';\n\n/**\n * Renders the full body of a {@link SubnetDef} with the interface ports\n * restyled. The output is a post-processed version of {@link dotExport}: the\n * port-place node attribute lines are rewritten so the post-processor swaps in\n * the {@code interface-port} category, channel-transition lines swap in\n * {@code sync-channel}, and an extra {@code subgraph cluster_iface_<name>}\n * block is appended that lists the port nodes by id — overriding their\n * cluster membership without re-emitting them (DOT semantics: a node\n * referenced inside a subgraph block by id alone is treated as a member of\n * that cluster).\n */\nexport function fullBody(def: SubnetDef<unknown>): string {\n let dot = dotExport(def.body);\n const portIds = portNodeIds(def.iface);\n const channelIds = channelNodeIds(def.iface);\n\n // Restyle: rewrite the matched node lines so the post-processor swaps in\n // the interface-port and sync-channel categories. The renderer emits each\n // node as one line ending with `];` so a per-id rewrite is sufficient and\n // deterministic.\n for (const portId of portIds) {\n dot = restyleNode(dot, portId, nodeStyle('interface-port'));\n }\n for (const chId of channelIds) {\n dot = restyleNode(dot, chId, nodeStyle('sync-channel'));\n }\n\n // Wrap the port and channel ids in a header cluster so the doclet's viewer\n // can render the boundary distinctly. Done by injecting an extra subgraph\n // block before the closing `}` of the digraph.\n if (portIds.size > 0 || channelIds.size > 0) {\n let iface = '';\n iface += ` subgraph cluster_iface_${sanitize(def.name)} {\\n`;\n iface += ` label=\"interface\";\\n`;\n iface += ` style=\"rounded,dashed\";\\n`;\n iface += ` bgcolor=\"#F0F6FF\";\\n`;\n iface += ` penwidth=2;\\n`;\n for (const id of portIds) {\n iface += ` ${id};\\n`;\n }\n for (const id of channelIds) {\n iface += ` ${id};\\n`;\n }\n iface += ` }\\n`;\n\n const lastBrace = dot.lastIndexOf('}');\n if (lastBrace > 0) {\n dot = dot.substring(0, lastBrace) + iface + dot.substring(lastBrace);\n }\n }\n return dot;\n}\n\n/**\n * Renders an interface-only diagram: just the port places + channel\n * transitions + a single stub node labelled \"(internals omitted)\" so the\n * reader knows the body has not been drawn.\n */\nexport function interfaceOnly(def: SubnetDef<unknown>): string {\n const sb: string[] = [];\n sb.push(`digraph ${sanitize(def.name)} {\\n`);\n sb.push(` rankdir=LR;\\n`);\n sb.push(` nodesep=0.5;\\n`);\n sb.push(` ranksep=0.6;\\n`);\n sb.push(` fontname=\"${FONT.family}\";\\n`);\n sb.push(` node [fontname=\"${FONT.family}\", fontsize=12];\\n`);\n sb.push(` edge [fontname=\"${FONT.family}\", fontsize=10];\\n`);\n sb.push('\\n');\n\n const stubId = 'stub_' + sanitize(def.name);\n\n // Group ports by direction: inputs on the left, outputs on the right,\n // inouts above. This keeps the interface diagram visually structured even\n // when the body internals are absent.\n const inputs: Port<unknown>[] = [];\n const outputs: Port<unknown>[] = [];\n const inouts: Port<unknown>[] = [];\n for (const port of def.iface.ports.values()) {\n switch (port.direction) {\n case 'input': inputs.push(port); break;\n case 'output': outputs.push(port); break;\n case 'inout': inouts.push(port); break;\n }\n }\n\n // Emit port nodes.\n for (const port of inputs) emitPortNode(sb, port, 'input');\n for (const port of outputs) emitPortNode(sb, port, 'output');\n for (const port of inouts) emitPortNode(sb, port, 'inout');\n\n // Emit channel nodes.\n const syncStyle = nodeStyle('sync-channel');\n for (const ch of def.iface.channels.values()) {\n sb.push(` ${channelNodeId(ch)} [`);\n sb.push(`label=\"⇄ ${escapeLabel(ch.name)}\", `);\n sb.push(`shape=${syncStyle.shape}, `);\n sb.push(`style=\"filled\", `);\n sb.push(`fillcolor=\"${syncStyle.fill}\", `);\n sb.push(`color=\"${syncStyle.stroke}\", `);\n sb.push(`penwidth=${trimNumber(syncStyle.penwidth)}`);\n sb.push(`];\\n`);\n }\n\n // Emit stub node.\n sb.push(` ${stubId} [`);\n sb.push(`label=\"${escapeLabel(def.name)}\\\\n(internals omitted)\", `);\n sb.push(`shape=box, style=\"filled,dashed,rounded\", `);\n sb.push(`fillcolor=\"#FFFFFF\", color=\"#666666\", penwidth=1, `);\n sb.push(`fontsize=11`);\n sb.push(`];\\n`);\n sb.push('\\n');\n\n // Connect inputs -> stub -> outputs; inouts and channels link both ways.\n for (const port of inputs) {\n sb.push(` ${portNodeId(port)} -> ${stubId} [color=\"#1d4ed8\", arrowhead=normal];\\n`);\n }\n for (const port of outputs) {\n sb.push(` ${stubId} -> ${portNodeId(port)} [color=\"#1d4ed8\", arrowhead=normal];\\n`);\n }\n for (const port of inouts) {\n sb.push(` ${portNodeId(port)} -> ${stubId} [color=\"#1d4ed8\", arrowhead=normalnormal, dir=both];\\n`);\n }\n for (const ch of def.iface.channels.values()) {\n sb.push(` ${channelNodeId(ch)} -> ${stubId} [color=\"#6d28d9\", arrowhead=normal, style=dashed];\\n`);\n }\n\n sb.push(`}\\n`);\n return sb.join('');\n}\n\n// ============================================================\n// Helpers\n// ============================================================\n\nfunction emitPortNode(sb: string[], port: Port<unknown>, direction: string): void {\n const style = nodeStyle('interface-port');\n // Token type isn't carried at runtime in TypeScript (generics erased), so\n // the xlabel is the direction marker only — Java additionally appends the\n // port's tokenType simple name. The structural content is otherwise\n // identical.\n sb.push(` ${portNodeId(port)} [`);\n sb.push(`label=\"${escapeLabel(port.name)}\", `);\n sb.push(`xlabel=\"${escapeLabel(direction)}\", `);\n sb.push(`shape=${style.shape}, `);\n sb.push(`style=\"filled,${style.style ?? 'solid'}\", `);\n sb.push(`fillcolor=\"${style.fill}\", `);\n sb.push(`color=\"${style.stroke}\", `);\n sb.push(`penwidth=${trimNumber(style.penwidth)}`);\n if (style.width !== undefined) {\n sb.push(`, width=${trimNumber(style.width)}, fixedsize=true`);\n }\n sb.push(`];\\n`);\n}\n\nfunction portNodeId(port: Port<unknown>): string {\n return 'p_' + sanitize(port.place.name);\n}\n\nfunction channelNodeId(ch: Channel): string {\n return 't_' + sanitize(ch.transition.name);\n}\n\nfunction portNodeIds(iface: Interface): Set<string> {\n const ids = new Set<string>();\n for (const port of iface.ports.values()) ids.add(portNodeId(port));\n return ids;\n}\n\nfunction channelNodeIds(iface: Interface): Set<string> {\n const ids = new Set<string>();\n for (const ch of iface.channels.values()) ids.add(channelNodeId(ch));\n return ids;\n}\n\n/**\n * Rewrites the {@code fillcolor=}, {@code color=}, {@code style=}, and\n * {@code penwidth=} attributes of the line declaring the given node id so\n * the supplied style takes precedence. Operates as a plain text rewrite:\n * the {@link import('../export/dot-renderer.js').renderDot} output formats\n * each node line deterministically, so a per-attribute regex is reliable.\n */\nfunction restyleNode(\n dot: string,\n nodeId: string,\n style: ReturnType<typeof nodeStyle>,\n): string {\n // The node line begins with: <id> [\n // and ends with: ];\n // Find the line, then surgically swap fillcolor / color / style / penwidth.\n const marker = nodeId + ' [';\n let start = dot.indexOf('\\n ' + marker);\n if (start < 0) start = dot.indexOf(' ' + marker);\n if (start < 0) return dot;\n // Skip the leading newline if present so we operate on the line proper.\n if (dot.charAt(start) === '\\n') start += 1;\n const lineEnd = dot.indexOf('];', start);\n if (lineEnd < 0) return dot;\n let line = dot.substring(start, lineEnd + 2);\n\n // Order matters: keep `fillcolor` before `color` so the substring search\n // for `color=\"` doesn't accidentally hit `fillcolor=\"`.\n line = replaceAttr(line, 'fillcolor', style.fill);\n line = replaceAttr(line, 'color', style.stroke);\n line = replaceAttr(line, 'penwidth', trimNumber(style.penwidth));\n if (style.style !== undefined) {\n // Compose with `filled` because the renderer already includes that.\n line = replaceAttr(line, 'style', `\"filled,${style.style}\"`);\n }\n\n return dot.substring(0, start) + line + dot.substring(lineEnd + 2);\n}\n\n/**\n * Replaces the value of a {@code key=value} pair within a single DOT\n * attribute list. Quotes the value when the existing form was quoted, leaves\n * the value unquoted when the existing form was unquoted (numeric).\n */\nfunction replaceAttr(line: string, key: string, value: string): string {\n // Match key=\"...\" (quoted) — the key must be preceded by a non-word char\n // (start, comma, or space) so `color=` doesn't match inside `fillcolor=`.\n const quotedPat = key + '=\"';\n const qStart = findAttrStart(line, quotedPat);\n if (qStart >= 0) {\n const valStart = qStart + quotedPat.length;\n const valEnd = line.indexOf('\"', valStart);\n if (valEnd < 0) return line;\n let v = value;\n if (v.startsWith('\"') && v.endsWith('\"') && v.length >= 2) {\n v = v.substring(1, v.length - 1);\n }\n return line.substring(0, valStart) + v + line.substring(valEnd);\n }\n // Match key=NN (numeric, ends at ',' or ']').\n const unquoted = key + '=';\n const uStart = findAttrStart(line, unquoted);\n if (uStart < 0) return line;\n const valStart = uStart + unquoted.length;\n let valEnd = valStart;\n while (valEnd < line.length) {\n const c = line.charAt(valEnd);\n if (c === ',' || c === ']') break;\n valEnd++;\n }\n return line.substring(0, valStart) + value + line.substring(valEnd);\n}\n\n/**\n * Finds the start of a `key=` attribute pattern in `line`, ensuring the\n * match is not a suffix of another attribute name (e.g. `color=` must not\n * match inside `fillcolor=`). Returns -1 when no boundary-respecting match\n * exists.\n */\nfunction findAttrStart(line: string, pattern: string): number {\n let from = 0;\n while (from < line.length) {\n const idx = line.indexOf(pattern, from);\n if (idx < 0) return -1;\n if (idx === 0) return idx;\n const prev = line.charAt(idx - 1);\n // Word-boundary check: previous char must not be alphanumeric/underscore.\n if (!/[A-Za-z0-9_]/.test(prev)) return idx;\n from = idx + 1;\n }\n return -1;\n}\n\nfunction trimNumber(d: number): string {\n if (Number.isInteger(d)) return String(d);\n return String(d);\n}\n\nfunction escapeLabel(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n","/**\n * SVG renderer using `@viz-js/viz` (Graphviz WASM).\n *\n * Pure WASM — zero external dependencies. No system `dot` binary required.\n *\n * Mirrors: Java's `PetriNetTaglet.dotToSvg()` (which uses `dot -Tsvg` subprocess)\n *\n * @module doclet/svg-renderer\n */\n\n/**\n * Renders a DOT string to SVG using the `@viz-js/viz` WASM engine.\n *\n * Strips the XML prolog/DOCTYPE and explicit width/height attributes so the SVG\n * scales via viewBox + CSS instead of overriding with fixed pt sizes.\n *\n * @param dot - the DOT source string\n * @returns SVG markup string\n * @throws if `@viz-js/viz` is not installed or DOT parsing fails\n */\nexport async function dotToSvg(dot: string): Promise<string> {\n // Dynamic import — @viz-js/viz is an optional peer dependency\n const { instance } = await import('@viz-js/viz');\n const viz = await instance();\n let svg = viz.renderString(dot, { format: 'svg', engine: 'dot' });\n\n // Strip XML prolog and DOCTYPE — invalid inside HTML5\n const svgStart = svg.indexOf('<svg');\n if (svgStart > 0) svg = svg.substring(svgStart);\n\n // Strip explicit width/height attributes (e.g. \"1942pt\") so the SVG\n // scales via viewBox + CSS instead of overriding with fixed pt sizes\n svg = svg.replace(/\\s+(?:width|height)=\"[^\"]*\"/g, '');\n\n return svg;\n}\n"],"mappings":"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","names":["dirname","interfaceOnly","valStart","valEnd","interfaceOnly","dotExport"]}
|
|
1
|
+
{"version":3,"sources":["../../src/doclet/petri-net-plugin.ts","../../src/doclet/net-resolver.ts","../../src/doclet/diagram-renderer.ts","../../src/doclet/subnet-header.ts","../../src/doclet/subnet-dot-export.ts","../../src/doclet/svg-renderer.ts"],"sourcesContent":["/**\n * TypeDoc plugin for `@petrinet` and `@subnet` tags — auto-generates\n * interactive SVG diagrams from PetriNet / SubnetDef / Instance definitions\n * and embeds them in TypeDoc output.\n *\n * Mirrors: `org.libpetri.doclet.PetriNetTaglet` + `SubnetTaglet`\n *\n * Plugin lifecycle (TypeDoc hooks):\n * 1. `bootstrapEnd` → register `@petrinet` and `@subnet` as known block tags.\n * 2. `preRenderAsyncJobs` → walk reflections, resolve references, generate\n * SVGs, cache HTML.\n * 3. `comment.beforeTags` → inject cached HTML via `JSX.Raw`, skip default\n * rendering for the recognised tags.\n *\n * @module doclet/petri-net-plugin\n */\n\nimport {\n type Application,\n type CommentTag,\n type DeclarationReflection,\n type ProjectReflection,\n type Reflection,\n JSX,\n} from 'typedoc';\nimport { resolveNet, type ResolvedNet } from './net-resolver.js';\nimport { renderSvg, renderSubnetSvg, escapeHtml } from './diagram-renderer.js';\nimport { forSubnetDef, forInstance } from './subnet-header.js';\nimport { fullBody as subnetFullBody, interfaceOnly as subnetInterfaceOnly } from './subnet-dot-export.js';\n\n// Lazy import to avoid requiring libpetri/export at module level.\nasync function getDotExport(): Promise<typeof import('../export/dot-exporter.js').dotExport> {\n const mod = await import('../export/dot-exporter.js');\n return mod.dotExport;\n}\n\n/** Block tag for full body diagrams — resolves PetriNet / SubnetDef / Instance. */\nconst TAG_PETRINET = '@petrinet' as `@${string}`;\n/** Block tag for interface-only subnet diagrams. */\nconst TAG_SUBNET = '@subnet' as `@${string}`;\n\n/** Cache: reflection ID → rendered HTML string */\nconst htmlCache = new Map<number, string>();\n\n/**\n * Loads the petri-net plugin into the TypeDoc application.\n *\n * @param app - the TypeDoc Application instance\n */\nexport function load(app: Application): void {\n // 1. Register both tags as known block tags at bootstrap time.\n app.on('bootstrapEnd', () => {\n const blockTags = app.options.getValue('blockTags') as string[];\n const additions: string[] = [];\n if (!blockTags.includes(TAG_PETRINET)) additions.push(TAG_PETRINET);\n if (!blockTags.includes(TAG_SUBNET)) additions.push(TAG_SUBNET);\n if (additions.length > 0) {\n app.options.setValue('blockTags', [...blockTags, ...additions]);\n }\n });\n\n // 2. Resolve references and generate SVG during pre-render async phase.\n app.renderer.preRenderAsyncJobs.push(async (output) => {\n htmlCache.clear();\n await processProject(app, output.project);\n });\n\n // 3. Inject cached HTML into comment output, suppress default tag rendering.\n app.renderer.hooks.on('comment.beforeTags', (_context, comment, reflection) => {\n const cached = htmlCache.get(reflection.id);\n if (!cached) return JSX.createElement(JSX.Raw, { html: '' });\n\n // Mark our tags as skip so TypeDoc doesn't render them as plain text.\n for (const tag of comment.blockTags) {\n if (tag.tag === TAG_PETRINET || tag.tag === TAG_SUBNET) {\n tag.skipRendering = true;\n }\n }\n\n return JSX.createElement(JSX.Raw, { html: cached });\n });\n}\n\n/**\n * Walks all reflections in the project and processes `@petrinet` / `@subnet`\n * tags. Per-reflection HTML accumulates in {@link htmlCache} so multiple tags\n * on one symbol render in declaration order.\n */\nasync function processProject(app: Application, project: ProjectReflection): Promise<void> {\n const reflections = Object.values(project.reflections);\n\n for (const reflection of reflections) {\n const comment = reflection.comment;\n if (!comment) continue;\n\n for (const tag of comment.blockTags) {\n const isPetrinet = tag.tag === TAG_PETRINET;\n const isSubnet = tag.tag === TAG_SUBNET;\n if (!isPetrinet && !isSubnet) continue;\n\n const reference = tagContent(tag);\n try {\n const html = isSubnet\n ? await generateInterfaceOnly(reference, reflection)\n : await generateDiagram(reference, reflection);\n const existing = htmlCache.get(reflection.id) ?? '';\n htmlCache.set(reflection.id, existing + html);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n const tagName = isSubnet ? '@subnet' : '@petrinet';\n app.logger.warn(`${tagName} error for ${reflection.getFriendlyFullName()}: ${msg}`);\n const html = errorHtml(`Error generating diagram for '${reference}': ${msg}`);\n const existing = htmlCache.get(reflection.id) ?? '';\n htmlCache.set(reflection.id, existing + html);\n }\n }\n }\n}\n\n/**\n * Generates a diagram HTML string for a single `@petrinet` reference. Resolves\n * the reference to one of {@link ResolvedNet} variants and dispatches to the\n * matching renderer.\n */\nasync function generateDiagram(\n reference: string,\n reflection: Reflection,\n): Promise<string> {\n const trimmed = reference.trim();\n if (!trimmed) {\n return errorHtml(`Empty @petrinet reference on ${reflection.getFriendlyFullName()}`);\n }\n\n const sourceFile = getSourceFilePath(reflection);\n if (!sourceFile) {\n return errorHtml(`Cannot determine source file for ${reflection.getFriendlyFullName()}`);\n }\n\n const resolved = await resolveNet(trimmed, sourceFile);\n if (!resolved) {\n return errorHtml(`Cannot resolve PetriNet/SubnetDef/Instance: ${trimmed}`);\n }\n\n return await renderResolved(resolved, /* interfaceOnly */ false);\n}\n\n/**\n * Generates an interface-only diagram for a `@subnet` reference. When the\n * resolved reference is not a {@link import('../core/subnet-def.js').SubnetDef},\n * falls back to the regular diagram so the tag still produces useful output.\n */\nasync function generateInterfaceOnly(\n reference: string,\n reflection: Reflection,\n): Promise<string> {\n const trimmed = reference.trim();\n if (!trimmed) {\n return errorHtml(`Empty @subnet reference on ${reflection.getFriendlyFullName()}`);\n }\n\n const sourceFile = getSourceFilePath(reflection);\n if (!sourceFile) {\n return errorHtml(`Cannot determine source file for ${reflection.getFriendlyFullName()}`);\n }\n\n const resolved = await resolveNet(trimmed, sourceFile);\n if (!resolved) {\n return errorHtml(`Cannot resolve SubnetDef: ${trimmed}`);\n }\n\n return await renderResolved(resolved, /* interfaceOnly */ true);\n}\n\n/**\n * Dispatches a {@link ResolvedNet} to the matching renderer. The\n * `interfaceOnly` flag is honoured only when the resolved kind is `subnet` —\n * for `net` and `instance` it is ignored (the body is the whole point of\n * those references).\n */\nasync function renderResolved(\n resolved: ResolvedNet,\n interfaceOnly: boolean,\n): Promise<string> {\n switch (resolved.kind) {\n case 'net': {\n const dotExport = await getDotExport();\n const dot = dotExport(resolved.value);\n return renderDiagramHtml(resolved.title, dot, /* header */ null);\n }\n case 'subnet': {\n const dot = interfaceOnly\n ? subnetInterfaceOnly(resolved.value)\n : subnetFullBody(resolved.value);\n const header = forSubnetDef(resolved.value, interfaceOnly);\n const title = resolved.value.name + (interfaceOnly ? ' (interface)' : '');\n return renderDiagramHtml(title, dot, header);\n }\n case 'instance': {\n const dotExport = await getDotExport();\n const dot = dotExport(resolved.value.renamedBody);\n const header = forInstance(resolved.value);\n return renderDiagramHtml(resolved.title, dot, header);\n }\n }\n}\n\n/**\n * Emits the diagram HTML. The canonical viewer renders DOT to SVG\n * client-side via Graphviz-WASM, so no server-side SVG rendering happens\n * here. Routes through the subnet-aware renderer when `header` is non-null,\n * the plain renderer otherwise.\n */\nfunction renderDiagramHtml(\n title: string,\n dot: string,\n header: string | null,\n): string {\n if (header !== null) {\n return renderSubnetSvg(title, header, dot);\n }\n return renderSvg(title, dot);\n}\n\n/**\n * Extracts text content from a CommentTag.\n */\nfunction tagContent(tag: CommentTag): string {\n return tag.content\n .map((part) => part.text)\n .join('')\n .trim();\n}\n\n/**\n * Gets the source file path from a reflection. Walks parents because\n * comment-bearing reflections sometimes lack their own `sources` (e.g.\n * inherited members).\n */\nfunction getSourceFilePath(reflection: Reflection): string | null {\n const decl = reflection as DeclarationReflection;\n if (decl.sources && decl.sources.length > 0) {\n return decl.sources[0]!.fullFileName;\n }\n if (reflection.parent) {\n return getSourceFilePath(reflection.parent);\n }\n return null;\n}\n\n/**\n * Renders an error message as styled HTML.\n */\nfunction errorHtml(message: string): string {\n return `<div class=\"petrinet-error\" style=\"color: #dc3545; border: 1px solid #dc3545; padding: 10px; border-radius: 4px;\">\n<strong>@petrinet Error:</strong> ${escapeHtml(message)}\n</div>`;\n}\n","/**\n * Dynamic import-based resolver for `@petrinet` / `@subnet` references.\n *\n * Resolves three kinds of static exports per Java's `PetriNetTaglet` design:\n * 1. `PetriNet` — full body diagram (existing behaviour).\n * 2. `SubnetDef<?>` — body diagram with interface ports highlighted, plus a\n * subnet header with port/channel badges.\n * 3. `Instance<?>` — renamed body diagram (already prefix-clustered by the\n * DOT exporter), plus an instance header with prefix, def name, and\n * params summary.\n *\n * TypeScript cannot use reflection like Java — modules must be importable at\n * doc time (typically from `dist/` after `npm run build`).\n *\n * Tag format:\n * ```\n * @petrinet ./path/to/module#exportName — access a static export\n * @petrinet ./path/to/module#functionName() — call a function returning one\n * @petrinet #localExport — resolve from same file\n * ```\n *\n * Mirrors: `org.libpetri.doclet.PetriNetTaglet.resolveReference`\n *\n * @module doclet/net-resolver\n */\n\nimport { resolve, dirname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { PetriNet } from '../core/petri-net.js';\nimport type { SubnetDef } from '../core/subnet-def.js';\nimport type { Instance } from '../core/instance.js';\n\n/**\n * Discriminated-union result from {@link resolveNet}. Each variant carries\n * the resolved value plus a display title.\n */\nexport type ResolvedNet =\n | { readonly kind: 'net'; readonly value: PetriNet; readonly title: string }\n | { readonly kind: 'subnet'; readonly value: SubnetDef<unknown>; readonly title: string }\n | { readonly kind: 'instance'; readonly value: Instance<unknown>; readonly title: string };\n\n/**\n * Parses a `@petrinet` / `@subnet` reference and resolves it via dynamic\n * import. Returns `null` when the reference cannot be parsed or imported, or\n * when the resolved value is none of the three supported kinds.\n *\n * @param reference - the tag content, e.g. `./definition#buildDebugNet()`\n * @param sourceFilePath - absolute path to the source file containing the tag\n */\nexport async function resolveNet(\n reference: string,\n sourceFilePath: string,\n): Promise<ResolvedNet | null> {\n const trimmed = reference.trim().split(/\\s+/)[0] ?? '';\n if (!trimmed) return null;\n\n const hashIndex = trimmed.indexOf('#');\n if (hashIndex === -1) return null;\n\n const modulePath = trimmed.substring(0, hashIndex);\n const exportRef = trimmed.substring(hashIndex + 1);\n if (!exportRef) return null;\n\n const isCall = exportRef.endsWith('()');\n const exportName = isCall ? exportRef.slice(0, -2) : exportRef;\n\n // Resolve module path relative to the source file.\n let absolutePath: string;\n if (modulePath) {\n absolutePath = resolve(dirname(sourceFilePath), modulePath);\n } else {\n // `#localExport` — resolve from same file's compiled output.\n absolutePath = sourceFilePath;\n }\n\n // Try `.js` extension for compiled output, then `.ts` for ts-node scenarios.\n const candidates = [\n absolutePath,\n absolutePath + '.js',\n absolutePath + '.ts',\n absolutePath.replace(/\\.ts$/, '.js'),\n ];\n\n let mod: Record<string, unknown> | undefined;\n for (const candidate of candidates) {\n try {\n mod = await import(pathToFileURL(candidate).href) as Record<string, unknown>;\n break;\n } catch {\n // Try next candidate.\n }\n }\n\n if (!mod) return null;\n\n const exported = mod[exportName];\n if (exported == null) return null;\n\n let value: unknown;\n if (isCall) {\n if (typeof exported !== 'function') return null;\n const result = (exported as (...args: unknown[]) => unknown)();\n // Support functions that return `{ net: PetriNet, ... }` for legacy\n // callers; otherwise pass the result through directly.\n if (\n result !== null && typeof result === 'object' && 'net' in result &&\n isPetriNetLike((result as { net: unknown }).net)\n ) {\n value = (result as { net: unknown }).net;\n } else {\n value = result;\n }\n } else {\n value = exported;\n }\n\n return classify(value);\n}\n\n/**\n * Wraps the resolved value into a {@link ResolvedNet} variant by structural\n * shape — checks {@link Instance} before {@link SubnetDef} before\n * {@link PetriNet} so the most specific match wins (Instance has both `def`\n * and `renamedBody`; SubnetDef has `iface` and `body`; PetriNet has only\n * `transitions` + `name`).\n *\n * Returns `null` when the value matches none of the supported shapes.\n */\nfunction classify(value: unknown): ResolvedNet | null {\n if (value === null || typeof value !== 'object') return null;\n\n if (isInstanceLike(value)) {\n const inst = value as Instance<unknown>;\n return { kind: 'instance', value: inst, title: `${inst.def.name} :: ${inst.prefix}` };\n }\n if (isSubnetDefLike(value)) {\n const def = value as SubnetDef<unknown>;\n return { kind: 'subnet', value: def, title: def.name };\n }\n if (isPetriNetLike(value)) {\n const net = value as PetriNet;\n return { kind: 'net', value: net, title: net.name };\n }\n return null;\n}\n\n/**\n * Structural test for {@link PetriNet}: has a string `name` and a `transitions`\n * Set. Avoids `instanceof` because the imported module may have re-bound the\n * class identity (TypeDoc's bundled output vs `dist/` import path).\n */\nfunction isPetriNetLike(value: unknown): value is PetriNet {\n if (value === null || typeof value !== 'object') return false;\n const candidate = value as { name?: unknown; transitions?: unknown };\n return typeof candidate.name === 'string' && candidate.transitions instanceof Set;\n}\n\n/**\n * Structural test for {@link SubnetDef}: has a string `name`, a {@link\n * PetriNet}-shaped `body`, and an `iface` carrying `ports` + `channels` maps.\n */\nfunction isSubnetDefLike(value: unknown): value is SubnetDef<unknown> {\n if (value === null || typeof value !== 'object') return false;\n const candidate = value as { name?: unknown; body?: unknown; iface?: unknown };\n if (typeof candidate.name !== 'string') return false;\n if (!isPetriNetLike(candidate.body)) return false;\n const iface = candidate.iface as { ports?: unknown; channels?: unknown } | undefined;\n return iface !== undefined && iface !== null\n && iface.ports instanceof Map && iface.channels instanceof Map;\n}\n\n/**\n * Structural test for {@link Instance}: has a string `prefix`, a {@link\n * SubnetDef}-shaped `def`, and a {@link PetriNet}-shaped `renamedBody`.\n */\nfunction isInstanceLike(value: unknown): value is Instance<unknown> {\n if (value === null || typeof value !== 'object') return false;\n const candidate = value as { prefix?: unknown; def?: unknown; renamedBody?: unknown };\n return typeof candidate.prefix === 'string'\n && isSubnetDefLike(candidate.def)\n && isPetriNetLike(candidate.renamedBody);\n}\n","/**\n * Shared HTML renderer for Petri Net diagrams in TypeDoc.\n *\n * Generates consistent HTML markup that mounts the canonical\n * {@link https://libpetri.org | libpetri} viewer client-side. The viewer IIFE\n * bundle (Graphviz WASM inlined, offline-safe) is inlined into the generated\n * HTML, making the plugin fully self-contained with no external file\n * dependencies.\n *\n * Each diagram container carries its DOT source as a `data-dot` attribute. An\n * init snippet reads the attribute and calls\n * `window.LibpetriViewer.mount(dot, container, { chrome: true })` to render the\n * SVG and wire pan/zoom + cluster legend/filter chrome.\n *\n * Mirrors: `org.libpetri.doclet.DiagramRenderer`\n *\n * @module doclet/diagram-renderer\n */\n\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction loadResource(filename: string): string {\n return readFileSync(join(__dirname, 'resources', filename), 'utf-8');\n}\n\nlet inlineCss: string | undefined;\nlet inlineJs: string | undefined;\n\nfunction css(): string {\n return (inlineCss ??= loadResource('petrinet-diagrams.css'));\n}\n\nfunction js(): string {\n return (inlineJs ??= loadResource('petrinet-diagrams.js'));\n}\n\n/**\n * Escapes HTML special characters for safe embedding as text content.\n */\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/**\n * Escapes a string for safe inclusion in an HTML attribute value enclosed in\n * double quotes. Identical to {@link escapeHtml} plus single-quote escaping\n * (defence-in-depth even though we always emit double-quoted attributes).\n */\nfunction escapeAttr(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Renders a diagram from a DOT source string. The viewer renders the SVG\n * client-side via Graphviz-WASM; no server-side SVG is emitted on the\n * embedded path.\n *\n * Inlines CSS and the viewer IIFE from bundled resources. The IIFE is guarded\n * by an idempotency check (`window._libpetriViewerInit`) so it only executes\n * once per page even when multiple `@petrinet` tags appear.\n *\n * @param title - optional title (null/undefined for no title)\n * @param dotSource - the DOT source code; embedded as `data-dot` and shown in\n * the collapsible \"View DOT Source\" block\n * @returns HTML markup with diagram controls\n */\nexport function renderSvg(\n title: string | null | undefined,\n dotSource: string,\n): string {\n return renderInternal(title ?? null, /* headerHtml */ null, dotSource);\n}\n\n/**\n * Renders a subnet- or instance-aware diagram. Identical to {@link renderSvg}\n * apart from an extra {@code headerHtml} block (the port/channel/params\n * badge bar) prepended above the diagram, and the CSS class\n * {@code subnet-diagram} on the wrapper.\n *\n * @param title diagram title (e.g. \"BoundedBuffer :: b1\")\n * @param headerHtml the HTML produced by {@link import('./subnet-header.js')}\n * @param dotSource the DOT source code\n * @returns HTML markup\n */\nexport function renderSubnetSvg(\n title: string | null | undefined,\n headerHtml: string,\n dotSource: string,\n): string {\n return renderInternal(title ?? null, headerHtml, dotSource);\n}\n\nlet diagramIdCounter = 0;\n\nfunction renderInternal(\n title: string | null,\n headerHtml: string | null,\n dotSource: string,\n): string {\n const titleHtml = title !== null ? `<h4>${escapeHtml(title)}</h4>\\n` : '';\n const summaryText = title !== null ? 'View DOT Source' : 'View Source';\n const diagramClass = headerHtml !== null ? 'petrinet-diagram subnet-diagram' : 'petrinet-diagram';\n const headerBlock = headerHtml !== null ? headerHtml : '';\n const dotAttr = escapeAttr(dotSource);\n const containerId = `libpetri-diagram-${++diagramIdCounter}`;\n\n return `<style>${css()}</style>\n<script>if(!window._libpetriViewerInit){window._libpetriViewerInit=true;\n${js()}\n}</script>\n<div class=\"${diagramClass}\">\n${titleHtml}${headerBlock}<div class=\"diagram-container\" id=\"${containerId}\" data-libpetri-diagram=\"true\" data-dot=\"${dotAttr}\"></div>\n<details>\n<summary>${summaryText}</summary>\n<pre><code>${escapeHtml(dotSource)}</code></pre>\n</details>\n</div>\n<script>(function(){function mount(){var el=document.getElementById(${JSON.stringify(containerId)});if(!el)return;if(el.dataset.libpetriMounted)return;if(!window.LibpetriViewer||typeof window.LibpetriViewer.mount!=='function'){return setTimeout(mount,30);}el.dataset.libpetriMounted='1';try{window.LibpetriViewer.mount(el.dataset.dot,el,{chrome:true});}catch(e){console.error('[libpetri] mount failed',e);}}if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',mount);}else{mount();}})();</script>`;\n}\n","/**\n * HTML-fragment generator for the small \"subnet header\" badge bar that the\n * {@link import('./diagram-renderer.js')} layers above subnet diagrams.\n *\n * For a {@link import('../core/subnet-def.js').SubnetDef} the header lists\n * the subnet name, the parameter type (best-effort — TypeScript erases\n * generics at runtime so the slot is shown as a placeholder), and one badge\n * per port and channel — colour-coded by direction\n * (`interface-port-input` / `-output` / `-inout` CSS classes, plus\n * `interface-channel` for sync channels).\n *\n * For an {@link import('../core/instance.js').Instance} the header lists the\n * instance prefix, the originating definition's name, and the {@link\n * import('../core/instance.js').Instance#params} summary.\n *\n * Mirrors: `org.libpetri.doclet.SubnetHeader`\n *\n * @module doclet/subnet-header\n */\n\nimport type { Instance } from '../core/instance.js';\nimport type { Interface, Port } from '../core/interface.js';\nimport type { SubnetDef } from '../core/subnet-def.js';\nimport { escapeHtml } from './diagram-renderer.js';\n\n/**\n * Builds the header HTML for a {@link SubnetDef} field.\n *\n * @param def the subnet definition\n * @param interfaceOnly when `true`, the header carries the \"(interface only)\"\n * badge so the reader knows the body is intentionally\n * omitted\n */\nexport function forSubnetDef(def: SubnetDef<unknown>, interfaceOnly: boolean): string {\n const sb: string[] = [];\n sb.push(`<div class=\"subnet-header\">\\n`);\n sb.push(` <div class=\"subnet-header-row\">\\n`);\n sb.push(` <span class=\"subnet-header-label\">subnet</span>\\n`);\n sb.push(` <span class=\"subnet-header-name\">${escapeHtml(def.name)}</span>\\n`);\n // TypeScript erases generics at runtime, so the parameter-type slot is\n // populated with a placeholder (\"?\"). Java emits the simple class name —\n // the structural HTML is otherwise byte-equivalent.\n sb.push(` <span class=\"subnet-header-param\"><?></span>\\n`);\n if (interfaceOnly) {\n sb.push(` <span class=\"subnet-header-badge subnet-header-badge-interface\">interface only</span>\\n`);\n }\n sb.push(` </div>\\n`);\n sb.push(renderPortChannelBadges(def.iface));\n sb.push(`</div>\\n`);\n return sb.join('');\n}\n\n/**\n * Builds the header HTML for an {@link Instance} field.\n */\nexport function forInstance(instance: Instance<unknown>): string {\n const def = instance.def;\n const sb: string[] = [];\n sb.push(`<div class=\"subnet-header\">\\n`);\n sb.push(` <div class=\"subnet-header-row\">\\n`);\n sb.push(` <span class=\"subnet-header-label\">instance</span>\\n`);\n sb.push(` <span class=\"subnet-header-name\">${escapeHtml(instance.prefix)}</span>\\n`);\n sb.push(` <span class=\"subnet-header-of\">of</span>\\n`);\n sb.push(` <span class=\"subnet-header-name\">${escapeHtml(def.name)}</span>\\n`);\n const params = instance.params;\n if (params !== null && params !== undefined) {\n sb.push(` <span class=\"subnet-header-params\">params=${escapeHtml(String(params))}</span>\\n`);\n }\n sb.push(` </div>\\n`);\n sb.push(renderPortChannelBadges(def.iface));\n sb.push(`</div>\\n`);\n return sb.join('');\n}\n\n/**\n * Renders the per-port and per-channel badge row. Each badge carries a CSS\n * class identifying its kind so the stylesheet can colour-code by direction.\n */\nfunction renderPortChannelBadges(iface: Interface): string {\n if (iface.ports.size === 0 && iface.channels.size === 0) {\n return '';\n }\n const sb: string[] = [];\n sb.push(` <div class=\"subnet-header-badges\">\\n`);\n for (const port of iface.ports.values()) {\n const kind = portKind(port);\n sb.push(` <span class=\"interface-port-badge interface-port-badge-${kind}\">`);\n sb.push(`<span class=\"badge-direction\">${kind}</span>`);\n sb.push(`<span class=\"badge-name\">${escapeHtml(port.name)}</span>`);\n // TypeScript erases generics so we can't print the runtime token type;\n // omit the type-name span rather than emit a bogus value.\n sb.push(`</span>\\n`);\n }\n for (const channel of iface.channels.values()) {\n sb.push(` <span class=\"interface-channel-badge\">`);\n sb.push(`<span class=\"badge-direction\">channel</span>`);\n sb.push(`<span class=\"badge-name\">${escapeHtml(channel.name)}</span>`);\n sb.push(`</span>\\n`);\n }\n sb.push(` </div>\\n`);\n return sb.join('');\n}\n\nfunction portKind(port: Port<unknown>): 'input' | 'output' | 'inout' {\n return port.direction;\n}\n","/**\n * DOT generators for the subnet-aware diagrams the {@link\n * import('./petri-net-plugin.js')} plugin draws.\n *\n * Two flavours:\n * - {@link fullBody} — the subnet's complete body, but with its interface-port\n * places restyled with the `interface-port` category from\n * `petri-net-styles.json` so they read as boundary elements at a glance. A\n * small `subgraph cluster_iface_*` with label `\"interface\"` surrounds the\n * port places and channel transitions to advertise the subnet boundary\n * visually.\n * - {@link interfaceOnly} — a tiny diagram of just the port places, the\n * channel transitions, and a single stub node indicating the body is\n * omitted. Used by the `@subnet` block tag.\n *\n * This module stays in the doclet directory (rather than living in\n * `export/`) because it is a doclet-presentation concern — the production\n * export pipeline never adds the `interface` cluster.\n *\n * Mirrors: `org.libpetri.doclet.SubnetDotExport`\n *\n * @module doclet/subnet-dot-export\n */\n\nimport type { SubnetDef } from '../core/subnet-def.js';\nimport type { Interface, Port, Channel } from '../core/interface.js';\nimport { dotExport } from '../export/dot-exporter.js';\nimport { sanitize } from '../export/petri-net-mapper.js';\nimport { nodeStyle, FONT } from '../export/styles.js';\n\n/**\n * Renders the full body of a {@link SubnetDef} with the interface ports\n * restyled. The output is a post-processed version of {@link dotExport}: the\n * port-place node attribute lines are rewritten so the post-processor swaps in\n * the {@code interface-port} category, channel-transition lines swap in\n * {@code sync-channel}, and an extra {@code subgraph cluster_iface_<name>}\n * block is appended that lists the port nodes by id — overriding their\n * cluster membership without re-emitting them (DOT semantics: a node\n * referenced inside a subgraph block by id alone is treated as a member of\n * that cluster).\n */\nexport function fullBody(def: SubnetDef<unknown>): string {\n let dot = dotExport(def.body);\n const portIds = portNodeIds(def.iface);\n const channelIds = channelNodeIds(def.iface);\n\n // Restyle: rewrite the matched node lines so the post-processor swaps in\n // the interface-port and sync-channel categories. The renderer emits each\n // node as one line ending with `];` so a per-id rewrite is sufficient and\n // deterministic.\n for (const portId of portIds) {\n dot = restyleNode(dot, portId, nodeStyle('interface-port'));\n }\n for (const chId of channelIds) {\n dot = restyleNode(dot, chId, nodeStyle('sync-channel'));\n }\n\n // Wrap the port and channel ids in a header cluster so the doclet's viewer\n // can render the boundary distinctly. Done by injecting an extra subgraph\n // block before the closing `}` of the digraph.\n if (portIds.size > 0 || channelIds.size > 0) {\n let iface = '';\n iface += ` subgraph cluster_iface_${sanitize(def.name)} {\\n`;\n iface += ` label=\"interface\";\\n`;\n iface += ` style=\"rounded,dashed\";\\n`;\n iface += ` bgcolor=\"#F0F6FF\";\\n`;\n iface += ` penwidth=2;\\n`;\n for (const id of portIds) {\n iface += ` ${id};\\n`;\n }\n for (const id of channelIds) {\n iface += ` ${id};\\n`;\n }\n iface += ` }\\n`;\n\n const lastBrace = dot.lastIndexOf('}');\n if (lastBrace > 0) {\n dot = dot.substring(0, lastBrace) + iface + dot.substring(lastBrace);\n }\n }\n return dot;\n}\n\n/**\n * Renders an interface-only diagram: just the port places + channel\n * transitions + a single stub node labelled \"(internals omitted)\" so the\n * reader knows the body has not been drawn.\n */\nexport function interfaceOnly(def: SubnetDef<unknown>): string {\n const sb: string[] = [];\n sb.push(`digraph ${sanitize(def.name)} {\\n`);\n sb.push(` rankdir=LR;\\n`);\n sb.push(` nodesep=0.5;\\n`);\n sb.push(` ranksep=0.6;\\n`);\n sb.push(` fontname=\"${FONT.family}\";\\n`);\n sb.push(` node [fontname=\"${FONT.family}\", fontsize=12];\\n`);\n sb.push(` edge [fontname=\"${FONT.family}\", fontsize=10];\\n`);\n sb.push('\\n');\n\n const stubId = 'stub_' + sanitize(def.name);\n\n // Group ports by direction: inputs on the left, outputs on the right,\n // inouts above. This keeps the interface diagram visually structured even\n // when the body internals are absent.\n const inputs: Port<unknown>[] = [];\n const outputs: Port<unknown>[] = [];\n const inouts: Port<unknown>[] = [];\n for (const port of def.iface.ports.values()) {\n switch (port.direction) {\n case 'input': inputs.push(port); break;\n case 'output': outputs.push(port); break;\n case 'inout': inouts.push(port); break;\n }\n }\n\n // Emit port nodes.\n for (const port of inputs) emitPortNode(sb, port, 'input');\n for (const port of outputs) emitPortNode(sb, port, 'output');\n for (const port of inouts) emitPortNode(sb, port, 'inout');\n\n // Emit channel nodes.\n const syncStyle = nodeStyle('sync-channel');\n for (const ch of def.iface.channels.values()) {\n sb.push(` ${channelNodeId(ch)} [`);\n sb.push(`label=\"⇄ ${escapeLabel(ch.name)}\", `);\n sb.push(`shape=${syncStyle.shape}, `);\n sb.push(`style=\"filled\", `);\n sb.push(`fillcolor=\"${syncStyle.fill}\", `);\n sb.push(`color=\"${syncStyle.stroke}\", `);\n sb.push(`penwidth=${trimNumber(syncStyle.penwidth)}`);\n sb.push(`];\\n`);\n }\n\n // Emit stub node.\n sb.push(` ${stubId} [`);\n sb.push(`label=\"${escapeLabel(def.name)}\\\\n(internals omitted)\", `);\n sb.push(`shape=box, style=\"filled,dashed,rounded\", `);\n sb.push(`fillcolor=\"#FFFFFF\", color=\"#666666\", penwidth=1, `);\n sb.push(`fontsize=11`);\n sb.push(`];\\n`);\n sb.push('\\n');\n\n // Connect inputs -> stub -> outputs; inouts and channels link both ways.\n for (const port of inputs) {\n sb.push(` ${portNodeId(port)} -> ${stubId} [color=\"#1d4ed8\", arrowhead=normal];\\n`);\n }\n for (const port of outputs) {\n sb.push(` ${stubId} -> ${portNodeId(port)} [color=\"#1d4ed8\", arrowhead=normal];\\n`);\n }\n for (const port of inouts) {\n sb.push(` ${portNodeId(port)} -> ${stubId} [color=\"#1d4ed8\", arrowhead=normalnormal, dir=both];\\n`);\n }\n for (const ch of def.iface.channels.values()) {\n sb.push(` ${channelNodeId(ch)} -> ${stubId} [color=\"#6d28d9\", arrowhead=normal, style=dashed];\\n`);\n }\n\n sb.push(`}\\n`);\n return sb.join('');\n}\n\n// ============================================================\n// Helpers\n// ============================================================\n\nfunction emitPortNode(sb: string[], port: Port<unknown>, direction: string): void {\n const style = nodeStyle('interface-port');\n // Token type isn't carried at runtime in TypeScript (generics erased), so\n // the xlabel is the direction marker only — Java additionally appends the\n // port's tokenType simple name. The structural content is otherwise\n // identical.\n sb.push(` ${portNodeId(port)} [`);\n sb.push(`label=\"${escapeLabel(port.name)}\", `);\n sb.push(`xlabel=\"${escapeLabel(direction)}\", `);\n sb.push(`shape=${style.shape}, `);\n sb.push(`style=\"filled,${style.style ?? 'solid'}\", `);\n sb.push(`fillcolor=\"${style.fill}\", `);\n sb.push(`color=\"${style.stroke}\", `);\n sb.push(`penwidth=${trimNumber(style.penwidth)}`);\n if (style.width !== undefined) {\n sb.push(`, width=${trimNumber(style.width)}, fixedsize=true`);\n }\n sb.push(`];\\n`);\n}\n\nfunction portNodeId(port: Port<unknown>): string {\n return 'p_' + sanitize(port.place.name);\n}\n\nfunction channelNodeId(ch: Channel): string {\n return 't_' + sanitize(ch.transition.name);\n}\n\nfunction portNodeIds(iface: Interface): Set<string> {\n const ids = new Set<string>();\n for (const port of iface.ports.values()) ids.add(portNodeId(port));\n return ids;\n}\n\nfunction channelNodeIds(iface: Interface): Set<string> {\n const ids = new Set<string>();\n for (const ch of iface.channels.values()) ids.add(channelNodeId(ch));\n return ids;\n}\n\n/**\n * Rewrites the {@code fillcolor=}, {@code color=}, {@code style=}, and\n * {@code penwidth=} attributes of the line declaring the given node id so\n * the supplied style takes precedence. Operates as a plain text rewrite:\n * the {@link import('../export/dot-renderer.js').renderDot} output formats\n * each node line deterministically, so a per-attribute regex is reliable.\n */\nfunction restyleNode(\n dot: string,\n nodeId: string,\n style: ReturnType<typeof nodeStyle>,\n): string {\n // The node line begins with: <id> [\n // and ends with: ];\n // Find the line, then surgically swap fillcolor / color / style / penwidth.\n const marker = nodeId + ' [';\n let start = dot.indexOf('\\n ' + marker);\n if (start < 0) start = dot.indexOf(' ' + marker);\n if (start < 0) return dot;\n // Skip the leading newline if present so we operate on the line proper.\n if (dot.charAt(start) === '\\n') start += 1;\n const lineEnd = dot.indexOf('];', start);\n if (lineEnd < 0) return dot;\n let line = dot.substring(start, lineEnd + 2);\n\n // Order matters: keep `fillcolor` before `color` so the substring search\n // for `color=\"` doesn't accidentally hit `fillcolor=\"`.\n line = replaceAttr(line, 'fillcolor', style.fill);\n line = replaceAttr(line, 'color', style.stroke);\n line = replaceAttr(line, 'penwidth', trimNumber(style.penwidth));\n if (style.style !== undefined) {\n // Compose with `filled` because the renderer already includes that.\n line = replaceAttr(line, 'style', `\"filled,${style.style}\"`);\n }\n\n return dot.substring(0, start) + line + dot.substring(lineEnd + 2);\n}\n\n/**\n * Replaces the value of a {@code key=value} pair within a single DOT\n * attribute list. Quotes the value when the existing form was quoted, leaves\n * the value unquoted when the existing form was unquoted (numeric).\n */\nfunction replaceAttr(line: string, key: string, value: string): string {\n // Match key=\"...\" (quoted) — the key must be preceded by a non-word char\n // (start, comma, or space) so `color=` doesn't match inside `fillcolor=`.\n const quotedPat = key + '=\"';\n const qStart = findAttrStart(line, quotedPat);\n if (qStart >= 0) {\n const valStart = qStart + quotedPat.length;\n const valEnd = line.indexOf('\"', valStart);\n if (valEnd < 0) return line;\n let v = value;\n if (v.startsWith('\"') && v.endsWith('\"') && v.length >= 2) {\n v = v.substring(1, v.length - 1);\n }\n return line.substring(0, valStart) + v + line.substring(valEnd);\n }\n // Match key=NN (numeric, ends at ',' or ']').\n const unquoted = key + '=';\n const uStart = findAttrStart(line, unquoted);\n if (uStart < 0) return line;\n const valStart = uStart + unquoted.length;\n let valEnd = valStart;\n while (valEnd < line.length) {\n const c = line.charAt(valEnd);\n if (c === ',' || c === ']') break;\n valEnd++;\n }\n return line.substring(0, valStart) + value + line.substring(valEnd);\n}\n\n/**\n * Finds the start of a `key=` attribute pattern in `line`, ensuring the\n * match is not a suffix of another attribute name (e.g. `color=` must not\n * match inside `fillcolor=`). Returns -1 when no boundary-respecting match\n * exists.\n */\nfunction findAttrStart(line: string, pattern: string): number {\n let from = 0;\n while (from < line.length) {\n const idx = line.indexOf(pattern, from);\n if (idx < 0) return -1;\n if (idx === 0) return idx;\n const prev = line.charAt(idx - 1);\n // Word-boundary check: previous char must not be alphanumeric/underscore.\n if (!/[A-Za-z0-9_]/.test(prev)) return idx;\n from = idx + 1;\n }\n return -1;\n}\n\nfunction trimNumber(d: number): string {\n if (Number.isInteger(d)) return String(d);\n return String(d);\n}\n\nfunction escapeLabel(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n","/**\n * SVG renderer using `@viz-js/viz` (Graphviz WASM).\n *\n * Pure WASM — zero external dependencies. No system `dot` binary required.\n *\n * Mirrors: Java's `PetriNetTaglet.dotToSvg()` (which uses `dot -Tsvg` subprocess)\n *\n * @module doclet/svg-renderer\n */\n\n/**\n * Renders a DOT string to SVG using the `@viz-js/viz` WASM engine.\n *\n * Strips the XML prolog/DOCTYPE and explicit width/height attributes so the SVG\n * scales via viewBox + CSS instead of overriding with fixed pt sizes.\n *\n * @param dot - the DOT source string\n * @returns SVG markup string\n * @throws if `@viz-js/viz` is not installed or DOT parsing fails\n */\nexport async function dotToSvg(dot: string): Promise<string> {\n // Dynamic import — @viz-js/viz is an optional peer dependency\n const { instance } = await import('@viz-js/viz');\n const viz = await instance();\n let svg = viz.renderString(dot, { format: 'svg', engine: 'dot' });\n\n // Strip XML prolog and DOCTYPE — invalid inside HTML5\n const svgStart = svg.indexOf('<svg');\n if (svgStart > 0) svg = svg.substring(svgStart);\n\n // Strip explicit width/height attributes (e.g. \"1942pt\") so the SVG\n // scales via viewBox + CSS instead of overriding with fixed pt sizes\n svg = svg.replace(/\\s+(?:width|height)=\"[^\"]*\"/g, '');\n\n return svg;\n}\n"],"mappings":"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","names":["dirname","interfaceOnly","valStart","valEnd","interfaceOnly","dotExport"]}
|
package/dist/export/index.d.ts
CHANGED
package/dist/export/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PetriNet, S as SubnetDef, a as Place, T as Token, b as Transition, E as EnvironmentPlace, c as TransitionContext, O as Out } from './petri-net-
|
|
2
|
-
export { A as Arc, d as ArcInhibitor, e as ArcInput, f as ArcOutput, g as ArcRead, h as ArcReset, C as Channel, i as ComposeBindings, F as FusionSet, j as FusionSetBuilder, I as In, k as InAll, l as InAtLeast, m as InExactly, n as InOne, o as Instance, p as Interface, q as InterfaceBuilder, L as LogFn, M as MAX_DURATION_MS, r as
|
|
3
|
-
import { E as EventStore } from './event-store-
|
|
4
|
-
export { A as ActionTimedOut, a as ExecutionCompleted, b as ExecutionStarted, I as InMemoryEventStore, L as LogMessage, M as MarkingSnapshot, N as NetEvent, T as TokenAdded, c as TokenRemoved, d as TransitionClockRestarted, e as TransitionCompleted, f as TransitionEnabled, g as TransitionFailed, h as TransitionStarted, i as TransitionTimedOut, j as eventTransitionName, k as eventsOfType, l as failures, m as filterEvents, n as inMemoryEventStore, o as isFailureEvent, p as noopEventStore, t as transitionEvents } from './event-store-
|
|
1
|
+
import { P as PetriNet, S as SubnetDef, a as Place, T as Token, b as Transition, E as EnvironmentPlace, c as TransitionContext, O as Out } from './petri-net-B4wQwsUj.js';
|
|
2
|
+
export { A as Arc, d as ArcInhibitor, e as ArcInput, f as ArcOutput, g as ArcRead, h as ArcReset, C as Channel, i as ComposeBindings, F as FusionSet, j as FusionSetBuilder, I as In, k as InAll, l as InAtLeast, m as InExactly, n as InOne, o as Instance, p as Interface, q as InterfaceBuilder, K as KeyFn, L as LogFn, M as MAX_DURATION_MS, r as MatchKey, s as MatchSpec, N as NameId, t as OutAnd, u as OutForwardInput, v as OutPlace, w as OutTimeout, x as OutXor, y as OutputEntry, z as PetriNetBuilder, B as Port, D as PortDirection, G as SubnetDefBuilder, H as SubnetInstance, J as Timing, Q as TimingDeadline, R as TimingDelayed, U as TimingExact, V as TimingImmediate, W as TimingWindow, X as TokenInput, Y as TokenOutput, Z as TransitionAction, _ as TransitionBuilder, $ as VerificationHarness, a0 as VerificationResult, a1 as all, a2 as allPlaces, a3 as and, a4 as andPlaces, a5 as arcPlace, a6 as atLeast, a7 as consumptionCount, a8 as deadline, a9 as delayed, aa as earliest, ab as enumerateBranches, ac as environmentPlace, ad as exact, ae as exactly, af as fork, ag as forwardInput, ah as hasDeadline, ai as hasGuard, aj as immediate, ak as inhibitorArc, al as inputArc, am as isUnit, an as keyForPlace, ao as latest, ap as matchCorrelates, aq as matchKey, ar as matchSpec, as as matchesGuard, at as nameId, au as one, av as outPlace, aw as outputArc, ax as passthrough, ay as place, az as produce, aA as readArc, aB as requiredCount, aC as resetArc, aD as timeout, aE as timeoutPlace, aF as tokenAt, aG as tokenOf, aH as transform, aI as transformAsync, aJ as transformFrom, aK as unitToken, aL as window, aM as withTimeout, aN as xor, aO as xorPlaces } from './petri-net-B4wQwsUj.js';
|
|
3
|
+
import { E as EventStore } from './event-store-CAkN_ayv.js';
|
|
4
|
+
export { A as ActionTimedOut, a as ExecutionCompleted, b as ExecutionStarted, I as InMemoryEventStore, L as LogMessage, M as MarkingSnapshot, N as NetEvent, T as TokenAdded, c as TokenRemoved, d as TransitionClockRestarted, e as TransitionCompleted, f as TransitionEnabled, g as TransitionFailed, h as TransitionStarted, i as TransitionTimedOut, j as eventTransitionName, k as eventsOfType, l as failures, m as filterEvents, n as inMemoryEventStore, o as isFailureEvent, p as noopEventStore, t as transitionEvents } from './event-store-CAkN_ayv.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Discriminated sum-type abstraction over Petri nets, distinguishing **closed**
|
|
@@ -148,6 +148,7 @@ declare class CompiledNet {
|
|
|
148
148
|
private readonly _consumptionPlaceIds;
|
|
149
149
|
private readonly _cardinalityChecks;
|
|
150
150
|
private readonly _hasGuards;
|
|
151
|
+
private readonly _hasMatch;
|
|
151
152
|
private constructor();
|
|
152
153
|
static compile(net: PetriNet): CompiledNet;
|
|
153
154
|
place(pid: number): Place<any>;
|
|
@@ -158,6 +159,7 @@ declare class CompiledNet {
|
|
|
158
159
|
consumptionPlaceIds(tid: number): readonly number[];
|
|
159
160
|
cardinalityCheck(tid: number): CardinalityCheck | null;
|
|
160
161
|
hasGuards(tid: number): boolean;
|
|
162
|
+
hasMatch(tid: number): boolean;
|
|
161
163
|
/**
|
|
162
164
|
* Two-phase bitmap enablement check for a transition:
|
|
163
165
|
* 1. **Presence check**: verifies all required places (inputs + reads) have tokens
|
|
@@ -250,6 +252,18 @@ interface BitmapNetExecutorOptions {
|
|
|
250
252
|
declare class BitmapNetExecutor implements PetriNetExecutor {
|
|
251
253
|
private readonly compiled;
|
|
252
254
|
private readonly marking;
|
|
255
|
+
/** Monotonic source for ν-name minting (ctx.freshName(), NU-010). */
|
|
256
|
+
private freshNameCounter;
|
|
257
|
+
/**
|
|
258
|
+
* ν-net incremental match caches (NU-020): per matched transition, an
|
|
259
|
+
* {@link IncrementalMatcher} kept in lockstep with the marking when the
|
|
260
|
+
* transition is fast-path eligible (every correlated input is `one`/`exactly`,
|
|
261
|
+
* consumed by no other transition, never reset), else `null` → fall back to
|
|
262
|
+
* the O(n) rebuild {@link findBinding}. Turns a draining matched join from
|
|
263
|
+
* O(n²) into O(n log n). Mirrors the precompiled executor and the Rust backends.
|
|
264
|
+
*/
|
|
265
|
+
private matchCaches;
|
|
266
|
+
private placeMatchTargets;
|
|
253
267
|
private readonly eventStore;
|
|
254
268
|
private readonly environmentPlaces;
|
|
255
269
|
private readonly hasEnvironmentPlaces;
|
|
@@ -287,6 +301,15 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
|
|
|
287
301
|
private draining;
|
|
288
302
|
private closed;
|
|
289
303
|
constructor(net: PetriNet, initialTokens: Map<Place<any>, Token<any>[]>, options?: BitmapNetExecutorOptions);
|
|
304
|
+
/**
|
|
305
|
+
* Builds the ν-net incremental match caches (NU-020). A matched join is
|
|
306
|
+
* fast-path eligible only when every correlated input is `one`/`exactly`, is
|
|
307
|
+
* consumed by no other transition, and is never reset — so the cache can never
|
|
308
|
+
* desync from the marking. Mirrors the precompiled executor.
|
|
309
|
+
*/
|
|
310
|
+
private initMatchCaches;
|
|
311
|
+
/** Mirror a token added to correlated input `pid` into every fast-path matcher. */
|
|
312
|
+
private cacheAddToken;
|
|
290
313
|
run(timeoutMs?: number): Promise<Marking>;
|
|
291
314
|
private executeLoop;
|
|
292
315
|
inject<T>(envPlace: EnvironmentPlace<T>, token: Token<T>): Promise<boolean>;
|
|
@@ -423,6 +446,7 @@ declare class PrecompiledNet {
|
|
|
423
446
|
readonly consumptionPlaceIds: readonly (readonly number[])[];
|
|
424
447
|
readonly cardinalityChecks: readonly (CardinalityCheck | null)[];
|
|
425
448
|
readonly hasGuards: readonly boolean[];
|
|
449
|
+
readonly hasMatch: readonly boolean[];
|
|
426
450
|
readonly allImmediate: boolean;
|
|
427
451
|
readonly allSamePriority: boolean;
|
|
428
452
|
readonly anyDeadlines: boolean;
|
|
@@ -499,6 +523,27 @@ declare class PrecompiledNetExecutor implements PetriNetExecutor {
|
|
|
499
523
|
private readonly eventStoreEnabled;
|
|
500
524
|
/** Per-place token arrays, indexed by pid. */
|
|
501
525
|
private readonly tokenQueues;
|
|
526
|
+
/** Monotonic source for ν-name minting (ctx.freshName(), NU-010). */
|
|
527
|
+
private freshNameCounter;
|
|
528
|
+
/**
|
|
529
|
+
* Per-transition ν-name minter cache, indexed by tid (built lazily). Each
|
|
530
|
+
* supplier is created once and reused across firings, so installing it on a
|
|
531
|
+
* per-fire context is a field assignment rather than a per-fire closure
|
|
532
|
+
* allocation — keeping the fire path lean for non-ν transitions. Every
|
|
533
|
+
* transition gets one (forks mint but carry no MatchSpec, so gating on
|
|
534
|
+
* `hasMatch` would wrongly starve them).
|
|
535
|
+
*/
|
|
536
|
+
private readonly freshNameSuppliers;
|
|
537
|
+
/**
|
|
538
|
+
* Per matched transition: an {@link IncrementalMatcher} kept in lockstep with
|
|
539
|
+
* the token queues when the transition is fast-path eligible (every correlated
|
|
540
|
+
* input is `one`/`exactly`, consumed by no other transition, and never reset),
|
|
541
|
+
* else `null` → fall back to the O(n) rebuild {@link findBinding}. This turns a
|
|
542
|
+
* draining matched join from O(n²) into O(n log n).
|
|
543
|
+
*/
|
|
544
|
+
private matchCaches;
|
|
545
|
+
/** Per place (by pid): the `[tid, keyIndex]` of every fast-path correlated input it feeds. */
|
|
546
|
+
private placeMatchTargets;
|
|
502
547
|
private readonly markingBitmap;
|
|
503
548
|
private readonly dirtyBitmap;
|
|
504
549
|
private readonly dirtyScanBuffer;
|
|
@@ -529,6 +574,17 @@ declare class PrecompiledNetExecutor implements PetriNetExecutor {
|
|
|
529
574
|
private closed;
|
|
530
575
|
private marking;
|
|
531
576
|
constructor(net: PetriNet, initialTokens: Map<Place<any>, Token<any>[]>, options?: PrecompiledNetExecutorOptions);
|
|
577
|
+
/**
|
|
578
|
+
* Builds the ν-net incremental match caches (NU-020). A matched join is
|
|
579
|
+
* fast-path eligible only when every correlated input is `one`/`exactly`, is
|
|
580
|
+
* consumed by no other transition, and is never reset — so tokens enter a
|
|
581
|
+
* correlated input only via produce/inject (mirrored by `add`) and leave only
|
|
582
|
+
* via this join's matched consume (mirrored by `consume`), and the cache can
|
|
583
|
+
* never desync. Mirrors the Rust backends.
|
|
584
|
+
*/
|
|
585
|
+
private initMatchCaches;
|
|
586
|
+
/** Mirror a token added to correlated input `pid` into every fast-path matcher. */
|
|
587
|
+
private cacheAddToken;
|
|
532
588
|
private markTransitionDirty;
|
|
533
589
|
private markDirty;
|
|
534
590
|
private setMarkingBit;
|
|
@@ -554,6 +610,13 @@ declare class PrecompiledNetExecutor implements PetriNetExecutor {
|
|
|
554
610
|
private fireReadyImmediate;
|
|
555
611
|
private fireReadyGeneral;
|
|
556
612
|
private fireTransition;
|
|
613
|
+
/**
|
|
614
|
+
* Consumes the name-matched tokens for a ν-net join (NU-020): correlated
|
|
615
|
+
* inputs take tokens whose projected name equals the chosen binding (guard
|
|
616
|
+
* first, then name equality — NU-021); other inputs consume FIFO. Reset arcs
|
|
617
|
+
* are honoured as on the opcode path. Mirrors {@link fireTransitionGuarded}.
|
|
618
|
+
*/
|
|
619
|
+
private fireTransitionMatched;
|
|
557
620
|
private fireTransitionGuarded;
|
|
558
621
|
private updateBitmapAfterConsumption;
|
|
559
622
|
private processCompletedTransitions;
|