@kky42/pievo-server 1.0.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/.output/nitro.json +17 -0
- package/.output/public/assets/CodeField-dOzyFQNH.js +34 -0
- package/.output/public/assets/LoopView-B4H9QibC.js +55 -0
- package/.output/public/assets/Modal-D33gNSgx.js +1 -0
- package/.output/public/assets/SignIn-SHuRRyOv.js +1 -0
- package/.output/public/assets/actionUi-ChGGALzg.js +1 -0
- package/.output/public/assets/app-DElSo_jy.css +2 -0
- package/.output/public/assets/artifactView-DFuubXLJ.js +66 -0
- package/.output/public/assets/index-DfpTWRSz.js +12 -0
- package/.output/public/assets/invite._token-DJtd-XE2.js +1 -0
- package/.output/public/assets/invite._token-T8oo4Qtw.js +1 -0
- package/.output/public/assets/jsx-runtime-BseJUIpC.js +1 -0
- package/.output/public/assets/lifecycleUi-DKkChdnU.js +1 -0
- package/.output/public/assets/loopApi-BM2nj71x.js +3 -0
- package/.output/public/assets/loops._loopId-B19Jw7jC.js +5 -0
- package/.output/public/assets/loops._loopId_.runs._runId-_CflHV38.js +3 -0
- package/.output/public/assets/notifyFns-DCubjpRy.js +1 -0
- package/.output/public/assets/preload-helper-CKUiEq3b.js +3 -0
- package/.output/public/assets/routes-B9tgli5f.js +1 -0
- package/.output/public/assets/routes-CTtlM_qt.js +1 -0
- package/.output/public/assets/t._teamId-Bm21mngW.js +1 -0
- package/.output/public/assets/t._teamId-gR7BVKkR.js +1 -0
- package/.output/public/assets/ui-Dp88qUWh.js +1 -0
- package/.output/public/assets/useRouter-DsjH8G0p.js +1 -0
- package/.output/public/favicon.svg +12 -0
- package/.output/public/fonts/GeistPixel-Square.woff2 +0 -0
- package/.output/server/_chunks/ssr-renderer.mjs +26 -0
- package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +419 -0
- package/.output/server/_libs/@aws-sdk/checksums+[...].mjs +10732 -0
- package/.output/server/_libs/@aws-sdk/client-s3+[...].mjs +9475 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +137 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +440 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +62 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +818 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +59 -0
- package/.output/server/_libs/@base-ui/react+[...].mjs +11125 -0
- package/.output/server/_libs/@codemirror/autocomplete+[...].mjs +19713 -0
- package/.output/server/_libs/@codemirror/lang-css+[...].mjs +2636 -0
- package/.output/server/_libs/@codemirror/lang-html+[...].mjs +2247 -0
- package/.output/server/_libs/@codemirror/lang-json+[...].mjs +79 -0
- package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1736 -0
- package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +342 -0
- package/.output/server/_libs/@tanstack/react-router+[...].mjs +14300 -0
- package/.output/server/_libs/@uiw/codemirror-extensions-basic-setup+[...].mjs +76 -0
- package/.output/server/_libs/atomic-sleep.mjs +27 -0
- package/.output/server/_libs/aws-crypto__crc32c.mjs +314 -0
- package/.output/server/_libs/aws-sdk__nested-clients.mjs +2671 -0
- package/.output/server/_libs/babel__runtime.mjs +30 -0
- package/.output/server/_libs/clsx.mjs +16 -0
- package/.output/server/_libs/codemirror__commands.mjs +1725 -0
- package/.output/server/_libs/codemirror__lint.mjs +565 -0
- package/.output/server/_libs/codemirror__search.mjs +1138 -0
- package/.output/server/_libs/codemirror__theme-one-dark.mjs +161 -0
- package/.output/server/_libs/colorette.mjs +129 -0
- package/.output/server/_libs/croner.mjs +735 -0
- package/.output/server/_libs/d3-array.mjs +231 -0
- package/.output/server/_libs/d3-color.mjs +330 -0
- package/.output/server/_libs/d3-format.mjs +252 -0
- package/.output/server/_libs/d3-interpolate.mjs +163 -0
- package/.output/server/_libs/d3-path.mjs +77 -0
- package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
- package/.output/server/_libs/d3-shape.mjs +689 -0
- package/.output/server/_libs/dateformat.mjs +341 -0
- package/.output/server/_libs/decimal.js-light.mjs +884 -0
- package/.output/server/_libs/diff.mjs +732 -0
- package/.output/server/_libs/dom-serializer+[...].mjs +708 -0
- package/.output/server/_libs/domhandler.mjs +461 -0
- package/.output/server/_libs/dompurify.mjs +2111 -0
- package/.output/server/_libs/domutils.mjs +868 -0
- package/.output/server/_libs/drizzle-orm+postgres.mjs +7689 -0
- package/.output/server/_libs/electric-sql__pglite.mjs +14674 -0
- package/.output/server/_libs/end-of-stream+once+wrappy.mjs +145 -0
- package/.output/server/_libs/es-toolkit.mjs +1737 -0
- package/.output/server/_libs/eventemitter3.mjs +236 -0
- package/.output/server/_libs/fast-copy.mjs +285 -0
- package/.output/server/_libs/fast-safe-stringify.mjs +172 -0
- package/.output/server/_libs/h3+rou3+srvx.mjs +1201 -0
- package/.output/server/_libs/html-dom-parser+htmlparser2.mjs +1560 -0
- package/.output/server/_libs/html-react-parser+[...].mjs +1360 -0
- package/.output/server/_libs/initdb.wasm +0 -0
- package/.output/server/_libs/marked.mjs +1548 -0
- package/.output/server/_libs/on-exit-leak-free.mjs +80 -0
- package/.output/server/_libs/pglite.data +37667 -8
- package/.output/server/_libs/pglite.wasm +0 -0
- package/.output/server/_libs/pino+[...].mjs +3196 -0
- package/.output/server/_libs/pino-abstract-transport+split2.mjs +194 -0
- package/.output/server/_libs/pino-pretty+[...].mjs +1623 -0
- package/.output/server/_libs/pinojs__redact.mjs +280 -0
- package/.output/server/_libs/react-redux+[...].mjs +205 -0
- package/.output/server/_libs/recharts+victory-vendor.mjs +15875 -0
- package/.output/server/_libs/tanstack__history.mjs +342 -0
- package/.output/server/_libs/ufo.mjs +64 -0
- package/.output/server/_libs/uiw__codemirror-themes.mjs +32 -0
- package/.output/server/_libs/uiw__react-codemirror.mjs +354 -0
- package/.output/server/_runtime.mjs +37 -0
- package/.output/server/_ssr/CodeField-tm4rr6G3.mjs +143 -0
- package/.output/server/_ssr/DashboardView-CC7htv28.mjs +2795 -0
- package/.output/server/_ssr/LoopPlaybook-BXH8mhiX.mjs +2105 -0
- package/.output/server/_ssr/LoopView-DCugEbHx.mjs +1106 -0
- package/.output/server/_ssr/Modal-DpKZHLZK.mjs +49 -0
- package/.output/server/_ssr/SignIn-dTndU6Hw.mjs +67 -0
- package/.output/server/_ssr/actionUi-CZbEixbf.mjs +119 -0
- package/.output/server/_ssr/adapters-BS8XosjF.mjs +130 -0
- package/.output/server/_ssr/artifactFiles-Cagtj7J0.mjs +61 -0
- package/.output/server/_ssr/artifactKind-BW0isV8L.mjs +37 -0
- package/.output/server/_ssr/artifactView-DS4O22wl.mjs +304 -0
- package/.output/server/_ssr/artifacts-DngKyW2u.mjs +2 -0
- package/.output/server/_ssr/auth-DY1DuYZd.mjs +38429 -0
- package/.output/server/_ssr/boot-BbtG0ImW.mjs +9010 -0
- package/.output/server/_ssr/boot-CMHTxQpJ.mjs +2 -0
- package/.output/server/_ssr/bun-sqlite-dialect-BW9W1_Ps-CU1Spd6z.mjs +162 -0
- package/.output/server/_ssr/core-RrmWoKne.mjs +5 -0
- package/.output/server/_ssr/createServerRpc-BD8Xn_0_.mjs +12 -0
- package/.output/server/_ssr/d1-sqlite-dialect-BLC8LXE6-DfG7tB8s.mjs +112 -0
- package/.output/server/_ssr/db-DWAuZq1o.mjs +2 -0
- package/.output/server/_ssr/dist-BIxFFVZg.mjs +342 -0
- package/.output/server/_ssr/empty-plugin-adapters-DKUlnwwl.mjs +5 -0
- package/.output/server/_ssr/factory-Blq0DYfT.mjs +6903 -0
- package/.output/server/_ssr/invite._token-BRCo9LGB.mjs +36 -0
- package/.output/server/_ssr/invite._token-DJxGLILJ.mjs +28 -0
- package/.output/server/_ssr/invite._token-NewFt27g.mjs +92 -0
- package/.output/server/_ssr/kysely-adapter-D3XTe64J.mjs +2 -0
- package/.output/server/_ssr/kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs +19 -0
- package/.output/server/_ssr/lifecycleUi-C9lg1r3r.mjs +38 -0
- package/.output/server/_ssr/logger-Dw82jNjH.mjs +2 -0
- package/.output/server/_ssr/loopApi-BtfkZQYK.mjs +532 -0
- package/.output/server/_ssr/loopApi-Cxe8WyOB.mjs +105 -0
- package/.output/server/_ssr/loops._loopId-7NQJPB9W.mjs +30 -0
- package/.output/server/_ssr/loops._loopId-DhnArGdL.mjs +1635 -0
- package/.output/server/_ssr/loops._loopId_.runs._runId-Bvuo2nki.mjs +29 -0
- package/.output/server/_ssr/loops._loopId_.runs._runId-Dip5Xk-q.mjs +674 -0
- package/.output/server/_ssr/machineFns-Dvr5ICUy.mjs +266 -0
- package/.output/server/_ssr/node-sqlite-dialect-DhyOpJTX.mjs +162 -0
- package/.output/server/_ssr/notifyFns-BcMRY5kP.mjs +118 -0
- package/.output/server/_ssr/notifyFns-Q458pZmE.mjs +580 -0
- package/.output/server/_ssr/router-J8KZ30xw.mjs +678 -0
- package/.output/server/_ssr/routes-Bcs4T1ox.mjs +28 -0
- package/.output/server/_ssr/routes-BoGrcf-b.mjs +43 -0
- package/.output/server/_ssr/routes-D4am3Zff.mjs +28 -0
- package/.output/server/_ssr/runDiff-CpEFqo7G.mjs +113 -0
- package/.output/server/_ssr/ssr.mjs +5837 -0
- package/.output/server/_ssr/start-4ifArtKx.mjs +4 -0
- package/.output/server/_ssr/store-b3JcQ08F.mjs +2 -0
- package/.output/server/_ssr/t._teamId-CeUhzgzT.mjs +32 -0
- package/.output/server/_ssr/t._teamId-DR-hQK7o.mjs +47 -0
- package/.output/server/_ssr/t._teamId-Dy_McbRt.mjs +31 -0
- package/.output/server/_ssr/teamCookie-B7hLOIie.mjs +10 -0
- package/.output/server/_ssr/teamFns-BIDnsg2A.mjs +473 -0
- package/.output/server/_ssr/teamFns-DA4ovI5g.mjs +33 -0
- package/.output/server/_ssr/tokens-ytd60FUt.mjs +2 -0
- package/.output/server/_ssr/ui-Dej2qjuS.mjs +267 -0
- package/.output/server/_tanstack-start-manifest_v-CVS6c7re.mjs +95 -0
- package/.output/server/drizzle/0000_round_marauders.sql +193 -0
- package/.output/server/drizzle/0001_naive_silver_fox.sql +25 -0
- package/.output/server/drizzle/0002_funny_sage.sql +12 -0
- package/.output/server/drizzle/0003_optimal_slapstick.sql +102 -0
- package/.output/server/drizzle/0004_remove_grok_agent.sql +5 -0
- package/.output/server/drizzle/0005_heavy_gauntlet.sql +8 -0
- package/.output/server/drizzle/0006_tranquil_sharon_carter.sql +1 -0
- package/.output/server/drizzle/0007_faulty_starbolt.sql +30 -0
- package/.output/server/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
- package/.output/server/drizzle/meta/0000_snapshot.json +1333 -0
- package/.output/server/drizzle/meta/0001_snapshot.json +1498 -0
- package/.output/server/drizzle/meta/0002_snapshot.json +1576 -0
- package/.output/server/drizzle/meta/0003_snapshot.json +1666 -0
- package/.output/server/drizzle/meta/0005_snapshot.json +1666 -0
- package/.output/server/drizzle/meta/0006_snapshot.json +1672 -0
- package/.output/server/drizzle/meta/0007_snapshot.json +1787 -0
- package/.output/server/drizzle/meta/_journal.json +69 -0
- package/.output/server/index.mjs +464 -0
- package/.output/server/node_modules/tslib/modules/index.js +70 -0
- package/.output/server/node_modules/tslib/modules/package.json +3 -0
- package/.output/server/node_modules/tslib/package.json +47 -0
- package/.output/server/node_modules/tslib/tslib.js +484 -0
- package/.output/server/package.json +9 -0
- package/LICENSE +21 -0
- package/drizzle/0000_round_marauders.sql +193 -0
- package/drizzle/0001_naive_silver_fox.sql +25 -0
- package/drizzle/0002_funny_sage.sql +12 -0
- package/drizzle/0003_optimal_slapstick.sql +102 -0
- package/drizzle/0004_remove_grok_agent.sql +5 -0
- package/drizzle/0005_heavy_gauntlet.sql +8 -0
- package/drizzle/0006_tranquil_sharon_carter.sql +1 -0
- package/drizzle/0007_faulty_starbolt.sql +30 -0
- package/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
- package/drizzle/meta/0000_snapshot.json +1333 -0
- package/drizzle/meta/0001_snapshot.json +1498 -0
- package/drizzle/meta/0002_snapshot.json +1576 -0
- package/drizzle/meta/0003_snapshot.json +1666 -0
- package/drizzle/meta/0005_snapshot.json +1666 -0
- package/drizzle/meta/0006_snapshot.json +1672 -0
- package/drizzle/meta/0007_snapshot.json +1787 -0
- package/drizzle/meta/_journal.json +69 -0
- package/package.json +84 -0
- package/scripts/pievo-server.mjs +390 -0
- package/scripts/prestart.mjs +66 -0
- package/scripts/server-cli-lib.mjs +451 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { o as __toESM } from "../_runtime.mjs";
|
|
2
|
+
import { C as require_jsx_runtime, S as require_react } from "../_libs/@base-ui/react+[...].mjs";
|
|
3
|
+
import { s as getArtifact } from "./loopApi-Cxe8WyOB.mjs";
|
|
4
|
+
import { t as artifactKind } from "./artifactKind-BW0isV8L.mjs";
|
|
5
|
+
import { t as purify } from "../_libs/dompurify.mjs";
|
|
6
|
+
import { t as g } from "../_libs/marked.mjs";
|
|
7
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/artifactView-DS4O22wl.js
|
|
8
|
+
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
9
|
+
var import_jsx_runtime = require_jsx_runtime();
|
|
10
|
+
/** Download URL for one artifact - the path is segment-encoded so a nested path
|
|
11
|
+
* (`data/raw.json`) round-trips and can't be mistaken for extra route segments. */
|
|
12
|
+
function downloadHref(loopId, path) {
|
|
13
|
+
const enc = path.split("/").map(encodeURIComponent).join("/");
|
|
14
|
+
return `/api/artifact/${encodeURIComponent(loopId)}/${enc}`;
|
|
15
|
+
}
|
|
16
|
+
/** Inline render URL for an image artifact - the same bytes as `downloadHref`
|
|
17
|
+
* but served with the real image content-type + `inline` disposition (see the
|
|
18
|
+
* route). Used as an <img> src; never for a document the browser navigates to. */
|
|
19
|
+
function inlineHref(loopId, path) {
|
|
20
|
+
return `${downloadHref(loopId, path)}?view=inline`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Shared markdown → sanitized HTML pipeline: marked (GFM) → DOMPurify (an
|
|
24
|
+
* allowlisted prose subset, NO script/handlers). ONE sanitizer config for every
|
|
25
|
+
* markdown surface (including the Files viewer's `TaskFileView`) so the allowlist
|
|
26
|
+
* can't drift between them. Render the output under
|
|
27
|
+
* the `.taskmd` styles.
|
|
28
|
+
*/
|
|
29
|
+
var MD_SANITIZE = {
|
|
30
|
+
ALLOWED_TAGS: [
|
|
31
|
+
"h1",
|
|
32
|
+
"h2",
|
|
33
|
+
"h3",
|
|
34
|
+
"h4",
|
|
35
|
+
"h5",
|
|
36
|
+
"h6",
|
|
37
|
+
"p",
|
|
38
|
+
"br",
|
|
39
|
+
"hr",
|
|
40
|
+
"strong",
|
|
41
|
+
"b",
|
|
42
|
+
"em",
|
|
43
|
+
"i",
|
|
44
|
+
"del",
|
|
45
|
+
"s",
|
|
46
|
+
"code",
|
|
47
|
+
"pre",
|
|
48
|
+
"blockquote",
|
|
49
|
+
"ul",
|
|
50
|
+
"ol",
|
|
51
|
+
"li",
|
|
52
|
+
"a",
|
|
53
|
+
"span",
|
|
54
|
+
"table",
|
|
55
|
+
"thead",
|
|
56
|
+
"tbody",
|
|
57
|
+
"tr",
|
|
58
|
+
"th",
|
|
59
|
+
"td",
|
|
60
|
+
"img"
|
|
61
|
+
],
|
|
62
|
+
ALLOWED_ATTR: [
|
|
63
|
+
"href",
|
|
64
|
+
"title",
|
|
65
|
+
"target",
|
|
66
|
+
"rel",
|
|
67
|
+
"src",
|
|
68
|
+
"alt"
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
/** Markdown string → sanitized HTML string (safe for dangerouslySetInnerHTML). */
|
|
72
|
+
function renderMarkdown(content) {
|
|
73
|
+
return purify.sanitize(g.parse(content, {
|
|
74
|
+
async: false,
|
|
75
|
+
gfm: true
|
|
76
|
+
}), MD_SANITIZE);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Renders markdown (a loop's task file, or any `.md` artifact) as a calm,
|
|
80
|
+
* formatted document instead of a raw mono dump. Pipeline: the shared
|
|
81
|
+
* `renderMarkdown` (marked GFM → DOMPurify allowlist) → `.taskmd` styles.
|
|
82
|
+
* Bare prose only — the host (the unified Files viewer) owns the surface,
|
|
83
|
+
* padding cadence, and scroll.
|
|
84
|
+
*/
|
|
85
|
+
function TaskFileView({ content }) {
|
|
86
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
87
|
+
className: "taskmd px-5 py-4",
|
|
88
|
+
dangerouslySetInnerHTML: { __html: (0, import_react.useMemo)(() => renderMarkdown(content), [content]) }
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Shared pieces of the artifact content viewer - one source for the Files
|
|
93
|
+
* panel's detail pane AND the dashboard artifact primitives (`<loop-embed>`,
|
|
94
|
+
* `<loop-calendar>`'s and `<loop-kanban>`'s detail), so the caption strip, the
|
|
95
|
+
* binary/oversize copy, and the type-appropriate render can't drift between
|
|
96
|
+
* surfaces.
|
|
97
|
+
*
|
|
98
|
+
* Display types (see `lib/artifactKind`):
|
|
99
|
+
* - HTML → a STRICT sandboxed iframe (`sandbox="allow-scripts"`, deliberately
|
|
100
|
+
* NO `allow-same-origin`): user-machine-synced markup renders richly
|
|
101
|
+
* but in an opaque origin, so its scripts can't read the app's
|
|
102
|
+
* cookies/session or reach `parent` - stored-XSS is contained by
|
|
103
|
+
* design. A Preview/Source toggle exposes the raw markup too.
|
|
104
|
+
* - image → an <img> pointed at the hardened inline route (`inlineHref`); the
|
|
105
|
+
* bytes are NEVER inlined into the app DOM (SVG is scriptable, so it
|
|
106
|
+
* rides as an image, which does not execute embedded scripts).
|
|
107
|
+
* - markdown → the shared markdown pipeline (Preview) with a raw Source toggle.
|
|
108
|
+
* - text → monospace source.
|
|
109
|
+
* Everything keeps a Download fallback; an oversize (metadata-only) artifact has
|
|
110
|
+
* no synced bytes to render, so it says so rather than showing an empty pane.
|
|
111
|
+
*/
|
|
112
|
+
var isMarkdown = (path) => artifactKind(path) === "markdown";
|
|
113
|
+
/** A small monospace caption strip above a file's content (path · meta [· action]). */
|
|
114
|
+
function ViewerHead({ path, meta, action }) {
|
|
115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
116
|
+
className: "sticky top-0 z-10 flex flex-wrap items-center gap-x-2 gap-y-1 border-b border-hairline bg-surface px-5 py-2.5",
|
|
117
|
+
children: [
|
|
118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
119
|
+
className: "break-all font-mono text-label text-primary",
|
|
120
|
+
children: path
|
|
121
|
+
}),
|
|
122
|
+
meta && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
123
|
+
className: "font-mono text-caption text-disabled",
|
|
124
|
+
children: ["· ", meta]
|
|
125
|
+
}),
|
|
126
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
127
|
+
className: "ml-auto shrink-0",
|
|
128
|
+
children: action
|
|
129
|
+
})
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/** The binary / oversize body - download affordance or the metadata-only note. */
|
|
134
|
+
function BinaryNotice({ loopId, path, oversize }) {
|
|
135
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
136
|
+
className: "px-5 py-8 text-body text-secondary",
|
|
137
|
+
children: oversize ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
138
|
+
className: "text-disabled",
|
|
139
|
+
children: "Too large to preview - stored as metadata only (no synced bytes)."
|
|
140
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
141
|
+
"Binary file - not previewable.",
|
|
142
|
+
" ",
|
|
143
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
|
|
144
|
+
href: downloadHref(loopId, path),
|
|
145
|
+
download: true,
|
|
146
|
+
className: "text-interactive underline underline-offset-2 transition-colors hover:text-display",
|
|
147
|
+
children: "Download"
|
|
148
|
+
})
|
|
149
|
+
] })
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/** The viewer's action strip: a Preview/Source toggle (renderable types only)
|
|
153
|
+
* plus an always-present Download. Sits just under the content head. */
|
|
154
|
+
function ViewerActions({ loopId, path, mode, onMode, showToggle }) {
|
|
155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
156
|
+
className: "flex items-center gap-2 border-b border-hairline bg-surface px-5 py-1.5",
|
|
157
|
+
children: [showToggle && mode && onMode && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
158
|
+
className: "inline-flex overflow-hidden rounded-control border border-hairline",
|
|
159
|
+
children: ["preview", "source"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
160
|
+
type: "button",
|
|
161
|
+
onClick: () => onMode(m),
|
|
162
|
+
className: `cursor-pointer border-none px-2.5 py-0.5 text-caption font-medium transition-colors ${mode === m ? "bg-raised text-display" : "bg-transparent text-secondary hover:text-display"}`,
|
|
163
|
+
children: m === "preview" ? "Preview" : "Source"
|
|
164
|
+
}, m))
|
|
165
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
|
|
166
|
+
href: downloadHref(loopId, path),
|
|
167
|
+
download: true,
|
|
168
|
+
className: "ml-auto shrink-0 text-caption font-medium text-interactive underline underline-offset-2 transition-colors hover:text-display",
|
|
169
|
+
children: "Download ↓"
|
|
170
|
+
})]
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Rendered HTML in a STRICT sandbox. `sandbox="allow-scripts"` WITHOUT
|
|
175
|
+
* `allow-same-origin` is the load-bearing isolation: the frame gets an opaque
|
|
176
|
+
* origin, so document.cookie is empty, storage is inaccessible, and `parent`
|
|
177
|
+
* access throws a cross-origin SecurityError - synced markup can render (styles
|
|
178
|
+
* + its own scripts run) yet can't touch the app's session or DOM. `srcDoc`
|
|
179
|
+
* keeps the bytes off any navigable app-origin URL. Bounded height with internal
|
|
180
|
+
* scroll; a white backdrop matches what report HTML expects regardless of theme.
|
|
181
|
+
*/
|
|
182
|
+
function HtmlPreview({ html }) {
|
|
183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("iframe", {
|
|
184
|
+
title: "Rendered HTML artifact (sandboxed)",
|
|
185
|
+
srcDoc: html,
|
|
186
|
+
sandbox: "allow-scripts",
|
|
187
|
+
referrerPolicy: "no-referrer",
|
|
188
|
+
className: "h-[min(70vh,620px)] w-full border-0 bg-white"
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/** An image artifact, rendered from the hardened inline route (never inlined
|
|
192
|
+
* into the app DOM). Falls back to a download prompt if the bytes won't load. */
|
|
193
|
+
function ImageView({ loopId, file }) {
|
|
194
|
+
const [failed, setFailed] = (0, import_react.useState)(false);
|
|
195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
196
|
+
className: "min-w-0",
|
|
197
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ViewerActions, {
|
|
198
|
+
loopId,
|
|
199
|
+
path: file.path,
|
|
200
|
+
showToggle: false
|
|
201
|
+
}), failed ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
202
|
+
className: "px-5 py-8 text-body text-secondary",
|
|
203
|
+
children: [
|
|
204
|
+
"Couldn't load this image.",
|
|
205
|
+
" ",
|
|
206
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
|
|
207
|
+
href: downloadHref(loopId, file.path),
|
|
208
|
+
download: true,
|
|
209
|
+
className: "text-interactive underline underline-offset-2 transition-colors hover:text-display",
|
|
210
|
+
children: "Download"
|
|
211
|
+
}),
|
|
212
|
+
" ",
|
|
213
|
+
"instead."
|
|
214
|
+
]
|
|
215
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
216
|
+
className: "flex justify-center overflow-auto px-5 py-6",
|
|
217
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
218
|
+
src: inlineHref(loopId, file.path),
|
|
219
|
+
alt: file.path,
|
|
220
|
+
onError: () => setFailed(true),
|
|
221
|
+
className: "max-w-full rounded-control border border-hairline bg-white object-contain"
|
|
222
|
+
})
|
|
223
|
+
})]
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/** A text-bearing artifact (html / markdown / plain text): fetch the bytes, then
|
|
227
|
+
* render per its kind with a Preview/Source toggle (html + markdown) + download. */
|
|
228
|
+
function TextArtifactView({ loopId, file, kind }) {
|
|
229
|
+
const [loaded, setLoaded] = (0, import_react.useState)({ loading: true });
|
|
230
|
+
const [mode, setMode] = (0, import_react.useState)("preview");
|
|
231
|
+
(0, import_react.useEffect)(() => {
|
|
232
|
+
let alive = true;
|
|
233
|
+
setLoaded({ loading: true });
|
|
234
|
+
getArtifact({ data: {
|
|
235
|
+
loopId,
|
|
236
|
+
path: file.path
|
|
237
|
+
} }).then((c) => alive && setLoaded(c)).catch((e) => alive && setLoaded({ error: String(e) }));
|
|
238
|
+
return () => {
|
|
239
|
+
alive = false;
|
|
240
|
+
};
|
|
241
|
+
}, [
|
|
242
|
+
loopId,
|
|
243
|
+
file.path,
|
|
244
|
+
file.updatedAt
|
|
245
|
+
]);
|
|
246
|
+
if ("loading" in loaded) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
247
|
+
className: "px-5 py-6 text-body text-disabled",
|
|
248
|
+
children: "Loading…"
|
|
249
|
+
});
|
|
250
|
+
if ("binary" in loaded) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BinaryNotice, {
|
|
251
|
+
loopId,
|
|
252
|
+
path: file.path,
|
|
253
|
+
oversize: loaded.oversize
|
|
254
|
+
});
|
|
255
|
+
if ("error" in loaded) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
256
|
+
className: "px-5 py-6 text-body text-accent",
|
|
257
|
+
children: ["Couldn't load this file - ", loaded.error]
|
|
258
|
+
});
|
|
259
|
+
const text = loaded.text || "(empty file)";
|
|
260
|
+
const renderable = kind === "html" || kind === "markdown";
|
|
261
|
+
const showSource = !renderable || mode === "source";
|
|
262
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
263
|
+
className: "min-w-0",
|
|
264
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ViewerActions, {
|
|
265
|
+
loopId,
|
|
266
|
+
path: file.path,
|
|
267
|
+
mode,
|
|
268
|
+
onMode: setMode,
|
|
269
|
+
showToggle: renderable
|
|
270
|
+
}), kind === "html" && !showSource ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HtmlPreview, { html: loaded.text || "" }) : kind === "markdown" && !showSource ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TaskFileView, { content: text }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
|
|
271
|
+
className: "m-0 overflow-x-auto whitespace-pre-wrap px-5 py-4 font-mono text-label leading-relaxed text-secondary",
|
|
272
|
+
children: text
|
|
273
|
+
})]
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* One artifact's content body, dispatched by display kind (see `artifactKind`).
|
|
278
|
+
* Oversize → metadata-only note (no bytes); image → hardened <img>; other binary
|
|
279
|
+
* → download; text-bearing → the fetch-and-render viewer.
|
|
280
|
+
*/
|
|
281
|
+
function ArtifactBody({ loopId, file }) {
|
|
282
|
+
const kind = artifactKind(file.path);
|
|
283
|
+
if (file.oversize) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BinaryNotice, {
|
|
284
|
+
loopId,
|
|
285
|
+
path: file.path,
|
|
286
|
+
oversize: true
|
|
287
|
+
});
|
|
288
|
+
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageView, {
|
|
289
|
+
loopId,
|
|
290
|
+
file
|
|
291
|
+
}, `${file.path}:${file.updatedAt ?? ""}`);
|
|
292
|
+
if (file.binary) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BinaryNotice, {
|
|
293
|
+
loopId,
|
|
294
|
+
path: file.path,
|
|
295
|
+
oversize: false
|
|
296
|
+
});
|
|
297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextArtifactView, {
|
|
298
|
+
loopId,
|
|
299
|
+
file,
|
|
300
|
+
kind
|
|
301
|
+
}, file.path);
|
|
302
|
+
}
|
|
303
|
+
//#endregion
|
|
304
|
+
export { isMarkdown as i, TaskFileView as n, ViewerHead as r, ArtifactBody as t };
|