@metaobjectsdev/docs-site 0.15.8-rc.1
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/LICENSE +189 -0
- package/README.md +62 -0
- package/assets/site.css +13 -0
- package/assets/site.js +25 -0
- package/dist/badges.d.ts +14 -0
- package/dist/badges.d.ts.map +1 -0
- package/dist/badges.js +21 -0
- package/dist/badges.js.map +1 -0
- package/dist/builders/extras.d.ts +23 -0
- package/dist/builders/extras.d.ts.map +1 -0
- package/dist/builders/extras.js +70 -0
- package/dist/builders/extras.js.map +1 -0
- package/dist/builders/index-data.d.ts +52 -0
- package/dist/builders/index-data.d.ts.map +1 -0
- package/dist/builders/index-data.js +115 -0
- package/dist/builders/index-data.js.map +1 -0
- package/dist/builders/object-data.d.ts +97 -0
- package/dist/builders/object-data.d.ts.map +1 -0
- package/dist/builders/object-data.js +336 -0
- package/dist/builders/object-data.js.map +1 -0
- package/dist/builders/output-data.d.ts +26 -0
- package/dist/builders/output-data.d.ts.map +1 -0
- package/dist/builders/output-data.js +35 -0
- package/dist/builders/output-data.js.map +1 -0
- package/dist/builders/package-data.d.ts +48 -0
- package/dist/builders/package-data.d.ts.map +1 -0
- package/dist/builders/package-data.js +142 -0
- package/dist/builders/package-data.js.map +1 -0
- package/dist/builders/prompt-data.d.ts +31 -0
- package/dist/builders/prompt-data.d.ts.map +1 -0
- package/dist/builders/prompt-data.js +68 -0
- package/dist/builders/prompt-data.js.map +1 -0
- package/dist/coverage.d.ts +19 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +26 -0
- package/dist/coverage.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/link-check.d.ts +2 -0
- package/dist/link-check.d.ts.map +1 -0
- package/dist/link-check.js +30 -0
- package/dist/link-check.js.map +1 -0
- package/dist/link-graph.d.ts +54 -0
- package/dist/link-graph.d.ts.map +1 -0
- package/dist/link-graph.js +198 -0
- package/dist/link-graph.js.map +1 -0
- package/dist/load.d.ts +11 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +40 -0
- package/dist/load.js.map +1 -0
- package/dist/mermaid.d.ts +56 -0
- package/dist/mermaid.d.ts.map +1 -0
- package/dist/mermaid.js +136 -0
- package/dist/mermaid.js.map +1 -0
- package/dist/mustache-highlight.d.ts +10 -0
- package/dist/mustache-highlight.d.ts.map +1 -0
- package/dist/mustache-highlight.js +55 -0
- package/dist/mustache-highlight.js.map +1 -0
- package/dist/package-docs.d.ts +12 -0
- package/dist/package-docs.d.ts.map +1 -0
- package/dist/package-docs.js +34 -0
- package/dist/package-docs.js.map +1 -0
- package/dist/scaffold.d.ts +7 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +24 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/site.d.ts +23 -0
- package/dist/site.d.ts.map +1 -0
- package/dist/site.js +219 -0
- package/dist/site.js.map +1 -0
- package/dist/yaml-comments.d.ts +6 -0
- package/dist/yaml-comments.d.ts.map +1 -0
- package/dist/yaml-comments.js +49 -0
- package/dist/yaml-comments.js.map +1 -0
- package/package.json +45 -0
- package/src/badges.ts +26 -0
- package/src/builders/extras.ts +61 -0
- package/src/builders/index-data.ts +95 -0
- package/src/builders/object-data.ts +261 -0
- package/src/builders/output-data.ts +35 -0
- package/src/builders/package-data.ts +134 -0
- package/src/builders/prompt-data.ts +61 -0
- package/src/coverage.ts +29 -0
- package/src/index.ts +3 -0
- package/src/link-check.ts +24 -0
- package/src/link-graph.ts +204 -0
- package/src/load.ts +47 -0
- package/src/mermaid.ts +142 -0
- package/src/mustache-highlight.ts +43 -0
- package/src/package-docs.ts +33 -0
- package/src/scaffold.ts +26 -0
- package/src/site.ts +289 -0
- package/src/yaml-comments.ts +33 -0
- package/templates/chrome-foot.mustache +17 -0
- package/templates/chrome-head.mustache +21 -0
- package/templates/coverage.html.mustache +24 -0
- package/templates/enums.html.mustache +14 -0
- package/templates/index.html.mustache +54 -0
- package/templates/object.html.mustache +46 -0
- package/templates/output.html.mustache +16 -0
- package/templates/package.html.mustache +43 -0
- package/templates/prompt.html.mustache +28 -0
package/src/site.ts
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { render, InMemoryProvider } from "@metaobjectsdev/render";
|
|
5
|
+
import { loadModel } from "./load";
|
|
6
|
+
import { LinkGraph, fqnOf } from "./link-graph";
|
|
7
|
+
import { CoverageTracker } from "./coverage";
|
|
8
|
+
import type { CoverageReport } from "./coverage";
|
|
9
|
+
import { harvestComments } from "./yaml-comments";
|
|
10
|
+
import { buildIndexPage } from "./builders/index-data";
|
|
11
|
+
import type { CoreConfig } from "./builders/index-data";
|
|
12
|
+
import { buildPackagePage } from "./builders/package-data";
|
|
13
|
+
import { buildObjectPage } from "./builders/object-data";
|
|
14
|
+
import { buildPromptPage } from "./builders/prompt-data";
|
|
15
|
+
import { buildOutputPage } from "./builders/output-data";
|
|
16
|
+
import { buildEnumsPage, findAnomalies, buildSearchIndex } from "./builders/extras";
|
|
17
|
+
import type { Anomaly } from "./builders/extras";
|
|
18
|
+
import { checkLinks } from "./link-check";
|
|
19
|
+
import { legendHtml, esc as escBadge } from "./badges";
|
|
20
|
+
import type { ObjectPageData } from "./builders/object-data";
|
|
21
|
+
import type { PromptPageData } from "./builders/prompt-data";
|
|
22
|
+
import type { OutputPageData } from "./builders/output-data";
|
|
23
|
+
|
|
24
|
+
// ─── Public API ────────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
export interface SiteOptions {
|
|
27
|
+
sourceDirs: string[];
|
|
28
|
+
outDir: string;
|
|
29
|
+
title: string;
|
|
30
|
+
stamp: string;
|
|
31
|
+
commit: string;
|
|
32
|
+
core?: CoreConfig;
|
|
33
|
+
/** Override dir; if a file of the same basename exists here, it wins over the bundled templates/ dir. */
|
|
34
|
+
templatesDir?: string;
|
|
35
|
+
/** Override dir for assets; if a file of the same basename exists here, it wins over the bundled assets/ dir. */
|
|
36
|
+
assetsDir?: string | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface SiteResult {
|
|
40
|
+
pages: string[];
|
|
41
|
+
coverage: CoverageReport;
|
|
42
|
+
anomalies: Anomaly[];
|
|
43
|
+
dangling: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─── Helpers ───────────────────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
/** Relative-root prefix: "" for root pages, "../../" for depth-2 pages. */
|
|
49
|
+
function relRootFor(href: string): string {
|
|
50
|
+
const depth = href.split("/").length - 1;
|
|
51
|
+
return "../".repeat(depth);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Write a file, creating parent dirs as needed. */
|
|
55
|
+
function writeOut(outDir: string, relPath: string, content: string | Uint8Array): string {
|
|
56
|
+
const abs = join(outDir, relPath);
|
|
57
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
58
|
+
writeFileSync(abs, content);
|
|
59
|
+
return relPath;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ─── Template loading ──────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
const SELF_DIR = dirname(fileURLToPath(import.meta.url));
|
|
65
|
+
|
|
66
|
+
const BUNDLED_TEMPLATES = resolve(SELF_DIR, "../templates");
|
|
67
|
+
|
|
68
|
+
function loadTemplate(name: string, overrideDir?: string): string {
|
|
69
|
+
if (overrideDir) {
|
|
70
|
+
const candidate = join(overrideDir, name);
|
|
71
|
+
if (existsSync(candidate)) return readFileSync(candidate, "utf8");
|
|
72
|
+
}
|
|
73
|
+
return readFileSync(join(BUNDLED_TEMPLATES, name), "utf8");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const BUNDLED_ASSETS = resolve(SELF_DIR, "../assets");
|
|
77
|
+
|
|
78
|
+
function loadAsset(name: string, overrideDir?: string): string {
|
|
79
|
+
if (overrideDir) {
|
|
80
|
+
const candidate = join(overrideDir, name);
|
|
81
|
+
if (existsSync(candidate)) return readFileSync(candidate, "utf8");
|
|
82
|
+
}
|
|
83
|
+
return readFileSync(join(BUNDLED_ASSETS, name), "utf8");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ─── Nav HTML ─────────────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Build the sidebar nav HTML for a specific page as a collapsible tree.
|
|
90
|
+
* Each package is a <details> element (open if it's the current page's package).
|
|
91
|
+
* Members are listed as links within each package. Deterministic: sorted packages, sorted members.
|
|
92
|
+
*/
|
|
93
|
+
function buildNavHtml(
|
|
94
|
+
g: LinkGraph,
|
|
95
|
+
relRoot: string,
|
|
96
|
+
currentPkgPath: string,
|
|
97
|
+
dataPackages: { pkg: string; pkgPath: string }[],
|
|
98
|
+
promptPackages: { pkg: string; pkgPath: string }[],
|
|
99
|
+
): string {
|
|
100
|
+
const nodes = g.nodes();
|
|
101
|
+
|
|
102
|
+
const renderGroup = (label: string, pkgList: { pkg: string; pkgPath: string }[]): string => {
|
|
103
|
+
if (pkgList.length === 0) return "";
|
|
104
|
+
const parts: string[] = [`<div class="text-xs font-semibold opacity-50 mt-3 mb-1">${label}</div>`];
|
|
105
|
+
for (const p of pkgList) {
|
|
106
|
+
const isOpen = p.pkgPath === currentPkgPath;
|
|
107
|
+
const pkgHref = escBadge(relRoot + p.pkgPath + "/index.html");
|
|
108
|
+
const pkgLabel = escBadge(p.pkg);
|
|
109
|
+
const members = nodes
|
|
110
|
+
.filter((n) => n.pkg === p.pkg)
|
|
111
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
112
|
+
const memberLinks = members.map((m) =>
|
|
113
|
+
`<a href="${escBadge(relRoot + m.href)}" class="link font-mono text-xs opacity-70 hover:opacity-100 pl-3 block">${escBadge(m.name)}</a>`
|
|
114
|
+
).join("\n");
|
|
115
|
+
parts.push(
|
|
116
|
+
`<details${isOpen ? " open" : ""}>\n` +
|
|
117
|
+
`<summary class="cursor-pointer font-mono text-xs opacity-70 hover:opacity-100"><a href="${pkgHref}">${pkgLabel}</a></summary>\n` +
|
|
118
|
+
memberLinks + `\n</details>`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return parts.join("\n");
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return [
|
|
125
|
+
renderGroup("Data", dataPackages),
|
|
126
|
+
renderGroup("Prompts", promptPackages),
|
|
127
|
+
].filter(Boolean).join("\n");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ─── Orchestrator ─────────────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
export async function generateSite(opts: SiteOptions): Promise<SiteResult> {
|
|
133
|
+
// 1. Load + graph + comments
|
|
134
|
+
const loaded = await loadModel(opts.sourceDirs);
|
|
135
|
+
const g = new LinkGraph(loaded);
|
|
136
|
+
const docs = harvestComments(opts.sourceDirs);
|
|
137
|
+
const cov = new CoverageTracker();
|
|
138
|
+
|
|
139
|
+
// 2. Derive package lists (deterministic sort)
|
|
140
|
+
const nodes = g.nodes();
|
|
141
|
+
const allPkgs = [...new Set(nodes.map((n) => n.pkg))].sort();
|
|
142
|
+
const promptPkgSet = new Set(nodes.filter((n) => n.kind !== "object").map((n) => n.pkg));
|
|
143
|
+
const dataPkgList = allPkgs
|
|
144
|
+
.filter((p) => !promptPkgSet.has(p))
|
|
145
|
+
.map((p) => ({ pkg: p, pkgPath: p.split("::").join("/") }));
|
|
146
|
+
const promptPkgList = allPkgs
|
|
147
|
+
.filter((p) => promptPkgSet.has(p))
|
|
148
|
+
.map((p) => ({ pkg: p, pkgPath: p.split("::").join("/") }));
|
|
149
|
+
|
|
150
|
+
// 3. Load chrome templates (fixed)
|
|
151
|
+
const chromeHead = loadTemplate("chrome-head.mustache", opts.templatesDir);
|
|
152
|
+
const chromeFoot = loadTemplate("chrome-foot.mustache", opts.templatesDir);
|
|
153
|
+
|
|
154
|
+
// 4. Rendering helper: concat chrome + page template, render with payload + shared fields
|
|
155
|
+
const provider = new InMemoryProvider({});
|
|
156
|
+
const pages: string[] = [];
|
|
157
|
+
|
|
158
|
+
const legend = legendHtml();
|
|
159
|
+
|
|
160
|
+
// TOC builders — only list sections with non-empty data; ids must match id="s-..." in templates
|
|
161
|
+
const objectTocHtml = (d: ObjectPageData): string => {
|
|
162
|
+
const sections: { id: string; label: string; present: boolean }[] = [
|
|
163
|
+
{ id: "s-overview", label: "Overview", present: !!d.desc },
|
|
164
|
+
{ id: "s-fields", label: "Fields", present: d.ownFields.length > 0 },
|
|
165
|
+
{ id: "s-indexes", label: "Indexes & keys", present: d.indexes.length > 0 },
|
|
166
|
+
{ id: "s-validators", label: "Validators", present: d.validators.length > 0 },
|
|
167
|
+
{ id: "s-relationships", label: "Relationships", present: d.relations.length > 0 },
|
|
168
|
+
{ id: "s-provenance", label: "Field provenance", present: d.origins.length > 0 },
|
|
169
|
+
{ id: "s-inheritance", label: "Inheritance", present: !!d.inheritanceMermaid },
|
|
170
|
+
{ id: "s-neighborhood", label: "Neighborhood", present: !!d.neighborhoodMermaid },
|
|
171
|
+
{ id: "s-referenced-by", label: "Referenced by", present: d.referencedBy.length > 0 },
|
|
172
|
+
];
|
|
173
|
+
return sections
|
|
174
|
+
.filter((s) => s.present)
|
|
175
|
+
.map((s) => `<a href="#${s.id}" class="link opacity-70 hover:opacity-100">${s.label}</a>`)
|
|
176
|
+
.join("\n");
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const promptTocHtml = (d: PromptPageData): string => {
|
|
180
|
+
const sections: { id: string; label: string; present: boolean }[] = [
|
|
181
|
+
{ id: "s-payload", label: "Payload tree", present: d.payloadTree.length > 0 },
|
|
182
|
+
{ id: "s-source", label: "Source", present: !!d.sourceHtml },
|
|
183
|
+
];
|
|
184
|
+
return sections
|
|
185
|
+
.filter((s) => s.present)
|
|
186
|
+
.map((s) => `<a href="#${s.id}" class="link opacity-70 hover:opacity-100">${s.label}</a>`)
|
|
187
|
+
.join("\n");
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const outputTocHtml = (d: OutputPageData): string => {
|
|
191
|
+
const sections: { id: string; label: string; present: boolean }[] = [
|
|
192
|
+
{ id: "s-contract", label: "Parse contract", present: d.fields.length > 0 },
|
|
193
|
+
];
|
|
194
|
+
return sections
|
|
195
|
+
.filter((s) => s.present)
|
|
196
|
+
.map((s) => `<a href="#${s.id}" class="link opacity-70 hover:opacity-100">${s.label}</a>`)
|
|
197
|
+
.join("\n");
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const renderPage = (
|
|
201
|
+
pageTemplateName: string,
|
|
202
|
+
href: string,
|
|
203
|
+
pageData: Record<string, unknown>,
|
|
204
|
+
tocHtml: string = "",
|
|
205
|
+
currentPkgPath: string = "",
|
|
206
|
+
): void => {
|
|
207
|
+
const relRoot = relRootFor(href);
|
|
208
|
+
const navHtml = buildNavHtml(g, relRoot, currentPkgPath, dataPkgList, promptPkgList);
|
|
209
|
+
const pageTpl = loadTemplate(pageTemplateName, opts.templatesDir);
|
|
210
|
+
const template = chromeHead + pageTpl + chromeFoot;
|
|
211
|
+
const payload = {
|
|
212
|
+
...pageData,
|
|
213
|
+
title: opts.title,
|
|
214
|
+
stamp: opts.stamp,
|
|
215
|
+
commit: opts.commit,
|
|
216
|
+
relRoot,
|
|
217
|
+
navHtml,
|
|
218
|
+
tocHtml,
|
|
219
|
+
legendHtml: legend,
|
|
220
|
+
};
|
|
221
|
+
const html = render({ template, payload, provider, format: "text" });
|
|
222
|
+
writeOut(opts.outDir, href, html);
|
|
223
|
+
pages.push(href);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// 5. Index page
|
|
227
|
+
const indexData = buildIndexPage(g, cov, {
|
|
228
|
+
title: opts.title,
|
|
229
|
+
stamp: opts.stamp,
|
|
230
|
+
commit: opts.commit,
|
|
231
|
+
core: opts.core,
|
|
232
|
+
sourceDirs: opts.sourceDirs,
|
|
233
|
+
});
|
|
234
|
+
renderPage("index.html.mustache", "index.html", indexData as unknown as Record<string, unknown>);
|
|
235
|
+
|
|
236
|
+
// 6. Enums page
|
|
237
|
+
const enumRows = buildEnumsPage(g);
|
|
238
|
+
renderPage("enums.html.mustache", "enums.html", { rows: enumRows } as Record<string, unknown>);
|
|
239
|
+
|
|
240
|
+
// 7. Anomalies + coverage (deferred until all pages built — build now, write after member pages)
|
|
241
|
+
const anomalies = findAnomalies(g, opts.sourceDirs);
|
|
242
|
+
|
|
243
|
+
// 8. Package + member pages (deterministic: pkgs sorted, then members sorted)
|
|
244
|
+
for (const pkg of allPkgs) {
|
|
245
|
+
const pkgData = buildPackagePage(pkg, g, cov, opts.sourceDirs);
|
|
246
|
+
const pkgHref = `${pkgData.pkgPath}/index.html`;
|
|
247
|
+
renderPage("package.html.mustache", pkgHref, pkgData as unknown as Record<string, unknown>, "", pkgData.pkgPath);
|
|
248
|
+
|
|
249
|
+
// Member pages sorted by name
|
|
250
|
+
const pkgNodes = nodes.filter((n) => n.pkg === pkg).sort((a, b) => a.name.localeCompare(b.name));
|
|
251
|
+
for (const n of pkgNodes) {
|
|
252
|
+
const fqn = fqnOf(n.node);
|
|
253
|
+
const pkgPath = n.pkgPath;
|
|
254
|
+
if (n.kind === "object") {
|
|
255
|
+
const data = buildObjectPage(fqn, g, cov);
|
|
256
|
+
renderPage("object.html.mustache", n.href, data as unknown as Record<string, unknown>, objectTocHtml(data), pkgPath);
|
|
257
|
+
} else if (n.kind === "prompt") {
|
|
258
|
+
const data = buildPromptPage(fqn, g, cov, opts.sourceDirs);
|
|
259
|
+
renderPage("prompt.html.mustache", n.href, data as unknown as Record<string, unknown>, promptTocHtml(data), pkgPath);
|
|
260
|
+
} else if (n.kind === "output") {
|
|
261
|
+
const data = buildOutputPage(fqn, g, cov, docs, opts.sourceDirs);
|
|
262
|
+
renderPage("output.html.mustache", n.href, data as unknown as Record<string, unknown>, outputTocHtml(data), pkgPath);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// 9. Coverage page (after all member pages so cov is fully populated)
|
|
268
|
+
const coverage = cov.report(loaded.root);
|
|
269
|
+
const coverageData = {
|
|
270
|
+
kinds: coverage.kinds,
|
|
271
|
+
attrs: coverage.attrs,
|
|
272
|
+
anomalies,
|
|
273
|
+
};
|
|
274
|
+
renderPage("coverage.html.mustache", "coverage.html", coverageData as Record<string, unknown>);
|
|
275
|
+
|
|
276
|
+
// 10. Write assets (consumer assetsDir wins over the bundled dir)
|
|
277
|
+
writeOut(opts.outDir, "assets/site.css", loadAsset("site.css", opts.assetsDir));
|
|
278
|
+
writeOut(opts.outDir, "assets/site.js", loadAsset("site.js", opts.assetsDir));
|
|
279
|
+
|
|
280
|
+
// 11. Search index
|
|
281
|
+
const searchIndex = buildSearchIndex(g);
|
|
282
|
+
writeOut(opts.outDir, "assets/search-index.json", JSON.stringify(searchIndex));
|
|
283
|
+
|
|
284
|
+
// 12. Link check (throws if any dangling links found)
|
|
285
|
+
const dangling = checkLinks(opts.outDir, pages);
|
|
286
|
+
if (dangling.length) throw new Error("link check failed:\n" + dangling.join("\n"));
|
|
287
|
+
|
|
288
|
+
return { pages, coverage, anomalies, dangling };
|
|
289
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
export interface CommentDocs { objectDesc: Map<string, string>; fieldNote: Map<string, string>; }
|
|
5
|
+
const clean = (c: string) => c.replace(/^[#\s─═-]+/, "").replace(/[─═]+\s*$/, "").trim();
|
|
6
|
+
|
|
7
|
+
export function harvestComments(sourceDirs: string[]): CommentDocs {
|
|
8
|
+
const objectDesc = new Map<string, string>(); const fieldNote = new Map<string, string>();
|
|
9
|
+
const files: string[] = [];
|
|
10
|
+
const walk = (d: string) => { for (const e of readdirSync(d)) { const p = join(d, e); if (statSync(p).isDirectory()) walk(p); else if (/\.ya?ml$/.test(e)) files.push(p); } };
|
|
11
|
+
for (const d of sourceDirs) walk(d);
|
|
12
|
+
for (const f of files) {
|
|
13
|
+
const lines = readFileSync(f, "utf8").split("\n");
|
|
14
|
+
let current: string | undefined;
|
|
15
|
+
for (let i = 0; i < lines.length; i++) {
|
|
16
|
+
const m = lines[i]!.match(/^\s*-\s*object\.\w+:/);
|
|
17
|
+
if (m) {
|
|
18
|
+
current = undefined;
|
|
19
|
+
for (let j = i + 1; j < Math.min(i + 4, lines.length); j++) {
|
|
20
|
+
const nm = lines[j]!.match(/^\s*name:\s*(\S+)/); if (nm) { current = nm[1]; break; }
|
|
21
|
+
}
|
|
22
|
+
if (current) {
|
|
23
|
+
const desc: string[] = [];
|
|
24
|
+
for (let k = i - 1; k >= 0 && lines[k]!.trim().startsWith("#"); k--) { const c = clean(lines[k]!.trim()); if (c) desc.unshift(c); }
|
|
25
|
+
if (desc.length) objectDesc.set(current, desc.join(" ").replace(/\s+/g, " ").slice(0, 400));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const fm = lines[i]!.match(/^\s*-\s*field\.\w+:\s*\{\s*name:\s*(\w+)[^}]*\}\s*#\s*(.+)$/);
|
|
29
|
+
if (fm && current) fieldNote.set(`${current}.${fm[1]}`, clean(fm[2]!).slice(0, 160));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return { objectDesc, fieldNote };
|
|
33
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
</main>
|
|
2
|
+
<aside class="pl-toc hidden xl:block w-56 shrink-0 h-screen sticky top-0 overflow-y-auto py-8 pr-6 text-xs">
|
|
3
|
+
{{#tocHtml}}<div class="opacity-50 mb-2 uppercase tracking-wide">On this page</div><div class="flex flex-col gap-1">{{{tocHtml}}}</div>{{/tocHtml}}
|
|
4
|
+
<div class="opacity-50 mt-6 mb-2 uppercase tracking-wide">Legend</div><div class="flex flex-wrap gap-1">{{{legendHtml}}}</div>
|
|
5
|
+
</aside>
|
|
6
|
+
</div>
|
|
7
|
+
<dialog id="search-modal" class="modal">
|
|
8
|
+
<div class="modal-box max-w-2xl p-0">
|
|
9
|
+
<label class="input input-bordered flex items-center gap-2 m-3"><input id="search" type="search" placeholder="search entities, fields, prompts…" class="grow" autofocus><kbd class="kbd kbd-xs">esc</kbd></label>
|
|
10
|
+
<div id="search-results" class="max-h-96 overflow-y-auto px-3 pb-3 flex flex-col gap-0.5"></div>
|
|
11
|
+
</div>
|
|
12
|
+
<form method="dialog" class="modal-backdrop"><button>close</button></form>
|
|
13
|
+
</dialog>
|
|
14
|
+
<footer class="pl-footer text-xs opacity-40 px-10 pb-6">generated {{stamp}} · {{commit}} · metadata-docs</footer>
|
|
15
|
+
<script>window.__REL_ROOT__ = "{{relRoot}}";</script>
|
|
16
|
+
<script src="{{relRoot}}assets/site.js"></script>
|
|
17
|
+
</body></html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-theme="night">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
5
|
+
<title>{{title}}</title>
|
|
6
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/daisyui@5.5.19/daisyui.css">
|
|
7
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/daisyui@5.5.19/themes.css">
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.2.4/dist/index.global.js"></script>
|
|
9
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/svg-pan-zoom@3.6.2/dist/svg-pan-zoom.min.js"></script>
|
|
11
|
+
<link rel="stylesheet" href="{{relRoot}}assets/site.css">
|
|
12
|
+
</head>
|
|
13
|
+
<body class="min-h-screen bg-base-200 text-base-content">
|
|
14
|
+
<div class="flex">
|
|
15
|
+
<nav class="pl-sidebar hidden lg:flex flex-col w-72 shrink-0 h-screen sticky top-0 border-r border-base-300 bg-base-100 overflow-y-auto p-4 gap-1 text-sm">
|
|
16
|
+
<a href="{{relRoot}}index.html" class="font-bold font-mono text-primary">{{title}}</a>
|
|
17
|
+
<button id="search-open" class="btn btn-sm btn-block justify-between my-2 font-normal opacity-80">
|
|
18
|
+
<span>search…</span><kbd class="kbd kbd-xs">⌘K</kbd></button>
|
|
19
|
+
{{{navHtml}}}
|
|
20
|
+
</nav>
|
|
21
|
+
<main class="min-w-0 flex-1 max-w-4xl px-6 lg:px-10 py-8">
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<h1 class="text-2xl font-bold font-mono">Coverage</h1>
|
|
2
|
+
<p class="text-sm opacity-60 mt-1">Which metadata node kinds and attributes are rendered by the doc pages.</p>
|
|
3
|
+
{{#kinds.length}}
|
|
4
|
+
<h2 class="text-lg font-semibold mt-6">Node kinds</h2>
|
|
5
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
6
|
+
<thead><tr><th>Kind</th><th>Count</th><th>Rendered</th></tr></thead><tbody>
|
|
7
|
+
{{#kinds}}<tr><td class="font-mono">{{key}}</td><td>{{count}}</td><td>{{#consumed}}<span class="badge badge-success badge-xs">✓</span>{{/consumed}}{{^consumed}}<span class="badge badge-error badge-xs">✗</span>{{/consumed}}</td></tr>{{/kinds}}
|
|
8
|
+
</tbody></table></div>
|
|
9
|
+
{{/kinds.length}}
|
|
10
|
+
{{#attrs.length}}
|
|
11
|
+
<h2 class="text-lg font-semibold mt-6">Attributes</h2>
|
|
12
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
13
|
+
<thead><tr><th>Attribute</th><th>Count</th><th>Rendered</th></tr></thead><tbody>
|
|
14
|
+
{{#attrs}}<tr><td class="font-mono">{{key}}</td><td>{{count}}</td><td>{{#consumed}}<span class="badge badge-success badge-xs">✓</span>{{/consumed}}{{^consumed}}<span class="badge badge-error badge-xs">✗</span>{{/consumed}}</td></tr>{{/attrs}}
|
|
15
|
+
</tbody></table></div>
|
|
16
|
+
{{/attrs.length}}
|
|
17
|
+
{{#anomalies.length}}
|
|
18
|
+
<h2 class="text-lg font-semibold mt-6">Anomalies</h2>
|
|
19
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
20
|
+
<thead><tr><th>Kind</th><th>Subject</th><th>Detail</th></tr></thead><tbody>
|
|
21
|
+
{{#anomalies}}<tr><td class="font-mono opacity-70">{{kind}}</td><td><a class="link font-mono" href="{{relRoot}}{{href}}">{{subject}}</a></td><td class="text-xs opacity-70">{{detail}}</td></tr>{{/anomalies}}
|
|
22
|
+
</tbody></table></div>
|
|
23
|
+
{{/anomalies.length}}
|
|
24
|
+
{{^anomalies.length}}<p class="text-sm opacity-50 mt-4">No anomalies detected.</p>{{/anomalies.length}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<h1 class="text-2xl font-bold font-mono">Enums</h1>
|
|
2
|
+
<p class="text-sm opacity-60 mt-1">All enum-valued fields across the metadata.</p>
|
|
3
|
+
{{#rows.length}}
|
|
4
|
+
<div class="overflow-x-auto mt-4"><table class="table table-xs">
|
|
5
|
+
<thead><tr><th>Owner</th><th>Field</th><th>Values</th><th>Default</th></tr></thead><tbody>
|
|
6
|
+
{{#rows}}<tr>
|
|
7
|
+
<td><a class="link font-mono" href="{{relRoot}}{{ownerHref}}">{{owner}}</a></td>
|
|
8
|
+
<td class="font-mono">{{field}}</td>
|
|
9
|
+
<td class="flex flex-wrap gap-1">{{#values}}<span class="badge badge-ghost badge-xs font-mono">{{.}}</span>{{/values}}</td>
|
|
10
|
+
<td class="font-mono opacity-60">{{deflt}}</td>
|
|
11
|
+
</tr>{{/rows}}
|
|
12
|
+
</tbody></table></div>
|
|
13
|
+
{{/rows.length}}
|
|
14
|
+
{{^rows.length}}<p class="text-sm opacity-50 mt-4">No enum fields found.</p>{{/rows.length}}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<h1 class="text-2xl font-bold font-mono">{{title}}</h1>
|
|
2
|
+
<div class="stats stats-horizontal shadow my-4 text-sm">
|
|
3
|
+
<div class="stat"><div class="stat-title">objects</div><div class="stat-value font-mono text-lg">{{stats.objects}}</div></div>
|
|
4
|
+
<div class="stat"><div class="stat-title">tables</div><div class="stat-value font-mono text-lg">{{stats.tables}}</div></div>
|
|
5
|
+
<div class="stat"><div class="stat-title">packages</div><div class="stat-value font-mono text-lg">{{stats.packages}}</div></div>
|
|
6
|
+
<div class="stat"><div class="stat-title">prompt VOs</div><div class="stat-value font-mono text-lg">{{stats.promptVos}}</div></div>
|
|
7
|
+
<div class="stat"><div class="stat-title">prompts</div><div class="stat-value font-mono text-lg">{{stats.prompts}}</div></div>
|
|
8
|
+
<div class="stat"><div class="stat-title">contracts</div><div class="stat-value font-mono text-lg">{{stats.contracts}}</div></div>
|
|
9
|
+
<div class="stat"><div class="stat-title">enums</div><div class="stat-value font-mono text-lg">{{stats.enums}}</div></div>
|
|
10
|
+
</div>
|
|
11
|
+
{{#coreMermaid}}
|
|
12
|
+
<div class="card bg-base-100 border border-base-300 p-4 my-4">
|
|
13
|
+
<div class="font-semibold mb-2">Core ERD</div>
|
|
14
|
+
<div class="pl-diagram"><pre class="mermaid">{{coreMermaid}}</pre></div>
|
|
15
|
+
<div class="text-xs opacity-50 mt-1">{{coreCaption}}</div>
|
|
16
|
+
{{#coreLegend.length}}<div class="flex flex-wrap gap-1 mt-2 text-xs">{{#coreLegend}}<span class="badge badge-xs" style="background:{{fill}};border-color:{{stroke}};color:#cbd5e1">{{pkg}}</span>{{/coreLegend}}</div>
|
|
17
|
+
<div class="text-[11px] opacity-50 mt-1"><span class="font-mono">▭</span> entity · <span class="font-mono">⬭</span> value object · <span class="font-mono">▱</span> view</div>{{/coreLegend.length}}
|
|
18
|
+
</div>
|
|
19
|
+
{{/coreMermaid}}
|
|
20
|
+
{{#packageMermaid}}
|
|
21
|
+
<div class="card bg-base-100 border border-base-300 p-4 my-4">
|
|
22
|
+
<div class="font-semibold mb-2">Package dependencies</div>
|
|
23
|
+
<div class="pl-diagram"><pre class="mermaid">{{packageMermaid}}</pre></div>
|
|
24
|
+
</div>
|
|
25
|
+
{{/packageMermaid}}
|
|
26
|
+
{{#fullEdges.length}}
|
|
27
|
+
<details class="my-4">
|
|
28
|
+
<summary class="cursor-pointer text-sm font-semibold">All cross-package edges</summary>
|
|
29
|
+
<div class="overflow-x-auto mt-2"><table class="table table-xs">
|
|
30
|
+
<thead><tr><th>From</th><th>To</th><th>n</th></tr></thead><tbody>
|
|
31
|
+
{{#fullEdges}}<tr><td class="font-mono">{{from}}</td><td class="font-mono">{{to}}</td><td>{{n}}</td></tr>{{/fullEdges}}
|
|
32
|
+
</tbody></table></div>
|
|
33
|
+
</details>
|
|
34
|
+
{{/fullEdges.length}}
|
|
35
|
+
{{#dataPackages.length}}
|
|
36
|
+
<h2 class="text-lg font-semibold mt-6">Data packages</h2>
|
|
37
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 mt-2">
|
|
38
|
+
{{#dataPackages}}<a href="{{relRoot}}{{href}}" class="card bg-base-100 border border-base-300 p-3 hover:border-primary transition-colors">
|
|
39
|
+
<div class="font-mono font-semibold text-sm">{{pkg}}</div>
|
|
40
|
+
<div class="text-xs opacity-60 mt-1">{{objectCount}} objects · {{promptCount}} prompts · {{contractCount}} contracts</div>
|
|
41
|
+
<div class="text-xs opacity-60 mt-1">{{purpose}}</div>
|
|
42
|
+
</a>{{/dataPackages}}
|
|
43
|
+
</div>
|
|
44
|
+
{{/dataPackages.length}}
|
|
45
|
+
{{#promptPackages.length}}
|
|
46
|
+
<h2 class="text-lg font-semibold mt-6">Prompt packages</h2>
|
|
47
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 mt-2">
|
|
48
|
+
{{#promptPackages}}<a href="{{relRoot}}{{href}}" class="card bg-base-100 border border-base-300 p-3 hover:border-secondary transition-colors">
|
|
49
|
+
<div class="font-mono font-semibold text-sm">{{pkg}}</div>
|
|
50
|
+
<div class="text-xs opacity-60 mt-1">{{objectCount}} objects · {{promptCount}} prompts · {{contractCount}} contracts</div>
|
|
51
|
+
<div class="text-xs opacity-60 mt-1">{{purpose}}</div>
|
|
52
|
+
</a>{{/promptPackages}}
|
|
53
|
+
</div>
|
|
54
|
+
{{/promptPackages.length}}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<div class="text-xs breadcrumbs font-mono opacity-70"><ul><li>{{{breadcrumbHtml}}}</li></ul></div>
|
|
2
|
+
<h1 class="text-2xl font-bold font-mono mt-1">{{name}}
|
|
3
|
+
<span class="badge badge-primary badge-sm align-middle">{{kindBadge}}</span>
|
|
4
|
+
{{#isView}}<span class="badge badge-info badge-sm align-middle">view</span>{{/isView}}
|
|
5
|
+
{{#isAbstract}}<span class="badge badge-ghost badge-sm align-middle">abstract</span>{{/isAbstract}}</h1>
|
|
6
|
+
<div class="font-mono text-xs opacity-60 mt-1">
|
|
7
|
+
{{#tableName}}{{#isView}}view{{/isView}}{{^isView}}table{{/isView}} <code>{{tableName}}</code>{{/tableName}}
|
|
8
|
+
{{#pkHtml}} · pk {{{pkHtml}}}{{/pkHtml}}{{#generation}} · gen {{generation}}{{/generation}}</div>
|
|
9
|
+
{{#desc}}<section id="s-overview" class="mt-4"><p class="text-sm leading-relaxed">{{desc}}</p></section>{{/desc}}
|
|
10
|
+
|
|
11
|
+
<section id="s-fields" class="mt-6"><h2 class="text-lg font-semibold">Fields</h2>
|
|
12
|
+
<div class="overflow-x-auto"><table class="table table-xs"><thead><tr><th>Field</th><th>Type</th><th></th><th>Description</th></tr></thead><tbody>
|
|
13
|
+
{{#ownFields}}<tr id="{{anchor}}"><td class="font-mono">{{name}}{{#isArray}}[]{{/isArray}}</td><td class="opacity-60">{{type}}</td><td>{{{badgesHtml}}}</td><td class="text-xs">{{desc}}</td></tr>
|
|
14
|
+
{{#enumValues.length}}<tr><td></td><td colspan="3" class="pl-4">{{#enumValues}}<span class="badge badge-soft badge-accent badge-xs mr-1">{{value}}{{#deflt}} ★{{/deflt}}</span>{{/enumValues}}</td></tr>{{/enumValues.length}}
|
|
15
|
+
{{/ownFields}}
|
|
16
|
+
</tbody></table></div>
|
|
17
|
+
{{#inheritedFields.length}}<div class="collapse collapse-arrow bg-base-100 border border-base-300 mt-2"><input type="checkbox"><div class="collapse-title text-sm font-semibold opacity-70">Inherited fields ({{inheritedFields.length}})</div><div class="collapse-content"><table class="table table-xs opacity-80"><tbody>
|
|
18
|
+
{{#inheritedFields}}<tr id="{{anchor}}"><td class="font-mono">{{name}}{{#isArray}}[]{{/isArray}} <span class="text-[10px] opacity-50">↑ <a class="link" href="{{inheritedFrom.href}}">{{inheritedFrom.name}}</a></span></td><td class="opacity-60">{{type}}</td><td>{{{badgesHtml}}}</td></tr>{{/inheritedFields}}
|
|
19
|
+
</tbody></table></div></div>{{/inheritedFields.length}}</section>
|
|
20
|
+
|
|
21
|
+
{{#indexes.length}}<section id="s-indexes" class="mt-6"><h2 class="text-lg font-semibold">Indexes & keys</h2>
|
|
22
|
+
<table class="table table-xs"><thead><tr><th>Name</th><th>Kind</th><th>Fields</th><th>Detail</th></tr></thead><tbody>
|
|
23
|
+
{{#indexes}}<tr><td class="font-mono">{{name}}</td><td><span class="badge badge-soft {{#unique}}badge-success{{/unique}}{{^unique}}badge-neutral{{/unique}} badge-xs">{{kind}}</span></td><td class="font-mono text-xs">{{fields}}</td><td class="text-xs opacity-70">{{extra}}</td></tr>{{/indexes}}
|
|
24
|
+
</tbody></table></section>{{/indexes.length}}
|
|
25
|
+
|
|
26
|
+
{{#validators.length}}<section id="s-validators" class="mt-6"><h2 class="text-lg font-semibold">Validators</h2>
|
|
27
|
+
<table class="table table-xs"><tbody>{{#validators}}<tr><td class="font-mono text-xs opacity-70">{{subject}}</td><td class="font-mono text-xs">{{rule}}</td></tr>{{/validators}}</tbody></table></section>{{/validators.length}}
|
|
28
|
+
|
|
29
|
+
{{#relations.length}}<section id="s-relationships" class="mt-6"><h2 class="text-lg font-semibold">Relationships</h2>
|
|
30
|
+
<table class="table table-xs"><tbody>{{#relations}}<tr><td class="font-mono">{{name}}</td><td class="text-xs opacity-60">{{cardinality}}</td><td><a class="link font-mono text-xs" href="{{toHref}}">{{toName}}</a></td></tr>{{/relations}}</tbody></table></section>{{/relations.length}}
|
|
31
|
+
|
|
32
|
+
{{#origins.length}}<section id="s-provenance" class="mt-6"><h2 class="text-lg font-semibold">Field provenance</h2>
|
|
33
|
+
<table class="table table-xs"><thead><tr><th>Field</th><th>From</th><th>Via</th></tr></thead><tbody>{{#origins}}<tr><td class="font-mono">{{field}}</td><td class="font-mono text-xs opacity-70">{{from}}</td><td class="font-mono text-xs opacity-70">{{via}}</td></tr>{{/origins}}</tbody></table></section>{{/origins.length}}
|
|
34
|
+
|
|
35
|
+
{{#inheritanceMermaid}}<section id="s-inheritance" class="mt-6"><h2 class="text-lg font-semibold">Inheritance</h2>
|
|
36
|
+
<div class="card bg-base-100 border border-base-300 p-2 pl-diagram"><pre class="mermaid">{{inheritanceMermaid}}</pre></div></section>{{/inheritanceMermaid}}
|
|
37
|
+
|
|
38
|
+
{{#neighborhoodMermaid}}<section id="s-neighborhood" class="mt-6"><h2 class="text-lg font-semibold">Neighborhood</h2>
|
|
39
|
+
<div class="card bg-base-100 border border-base-300 p-2 pl-diagram"><pre class="mermaid">{{neighborhoodMermaid}}</pre></div>
|
|
40
|
+
{{#neighborhoodLegend.length}}<div class="flex flex-wrap gap-1 mt-2 text-xs">{{#neighborhoodLegend}}<span class="badge badge-xs" style="background:{{fill}};border-color:{{stroke}};color:#cbd5e1">{{pkg}}</span>{{/neighborhoodLegend}}</div>{{/neighborhoodLegend.length}}
|
|
41
|
+
<div class="text-[11px] opacity-50 mt-1"><span class="font-mono">▭</span> entity · <span class="font-mono">⬭</span> value object · <span class="font-mono">▱</span> view <span class="opacity-70">(ER boxes: dashed = value, dotted = view)</span></div>
|
|
42
|
+
{{#neighborhoodMore}}<div class="text-xs opacity-50 mt-1">+{{neighborhoodMore}} more neighbor(s) — see <a class="link" href="#s-referenced-by">Referenced by</a>.</div>{{/neighborhoodMore}}</section>{{/neighborhoodMermaid}}
|
|
43
|
+
|
|
44
|
+
{{#referencedBy.length}}<section id="s-referenced-by" class="mt-6 text-sm"><span class="opacity-50">referenced by</span> {{#referencedBy}}<a class="link font-mono text-xs" href="{{href}}" title="{{via}}">{{name}}</a> {{/referencedBy}}</section>{{/referencedBy.length}}
|
|
45
|
+
{{#usedByTemplates.length}}<div class="text-sm mt-1"><span class="opacity-50">used by templates</span> {{#usedByTemplates}}<a class="link font-mono text-xs" href="{{href}}">{{name}}</a> {{/usedByTemplates}}</div>{{/usedByTemplates.length}}
|
|
46
|
+
<div class="text-[10px] opacity-40 mt-6 font-mono">{{sourceFile}}</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="text-xs breadcrumbs font-mono opacity-70"><ul><li>{{{breadcrumbHtml}}}</li></ul></div>
|
|
2
|
+
<h1 class="text-2xl font-bold font-mono mt-1">{{name}} <span class="badge badge-accent badge-sm align-middle">{{format}}</span> <span class="badge badge-ghost badge-sm align-middle">output</span></h1>
|
|
3
|
+
{{#payloadName}}<div class="text-sm mt-2 opacity-70">payload: <a class="link font-mono" href="{{payloadHref}}">{{payloadName}}</a></div>{{/payloadName}}
|
|
4
|
+
<div class="text-sm mt-1 opacity-60 font-mono">
|
|
5
|
+
textRef: {{textRef}}
|
|
6
|
+
{{^textRefResolves}}<span class="badge badge-warning badge-xs ml-2">forward-pointing</span>{{/textRefResolves}}
|
|
7
|
+
</div>
|
|
8
|
+
{{#desc}}<p class="mt-3 text-sm">{{desc}}</p>{{/desc}}
|
|
9
|
+
{{#fields.length}}
|
|
10
|
+
<section id="s-contract" class="mt-6"><h2 class="text-lg font-semibold">Parse contract</h2>
|
|
11
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
12
|
+
<thead><tr><th>Field</th><th>Type</th><th>Wire</th><th>Meaning</th></tr></thead><tbody>
|
|
13
|
+
{{#fields}}<tr><td class="font-mono">{{name}}{{#isArray}}[]{{/isArray}}</td><td class="opacity-60">{{type}}</td><td class="font-mono text-xs opacity-70">{{wire}}</td><td>{{{refHtml}}}{{#note}} {{note}}{{/note}}</td></tr>{{/fields}}
|
|
14
|
+
</tbody></table></div>
|
|
15
|
+
</section>
|
|
16
|
+
{{/fields.length}}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<div class="text-xs breadcrumbs font-mono opacity-70"><ul><li>{{{breadcrumbHtml}}}</li></ul></div>
|
|
2
|
+
<h1 class="text-2xl font-bold font-mono">{{title}}</h1>
|
|
3
|
+
{{#descHtml}}<p class="text-sm my-3">{{descHtml}}</p>{{/descHtml}}
|
|
4
|
+
{{#keyCards.length}}
|
|
5
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 my-4">
|
|
6
|
+
{{#keyCards}}<a href="{{href}}" class="card bg-base-100 border border-base-300 p-3"><div class="font-mono font-semibold">{{name}}</div><div class="text-xs opacity-50">{{inbound}} refs</div></a>{{/keyCards}}
|
|
7
|
+
</div>
|
|
8
|
+
{{/keyCards.length}}
|
|
9
|
+
{{#erdMermaid}}<div class="card bg-base-100 border border-base-300 p-2 pl-diagram my-4"><pre class="mermaid">{{erdMermaid}}</pre>{{#erdLegend.length}}<div class="flex flex-wrap gap-1 mt-2 text-xs">{{#erdLegend}}<span class="badge badge-xs" style="background:{{fill}};border-color:{{stroke}};color:#cbd5e1">{{pkg}}</span>{{/erdLegend}}</div>{{/erdLegend.length}}<div class="text-[11px] opacity-50 mt-1"><span class="font-mono">▭</span> entity · <span class="font-mono">⬭</span> value object · <span class="font-mono">▱</span> view</div></div>{{/erdMermaid}}
|
|
10
|
+
{{#abstracts.length}}
|
|
11
|
+
<h2 class="text-lg font-semibold mt-6">Abstracts</h2>
|
|
12
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
13
|
+
<thead><tr><th>Name</th><th>Kind</th><th>Fields</th></tr></thead><tbody>
|
|
14
|
+
{{#abstracts}}<tr><td><a class="link font-mono" href="{{href}}">{{name}}</a></td><td class="opacity-60">{{kind}}</td><td>{{fieldCount}}</td></tr>{{/abstracts}}
|
|
15
|
+
</tbody></table></div>
|
|
16
|
+
{{/abstracts.length}}
|
|
17
|
+
{{#objects.length}}
|
|
18
|
+
<h2 class="text-lg font-semibold mt-6">Objects</h2>
|
|
19
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
20
|
+
<thead><tr><th>Name</th><th>Kind</th><th>Table</th><th>Fields</th><th>Extends</th></tr></thead><tbody>
|
|
21
|
+
{{#objects}}<tr><td><a class="link font-mono" href="{{href}}">{{name}}</a></td><td class="opacity-60">{{kind}}</td><td class="font-mono opacity-60">{{table}}</td><td>{{fieldCount}}</td><td class="font-mono opacity-60">{{extendsName}}</td></tr>{{/objects}}
|
|
22
|
+
</tbody></table></div>
|
|
23
|
+
{{/objects.length}}
|
|
24
|
+
{{#prompts.length}}
|
|
25
|
+
<h2 class="text-lg font-semibold mt-6">Prompts</h2>
|
|
26
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
27
|
+
<thead><tr><th>Name</th><th>Payload</th><th>Format</th><th>textRef</th></tr></thead><tbody>
|
|
28
|
+
{{#prompts}}<tr><td><a class="link font-mono" href="{{href}}">{{name}}</a></td><td><a class="link font-mono opacity-70" href="{{payloadHref}}">{{payloadName}}</a></td><td class="opacity-60">{{format}}</td><td class="font-mono text-xs opacity-50">{{textRef}}</td></tr>{{/prompts}}
|
|
29
|
+
</tbody></table></div>
|
|
30
|
+
{{/prompts.length}}
|
|
31
|
+
{{#outputs.length}}
|
|
32
|
+
<h2 class="text-lg font-semibold mt-6">Output contracts</h2>
|
|
33
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
34
|
+
<thead><tr><th>Name</th><th>Payload</th><th>Format</th><th>textRef</th></tr></thead><tbody>
|
|
35
|
+
{{#outputs}}<tr><td><a class="link font-mono" href="{{href}}">{{name}}</a></td><td><a class="link font-mono opacity-70" href="{{payloadHref}}">{{payloadName}}</a></td><td class="opacity-60">{{format}}</td><td class="font-mono text-xs opacity-50">{{textRef}}</td></tr>{{/outputs}}
|
|
36
|
+
</tbody></table></div>
|
|
37
|
+
{{/outputs.length}}
|
|
38
|
+
{{#referencedBy.length}}
|
|
39
|
+
<h2 class="text-lg font-semibold mt-6">Referenced by</h2>
|
|
40
|
+
<div class="flex flex-wrap gap-2 mt-2">
|
|
41
|
+
{{#referencedBy}}<a href="{{href}}" class="badge badge-ghost font-mono">{{pkg}} <span class="opacity-50 ml-1">×{{n}}</span></a>{{/referencedBy}}
|
|
42
|
+
</div>
|
|
43
|
+
{{/referencedBy.length}}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<div class="text-xs breadcrumbs font-mono opacity-70"><ul><li>{{{breadcrumbHtml}}}</li></ul></div>
|
|
2
|
+
<h1 class="text-2xl font-bold font-mono mt-1">{{name}} <span class="badge badge-secondary badge-sm align-middle">prompt</span></h1>
|
|
3
|
+
<div class="flex flex-wrap gap-1 mt-2">{{{attrsHtml}}}</div>
|
|
4
|
+
{{#payloadName}}<div class="text-sm mt-2 opacity-70">payload: <a class="link font-mono" href="{{payloadHref}}">{{payloadName}}</a></div>{{/payloadName}}
|
|
5
|
+
{{#desc}}<p class="text-sm mb-3">{{desc}}</p>{{/desc}}
|
|
6
|
+
{{#payloadTree.length}}
|
|
7
|
+
<section id="s-payload" class="mt-6"><h2 class="text-lg font-semibold">Payload tree</h2>
|
|
8
|
+
<div class="overflow-x-auto"><table class="table table-xs">
|
|
9
|
+
<thead><tr><th>Field</th><th>Type</th><th>Ref</th><th>Description</th></tr></thead><tbody>
|
|
10
|
+
{{#payloadTree}}<tr id="{{anchor}}" class="pl-indent-{{indent}}"><td class="font-mono">{{name}}{{#isArray}}[]{{/isArray}}</td><td class="opacity-60">{{type}}</td><td>{{{refHtml}}}</td><td class="text-xs opacity-70">{{desc}}</td></tr>{{/payloadTree}}
|
|
11
|
+
</tbody></table></div>
|
|
12
|
+
</section>
|
|
13
|
+
{{/payloadTree.length}}
|
|
14
|
+
{{#sourceHtml}}
|
|
15
|
+
<section id="s-source" class="mt-6"><h2 class="text-lg font-semibold">Source</h2>
|
|
16
|
+
<pre class="pl-mu">{{{sourceHtml}}}</pre>
|
|
17
|
+
</section>
|
|
18
|
+
{{/sourceHtml}}
|
|
19
|
+
{{#sourceMissingNote}}<div class="alert alert-warning text-sm mt-4">{{sourceMissingNote}}</div>{{/sourceMissingNote}}
|
|
20
|
+
{{#packageFiles.length}}
|
|
21
|
+
<h2 class="text-lg font-semibold mt-6">Other files in package</h2>
|
|
22
|
+
{{#packageFiles}}
|
|
23
|
+
<details class="mt-2">
|
|
24
|
+
<summary class="cursor-pointer font-mono text-sm opacity-70">{{file}}</summary>
|
|
25
|
+
<pre class="pl-mu mt-1">{{{html}}}</pre>
|
|
26
|
+
</details>
|
|
27
|
+
{{/packageFiles}}
|
|
28
|
+
{{/packageFiles.length}}
|