@arnilo/prism-tools 0.0.0-stage → 0.13.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/CHANGELOG.md +410 -0
- package/LICENSE +21 -0
- package/README.md +44 -2
- package/browser/README.md +98 -0
- package/browser/skills/browser-automation/SKILL.md +14 -0
- package/browser/src/actions/cdp.ts +131 -0
- package/browser/src/actions/dialog.ts +25 -0
- package/browser/src/actions/download_release.ts +22 -0
- package/browser/src/actions/index.ts +37 -0
- package/browser/src/actions/locator.ts +70 -0
- package/browser/src/actions/navigate.ts +23 -0
- package/browser/src/actions/screenshot.ts +27 -0
- package/browser/src/actions/scroll.ts +24 -0
- package/browser/src/actions/select_page.ts +21 -0
- package/browser/src/actions/types.ts +114 -0
- package/browser/src/actions/upload.ts +44 -0
- package/browser/src/actions/wait.ts +45 -0
- package/browser/src/browser.ts +197 -0
- package/browser/src/cdp.ts +178 -0
- package/browser/src/checkpoint.ts +189 -0
- package/browser/src/config.ts +72 -0
- package/browser/src/downloads.ts +253 -0
- package/browser/src/errors.ts +31 -0
- package/browser/src/evaluate.ts +101 -0
- package/browser/src/index.ts +129 -0
- package/browser/src/limits.ts +271 -0
- package/browser/src/manager.ts +730 -0
- package/browser/src/network.ts +263 -0
- package/browser/src/observe.ts +178 -0
- package/browser/src/policy.ts +133 -0
- package/browser/src/screenshot.ts +107 -0
- package/browser/src/shared-sandbox.ts +53 -0
- package/browser/src/snapshot.ts +99 -0
- package/browser/src/targets.ts +165 -0
- package/browser/src/tools.ts +480 -0
- package/browser/src/types.ts +316 -0
- package/browser/src/uploads.ts +174 -0
- package/coding/README.md +337 -0
- package/coding/src/agent/acp-operations.ts +146 -0
- package/coding/src/agent/artifacts.ts +38 -0
- package/coding/src/agent/ask-user-decision.ts +623 -0
- package/coding/src/agent/atomic-write.ts +23 -0
- package/coding/src/agent/bounded-file.ts +21 -0
- package/coding/src/agent/checks.ts +301 -0
- package/coding/src/agent/coding-checkpoint.ts +828 -0
- package/coding/src/agent/delete.ts +237 -0
- package/coding/src/agent/diagnostics-tool.ts +163 -0
- package/coding/src/agent/diagnostics.ts +262 -0
- package/coding/src/agent/edit-diff.ts +382 -0
- package/coding/src/agent/edit.ts +322 -0
- package/coding/src/agent/effects.ts +102 -0
- package/coding/src/agent/env.ts +28 -0
- package/coding/src/agent/execution-policy.ts +89 -0
- package/coding/src/agent/file-mutation-queue.ts +72 -0
- package/coding/src/agent/forge/github.ts +603 -0
- package/coding/src/agent/forge/index.ts +16 -0
- package/coding/src/agent/forge/types.ts +185 -0
- package/coding/src/agent/git-aware-repository.ts +305 -0
- package/coding/src/agent/git-exec.ts +326 -0
- package/coding/src/agent/git-status.ts +177 -0
- package/coding/src/agent/git-tools.ts +360 -0
- package/coding/src/agent/git.ts +1074 -0
- package/coding/src/agent/glob-match.ts +146 -0
- package/coding/src/agent/glob.ts +182 -0
- package/coding/src/agent/goal-verify.ts +385 -0
- package/coding/src/agent/grep-worker.ts +74 -0
- package/coding/src/agent/grep.ts +459 -0
- package/coding/src/agent/identity.ts +48 -0
- package/coding/src/agent/index.ts +676 -0
- package/coding/src/agent/language/client.ts +429 -0
- package/coding/src/agent/language/framing.ts +190 -0
- package/coding/src/agent/language/index.ts +23 -0
- package/coding/src/agent/language/intelligence.ts +682 -0
- package/coding/src/agent/language/types.ts +187 -0
- package/coding/src/agent/lifecycle-events.ts +121 -0
- package/coding/src/agent/lifecycle.ts +166 -0
- package/coding/src/agent/limits.ts +214 -0
- package/coding/src/agent/move.ts +178 -0
- package/coding/src/agent/mutation-path.ts +52 -0
- package/coding/src/agent/output-accumulator.ts +304 -0
- package/coding/src/agent/path-utils.ts +120 -0
- package/coding/src/agent/process/index.ts +58 -0
- package/coding/src/agent/process/recovery.ts +508 -0
- package/coding/src/agent/process/sessions-host.ts +222 -0
- package/coding/src/agent/process/sessions-monitor.ts +141 -0
- package/coding/src/agent/process/sessions-recovery.ts +241 -0
- package/coding/src/agent/process/sessions-spawn.ts +613 -0
- package/coding/src/agent/process/sessions-teardown.ts +281 -0
- package/coding/src/agent/process/sessions.ts +30 -0
- package/coding/src/agent/process/types.ts +358 -0
- package/coding/src/agent/read-path-set.ts +126 -0
- package/coding/src/agent/read.ts +713 -0
- package/coding/src/agent/repository/glob.ts +147 -0
- package/coding/src/agent/repository/indexed-search.ts +480 -0
- package/coding/src/agent/repository/list.ts +131 -0
- package/coding/src/agent/repository/operations.ts +22 -0
- package/coding/src/agent/repository/path.ts +98 -0
- package/coding/src/agent/repository/search.ts +277 -0
- package/coding/src/agent/repository/types.ts +243 -0
- package/coding/src/agent/repository/walk.ts +126 -0
- package/coding/src/agent/repository.ts +12 -0
- package/coding/src/agent/shell-background.ts +264 -0
- package/coding/src/agent/shell-output.ts +75 -0
- package/coding/src/agent/shell.ts +526 -0
- package/coding/src/agent/todo.ts +399 -0
- package/coding/src/agent/truncate.ts +251 -0
- package/coding/src/agent/write.ts +170 -0
- package/coding/src/ask-user-host.ts +48 -0
- package/coding/src/config.ts +278 -0
- package/coding/src/hard-deny.ts +97 -0
- package/coding/src/index.ts +318 -0
- package/coding/src/principal-guard.ts +84 -0
- package/coding/src/sandbox.ts +92 -0
- package/coding/src/security/approval.ts +144 -0
- package/coding/src/security/command-rules.ts +57 -0
- package/coding/src/security/docker-cli.ts +222 -0
- package/coding/src/security/docker-sandbox.ts +1205 -0
- package/coding/src/security/e2b-sandbox.ts +853 -0
- package/coding/src/security/egress/dns-pin.ts +88 -0
- package/coding/src/security/egress/index.ts +32 -0
- package/coding/src/security/egress/limits.ts +57 -0
- package/coding/src/security/egress/policy.ts +137 -0
- package/coding/src/security/egress/proxy.ts +599 -0
- package/coding/src/security/egress/types.ts +30 -0
- package/coding/src/security/index.ts +199 -0
- package/coding/src/security/native-sandbox.ts +639 -0
- package/coding/src/security/path-containment.ts +55 -0
- package/coding/src/security/sandbox-coding-operations.ts +392 -0
- package/coding/src/security/sandbox-fs-operations.ts +644 -0
- package/coding/src/security/sandbox-limits.ts +147 -0
- package/coding/src/security/sandbox-tar.ts +308 -0
- package/coding/src/security/sandbox.ts +179 -0
- package/coding/src/security/semaphore.ts +55 -0
- package/coding/src/targets.ts +110 -0
- package/coding/src/workspace/diff.ts +78 -0
- package/coding/src/workspace/errors.ts +28 -0
- package/coding/src/workspace/index.ts +5 -0
- package/coding/src/workspace/merge.ts +151 -0
- package/coding/src/workspace/routing.ts +76 -0
- package/coding/src/workspace/service.ts +545 -0
- package/computer-use/README.md +105 -0
- package/computer-use/skills/computer-use-linux/SKILL.md +17 -0
- package/computer-use/src/classify.ts +53 -0
- package/computer-use/src/command.ts +29 -0
- package/computer-use/src/config.ts +69 -0
- package/computer-use/src/create.ts +170 -0
- package/computer-use/src/devices.ts +247 -0
- package/computer-use/src/env.ts +28 -0
- package/computer-use/src/index.ts +157 -0
- package/computer-use/src/skill.ts +21 -0
- package/openapi/README.md +97 -0
- package/openapi/src/compile.ts +386 -0
- package/openapi/src/config.ts +73 -0
- package/openapi/src/errors.ts +16 -0
- package/openapi/src/execute.ts +241 -0
- package/openapi/src/index.ts +124 -0
- package/openapi/src/limits.ts +63 -0
- package/openapi/src/specs.ts +86 -0
- package/openapi/src/tools.ts +60 -0
- package/openapi/src/types.ts +61 -0
- package/package.json +171 -4
- package/research/README.md +72 -0
- package/research/skills/research-report/SKILL.md +12 -0
- package/research/skills/research-scoping/SKILL.md +10 -0
- package/research/skills/research-synthesis/SKILL.md +10 -0
- package/research/skills/source-triage/SKILL.md +10 -0
- package/research/src/check.ts +71 -0
- package/research/src/config.ts +41 -0
- package/research/src/index.ts +147 -0
- package/research/src/ledger.ts +157 -0
- package/research/src/urls.ts +21 -0
- package/web/README.md +287 -0
- package/web/skills/web-research/SKILL.md +17 -0
- package/web/src/brave.ts +66 -0
- package/web/src/cache.ts +151 -0
- package/web/src/config.ts +210 -0
- package/web/src/controls.ts +128 -0
- package/web/src/domains.ts +114 -0
- package/web/src/exa.ts +60 -0
- package/web/src/firecrawl.ts +160 -0
- package/web/src/index.ts +387 -0
- package/web/src/kagi.ts +73 -0
- package/web/src/limits.ts +55 -0
- package/web/src/native/convert.ts +84 -0
- package/web/src/native/fetch.ts +226 -0
- package/web/src/normalize.ts +131 -0
- package/web/src/obscura/cdp.ts +201 -0
- package/web/src/obscura/classify.ts +35 -0
- package/web/src/obscura/cli.ts +254 -0
- package/web/src/obscura/errors.ts +8 -0
- package/web/src/obscura/index.ts +59 -0
- package/web/src/obscura/limits.ts +92 -0
- package/web/src/obscura/mcp.ts +104 -0
- package/web/src/obscura/playwright.ts +133 -0
- package/web/src/obscura/process.ts +235 -0
- package/web/src/obscura/search-profile.ts +73 -0
- package/web/src/obscura/types.ts +48 -0
- package/web/src/obscura/web.ts +419 -0
- package/web/src/prompt-fetch.ts +88 -0
- package/web/src/render.ts +75 -0
- package/web/src/searxng.ts +78 -0
- package/web/src/slice.ts +139 -0
- package/web/src/tavily.ts +77 -0
- package/web/src/tools.ts +182 -0
- package/web/src/transport.ts +310 -0
- package/web/src/types.ts +199 -0
- package/work/README.md +77 -0
- package/work/THIRD_PARTY_NOTICES +24 -0
- package/work/docling/ocr.py +150 -0
- package/work/sandbox/Dockerfile +36 -0
- package/work/sandbox/soffice.sh +12 -0
- package/work/src/command.ts +29 -0
- package/work/src/config.ts +138 -0
- package/work/src/connectors/cli.ts +343 -0
- package/work/src/connectors/drafts.ts +647 -0
- package/work/src/connectors/errors.ts +8 -0
- package/work/src/connectors/file-bytes.ts +149 -0
- package/work/src/connectors/google-workspace-http.ts +399 -0
- package/work/src/connectors/google-workspace.ts +465 -0
- package/work/src/connectors/gws-tools.ts +378 -0
- package/work/src/connectors/http.ts +123 -0
- package/work/src/connectors/idempotency.ts +235 -0
- package/work/src/connectors/identity.ts +34 -0
- package/work/src/connectors/index.ts +93 -0
- package/work/src/connectors/limits.ts +50 -0
- package/work/src/connectors/m365-tools.ts +308 -0
- package/work/src/connectors/microsoft365-http.ts +428 -0
- package/work/src/connectors/microsoft365.ts +402 -0
- package/work/src/connectors/normalize.ts +120 -0
- package/work/src/connectors/tool-helpers.ts +398 -0
- package/work/src/connectors/tools.ts +42 -0
- package/work/src/connectors/types.ts +399 -0
- package/work/src/diagrams/canonicalize.ts +166 -0
- package/work/src/diagrams/caps.ts +52 -0
- package/work/src/diagrams/embed.ts +340 -0
- package/work/src/diagrams/errors.ts +76 -0
- package/work/src/diagrams/index.ts +81 -0
- package/work/src/diagrams/messages.ts +150 -0
- package/work/src/diagrams/origin.ts +52 -0
- package/work/src/diagrams/telemetry.ts +34 -0
- package/work/src/diagrams/xml.ts +267 -0
- package/work/src/document-extraction/index.ts +563 -0
- package/work/src/document-reader/ambient.d.ts +2 -0
- package/work/src/document-reader/errors.ts +7 -0
- package/work/src/document-reader/index.ts +181 -0
- package/work/src/document-reader/mistral-ocr.ts +318 -0
- package/work/src/document-reader/parsers.ts +171 -0
- package/work/src/documents/caps.ts +135 -0
- package/work/src/documents/diff.ts +269 -0
- package/work/src/documents/errors.ts +44 -0
- package/work/src/documents/fidelity.ts +98 -0
- package/work/src/documents/generate.ts +96 -0
- package/work/src/documents/hash.ts +8 -0
- package/work/src/documents/index.ts +14 -0
- package/work/src/documents/model-schema.ts +639 -0
- package/work/src/documents/parse.ts +252 -0
- package/work/src/documents/patch-history.ts +81 -0
- package/work/src/documents/patch.ts +476 -0
- package/work/src/documents/preview-html.ts +245 -0
- package/work/src/documents/preview.ts +227 -0
- package/work/src/documents/telemetry.ts +36 -0
- package/work/src/documents/translate/docx.ts +292 -0
- package/work/src/documents/translate/pptx.ts +304 -0
- package/work/src/documents/translate/xlsx.ts +137 -0
- package/work/src/documents/types.ts +188 -0
- package/work/src/index.ts +311 -0
- package/work/src/runtime/worker-pool-entry.ts +102 -0
- package/work/src/runtime/worker-pool.ts +267 -0
- package/work/src/sandbox/composition.ts +212 -0
- package/work/src/sandbox/image.ts +6 -0
- package/work/src/sandbox/index.ts +14 -0
- package/work/src/sheets/caps.ts +68 -0
- package/work/src/sheets/csv.ts +351 -0
- package/work/src/sheets/decimal.ts +388 -0
- package/work/src/sheets/errors.ts +52 -0
- package/work/src/sheets/index.ts +62 -0
- package/work/src/sheets/inference.ts +378 -0
- package/work/src/sheets/telemetry.ts +34 -0
- package/work/src/sheets/types.ts +162 -0
- package/work/src/sheets/xlsx.ts +388 -0
- package/work/src/skills/index.ts +8 -0
- package/work/src/skills/load.ts +43 -0
- package/work/src/tools/filesystem.ts +21 -0
- package/work/src/tools/index.ts +1 -0
- package/work/src/tools/local-filesystem.ts +33 -0
- package/work/src/tools/office.ts +311 -0
- package/work/vendor/hermes-agent/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/SKILL.md +196 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_comments.py +289 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_common.py +94 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_create.py +177 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_edit.py +250 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_read.py +149 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_revisions.py +147 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_template.py +70 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_validate.py +156 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/SKILL.md +125 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/_raster.py +76 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_marker.py +88 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_pymupdf.py +101 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_create.py +130 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_fill_form.py +97 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_form_layout.py +168 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_make_form.py +145 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_merge.py +50 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_meta.py +115 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_page_image.py +99 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_read.py +153 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_secure.py +71 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_split.py +84 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_stamp.py +143 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_watermark.py +51 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/SKILL.md +220 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_create.py +214 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_edit.py +436 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_from_template.py +88 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_read.py +131 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_render.py +93 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/SKILL.md +196 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/csv_to_xlsx.py +104 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_create.py +259 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_edit.py +263 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_read.py +160 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_recalc.py +111 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_restructure.py +337 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_to_csv.py +69 -0
- package/work/vendor-lock.json +11 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import type { DocumentsTelemetry } from "./telemetry.js";
|
|
2
|
+
import type { CellValue, DeckModel, DocBlock, DocModel, DocRun, DocumentModel, ListItem, SheetModel, SlideData } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export interface PreviewHtmlOptions {
|
|
5
|
+
/** Maximum output size in UTF-8 bytes (default 512 KiB). Excess content is truncated cleanly. */
|
|
6
|
+
readonly maxHtmlBytes?: number;
|
|
7
|
+
/** Optional telemetry seam hook. */
|
|
8
|
+
readonly telemetry?: DocumentsTelemetry;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const DEFAULT_MAX_HTML_BYTES = 512 * 1024; // 512 KiB
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Escapes characters with special meaning in HTML text and attribute values,
|
|
15
|
+
* and neutralizes active/external URL protocols (javascript:, http://, https://).
|
|
16
|
+
*/
|
|
17
|
+
export function escapeHtml(input: string): string {
|
|
18
|
+
return input
|
|
19
|
+
.replace(/&/g, "&")
|
|
20
|
+
.replace(/</g, "<")
|
|
21
|
+
.replace(/>/g, ">")
|
|
22
|
+
.replace(/"/g, """)
|
|
23
|
+
.replace(/'/g, "'")
|
|
24
|
+
.replace(/javascript\s*:/gi, "blocked-script:")
|
|
25
|
+
.replace(/https?:\/\//gi, "");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function renderRunHtml(run: DocRun): string {
|
|
29
|
+
let content = escapeHtml(run.text);
|
|
30
|
+
if (run.code) content = `<code>${content}</code>`;
|
|
31
|
+
if (run.strikethrough) content = `<s>${content}</s>`;
|
|
32
|
+
if (run.underline) content = `<u>${content}</u>`;
|
|
33
|
+
if (run.italic) content = `<em>${content}</em>`;
|
|
34
|
+
if (run.bold) content = `<strong>${content}</strong>`;
|
|
35
|
+
if (run.link) {
|
|
36
|
+
// Sanitize-by-construction: link targets are escaped as inert text, never rendered as live clickable href attributes
|
|
37
|
+
content = `${content} <span class="prism-link-text">(${escapeHtml(run.link)})</span>`;
|
|
38
|
+
}
|
|
39
|
+
return content;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function renderDocBlockHtml(block: DocBlock): string {
|
|
43
|
+
switch (block.type) {
|
|
44
|
+
case "heading": {
|
|
45
|
+
const tag = `h${block.level}`;
|
|
46
|
+
const idAttr = block.id ? ` id="${escapeHtml(block.id)}"` : "";
|
|
47
|
+
return `<${tag} class="prism-heading prism-heading-${block.level}"${idAttr}>${escapeHtml(block.text)}</${tag}>`;
|
|
48
|
+
}
|
|
49
|
+
case "paragraph": {
|
|
50
|
+
let body = "";
|
|
51
|
+
if (block.runs && block.runs.length > 0) {
|
|
52
|
+
body = block.runs.map(renderRunHtml).join("");
|
|
53
|
+
} else if (block.text !== undefined) {
|
|
54
|
+
body = escapeHtml(block.text);
|
|
55
|
+
}
|
|
56
|
+
return `<p class="prism-paragraph">${body}</p>`;
|
|
57
|
+
}
|
|
58
|
+
case "list": {
|
|
59
|
+
const tag = block.ordered ? "ol" : "ul";
|
|
60
|
+
const cls = block.ordered ? "prism-list prism-list-ordered" : "prism-list prism-list-unordered";
|
|
61
|
+
const items = block.items
|
|
62
|
+
.map((item) => {
|
|
63
|
+
if (typeof item === "string") {
|
|
64
|
+
return `<li>${escapeHtml(item)}</li>`;
|
|
65
|
+
}
|
|
66
|
+
const li = item as ListItem;
|
|
67
|
+
const body = li.runs && li.runs.length > 0 ? li.runs.map(renderRunHtml).join("") : escapeHtml(li.text);
|
|
68
|
+
return `<li>${body}</li>`;
|
|
69
|
+
})
|
|
70
|
+
.join("");
|
|
71
|
+
return `<${tag} class="${cls}">${items}</${tag}>`;
|
|
72
|
+
}
|
|
73
|
+
case "table": {
|
|
74
|
+
let tableHtml = '<table class="prism-table">';
|
|
75
|
+
if (block.headers && block.headers.length > 0) {
|
|
76
|
+
tableHtml += "<thead><tr>";
|
|
77
|
+
for (const h of block.headers) {
|
|
78
|
+
tableHtml += `<th>${escapeHtml(h)}</th>`;
|
|
79
|
+
}
|
|
80
|
+
tableHtml += "</tr></thead>";
|
|
81
|
+
}
|
|
82
|
+
tableHtml += "<tbody>";
|
|
83
|
+
for (const row of block.cells) {
|
|
84
|
+
tableHtml += "<tr>";
|
|
85
|
+
for (const cell of row) {
|
|
86
|
+
tableHtml += `<td>${renderCellHtml(cell)}</td>`;
|
|
87
|
+
}
|
|
88
|
+
tableHtml += "</tr>";
|
|
89
|
+
}
|
|
90
|
+
tableHtml += "</tbody></table>";
|
|
91
|
+
return tableHtml;
|
|
92
|
+
}
|
|
93
|
+
case "page-break":
|
|
94
|
+
return '<hr class="prism-page-break" />';
|
|
95
|
+
case "image": {
|
|
96
|
+
const alt = block.alt ? escapeHtml(block.alt) : "Embedded Image";
|
|
97
|
+
return `<div class="prism-image-placeholder"><span class="prism-image-alt">[Image: ${alt}]</span></div>`;
|
|
98
|
+
}
|
|
99
|
+
case "chart": {
|
|
100
|
+
const title = block.title ? ` - ${escapeHtml(block.title)}` : "";
|
|
101
|
+
return `<div class="prism-chart-placeholder"><strong class="prism-chart-title">[Chart: ${escapeHtml(block.chartType)}${title}]</strong></div>`;
|
|
102
|
+
}
|
|
103
|
+
default:
|
|
104
|
+
return "";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function renderCellHtml(cell: CellValue): string {
|
|
109
|
+
if (cell === null || cell === undefined) return "";
|
|
110
|
+
if (typeof cell === "string") return escapeHtml(cell);
|
|
111
|
+
if (typeof cell === "number" || typeof cell === "boolean") return String(cell);
|
|
112
|
+
if ("type" in cell) {
|
|
113
|
+
if (cell.type === "decimal" || cell.type === "date" || cell.type === "datetime") {
|
|
114
|
+
return escapeHtml(cell.value);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if ("formula" in cell) {
|
|
118
|
+
const cached = cell.cachedValue !== undefined && cell.cachedValue !== null ? ` = ${escapeHtml(String(cell.cachedValue))}` : "";
|
|
119
|
+
return `<code>${escapeHtml(cell.formula)}${cached}</code>`;
|
|
120
|
+
}
|
|
121
|
+
return "";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function renderDocHtml(doc: DocModel): string {
|
|
125
|
+
let html = '<article class="prism-preview prism-doc-preview">';
|
|
126
|
+
if (doc.title) {
|
|
127
|
+
html += `<h1 class="prism-doc-title">${escapeHtml(doc.title)}</h1>`;
|
|
128
|
+
}
|
|
129
|
+
for (const block of doc.blocks) {
|
|
130
|
+
html += renderDocBlockHtml(block);
|
|
131
|
+
}
|
|
132
|
+
html += "</article>";
|
|
133
|
+
return html;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function renderSheetHtml(model: SheetModel): string {
|
|
137
|
+
let html = '<div class="prism-preview prism-sheet-preview">';
|
|
138
|
+
if (model.title) {
|
|
139
|
+
html += `<h1 class="prism-sheet-title">${escapeHtml(model.title)}</h1>`;
|
|
140
|
+
}
|
|
141
|
+
for (const sheet of model.sheets) {
|
|
142
|
+
html += `<section class="prism-worksheet"><h2 class="prism-worksheet-name">${escapeHtml(sheet.name)}</h2>`;
|
|
143
|
+
html += '<table class="prism-table"><tbody>';
|
|
144
|
+
for (const row of sheet.cells) {
|
|
145
|
+
html += "<tr>";
|
|
146
|
+
for (const cell of row) {
|
|
147
|
+
html += `<td>${renderCellHtml(cell)}</td>`;
|
|
148
|
+
}
|
|
149
|
+
html += "</tr>";
|
|
150
|
+
}
|
|
151
|
+
html += "</tbody></table></section>";
|
|
152
|
+
}
|
|
153
|
+
html += "</div>";
|
|
154
|
+
return html;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function renderSlideHtml(slide: SlideData, index: number): string {
|
|
158
|
+
let html = `<section class="prism-slide prism-slide-${escapeHtml(slide.layout)}" data-slide-index="${index}">`;
|
|
159
|
+
if (slide.title) {
|
|
160
|
+
html += `<h2 class="prism-slide-title">${escapeHtml(slide.title)}</h2>`;
|
|
161
|
+
}
|
|
162
|
+
if (slide.subtitle) {
|
|
163
|
+
html += `<p class="prism-slide-subtitle">${escapeHtml(slide.subtitle)}</p>`;
|
|
164
|
+
}
|
|
165
|
+
if (slide.bullets && slide.bullets.length > 0) {
|
|
166
|
+
html += '<ul class="prism-slide-bullets">';
|
|
167
|
+
for (const bullet of slide.bullets) {
|
|
168
|
+
if (typeof bullet === "string") {
|
|
169
|
+
html += `<li>${escapeHtml(bullet)}</li>`;
|
|
170
|
+
} else {
|
|
171
|
+
const li = bullet as ListItem;
|
|
172
|
+
const body = li.runs && li.runs.length > 0 ? li.runs.map(renderRunHtml).join("") : escapeHtml(li.text);
|
|
173
|
+
html += `<li>${body}</li>`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
html += "</ul>";
|
|
177
|
+
}
|
|
178
|
+
if (slide.notes) {
|
|
179
|
+
html += `<aside class="prism-slide-notes"><small>${escapeHtml(slide.notes)}</small></aside>`;
|
|
180
|
+
}
|
|
181
|
+
html += "</section>";
|
|
182
|
+
return html;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function renderDeckHtml(deck: DeckModel): string {
|
|
186
|
+
let html = '<div class="prism-preview prism-deck-preview">';
|
|
187
|
+
if (deck.title) {
|
|
188
|
+
html += `<h1 class="prism-deck-title">${escapeHtml(deck.title)}</h1>`;
|
|
189
|
+
}
|
|
190
|
+
for (let i = 0; i < deck.slides.length; i += 1) {
|
|
191
|
+
html += renderSlideHtml(deck.slides[i], i);
|
|
192
|
+
}
|
|
193
|
+
html += "</div>";
|
|
194
|
+
return html;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Renders a Prism Document Model into safe, bounded, framework-neutral HTML.
|
|
199
|
+
*
|
|
200
|
+
* Guaranteed by construction to contain:
|
|
201
|
+
* - No `<script>` tags
|
|
202
|
+
* - No `javascript:` or external URL protocols (`http://`, `https://`)
|
|
203
|
+
* - No active iframes or live link anchors
|
|
204
|
+
* - All text values entity-escaped
|
|
205
|
+
* - Output capped at `maxHtmlBytes` budget
|
|
206
|
+
*/
|
|
207
|
+
export function renderPreviewHtml(model: DocumentModel, options?: PreviewHtmlOptions): string {
|
|
208
|
+
const maxBytes = options?.maxHtmlBytes ?? DEFAULT_MAX_HTML_BYTES;
|
|
209
|
+
const span = options?.telemetry?.startSpan("documents.preview", {
|
|
210
|
+
"documents.kind": model?.kind ?? "unknown",
|
|
211
|
+
"documents.preview_type": "html",
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
let rawHtml: string;
|
|
216
|
+
switch (model.kind) {
|
|
217
|
+
case "doc":
|
|
218
|
+
rawHtml = renderDocHtml(model as DocModel);
|
|
219
|
+
break;
|
|
220
|
+
case "sheet":
|
|
221
|
+
rawHtml = renderSheetHtml(model as SheetModel);
|
|
222
|
+
break;
|
|
223
|
+
case "deck":
|
|
224
|
+
rawHtml = renderDeckHtml(model as DeckModel);
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
rawHtml = "";
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const encodedBytes = new TextEncoder().encode(rawHtml);
|
|
231
|
+
if (encodedBytes.byteLength <= maxBytes) {
|
|
232
|
+
return rawHtml;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Budget exceeded: truncate and append terminal note
|
|
236
|
+
const truncatedSlice = encodedBytes.subarray(0, Math.max(0, maxBytes - 128));
|
|
237
|
+
const decoded = new TextDecoder("utf-8", { fatal: false }).decode(truncatedSlice);
|
|
238
|
+
return `${decoded}<div class="prism-preview-truncated">[Preview truncated: byte budget exceeded]</div>`;
|
|
239
|
+
} catch (err) {
|
|
240
|
+
span?.recordError();
|
|
241
|
+
throw err;
|
|
242
|
+
} finally {
|
|
243
|
+
span?.end();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import type { DocumentsTelemetry } from "./telemetry.js";
|
|
2
|
+
import type { CellValue, DeckModel, DocBlock, DocModel, DocumentModel, HeadingBlock, SheetData, SheetModel, SlideData } from "./types.js";
|
|
3
|
+
|
|
4
|
+
// --- Preview Block Definitions ---
|
|
5
|
+
|
|
6
|
+
export interface DocOutlineHeading {
|
|
7
|
+
readonly level: number;
|
|
8
|
+
readonly text: string;
|
|
9
|
+
readonly id?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DocOutlinePreviewBlock {
|
|
13
|
+
readonly type: "doc-outline";
|
|
14
|
+
readonly title?: string;
|
|
15
|
+
readonly headings: readonly DocOutlineHeading[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DocBlocksPreviewBlock {
|
|
19
|
+
readonly type: "doc-blocks";
|
|
20
|
+
readonly title?: string;
|
|
21
|
+
readonly blocks: readonly DocBlock[];
|
|
22
|
+
readonly totalBlocks: number;
|
|
23
|
+
readonly bounds: {
|
|
24
|
+
readonly fromIndex: number;
|
|
25
|
+
readonly toIndex: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SheetGridPreviewBlock {
|
|
30
|
+
readonly type: "sheet-grid";
|
|
31
|
+
readonly sheetIndex: number;
|
|
32
|
+
readonly name: string;
|
|
33
|
+
readonly rows: readonly (readonly CellValue[])[];
|
|
34
|
+
readonly totalRows: number;
|
|
35
|
+
readonly totalColumns: number;
|
|
36
|
+
readonly bounds: {
|
|
37
|
+
readonly fromRow: number;
|
|
38
|
+
readonly toRow: number;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface DeckSlideListPreviewBlock {
|
|
43
|
+
readonly type: "deck-slides";
|
|
44
|
+
readonly title?: string;
|
|
45
|
+
readonly slides: readonly SlideData[];
|
|
46
|
+
readonly totalSlides: number;
|
|
47
|
+
readonly bounds: {
|
|
48
|
+
readonly fromIndex: number;
|
|
49
|
+
readonly toIndex: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface TruncationNotePreviewBlock {
|
|
54
|
+
readonly type: "truncation-note";
|
|
55
|
+
readonly message: string;
|
|
56
|
+
readonly droppedItems: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type PreviewBlock =
|
|
60
|
+
| DocOutlinePreviewBlock
|
|
61
|
+
| DocBlocksPreviewBlock
|
|
62
|
+
| SheetGridPreviewBlock
|
|
63
|
+
| DeckSlideListPreviewBlock
|
|
64
|
+
| TruncationNotePreviewBlock;
|
|
65
|
+
|
|
66
|
+
export interface PreviewBlocksOptions {
|
|
67
|
+
/** Maximum rows per sheet-grid snapshot block (default: 200). */
|
|
68
|
+
readonly maxRowsPerBlock?: number;
|
|
69
|
+
/** Maximum total rows previewed per sheet across all grid blocks (default: 1,000). */
|
|
70
|
+
readonly maxTotalRowsPerSheet?: number;
|
|
71
|
+
/** Maximum blocks per document preview chunk (default: 200). */
|
|
72
|
+
readonly maxBlocksPerChunk?: number;
|
|
73
|
+
/** Maximum slides previewed (default: 100). */
|
|
74
|
+
readonly maxSlides?: number;
|
|
75
|
+
/** Optional telemetry seam hook. */
|
|
76
|
+
readonly telemetry?: DocumentsTelemetry;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const DEFAULT_MAX_ROWS_PER_BLOCK = 200;
|
|
80
|
+
const DEFAULT_MAX_TOTAL_ROWS_PER_SHEET = 1_000;
|
|
81
|
+
const DEFAULT_MAX_BLOCKS_PER_CHUNK = 200;
|
|
82
|
+
const DEFAULT_MAX_SLIDES = 100;
|
|
83
|
+
|
|
84
|
+
function renderDocPreviewBlocks(doc: DocModel, options?: PreviewBlocksOptions): PreviewBlock[] {
|
|
85
|
+
const blocks: PreviewBlock[] = [];
|
|
86
|
+
const maxBlocksPerChunk = options?.maxBlocksPerChunk ?? DEFAULT_MAX_BLOCKS_PER_CHUNK;
|
|
87
|
+
|
|
88
|
+
// 1. Extract outline
|
|
89
|
+
const headings: DocOutlineHeading[] = [];
|
|
90
|
+
for (const block of doc.blocks) {
|
|
91
|
+
if (block.type === "heading") {
|
|
92
|
+
const h = block as HeadingBlock;
|
|
93
|
+
headings.push({
|
|
94
|
+
level: h.level,
|
|
95
|
+
text: h.text,
|
|
96
|
+
id: h.id,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
blocks.push({
|
|
102
|
+
type: "doc-outline",
|
|
103
|
+
title: doc.title,
|
|
104
|
+
headings,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// 2. Chunk document blocks into bounded windows
|
|
108
|
+
const total = doc.blocks.length;
|
|
109
|
+
for (let i = 0; i < total; i += maxBlocksPerChunk) {
|
|
110
|
+
const chunk = doc.blocks.slice(i, i + maxBlocksPerChunk);
|
|
111
|
+
blocks.push({
|
|
112
|
+
type: "doc-blocks",
|
|
113
|
+
title: doc.title,
|
|
114
|
+
blocks: chunk,
|
|
115
|
+
totalBlocks: total,
|
|
116
|
+
bounds: {
|
|
117
|
+
fromIndex: i,
|
|
118
|
+
toIndex: i + chunk.length - 1,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return blocks;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function renderSheetPreviewBlocks(model: SheetModel, options?: PreviewBlocksOptions): PreviewBlock[] {
|
|
127
|
+
const blocks: PreviewBlock[] = [];
|
|
128
|
+
const maxRowsPerBlock = options?.maxRowsPerBlock ?? DEFAULT_MAX_ROWS_PER_BLOCK;
|
|
129
|
+
const maxTotalRows = options?.maxTotalRowsPerSheet ?? DEFAULT_MAX_TOTAL_ROWS_PER_SHEET;
|
|
130
|
+
|
|
131
|
+
for (let sheetIdx = 0; sheetIdx < model.sheets.length; sheetIdx += 1) {
|
|
132
|
+
const sheet: SheetData = model.sheets[sheetIdx];
|
|
133
|
+
const totalRows = sheet.cells.length;
|
|
134
|
+
let maxCols = 0;
|
|
135
|
+
for (const r of sheet.cells) {
|
|
136
|
+
if (r.length > maxCols) maxCols = r.length;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const previewableRows = Math.min(totalRows, maxTotalRows);
|
|
140
|
+
|
|
141
|
+
for (let r = 0; r < previewableRows; r += maxRowsPerBlock) {
|
|
142
|
+
const chunk = sheet.cells.slice(r, r + maxRowsPerBlock);
|
|
143
|
+
blocks.push({
|
|
144
|
+
type: "sheet-grid",
|
|
145
|
+
sheetIndex: sheetIdx,
|
|
146
|
+
name: sheet.name,
|
|
147
|
+
rows: chunk,
|
|
148
|
+
totalRows,
|
|
149
|
+
totalColumns: maxCols,
|
|
150
|
+
bounds: {
|
|
151
|
+
fromRow: r,
|
|
152
|
+
toRow: r + chunk.length - 1,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (totalRows > maxTotalRows) {
|
|
158
|
+
const dropped = totalRows - maxTotalRows;
|
|
159
|
+
blocks.push({
|
|
160
|
+
type: "truncation-note",
|
|
161
|
+
message: `Sheet "${sheet.name}" truncated. Showing first ${maxTotalRows} of ${totalRows} rows.`,
|
|
162
|
+
droppedItems: dropped,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return blocks;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function renderDeckPreviewBlocks(deck: DeckModel, options?: PreviewBlocksOptions): PreviewBlock[] {
|
|
171
|
+
const blocks: PreviewBlock[] = [];
|
|
172
|
+
const maxSlides = options?.maxSlides ?? DEFAULT_MAX_SLIDES;
|
|
173
|
+
const total = deck.slides.length;
|
|
174
|
+
const previewSlides = deck.slides.slice(0, maxSlides);
|
|
175
|
+
|
|
176
|
+
blocks.push({
|
|
177
|
+
type: "deck-slides",
|
|
178
|
+
title: deck.title,
|
|
179
|
+
slides: previewSlides,
|
|
180
|
+
totalSlides: total,
|
|
181
|
+
bounds: {
|
|
182
|
+
fromIndex: 0,
|
|
183
|
+
toIndex: previewSlides.length - 1,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (total > maxSlides) {
|
|
188
|
+
const dropped = total - maxSlides;
|
|
189
|
+
blocks.push({
|
|
190
|
+
type: "truncation-note",
|
|
191
|
+
message: `Presentation preview truncated. Showing first ${maxSlides} of ${total} slides.`,
|
|
192
|
+
droppedItems: dropped,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return blocks;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Renders a Prism Document Model into framework-neutral, structured preview blocks.
|
|
201
|
+
*
|
|
202
|
+
* Produces bounded snapshots with configurable row/block pagination for native UI rendering.
|
|
203
|
+
*/
|
|
204
|
+
export function renderPreviewBlocks(model: DocumentModel, options?: PreviewBlocksOptions): PreviewBlock[] {
|
|
205
|
+
const span = options?.telemetry?.startSpan("documents.preview", {
|
|
206
|
+
"documents.kind": model?.kind ?? "unknown",
|
|
207
|
+
"documents.preview_type": "blocks",
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
switch (model.kind) {
|
|
212
|
+
case "doc":
|
|
213
|
+
return renderDocPreviewBlocks(model as DocModel, options);
|
|
214
|
+
case "sheet":
|
|
215
|
+
return renderSheetPreviewBlocks(model as SheetModel, options);
|
|
216
|
+
case "deck":
|
|
217
|
+
return renderDeckPreviewBlocks(model as DeckModel, options);
|
|
218
|
+
default:
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
} catch (err) {
|
|
222
|
+
span?.recordError();
|
|
223
|
+
throw err;
|
|
224
|
+
} finally {
|
|
225
|
+
span?.end();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency-free telemetry seam for Document operations. When `telemetry` is omitted every
|
|
3
|
+
* call site short-circuits on an optional chain — zero allocations, zero per-span work.
|
|
4
|
+
* Implementations own timing/status; the seam only carries structure and allow-listed metadata attributes.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type DocumentsTelemetryAttributeValue = string | number | boolean;
|
|
8
|
+
|
|
9
|
+
export interface DocumentsTelemetrySpan {
|
|
10
|
+
setAttribute(name: string, value: DocumentsTelemetryAttributeValue): void;
|
|
11
|
+
addEvent(name: string, attributes?: Readonly<Record<string, DocumentsTelemetryAttributeValue>>): void;
|
|
12
|
+
/** Flags the span as failed without carrying any error text (no user data leaves the host). */
|
|
13
|
+
recordError(): void;
|
|
14
|
+
end(): void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface DocumentsTelemetry {
|
|
18
|
+
startSpan(
|
|
19
|
+
name: string,
|
|
20
|
+
attributes?: Readonly<Record<string, DocumentsTelemetryAttributeValue>>,
|
|
21
|
+
parent?: DocumentsTelemetrySpan,
|
|
22
|
+
): DocumentsTelemetrySpan;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const noopDocumentsSpan: DocumentsTelemetrySpan = {
|
|
26
|
+
setAttribute() {},
|
|
27
|
+
addEvent() {},
|
|
28
|
+
recordError() {},
|
|
29
|
+
end() {},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const noopDocumentsTelemetry: DocumentsTelemetry = {
|
|
33
|
+
startSpan() {
|
|
34
|
+
return noopDocumentsSpan;
|
|
35
|
+
},
|
|
36
|
+
};
|