Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions packages/app-bundle/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -804,11 +804,14 @@
"packages/app/src/components/session/preview-file-helpers.ts": "2244aaef25f7412df7b53a45a7d2f72380d45eb90caefa5e96c48d01e988eb4e",
"packages/app/src/components/session/preview-file-target.test.ts": "d9a341349d8922b0369f3fdf911cce35d96344962ad442267e9078106d266db3",
"packages/app/src/components/session/preview-file-target.ts": "11738d77fc1e86a4a968b65f3fb342f51792b6a2c2d57a08114197ff2e82a51b",
"packages/app/src/components/session/preview-file-view.tsx": "06c26f47cc47f71264c2b60904e91a356b4a63fc1a6c9a7acf971a4d51c9e4a9",
"packages/app/src/components/session/preview-file-view.tsx": "27153914e75d6e596fe56ebe6556653bc589c7f6c31fcdb24e37618814133268",
"packages/app/src/components/session/preview-find-in-sidebar.test.ts": "68cdc2d9743b3c3a6a6c1fab6cbd362d27b4f7179cba973cba67d10f01b35970",
"packages/app/src/components/session/preview-frontmatter-card.tsx": "00f439e3bf482673dfb06c0ce3464c0f51985093ed57b321cdebd38d452f2e5d",
"packages/app/src/components/session/preview-frontmatter.test.ts": "93ec9f7f4c604d8ed8ee6009779c425bffecfca331a122a7a700b588a8ca3c0c",
"packages/app/src/components/session/preview-frontmatter.ts": "036250edd8c2886ee8f8ac0723f2b9a41d363898006a53f47bc44b8194c5a3d3",
"packages/app/src/components/session/preview-html-view.tsx": "ebae43522dbc103fb7033a9aea06a4b04ac5bc0f4a6396d7ef428c2f71c21e99",
"packages/app/src/components/session/preview-html.test.ts": "f3e6a867e039a29dcf218f15be81f05aed7a5b4ccfb4d3575e20fc308544fc60",
"packages/app/src/components/session/preview-html.ts": "2df2bef7acc7c125d0fb795386500dc092e260bc15b65940869e912dedb03f5d",
"packages/app/src/components/session/preview-human-write-gate.ts": "4c4b1cf258a06b0012d722add0125ecb77a0f4e463dd95d193f21e5e73541098",
"packages/app/src/components/session/preview-latex-compile.test.ts": "bfd86b8e7ae2da8060aaabdb167ec8521983777040c7201a7bbb7d7e3c877ac6",
"packages/app/src/components/session/preview-latex-compile.ts": "b9388ca0ba698b023e73d823b6064428937fdacc4ce63f1682018f49387307b8",
Expand Down Expand Up @@ -967,13 +970,13 @@
"packages/session-ui/src/v2/components/editor-core.test.ts": "b2fa5f3a2395862fe59692e346568299acf76ad639d0d1336b09fec9cdaf4694",
"packages/session-ui/src/v2/components/editor-core.ts": "1457c2e2e223f6bbe0a1a5c8c9fd45974ebd86cefc90442ce6df02ae79d5946c",
"packages/session-ui/src/v2/components/file-name-picker.test.tsx": "1ce9741e315b549165d390c74b5885a43580aa70e24de987f9ba8388cd521b41",
"packages/session-ui/src/v2/components/markdown-utils.test.ts": "10e1034293bf385cf50d860bf1667d8370abc61dcee0c5a93295f21f5f55876a",
"packages/session-ui/src/v2/components/markdown-utils.ts": "3bc47cfed5b99ab23f857d5324be3189f3a7e800d991103d72ef1c2f970b910b",
"packages/session-ui/src/v2/components/markdown-utils.test.ts": "0e6540ac2ce2b33f38fa498807be9327764ab7deffdbeb59d2365b298dee85ee",
"packages/session-ui/src/v2/components/markdown-utils.ts": "8e42aaaef7dbb8f3c762de04fd8515c932f89a78e7da2a2d5a58499b136d7347",
"packages/session-ui/src/v2/components/preview-editor-helpers.test.ts": "6e242cabfded1ce2edddfa3c181fb709ce4408448bc2c1251707297ef633d64e",
"packages/session-ui/src/v2/components/preview-editor-helpers.ts": "7f61e97e54286af1bbf5e88538e9c73995eb30f19868c6f43694422205aeda4b",
"packages/session-ui/src/v2/components/preview-editor.test.ts": "b8da9320a594aaa680ed3848612fcea66f41c0a046a673f0cf6155c2a0b697dd",
"packages/session-ui/src/v2/components/preview-editor.tsx": "96cfbfbbe06cc797f71ac667a29ece3c44a192c9cd94d91e90f79359cdab932b",
"packages/session-ui/src/v2/components/preview-file-routing.test.ts": "6422e3b36de18a19b101f7321ae2b93e5bcd19a5d1b6e588b64f34af91098d6d",
"packages/session-ui/src/v2/components/preview-file-routing.test.ts": "2367ca08b0b9668b98ad2dade01016932d92ec0f0725f210eb29639ce6c6bb7d",
"packages/session-ui/src/v2/components/preview-nav-state.test.ts": "cec09a8b3c08ab16581d3d5b6ff704584b3c87d81c25e8af20f6f00272f3593f",
"packages/session-ui/src/v2/components/preview-nav-state.ts": "ccaeb94d1ab39271f5dcd49c935c8fc7b54d4ffbd66e1352e4d797c9205553fc",
"packages/session-ui/src/v2/components/preview-view-state.ts": "4ec961c7720417166dcccd45f0d4702afec664dfe7f4d0dd8668bb9b1d8af5e6",
Expand Down Expand Up @@ -1099,10 +1102,10 @@
"packages/ui/src/v2/components/text-shimmer-v2.tsx"
],
"exceptions": [],
"extracted_at": "2026-11-01T16:01:02.158Z",
"extracted_at": "2026-11-06T18:48:23.336Z",
"per_package": {
"packages/app": {
"A": 309,
"A": 312,
"M": 166,
"D": 0
},
Expand Down Expand Up @@ -1148,7 +1151,7 @@
}
},
"counts": {
"overlay_total": 1077,
"overlay_total": 1080,
"deletions": 7,
"server_coupled": 0
},
Expand Down Expand Up @@ -1954,6 +1957,9 @@
"packages/app/src/components/session/preview-frontmatter-card.tsx": "A",
"packages/app/src/components/session/preview-frontmatter.test.ts": "A",
"packages/app/src/components/session/preview-frontmatter.ts": "A",
"packages/app/src/components/session/preview-html-view.tsx": "A",
"packages/app/src/components/session/preview-html.test.ts": "A",
"packages/app/src/components/session/preview-html.ts": "A",
"packages/app/src/components/session/preview-human-write-gate.ts": "A",
"packages/app/src/components/session/preview-latex-compile.test.ts": "A",
"packages/app/src/components/session/preview-latex-compile.ts": "A",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
* the CM6 editor. Async fileType signal detects binary/error/oversize after
* file.read().
*
* #2141: .html/.htm files render in a scripts-off sandboxed frame
* (PreviewHtmlView) with the same Preview/Edit toggle as markdown.
*
* #934: images render via data URI from the SDK binary response. PDFs render
* via PDF.js (pdfjs-dist) to canvas — no iframe, no browser plugin. Save dot
* moved to parent (SessionPreviewTab); zoom controls moved here to share
Expand Down Expand Up @@ -45,6 +48,8 @@ import {
} from "./preview-latex-compile"
import { splitFrontmatter } from "./preview-frontmatter"
import { FrontmatterCard } from "./preview-frontmatter-card"
import { PreviewHtmlView } from "./preview-html-view"
import { popOutHtmlMessage } from "./preview-html"

// ---------------------------------------------------------------------------
// Helpers
Expand All @@ -55,7 +60,7 @@ function getExtension(path: string): string {
return dot > 0 ? path.slice(dot).toLowerCase() : ""
}

type FileCategory = "markdown" | "image" | "pdf" | "text"
type FileCategory = "markdown" | "html" | "image" | "pdf" | "text"

/**
* Sync, extension-based file classification (phase 1).
Expand All @@ -67,6 +72,7 @@ function getFileCategory(path: string): FileCategory {
if ((RENDERABLE_EXTENSIONS.markdown as readonly string[]).includes(ext)) return "markdown"
if ((RENDERABLE_EXTENSIONS.images as readonly string[]).includes(ext)) return "image"
if ((RENDERABLE_EXTENSIONS.pdf as readonly string[]).includes(ext)) return "pdf"
if ((RENDERABLE_EXTENSIONS.html as readonly string[]).includes(ext)) return "html"
return "text"
}

Expand Down Expand Up @@ -502,12 +508,12 @@ export function PreviewFileView(props: {

// ─── Render ────────────────────────────────────────────────────────────

const showModeToggle = () => category() === "markdown"
const showModeToggle = () => category() === "markdown" || category() === "html"

// Zoom is disabled in edit mode — pill disappears entirely
const isEditing = () => {
const cat = category()
if (cat === "markdown") return mode() === "edit"
if (cat === "markdown" || cat === "html") return mode() === "edit"
if (cat === "image" || cat === "pdf") return false
return true // text/code files are always in edit mode
}
Expand Down Expand Up @@ -712,6 +718,12 @@ export function PreviewFileView(props: {
link.remove()
}

// #2143: the pop-out rides its own bridge kind (open-external stays https-only).
const popOutHtml = () => {
if (window.parent === window) return
window.parent.postMessage(popOutHtmlMessage(selfAbsolute()), "*")
}

return (
<div
class="h-full relative overflow-hidden"
Expand Down Expand Up @@ -911,6 +923,21 @@ export function PreviewFileView(props: {
</button>
</TooltipV2>
</Show>
{/* Pop-out (#2143): open the rendered page in the system browser. The
extension opens only an existing local .html/.htm file and names a refusal. */}
<Show when={category() === "html"}>
<TooltipV2 openDelay={400} value="Open in browser">
<button
data-preview-open-browser
class="shrink-0 flex items-center justify-center w-7 h-7 rounded-md border border-border-base shadow-sm cursor-pointer text-text-weak hover:text-text-base hover:bg-background-stronger transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-border-focus"
style={previewControlSurfaceStyle}
onClick={popOutHtml}
aria-label="Open in browser"
>
<Icon name="square-arrow-top-right" size="small" />
</button>
</TooltipV2>
</Show>
{/* Zoom controls: [editable %] [reset] [+ over -] */}
<div
class="shrink-0 flex items-center h-7 rounded-md border border-border-base overflow-hidden shadow-sm"
Expand Down Expand Up @@ -1125,6 +1152,38 @@ export function PreviewFileView(props: {
</Show>
</Match>

{/* HTML (#2141): rendered in a scripts-off sandboxed frame; Edit = source */}
<Match when={category() === "html"}>
<Show
when={mode() === "preview"}
fallback={
<PreviewEditor
content={fileContent()}
filePath={props.filePath}
active={props.active}
onChange={handleEdit}
onSave={handleImmediateSave}
viewState={() => props.viewState?.()?.editor}
onViewStateChange={(editor) => props.onViewStateChange?.({ editor })}
/>
}
>
<PreviewHtmlView
filePath={props.filePath}
html={fileContent}
zoom={props.zoom}
sessionID={draftScope}
active={props.active}
readFile={(path) => sdk().client.file.read({ path }).then((result) => result.data as any)}
onExternalContent={(text) => {
// #2142: a poll found new page text; never clobber unsaved Source edits
if (unsavedContent() !== null) return
setFileContent(text)
}}
/>
</Show>
</Match>

{/* Text files: open directly in edit mode */}
<Match when={category() === "text"}>
<PreviewEditor
Expand Down
Loading
Loading