@inflexa-ai/harness 0.31.1 → 0.33.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/dist/agents/conversation-agent.d.ts +15 -0
- package/dist/agents/conversation-agent.js +16 -6
- package/dist/agents/report-session-agent.d.ts +9 -0
- package/dist/agents/report-session-agent.js +10 -2
- package/dist/agents/sandbox/shared.d.ts +13 -1
- package/dist/agents/sandbox/shared.js +22 -5
- package/dist/app/chat-turn.d.ts +11 -0
- package/dist/app/chat-turn.js +17 -1
- package/dist/app/spawn-report-session.d.ts +12 -0
- package/dist/app/spawn-report-session.js +21 -1
- package/dist/config/environment-stores.d.ts +53 -5
- package/dist/contracts/report-blocks.d.ts +8 -8
- package/dist/contracts/schemas/chat-parts.d.ts +6 -6
- package/dist/index.d.ts +8 -1
- package/dist/index.js +11 -0
- package/dist/prompts/briefing.d.ts +1 -1
- package/dist/prompts/briefing.js +4 -0
- package/dist/prompts/planner.js +13 -0
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +5 -5
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +4 -3
- package/dist/prompts/sandbox-standards.d.ts +20 -0
- package/dist/prompts/sandbox-standards.js +65 -0
- package/dist/provenance/seam.d.ts +203 -0
- package/dist/provenance/seam.js +71 -0
- package/dist/reference-data/catalog.js +11 -9
- package/dist/report-model/authoring-grammar.d.ts +2 -2
- package/dist/report-render/assets.d.ts +10 -0
- package/dist/report-render/assets.js +14 -0
- package/dist/report-render/design.js +256 -0
- package/dist/report-render/page.d.ts +75 -0
- package/dist/report-render/page.js +793 -1
- package/dist/report-render/provenance-data.d.ts +42 -0
- package/dist/report-render/provenance-data.js +62 -0
- package/dist/report-render/render.d.ts +20 -1
- package/dist/report-render/render.js +23 -10
- package/dist/report-render/types.d.ts +3 -0
- package/dist/report-render/views/chart-view.d.ts +5 -1
- package/dist/report-render/views/chart-view.js +6 -2
- package/dist/report-render/views/lineage.d.ts +93 -0
- package/dist/report-render/views/lineage.js +86 -0
- package/dist/report-render/views/page-view.d.ts +22 -1
- package/dist/report-render/views/page-view.js +12 -3
- package/dist/report-render/views/prose.d.ts +7 -1
- package/dist/report-render/views/prose.js +10 -6
- package/dist/report-render/views/references-view.d.ts +17 -1
- package/dist/report-render/views/references-view.js +12 -4
- package/dist/report-render/views/values.d.ts +17 -4
- package/dist/report-render/views/values.js +21 -8
- package/dist/runtime/assemble.d.ts +22 -0
- package/dist/runtime/assemble.js +4 -0
- package/dist/sandbox/create-sandbox.d.ts +20 -4
- package/dist/sandbox/create-sandbox.js +4 -0
- package/dist/sandbox/docker-client.d.ts +16 -6
- package/dist/sandbox/docker-client.js +47 -31
- package/dist/sandbox/farm.d.ts +95 -0
- package/dist/sandbox/farm.js +127 -0
- package/dist/sandbox/k8s-client.d.ts +24 -10
- package/dist/sandbox/k8s-client.js +85 -122
- package/dist/sandbox/mount-plan.d.ts +23 -1
- package/dist/sandbox/mount-plan.js +44 -7
- package/dist/sandbox/sandbox-error.d.ts +12 -0
- package/dist/sandbox/sandbox-error.js +2 -0
- package/dist/sandbox/types.d.ts +118 -0
- package/dist/schemas/artifact-manifest.d.ts +4 -4
- package/dist/schemas/plan-schemas.d.ts +3 -0
- package/dist/schemas/plan-schemas.js +1 -1
- package/dist/schemas/validate-plan.js +20 -1
- package/dist/schemas/workflow-state.d.ts +4 -0
- package/dist/schemas/workflow-state.js +10 -0
- package/dist/tasks/data-profile.d.ts +15 -0
- package/dist/tasks/data-profile.js +36 -26
- package/dist/tools/display/show-user.d.ts +1 -1
- package/dist/tools/execute-analysis.d.ts +18 -0
- package/dist/tools/execute-analysis.js +87 -0
- package/dist/tools/report-authoring/authoring-tools.d.ts +16 -1
- package/dist/tools/report-authoring/authoring-tools.js +58 -16
- package/dist/tools/report-session/derive-table.d.ts +3 -0
- package/dist/tools/report-session/derive-table.js +15 -0
- package/dist/tools/report-session/preview-report.d.ts +13 -4
- package/dist/tools/report-session/preview-report.js +23 -6
- package/dist/tools/report-session/record-version.d.ts +3 -0
- package/dist/tools/report-session/record-version.js +7 -3
- package/dist/tools/research/generate-plan.js +12 -2
- package/dist/tools/sandbox/index.d.ts +1 -0
- package/dist/tools/sandbox/index.js +1 -0
- package/dist/tools/sandbox/link-packages.d.ts +27 -0
- package/dist/tools/sandbox/link-packages.js +52 -0
- package/dist/tools/sandbox/list-available-packages.d.ts +50 -30
- package/dist/tools/sandbox/list-available-packages.js +131 -40
- package/dist/tools/start-report-session.d.ts +7 -0
- package/dist/tools/start-report-session.js +1 -0
- package/dist/workflows/execute-analysis.d.ts +15 -69
- package/dist/workflows/execute-analysis.js +5 -4
- package/package.json +2 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data-script carrier of the provenance of one analysis.
|
|
3
|
+
*
|
|
4
|
+
* A `fetch` of a local file is refused on a `file://` page, thus the document cannot load the way an image
|
|
5
|
+
* does. A classic script asset loads on any page, and it registers itself under one global when the browser
|
|
6
|
+
* runs it. The carrier is the same one that a table payload uses.
|
|
7
|
+
*
|
|
8
|
+
* The document and the attestation are opaque text. This module reads no field of them, and it parses
|
|
9
|
+
* nothing. Thus the format belongs to the writer of the document, and a change of that format costs no
|
|
10
|
+
* change here.
|
|
11
|
+
*
|
|
12
|
+
* The document and the attestation ride separate assets, thus a new attestation over an unchanged document
|
|
13
|
+
* rewrites the attestation alone. Each name carries the hash of its own bytes, thus two renders of one
|
|
14
|
+
* document give one name and the sweep of the stage removes a name that the page does not reference.
|
|
15
|
+
*
|
|
16
|
+
* The module is pure, and it reads no file. The renderer derives an asset, and the caller writes it.
|
|
17
|
+
*/
|
|
18
|
+
import type { DataAsset } from "./table-data.js";
|
|
19
|
+
/**
|
|
20
|
+
* The one global that both assets register under.
|
|
21
|
+
*
|
|
22
|
+
* The page script reads the same name, thus the carrier and the reader cannot disagree over a rename.
|
|
23
|
+
*/
|
|
24
|
+
export declare const REPORT_PROVENANCE_GLOBAL = "__REPORT_PROV";
|
|
25
|
+
/**
|
|
26
|
+
* The provenance that the page carries: the document text, and the attestation text where the source holds
|
|
27
|
+
* one.
|
|
28
|
+
*
|
|
29
|
+
* Both are opaque strings. The renderer moves them into the page and never into a parse, thus a document of
|
|
30
|
+
* any format rides unchanged and the page-side reader owns the format.
|
|
31
|
+
*/
|
|
32
|
+
export interface ProvenanceExport {
|
|
33
|
+
readonly document: string;
|
|
34
|
+
readonly attestation?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The data assets of one provenance export, in load order.
|
|
38
|
+
*
|
|
39
|
+
* A source that holds no attestation gives the document asset alone. Thus an unsigned document still rides
|
|
40
|
+
* the page, and the reader finds no attestation member on the global.
|
|
41
|
+
*/
|
|
42
|
+
export declare function provenanceDataAssets(provenance: ProvenanceExport): DataAsset[];
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data-script carrier of the provenance of one analysis.
|
|
3
|
+
*
|
|
4
|
+
* A `fetch` of a local file is refused on a `file://` page, thus the document cannot load the way an image
|
|
5
|
+
* does. A classic script asset loads on any page, and it registers itself under one global when the browser
|
|
6
|
+
* runs it. The carrier is the same one that a table payload uses.
|
|
7
|
+
*
|
|
8
|
+
* The document and the attestation are opaque text. This module reads no field of them, and it parses
|
|
9
|
+
* nothing. Thus the format belongs to the writer of the document, and a change of that format costs no
|
|
10
|
+
* change here.
|
|
11
|
+
*
|
|
12
|
+
* The document and the attestation ride separate assets, thus a new attestation over an unchanged document
|
|
13
|
+
* rewrites the attestation alone. Each name carries the hash of its own bytes, thus two renders of one
|
|
14
|
+
* document give one name and the sweep of the stage removes a name that the page does not reference.
|
|
15
|
+
*
|
|
16
|
+
* The module is pure, and it reads no file. The renderer derives an asset, and the caller writes it.
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
import { scriptJson } from "./script-json.js";
|
|
20
|
+
/**
|
|
21
|
+
* The one global that both assets register under.
|
|
22
|
+
*
|
|
23
|
+
* The page script reads the same name, thus the carrier and the reader cannot disagree over a rename.
|
|
24
|
+
*/
|
|
25
|
+
export const REPORT_PROVENANCE_GLOBAL = "__REPORT_PROV";
|
|
26
|
+
/** The member of the global that holds the document text. */
|
|
27
|
+
const DOCUMENT_MEMBER = "document";
|
|
28
|
+
/** The member of the global that holds the attestation text. */
|
|
29
|
+
const ATTESTATION_MEMBER = "attestation";
|
|
30
|
+
/** The count of hash characters in an asset name. It matches a table payload, thus one form reads across the directory. */
|
|
31
|
+
const HASH_CHARS = 12;
|
|
32
|
+
/**
|
|
33
|
+
* The source text of one member of the global.
|
|
34
|
+
*
|
|
35
|
+
* The global takes the null-prototype form, the same as the table registry, thus a member sits as an
|
|
36
|
+
* ordinary entry. The text rides as a JSON string literal, thus hostile bytes are data and never source. A
|
|
37
|
+
* `</script` sequence inside the text cannot close the element, because `scriptJson` writes each `<` as its
|
|
38
|
+
* escape.
|
|
39
|
+
*/
|
|
40
|
+
function memberSource(member, text) {
|
|
41
|
+
const registry = `window.${REPORT_PROVENANCE_GLOBAL}`;
|
|
42
|
+
return `${registry}=${registry}||Object.create(null);${registry}.${member}=${scriptJson(text)};\n`;
|
|
43
|
+
}
|
|
44
|
+
/** One member asset: the content-addressed file name under `suffix`, and the source text. */
|
|
45
|
+
function memberAsset(member, suffix, text) {
|
|
46
|
+
const bytes = memberSource(member, text);
|
|
47
|
+
const hash = createHash("sha256").update(bytes).digest("hex").slice(0, HASH_CHARS);
|
|
48
|
+
return { name: `prov-${hash}${suffix}`, bytes };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The data assets of one provenance export, in load order.
|
|
52
|
+
*
|
|
53
|
+
* A source that holds no attestation gives the document asset alone. Thus an unsigned document still rides
|
|
54
|
+
* the page, and the reader finds no attestation member on the global.
|
|
55
|
+
*/
|
|
56
|
+
export function provenanceDataAssets(provenance) {
|
|
57
|
+
const assets = [memberAsset(DOCUMENT_MEMBER, ".data.js", provenance.document)];
|
|
58
|
+
if (provenance.attestation !== undefined) {
|
|
59
|
+
assets.push(memberAsset(ATTESTATION_MEMBER, ".sig.data.js", provenance.attestation));
|
|
60
|
+
}
|
|
61
|
+
return assets;
|
|
62
|
+
}
|
|
@@ -18,7 +18,20 @@ import { type Result } from "neverthrow";
|
|
|
18
18
|
import type { ReportDocument } from "../contracts/report-blocks.js";
|
|
19
19
|
import { type CitationRecords } from "../report-model/reference-resolver.js";
|
|
20
20
|
import { type DerivationChain } from "./references.js";
|
|
21
|
+
import { type ProvenanceExport } from "./provenance-data.js";
|
|
21
22
|
import type { RenderedPage, RenderProblem, RenderValues } from "./types.js";
|
|
23
|
+
/**
|
|
24
|
+
* The optional inputs of one render: the bibliography of the pin, the chains of the session, and the frozen
|
|
25
|
+
* provenance of the analysis.
|
|
26
|
+
*
|
|
27
|
+
* Each member is absent on its own, and a caller gives the members that it holds. A positional tail of
|
|
28
|
+
* three optional inputs made a caller of the last one pad the two before it, thus the three ride one bag.
|
|
29
|
+
*/
|
|
30
|
+
export interface RenderOptions {
|
|
31
|
+
readonly records?: CitationRecords;
|
|
32
|
+
readonly derivations?: readonly DerivationChain[];
|
|
33
|
+
readonly provenance?: ProvenanceExport;
|
|
34
|
+
}
|
|
22
35
|
/**
|
|
23
36
|
* Render a report document, its value map, and the pinned citation records to one page and its data assets.
|
|
24
37
|
*
|
|
@@ -34,10 +47,16 @@ import type { RenderedPage, RenderProblem, RenderValues } from "./types.js";
|
|
|
34
47
|
* byte-identically with the chains and without them. A chain carries the relative source of its staged
|
|
35
48
|
* script and of its derived file as data, thus the entry links both and this module stages nothing.
|
|
36
49
|
*
|
|
50
|
+
* The provenance is the frozen document of the analysis, and it is optional too. The renderer moves the
|
|
51
|
+
* opaque text into two data assets that register one page global, and it parses no byte of it. Each
|
|
52
|
+
* grounded block then stamps its keys, and its marker carries the control that opens the chain. A caller
|
|
53
|
+
* that passes none renders the page byte for byte without the provenance script, without a stamp, and
|
|
54
|
+
* without a control.
|
|
55
|
+
*
|
|
37
56
|
* The renderer writes no file. The data assets ride the result, and the caller stages them beside the page.
|
|
38
57
|
* Thus the render stays pure, and two renders of one document give byte-identical assets.
|
|
39
58
|
*
|
|
40
59
|
* One artifact gives one payload. A table block and a chart block that bind it read that one asset, and a
|
|
41
60
|
* chart under the inline bound carries its rows in its own option and registers none.
|
|
42
61
|
*/
|
|
43
|
-
export declare function renderReportPage(document: ReportDocument, values: RenderValues, records
|
|
62
|
+
export declare function renderReportPage(document: ReportDocument, values: RenderValues, { records, derivations, provenance }?: RenderOptions): Result<RenderedPage, RenderProblem[]>;
|
|
@@ -22,6 +22,7 @@ import { deriveChartRender } from "./chart.js";
|
|
|
22
22
|
import { assemblePage, renderBand, renderReferenceSection } from "./views/page-view.js";
|
|
23
23
|
import { renderClaim, renderNav, renderSection, renderText } from "./views/prose.js";
|
|
24
24
|
import { citationKeyOf, derivationChains, ReferenceLedger } from "./references.js";
|
|
25
|
+
import { provenanceDataAssets } from "./provenance-data.js";
|
|
25
26
|
import { encodeTablePayload, tableDataAsset } from "./table-data.js";
|
|
26
27
|
import { renderCitation, renderFigure, renderMetric, renderMetricGrid, renderTable, tableColumns, tableDisplay } from "./views/values.js";
|
|
27
28
|
/**
|
|
@@ -39,16 +40,22 @@ import { renderCitation, renderFigure, renderMetric, renderMetricGrid, renderTab
|
|
|
39
40
|
* byte-identically with the chains and without them. A chain carries the relative source of its staged
|
|
40
41
|
* script and of its derived file as data, thus the entry links both and this module stages nothing.
|
|
41
42
|
*
|
|
43
|
+
* The provenance is the frozen document of the analysis, and it is optional too. The renderer moves the
|
|
44
|
+
* opaque text into two data assets that register one page global, and it parses no byte of it. Each
|
|
45
|
+
* grounded block then stamps its keys, and its marker carries the control that opens the chain. A caller
|
|
46
|
+
* that passes none renders the page byte for byte without the provenance script, without a stamp, and
|
|
47
|
+
* without a control.
|
|
48
|
+
*
|
|
42
49
|
* The renderer writes no file. The data assets ride the result, and the caller stages them beside the page.
|
|
43
50
|
* Thus the render stays pure, and two renders of one document give byte-identical assets.
|
|
44
51
|
*
|
|
45
52
|
* One artifact gives one payload. A table block and a chart block that bind it read that one asset, and a
|
|
46
53
|
* chart under the inline bound carries its rows in its own option and registers none.
|
|
47
54
|
*/
|
|
48
|
-
export function renderReportPage(document, values, records, derivations) {
|
|
55
|
+
export function renderReportPage(document, values, { records, derivations, provenance } = {}) {
|
|
49
56
|
const problems = [];
|
|
50
57
|
const ledger = new ReferenceLedger();
|
|
51
|
-
const data = { payloads: new Map(), mounts: 0 };
|
|
58
|
+
const data = { payloads: new Map(), mounts: 0, view: { lineage: provenance !== undefined } };
|
|
52
59
|
const content = [];
|
|
53
60
|
for (const [index, section] of document.sections.entries()) {
|
|
54
61
|
content.push(renderBand(index, renderBlock(section, values, ledger, records, data, 0, problems)));
|
|
@@ -56,10 +63,16 @@ export function renderReportPage(document, values, records, derivations) {
|
|
|
56
63
|
if (problems.length > 0) {
|
|
57
64
|
return err(problems);
|
|
58
65
|
}
|
|
59
|
-
const
|
|
66
|
+
const tableAssets = [...data.payloads.values()].map((entry) => tableDataAsset(entry.ids, entry.payload));
|
|
67
|
+
// The two asset groups stay apart in the skeleton, because the table decoder answers for a table payload
|
|
68
|
+
// alone. Thus a page that carries the provenance and no table loads no decoder.
|
|
69
|
+
const provenanceAssets = provenance === undefined ? [] : provenanceDataAssets(provenance);
|
|
60
70
|
const nav = renderNav(document.sections);
|
|
61
71
|
const references = renderReferenceSection(ledger, document.sections.length, records, derivationChains(derivations));
|
|
62
|
-
return ok({
|
|
72
|
+
return ok({
|
|
73
|
+
html: assemblePage(document.title, nav, content.join(""), references, { dataAssets: tableAssets, grids: data.mounts > 0, provenanceAssets }),
|
|
74
|
+
dataAssets: [...provenanceAssets, ...tableAssets],
|
|
75
|
+
});
|
|
63
76
|
}
|
|
64
77
|
/**
|
|
65
78
|
* Register the payload of one bound artifact, and name this block as a reader of it.
|
|
@@ -86,9 +99,9 @@ function renderBlock(block, values, ledger, records, data, depth, problems) {
|
|
|
86
99
|
case "text":
|
|
87
100
|
return renderText(block);
|
|
88
101
|
case "claim":
|
|
89
|
-
return renderClaim(block, ledger);
|
|
102
|
+
return renderClaim(block, ledger, data.view);
|
|
90
103
|
case "citation":
|
|
91
|
-
return renderCitation(block, ledger, citationRecordOf(records, citationKeyOf(block.binding)));
|
|
104
|
+
return renderCitation(block, ledger, citationRecordOf(records, citationKeyOf(block.binding)), data.view);
|
|
92
105
|
case "metric": {
|
|
93
106
|
const entry = values[block.id];
|
|
94
107
|
if (entry === undefined) {
|
|
@@ -99,7 +112,7 @@ function renderBlock(block, values, ledger, records, data, depth, problems) {
|
|
|
99
112
|
problems.push(wrongShape(block.id, entry.type, "scalar"));
|
|
100
113
|
return "";
|
|
101
114
|
}
|
|
102
|
-
return renderMetric(block, ledger, entry);
|
|
115
|
+
return renderMetric(block, ledger, entry, data.view);
|
|
103
116
|
}
|
|
104
117
|
case "table": {
|
|
105
118
|
const entry = values[block.id];
|
|
@@ -117,7 +130,7 @@ function renderBlock(block, values, ledger, records, data, depth, problems) {
|
|
|
117
130
|
const columns = tableColumns(entry);
|
|
118
131
|
data.mounts += 1;
|
|
119
132
|
registerPayload(data, block.binding, block.id, () => payloadOf(block.binding, entry, columns));
|
|
120
|
-
return renderTable(block, ledger, entry.rows.length, entry.total);
|
|
133
|
+
return renderTable(block, ledger, entry.rows.length, entry.total, data.view);
|
|
121
134
|
}
|
|
122
135
|
case "figure": {
|
|
123
136
|
const entry = values[block.id];
|
|
@@ -129,7 +142,7 @@ function renderBlock(block, values, ledger, records, data, depth, problems) {
|
|
|
129
142
|
problems.push(wrongShape(block.id, entry.type, "figure"));
|
|
130
143
|
return "";
|
|
131
144
|
}
|
|
132
|
-
return renderFigure(block, ledger, entry);
|
|
145
|
+
return renderFigure(block, ledger, entry, data.view);
|
|
133
146
|
}
|
|
134
147
|
case "chart": {
|
|
135
148
|
const entry = values[block.id];
|
|
@@ -154,7 +167,7 @@ function renderBlock(block, values, ledger, records, data, depth, problems) {
|
|
|
154
167
|
if (derived.value.readsPayload) {
|
|
155
168
|
registerPayload(data, block.binding, block.id, () => payloadOf(block.binding, entry, columns));
|
|
156
169
|
}
|
|
157
|
-
return renderChart(block, ledger, derived.value.option);
|
|
170
|
+
return renderChart(block, ledger, derived.value.option, data.view);
|
|
158
171
|
}
|
|
159
172
|
case "section":
|
|
160
173
|
return renderSection(block, depth, renderChildren(block.blocks, values, ledger, records, data, depth + 1, problems));
|
|
@@ -47,6 +47,9 @@ export type RenderValues = Record<string, RenderValue>;
|
|
|
47
47
|
*
|
|
48
48
|
* The renderer writes no file. Thus it gives the asset bytes back to the caller, and the caller stages
|
|
49
49
|
* them beside the page. A document with no table gives an empty list, and its page references none.
|
|
50
|
+
*
|
|
51
|
+
* The list holds the provenance assets of the render beside the table payloads, thus one stage writes each
|
|
52
|
+
* file that the page loads and the caller sorts nothing.
|
|
50
53
|
*/
|
|
51
54
|
export interface RenderedPage {
|
|
52
55
|
html: string;
|
|
@@ -11,11 +11,15 @@
|
|
|
11
11
|
import type { ChartBlock } from "../../contracts/report-blocks.js";
|
|
12
12
|
import type { EchartOption } from "../chart.js";
|
|
13
13
|
import type { ReferenceLedger } from "../references.js";
|
|
14
|
+
import { type ViewOptions } from "./lineage.js";
|
|
14
15
|
/**
|
|
15
16
|
* Render the card markup for a chart.
|
|
16
17
|
*
|
|
17
18
|
* The whole-table binding joins the reference ladder, thus the title line carries the marker and the
|
|
18
19
|
* appendix names the artifact that the chart plots. A chart with no title still shows its marker on the
|
|
19
20
|
* same line.
|
|
21
|
+
*
|
|
22
|
+
* `view.lineage` states that the page carries a provenance document. The card then stamps its keys, and the
|
|
23
|
+
* marker carries the control that opens the chain.
|
|
20
24
|
*/
|
|
21
|
-
export declare function renderChart(block: ChartBlock, ledger: ReferenceLedger, option: EchartOption): string;
|
|
25
|
+
export declare function renderChart(block: ChartBlock, ledger: ReferenceLedger, option: EchartOption, view?: ViewOptions): string;
|
|
@@ -10,6 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
|
10
10
|
* height, because the chart runtime measures the container and a container with no height shows no chart.
|
|
11
11
|
*/
|
|
12
12
|
import { raw } from "hono/html";
|
|
13
|
+
import { DEFAULT_VIEW_OPTIONS, lineagePlace, lineageStamp } from "./lineage.js";
|
|
13
14
|
import { Marker } from "./references-view.js";
|
|
14
15
|
import { scriptJson } from "../script-json.js";
|
|
15
16
|
/**
|
|
@@ -18,15 +19,18 @@ import { scriptJson } from "../script-json.js";
|
|
|
18
19
|
* The whole-table binding joins the reference ladder, thus the title line carries the marker and the
|
|
19
20
|
* appendix names the artifact that the chart plots. A chart with no title still shows its marker on the
|
|
20
21
|
* same line.
|
|
22
|
+
*
|
|
23
|
+
* `view.lineage` states that the page carries a provenance document. The card then stamps its keys, and the
|
|
24
|
+
* marker carries the control that opens the chain.
|
|
21
25
|
*/
|
|
22
|
-
export function renderChart(block, ledger, option) {
|
|
26
|
+
export function renderChart(block, ledger, option, view = DEFAULT_VIEW_OPTIONS) {
|
|
23
27
|
const n = ledger.mark(block.binding);
|
|
24
28
|
const containerId = chartContainerId(block.id);
|
|
25
29
|
// The JSON goes to the page through `raw()`, thus `scriptJson` is the sole guard of this sink. It
|
|
26
30
|
// replaces every `<` with `\u003c`, thus a `</script` sequence in a string cell cannot close the
|
|
27
31
|
// element early. The JSON parser reads `\u003c` as `<`, thus the option value stays exact.
|
|
28
32
|
const json = scriptJson(option);
|
|
29
|
-
return String(_jsxs("div", { class: "report-chart", children: [_jsxs("div", { class: "report-chart-title", children: [block.title, _jsx(Marker, { n: n })] }), _jsxs("div", { class: "report-chart-card corner-accents", children: [_jsx("div", { id: containerId, "data-echarts-id": block.id, class: "chart-container" }), _jsx("script", { type: "application/json", children: raw(json) })] }), block.caption !== undefined ? _jsx("p", { class: "report-caption", children: block.caption }) : null] }));
|
|
33
|
+
return String(_jsxs("div", { class: "report-chart", ...lineageStamp(view.lineage, block.id, [block.binding]), children: [_jsxs("div", { class: "report-chart-title", children: [block.title, _jsx(Marker, { n: n, lineage: lineagePlace(view.lineage, block.binding) })] }), _jsxs("div", { class: "report-chart-card corner-accents", children: [_jsx("div", { id: containerId, "data-echarts-id": block.id, class: "chart-container" }), _jsx("script", { type: "application/json", children: raw(json) })] }), block.caption !== undefined ? _jsx("p", { class: "report-caption", children: block.caption }) : null] }));
|
|
30
34
|
}
|
|
31
35
|
/** The container id derives from the block id, thus the id stays stable across renders. */
|
|
32
36
|
function chartContainerId(blockId) {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The lineage keys of a grounded block, and the control that opens the chain of one key.
|
|
3
|
+
*
|
|
4
|
+
* A grounded block stamps its identity into the markup: the block id, and one key for each reference that
|
|
5
|
+
* it binds, in marker order. The page script reads the stamp when a reader clicks a control. Thus the
|
|
6
|
+
* markup is the one contract between the renderer and the script, and neither side holds a copy of the
|
|
7
|
+
* other.
|
|
8
|
+
*
|
|
9
|
+
* A key is a pin or an external record. A pin names one immutable file by `path` and `hash`, and the walk
|
|
10
|
+
* resolves the node of those bytes. A citation names a paper, which no data chain reaches, thus its key
|
|
11
|
+
* carries the identity of the record instead.
|
|
12
|
+
*
|
|
13
|
+
* A reference that pins no single file gives no key. A derivation computes over two inputs, thus it names
|
|
14
|
+
* no file of its own and the marker of such a reference carries no control.
|
|
15
|
+
*
|
|
16
|
+
* The stamp is empty while the page carries no provenance document. Thus such a page holds no lineage
|
|
17
|
+
* attribute, no control, and the markup that it held before the stamp existed.
|
|
18
|
+
*
|
|
19
|
+
* The module also declares `ViewOptions`. Each view of the page reads that bag, and the lineage condition
|
|
20
|
+
* is the one truth that it holds today.
|
|
21
|
+
*/
|
|
22
|
+
import type { Reference } from "../../contracts/report-reference.js";
|
|
23
|
+
/**
|
|
24
|
+
* The page-wide truths of one render.
|
|
25
|
+
*
|
|
26
|
+
* A truth of this kind is constant across the whole page, thus each view of one page decides it alike. The
|
|
27
|
+
* bag threads one time through the view layer. Thus the next truth joins this interface, and no view
|
|
28
|
+
* signature grows one more parameter for it.
|
|
29
|
+
*
|
|
30
|
+
* `lineage` states that the page carries a provenance document. Each grounded block then stamps its keys
|
|
31
|
+
* and shows its control, and a page with no document carries neither.
|
|
32
|
+
*/
|
|
33
|
+
export interface ViewOptions {
|
|
34
|
+
readonly lineage: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The options that a view takes when the caller gives none. Each truth is off, thus the view renders its
|
|
38
|
+
* plain form.
|
|
39
|
+
*/
|
|
40
|
+
export declare const DEFAULT_VIEW_OPTIONS: ViewOptions;
|
|
41
|
+
/** The attribute that names the block of one stamp. The page script reads the same name. */
|
|
42
|
+
export declare const LINEAGE_BLOCK_ATTRIBUTE = "data-lineage-block";
|
|
43
|
+
/** The attribute that carries the keys of one stamp, as a JSON array in marker order. */
|
|
44
|
+
export declare const LINEAGE_KEYS_ATTRIBUTE = "data-lineage-keys";
|
|
45
|
+
/** The attribute of one control: the place of its key in the key list of the block. */
|
|
46
|
+
export declare const LINEAGE_KEY_ATTRIBUTE = "data-lineage-key";
|
|
47
|
+
/** The class of the control that opens the chain of one reference. */
|
|
48
|
+
export declare const LINEAGE_CONTROL_CLASS = "report-lineage";
|
|
49
|
+
/** The pin of one artifact: the analysis-relative path, and the content hash of the bytes. */
|
|
50
|
+
export interface LineagePin {
|
|
51
|
+
readonly path: string;
|
|
52
|
+
readonly hash: string;
|
|
53
|
+
}
|
|
54
|
+
/** The identity of one external record: the identifier space, and the identifier inside it. */
|
|
55
|
+
export interface LineageRecord {
|
|
56
|
+
readonly idKind: string;
|
|
57
|
+
readonly id: string;
|
|
58
|
+
}
|
|
59
|
+
/** One key of a stamp. A reference that pins no single file gives `null` in place of a key. */
|
|
60
|
+
export type LineageKey = LineagePin | LineageRecord;
|
|
61
|
+
/**
|
|
62
|
+
* The key of one reference, or `null` where the reference pins no single file.
|
|
63
|
+
*
|
|
64
|
+
* A derivation is the one artifact-side kind that gives `null`. It computes over two inputs, thus the
|
|
65
|
+
* document holds no node of its own bytes and one pin cannot address it.
|
|
66
|
+
*/
|
|
67
|
+
export declare function lineageKeyOf(reference: Reference): LineageKey | null;
|
|
68
|
+
/**
|
|
69
|
+
* The stamp attributes of one block, or an empty object while the page carries no provenance.
|
|
70
|
+
*
|
|
71
|
+
* The caller spreads the result onto the container element of the block. Thus a page with no provenance
|
|
72
|
+
* emits no attribute at all, and the spread is the one place that decides it.
|
|
73
|
+
*
|
|
74
|
+
* The key list keeps one entry for each binding, in marker order. Thus the place of a control indexes the
|
|
75
|
+
* bindings directly, and a binding that gives no key keeps its place as `null`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function lineageStamp(on: boolean, blockId: string, references: readonly Reference[]): Record<string, string>;
|
|
78
|
+
/**
|
|
79
|
+
* The place of the control of one reference, or `undefined` where the page carries no provenance or the
|
|
80
|
+
* reference pins nothing.
|
|
81
|
+
*
|
|
82
|
+
* A block that binds one reference passes no index, because its one key sits at the first place.
|
|
83
|
+
*/
|
|
84
|
+
export declare function lineagePlace(on: boolean, reference: Reference, index?: number): number | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* The control beside one marker. A click opens the chain of the key that sits at `place`.
|
|
87
|
+
*
|
|
88
|
+
* The control names its place and never its key. The stamp of the block holds the keys, thus one page
|
|
89
|
+
* carries one copy of each key and a claim of several bindings repeats none of them.
|
|
90
|
+
*/
|
|
91
|
+
export declare function LineageControl({ place }: {
|
|
92
|
+
place: number;
|
|
93
|
+
}): import("hono/jsx/jsx-dev-runtime").JSX.Element;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* The options that a view takes when the caller gives none. Each truth is off, thus the view renders its
|
|
4
|
+
* plain form.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_VIEW_OPTIONS = { lineage: false };
|
|
7
|
+
/** The attribute that names the block of one stamp. The page script reads the same name. */
|
|
8
|
+
export const LINEAGE_BLOCK_ATTRIBUTE = "data-lineage-block";
|
|
9
|
+
/** The attribute that carries the keys of one stamp, as a JSON array in marker order. */
|
|
10
|
+
export const LINEAGE_KEYS_ATTRIBUTE = "data-lineage-keys";
|
|
11
|
+
/** The attribute of one control: the place of its key in the key list of the block. */
|
|
12
|
+
export const LINEAGE_KEY_ATTRIBUTE = "data-lineage-key";
|
|
13
|
+
/** The class of the control that opens the chain of one reference. */
|
|
14
|
+
export const LINEAGE_CONTROL_CLASS = "report-lineage";
|
|
15
|
+
/** The name of the control for a reader who hears the page instead of seeing it. */
|
|
16
|
+
const LINEAGE_CONTROL_LABEL = "Show the lineage of this reference";
|
|
17
|
+
/** The class of the glyph inside the control. The design sheet holds the matching rule. */
|
|
18
|
+
const LINEAGE_GLYPH_CLASS = "report-lineage-glyph";
|
|
19
|
+
/**
|
|
20
|
+
* The glyph of the control: a branch of three nodes on the 16px grid.
|
|
21
|
+
*
|
|
22
|
+
* The drawing reads as a chain that divides, which is what the panel behind it shows. A text glyph reads
|
|
23
|
+
* as a disclosure of more prose, and a bracket form would give the page two notations that look alike and
|
|
24
|
+
* mean different things.
|
|
25
|
+
*
|
|
26
|
+
* The stroke takes the current color, thus the muted color of the button and its primary color on hover
|
|
27
|
+
* both reach the drawing and the sheet holds one color for the two states. The glyph is decoration, thus
|
|
28
|
+
* it hides from a reader who hears the page and the label of the button answers instead.
|
|
29
|
+
*/
|
|
30
|
+
function LineageGlyph() {
|
|
31
|
+
return (_jsxs("svg", { class: LINEAGE_GLYPH_CLASS, width: "13", height: "13", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "aria-hidden": "true", children: [_jsx("circle", { cx: "4", cy: "4", r: "2" }), _jsx("circle", { cx: "4", cy: "12", r: "2" }), _jsx("circle", { cx: "12", cy: "12", r: "2" }), _jsx("path", { d: "M4 6v4" }), _jsx("path", { d: "M6 12h4" }), _jsx("path", { d: "M12 10V8a4 4 0 0 0-4-4H6" })] }));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The key of one reference, or `null` where the reference pins no single file.
|
|
35
|
+
*
|
|
36
|
+
* A derivation is the one artifact-side kind that gives `null`. It computes over two inputs, thus the
|
|
37
|
+
* document holds no node of its own bytes and one pin cannot address it.
|
|
38
|
+
*/
|
|
39
|
+
export function lineageKeyOf(reference) {
|
|
40
|
+
switch (reference.kind) {
|
|
41
|
+
case "citation":
|
|
42
|
+
return { idKind: reference.idKind, id: reference.id };
|
|
43
|
+
case "derivation":
|
|
44
|
+
return null;
|
|
45
|
+
default:
|
|
46
|
+
return { path: reference.path, hash: reference.hash };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The stamp attributes of one block, or an empty object while the page carries no provenance.
|
|
51
|
+
*
|
|
52
|
+
* The caller spreads the result onto the container element of the block. Thus a page with no provenance
|
|
53
|
+
* emits no attribute at all, and the spread is the one place that decides it.
|
|
54
|
+
*
|
|
55
|
+
* The key list keeps one entry for each binding, in marker order. Thus the place of a control indexes the
|
|
56
|
+
* bindings directly, and a binding that gives no key keeps its place as `null`.
|
|
57
|
+
*/
|
|
58
|
+
export function lineageStamp(on, blockId, references) {
|
|
59
|
+
if (!on) {
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
// The JSON rides an attribute value, and the markup runtime escapes each attribute value. Thus a
|
|
63
|
+
// hostile path reaches the page as text and it cannot leave its slot.
|
|
64
|
+
return {
|
|
65
|
+
[LINEAGE_BLOCK_ATTRIBUTE]: blockId,
|
|
66
|
+
[LINEAGE_KEYS_ATTRIBUTE]: JSON.stringify(references.map(lineageKeyOf)),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The place of the control of one reference, or `undefined` where the page carries no provenance or the
|
|
71
|
+
* reference pins nothing.
|
|
72
|
+
*
|
|
73
|
+
* A block that binds one reference passes no index, because its one key sits at the first place.
|
|
74
|
+
*/
|
|
75
|
+
export function lineagePlace(on, reference, index = 0) {
|
|
76
|
+
return on && lineageKeyOf(reference) !== null ? index : undefined;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The control beside one marker. A click opens the chain of the key that sits at `place`.
|
|
80
|
+
*
|
|
81
|
+
* The control names its place and never its key. The stamp of the block holds the keys, thus one page
|
|
82
|
+
* carries one copy of each key and a claim of several bindings repeats none of them.
|
|
83
|
+
*/
|
|
84
|
+
export function LineageControl({ place }) {
|
|
85
|
+
return (_jsx("button", { type: "button", class: LINEAGE_CONTROL_CLASS, "aria-label": LINEAGE_CONTROL_LABEL, "aria-expanded": "false", [LINEAGE_KEY_ATTRIBUTE]: String(place), children: _jsx(LineageGlyph, {}) }));
|
|
86
|
+
}
|
|
@@ -37,6 +37,18 @@ export declare function renderBand(index: number, inner: string): string;
|
|
|
37
37
|
* such a path states it.
|
|
38
38
|
*/
|
|
39
39
|
export declare function renderReferenceSection(ledger: ReferenceLedger, index: number, records?: CitationRecords, chains?: DerivationChains): string;
|
|
40
|
+
/**
|
|
41
|
+
* What one page loads: the table payloads, the grid condition, and the provenance assets.
|
|
42
|
+
*
|
|
43
|
+
* The two asset groups carry one type, and they land in different places of the skeleton. A positional pair
|
|
44
|
+
* of one type takes no fault at the build when a caller swaps the two. Thus the group rides one bag, and
|
|
45
|
+
* each member of it carries its own name.
|
|
46
|
+
*/
|
|
47
|
+
export interface PageAssets {
|
|
48
|
+
readonly dataAssets: readonly DataAsset[];
|
|
49
|
+
readonly grids: boolean;
|
|
50
|
+
readonly provenanceAssets: readonly DataAsset[];
|
|
51
|
+
}
|
|
40
52
|
/**
|
|
41
53
|
* Assemble the page from the title, the navigation, the main content, the reference frame, and the data
|
|
42
54
|
* assets. The title passes through the runtime as text, and the runtime escapes it. The reference frame is
|
|
@@ -46,7 +58,16 @@ export declare function renderReferenceSection(ledger: ReferenceLedger, index: n
|
|
|
46
58
|
* of them. Thus every payload is registered before any reader looks. A page with no asset carries no tag
|
|
47
59
|
* and no decoder.
|
|
48
60
|
*
|
|
61
|
+
* The provenance assets lead the group, and they stand before each bootstrap. Thus a reader of the global
|
|
62
|
+
* finds the document whichever script asks for it first. A page with no provenance carries no such tag, and
|
|
63
|
+
* the rest of the skeleton is what it was.
|
|
64
|
+
*
|
|
65
|
+
* The provenance also gates the library reference and the lineage popover. The library stands in the head,
|
|
66
|
+
* beside the other two runtimes, and the popover script reads it when a reader clicks a control. Thus the
|
|
67
|
+
* place of the script in the order is free and it stands last. A page with no provenance carries no stamp
|
|
68
|
+
* and no control, thus neither the library nor the script would find anything to open.
|
|
69
|
+
*
|
|
49
70
|
* `grids` states that the content holds a grid mount. The grid runtime weighs about two megabytes, thus a
|
|
50
71
|
* page whose only payload feeds a chart references neither the runtime nor the grid boot.
|
|
51
72
|
*/
|
|
52
|
-
export declare function assemblePage(title: string, nav: string, content: string, references: string, dataAssets
|
|
73
|
+
export declare function assemblePage(title: string, nav: string, content: string, references: string, { dataAssets, grids, provenanceAssets }: PageAssets): string;
|
|
@@ -18,7 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
|
18
18
|
* one width, and the title over them sits on the same left edge.
|
|
19
19
|
*/
|
|
20
20
|
import { raw } from "hono/html";
|
|
21
|
-
import { ASSET_HEAD, CHART_BOOTSTRAP, FADE_IN_OBSERVER, GRID_ASSET_HEAD, GRID_BOOTSTRAP, SECTION_SPY, TABLE_DATA_DECODER } from "../page.js";
|
|
21
|
+
import { ASSET_HEAD, CHART_BOOTSTRAP, FADE_IN_OBSERVER, GRID_ASSET_HEAD, GRID_BOOTSTRAP, LINEAGE_ASSET_HEAD, LINEAGE_POPOVER, SECTION_SPY, TABLE_DATA_DECODER, } from "../page.js";
|
|
22
22
|
import { stagedSource } from "../assets.js";
|
|
23
23
|
import { DESIGN_CSS, ECHARTS_THEME, ECHARTS_THEME_NAME } from "../design.js";
|
|
24
24
|
import { renderReferences } from "./references-view.js";
|
|
@@ -82,10 +82,19 @@ export function renderReferenceSection(ledger, index, records, chains) {
|
|
|
82
82
|
* of them. Thus every payload is registered before any reader looks. A page with no asset carries no tag
|
|
83
83
|
* and no decoder.
|
|
84
84
|
*
|
|
85
|
+
* The provenance assets lead the group, and they stand before each bootstrap. Thus a reader of the global
|
|
86
|
+
* finds the document whichever script asks for it first. A page with no provenance carries no such tag, and
|
|
87
|
+
* the rest of the skeleton is what it was.
|
|
88
|
+
*
|
|
89
|
+
* The provenance also gates the library reference and the lineage popover. The library stands in the head,
|
|
90
|
+
* beside the other two runtimes, and the popover script reads it when a reader clicks a control. Thus the
|
|
91
|
+
* place of the script in the order is free and it stands last. A page with no provenance carries no stamp
|
|
92
|
+
* and no control, thus neither the library nor the script would find anything to open.
|
|
93
|
+
*
|
|
85
94
|
* `grids` states that the content holds a grid mount. The grid runtime weighs about two megabytes, thus a
|
|
86
95
|
* page whose only payload feeds a chart references neither the runtime nor the grid boot.
|
|
87
96
|
*/
|
|
88
|
-
export function assemblePage(title, nav, content, references, dataAssets, grids) {
|
|
97
|
+
export function assemblePage(title, nav, content, references, { dataAssets, grids, provenanceAssets }) {
|
|
89
98
|
return ("<!doctype html>" +
|
|
90
|
-
String(_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title }), raw(ASSET_HEAD), grids ? raw(GRID_ASSET_HEAD) : null, _jsx("style", { children: raw(DESIGN_CSS) })] }), _jsxs("body", { children: [raw(nav), _jsx("header", { class: "report-hero texture-noise", children: _jsx("div", { class: "report-container", children: _jsxs("div", { class: "report-content", children: [_jsx("p", { class: "report-eyebrow", children: HERO_EYEBROW }), _jsx("h1", { class: "report-display", children: title })] }) }) }), _jsxs("main", { children: [raw(content), references.length > 0 ? raw(references) : null] }), _jsx("footer", { class: "report-footer", children: _jsx("div", { class: "report-container", children: _jsxs("div", { class: "report-content report-footer-row", children: [_jsx("span", { class: "report-footer-title", children: title }), _jsx("span", { class: "report-footer-note", children: FOOTER_NOTE })] }) }) }), dataAssets.map((asset) => (_jsx("script", { src: stagedSource(asset.name) }))), dataAssets.length > 0 ? _jsx("script", { children: raw(TABLE_DATA_DECODER) }) : null, _jsx("script", { children: raw(THEME_REGISTRATION) }), _jsx("script", { children: raw(FADE_IN_OBSERVER) }), grids ? _jsx("script", { children: raw(GRID_BOOTSTRAP) }) : null, _jsx("script", { children: raw(CHART_BOOTSTRAP) }), _jsx("script", { children: raw(SECTION_SPY) })] })] })));
|
|
99
|
+
String(_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title }), raw(ASSET_HEAD), grids ? raw(GRID_ASSET_HEAD) : null, provenanceAssets.length > 0 ? raw(LINEAGE_ASSET_HEAD) : null, _jsx("style", { children: raw(DESIGN_CSS) })] }), _jsxs("body", { children: [raw(nav), _jsx("header", { class: "report-hero texture-noise", children: _jsx("div", { class: "report-container", children: _jsxs("div", { class: "report-content", children: [_jsx("p", { class: "report-eyebrow", children: HERO_EYEBROW }), _jsx("h1", { class: "report-display", children: title })] }) }) }), _jsxs("main", { children: [raw(content), references.length > 0 ? raw(references) : null] }), _jsx("footer", { class: "report-footer", children: _jsx("div", { class: "report-container", children: _jsxs("div", { class: "report-content report-footer-row", children: [_jsx("span", { class: "report-footer-title", children: title }), _jsx("span", { class: "report-footer-note", children: FOOTER_NOTE })] }) }) }), provenanceAssets.map((asset) => (_jsx("script", { src: stagedSource(asset.name) }))), dataAssets.map((asset) => (_jsx("script", { src: stagedSource(asset.name) }))), dataAssets.length > 0 ? _jsx("script", { children: raw(TABLE_DATA_DECODER) }) : null, _jsx("script", { children: raw(THEME_REGISTRATION) }), _jsx("script", { children: raw(FADE_IN_OBSERVER) }), grids ? _jsx("script", { children: raw(GRID_BOOTSTRAP) }) : null, _jsx("script", { children: raw(CHART_BOOTSTRAP) }), _jsx("script", { children: raw(SECTION_SPY) }), provenanceAssets.length > 0 ? _jsx("script", { children: raw(LINEAGE_POPOVER) }) : null] })] })));
|
|
91
100
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { ClaimBlock, SectionBlock, TextBlock } from "../../contracts/report-blocks.js";
|
|
12
12
|
import type { ReferenceLedger } from "../references.js";
|
|
13
|
+
import { type ViewOptions } from "./lineage.js";
|
|
13
14
|
/**
|
|
14
15
|
* Render a text block as escaped paragraphs, and then its list.
|
|
15
16
|
*
|
|
@@ -23,8 +24,13 @@ export declare function renderText(block: TextBlock): string;
|
|
|
23
24
|
* paragraph, thus they sit at the end of the claim text. The ledger marks each binding, thus a shared
|
|
24
25
|
* reference keeps one number across the page. An artifact binding and a citation binding read the same
|
|
25
26
|
* bracket, because one ladder counts them both.
|
|
27
|
+
*
|
|
28
|
+
* `view.lineage` states that the page carries a provenance document. The claim renders as paragraphs and it
|
|
29
|
+
* has no container of its own, thus one wrapper takes the stamp of the whole block. The wrapper carries no
|
|
30
|
+
* class, thus it adds no rule to the design sheet and each paragraph keeps its own spacing. A page with no
|
|
31
|
+
* document renders the paragraphs alone.
|
|
26
32
|
*/
|
|
27
|
-
export declare function renderClaim(block: ClaimBlock, ledger: ReferenceLedger): string;
|
|
33
|
+
export declare function renderClaim(block: ClaimBlock, ledger: ReferenceLedger, view?: ViewOptions): string;
|
|
28
34
|
/**
|
|
29
35
|
* Render a section wrapper around its rendered children. The heading level is `h2` at depth 0, `h3` at
|
|
30
36
|
* depth 1, and `h4` at depth 2 or deeper. The walk renders the children first, and it passes the markup
|
|
@@ -10,6 +10,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "hono/jsx/jsx-
|
|
|
10
10
|
* item takes the same escape as a paragraph, thus no item reaches the page as markup.
|
|
11
11
|
*/
|
|
12
12
|
import { raw } from "hono/html";
|
|
13
|
+
import { DEFAULT_VIEW_OPTIONS, lineagePlace, lineageStamp } from "./lineage.js";
|
|
13
14
|
import { Marker } from "./references-view.js";
|
|
14
15
|
/** The paragraph class of a text block and a claim block. The paragraph fills the content column. */
|
|
15
16
|
const PARAGRAPH_CLASS = "report-prose";
|
|
@@ -57,15 +58,18 @@ export function renderText(block) {
|
|
|
57
58
|
* paragraph, thus they sit at the end of the claim text. The ledger marks each binding, thus a shared
|
|
58
59
|
* reference keeps one number across the page. An artifact binding and a citation binding read the same
|
|
59
60
|
* bracket, because one ladder counts them both.
|
|
61
|
+
*
|
|
62
|
+
* `view.lineage` states that the page carries a provenance document. The claim renders as paragraphs and it
|
|
63
|
+
* has no container of its own, thus one wrapper takes the stamp of the whole block. The wrapper carries no
|
|
64
|
+
* class, thus it adds no rule to the design sheet and each paragraph keeps its own spacing. A page with no
|
|
65
|
+
* document renders the paragraphs alone.
|
|
60
66
|
*/
|
|
61
|
-
export function renderClaim(block, ledger) {
|
|
62
|
-
const markers = block.bindings.map((reference) => _jsx(Marker, { n: ledger.mark(reference) }));
|
|
67
|
+
export function renderClaim(block, ledger, view = DEFAULT_VIEW_OPTIONS) {
|
|
68
|
+
const markers = block.bindings.map((reference, index) => _jsx(Marker, { n: ledger.mark(reference), lineage: lineagePlace(view.lineage, reference, index) }));
|
|
63
69
|
const paragraphs = splitParagraphs(block.content.prose);
|
|
64
|
-
if (paragraphs.length === 0) {
|
|
65
|
-
return String(_jsx("p", { class: PARAGRAPH_CLASS, children: markers }));
|
|
66
|
-
}
|
|
67
70
|
const last = paragraphs.length - 1;
|
|
68
|
-
|
|
71
|
+
const body = paragraphs.length === 0 ? (_jsx("p", { class: PARAGRAPH_CLASS, children: markers })) : (_jsx(_Fragment, { children: paragraphs.map((paragraph, index) => (_jsxs("p", { class: PARAGRAPH_CLASS, children: [paragraph, index === last ? markers : null] }))) }));
|
|
72
|
+
return String(view.lineage ? _jsx("div", { ...lineageStamp(view.lineage, block.id, block.bindings), children: body }) : body);
|
|
69
73
|
}
|
|
70
74
|
/** The heading class of a section, by heading level. A heading uses the sans family, never the mono family. */
|
|
71
75
|
function headingClass(level) {
|