/** * The 9 built-in file viewer descriptors: every preview surface is a * registered viewer (image / pdf / docx / xlsx / pptx / markdown / html / * code / binary-download), exactly like external plugins register theirs. * The `binary-download` viewer sniffs NUL bytes via `detect` for unknown * binaries and serves doc/xls/ppt by extension; `code` is the catch-all * (`exts: []`, lowest priority) that claims any file no other viewer did. * * Every viewer carries the declarative settings-surface fields — `title` * and `icon` — so the Side card settings page can render the enable/disable * inventory without hardcoding (eating our own dogfood). */ import { IconCodeOutline16, IconDownloadOutline16 } from '@deepseek-ai/dsh-client-ui-primitives' import { DocxView, XlsxView } from '../office-view.tsx' import { PdfView } from '../PdfView.tsx' import { PptxView } from '../PptxView.tsx' import { TextEditor } from '../TextEditor.tsx' import { BinaryDownload } from '../binary-download.tsx' import { IconImageOutline16, IconMarkdownOutline16, IconPdfOutline16, IconDocxOutline16, IconXlsxOutline16, IconPptxOutline16, IconHtmlOutline16, } from '../icons.tsx' import type { FileViewerDescriptor } from '../service.ts' import { t } from '../locales.ts' import css from '../sidebar.module.css' /** The 9 built-in file viewer descriptors. */ export function builtinViewers(): readonly FileViewerDescriptor[] { return [ { id: 'image', title: () => t('viewerImage'), icon: (size: number) => , exts: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico', 'avif'], fetchStrategy: 'mediaUrl', component: ({ mediaUrl: url, title }) => (
{title}
), }, { id: 'pdf', title: () => t('viewerPdf'), icon: (size: number) => , exts: ['pdf'], fetchStrategy: 'mediaUrl', component: ({ scope, path, title }) => ( ), }, { id: 'docx', title: () => t('viewerDocx'), icon: (size: number) => , exts: ['docx'], fetchStrategy: 'mediaUrl', component: ({ scope, path, title }) => ( ), }, { id: 'xlsx', title: () => t('viewerXlsx'), icon: (size: number) => , exts: ['xlsx'], fetchStrategy: 'mediaUrl', component: ({ scope, path, title }) => ( ), }, { id: 'pptx', title: () => t('viewerPptx'), icon: (size: number) => , exts: ['pptx'], fetchStrategy: 'mediaUrl', component: ({ scope, path, title }) => ( ), }, { id: 'markdown', title: () => t('viewerMarkdown'), icon: (size: number) => , exts: ['md', 'markdown'], fetchStrategy: 'fsRead', component: (props) => , }, { id: 'html', title: () => t('viewerHtml'), icon: (size: number) => , exts: ['html', 'htm'], fetchStrategy: 'fsRead', // Declarative settings: the sandbox escape hatch and the default-unsafe // start state render under this viewer's row in the Side card settings // page (both warned on). settings: { toggles: [{ key: 'htmlViewerNoSandbox', title: () => t('settingsHtmlSandboxTitle'), desc: () => t('settingsHtmlSandboxDesc'), }, { key: 'htmlViewerDefaultUnsafe', title: () => t('settingsHtmlDefaultUnsafeTitle'), desc: () => t('settingsHtmlDefaultUnsafeDesc'), }], }, component: (props) => , }, { id: 'code', title: () => t('viewerCode'), icon: (size: number) => , exts: [], priority: -100, fetchStrategy: 'fsRead', component: (props) => , }, { id: 'binary-download', title: () => t('viewerBinary'), icon: (size: number) => , exts: ['doc', 'xls', 'ppt'], priority: -50, fetchStrategy: 'binary-download', // NUL probe: a file whose head bytes contain a NUL is binary — claimed // before the catch-all code viewer on the head re-match. detect: (_path, head) => head.includes(0), component: ({ scope, path }) => , }, ] }