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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/documents) [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/documents/ci.yml?branch=main)](https://github.com/ExaDev/documents/actions)

> A client-only, statically-built web UI for every conversion and editing tool in the [documents.js ecosystem](../README.md) — convert and edit docx, pptx, xlsx, odt, odp, ods, odg, pdf, and markdown documents entirely in the browser, with no server component.
> A client-only, statically-built web UI for every conversion and editing tool in the [documents.js ecosystem](../README.md) — convert and edit docx, pptx, xlsx, odt, odp, ods, odg, csv, svg, pdf, and markdown documents entirely in the browser, with no server component.

Private (unpublished to npm); deployed as a static site to GitHub Pages.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@vanilla-extract/recipes": "^0.5.7",
"dexie": "^4.4.4",
"dexie-react-hooks": "^4.4.0",
"documents.js": "^2.0.0",
"documents.js": "^2.3.0",
"markdown-codec": "^2.0.0",
"odf.js": "^3.0.1",
"react": "^19.2.8",
Expand Down
17 changes: 12 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/hooks/useInspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getRpcClient } from '../rpc/client';
import type { Diagnostic } from '../shared/diagnostics';
import { contentSummary } from '../shared/contentCounts';

// Reads a ContentDocument directly from bytes via the content.read RPC endpoint -- no conversion, no PDF layout pass. Used by every content-backed preview (markdown, docx, odt, xlsx, ods, pptx, odp, odg, odf).
// Reads a ContentDocument directly from bytes via the content.read RPC endpoint -- no conversion, no PDF layout pass. Used by every content-backed preview (markdown, csv, svg, docx, odt, xlsx, ods, pptx, odp, odg, odf).
export interface ReadContentInput {
format: DocumentFormat;
bytes: Uint8Array<ArrayBuffer>;
Expand Down
6 changes: 4 additions & 2 deletions src/routes/convert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,18 @@ export const Route = createFileRoute('/convert')({
component: ConvertLayout,
});

// csv reads as a spreadsheet-kind ContentDocument (readCsvContent), so it previews through the same data grid as xlsx/ods.
function isSheetFormat(format: string | null): boolean {
return format === 'xlsx' || format === 'ods';
return format === 'xlsx' || format === 'ods' || format === 'csv';
}

function isWordProcessingFormat(format: string | null): boolean {
return format === 'docx' || format === 'odt';
}

// svg reads as a drawing-kind ContentDocument (readSvgContent), so it previews through the same pages/shapes/vectors renderer as odg.
function isSlidesFormat(format: string | null): boolean {
return format === 'pptx' || format === 'odp' || format === 'odg';
return format === 'pptx' || format === 'odp' || format === 'odg' || format === 'svg';
}

// True for every format whose preview renders the ContentDocument natively via content.read rather than a PDF rendition. PDF itself is the only exception -- its "native" representation IS the PDF bytes rendered in an iframe.
Expand Down
6 changes: 5 additions & 1 deletion src/rpc/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DOCUMENT_FORMATS,
extractSourceFontsForFormat,
LayoutDocumentSchema,
readCsvContent,
readDocxContent,
readDocxExtras,
readDocumentMetadata,
Expand All @@ -19,6 +20,7 @@ import {
readMarkdownContent,
readPptxContent,
readPdf,
readSvgContent,
readXlsxContent,
setDocumentMetadata,
} from 'documents.js';
Expand Down Expand Up @@ -184,9 +186,11 @@ const SanitizedLayoutDocumentSchema = LayoutDocumentSchema.extend({
images: z.record(z.string(), SanitizedLayoutImageAssetSchema),
});

// Reads a ContentDocument directly from bytes, bypassing the conversion engine entirely -- no target build/encode, no PDF layout pass. Every format's standalone content reader is exported from documents.js (xlsx included since documents.js 2.0 -- before that, xlsx had to detour through the xlsx->ods bridge and read .content off the conversion result).
// Reads a ContentDocument directly from bytes, bypassing the conversion engine entirely -- no target build/encode, no PDF layout pass. Every format's standalone content reader is exported from documents.js (xlsx included since documents.js 2.0 -- before that, xlsx had to detour through the xlsx->ods bridge and read .content off the conversion result). markdown, csv, and svg are the plain-text formats: their readers take the decoded string, not a package, so each decodes its bytes up front the way markdown always has.
function readContentForFormat(format: DocumentFormat, bytes: Uint8Array<ArrayBuffer>): ContentDocument {
if (format === 'markdown') return readMarkdownContent(new TextDecoder().decode(bytes));
if (format === 'csv') return readCsvContent(new TextDecoder().decode(bytes));
if (format === 'svg') return readSvgContent(new TextDecoder().decode(bytes));
if (format === 'pdf') throw new Error('PDF has no standalone content reader');
const pkg = decodeDocumentPackage(format, bytes);
switch (format) {
Expand Down
2 changes: 2 additions & 0 deletions src/shared/extensionToFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const EXTENSION_TO_FORMAT: Readonly<Record<string, DocumentFormat>> = {
otg: 'odg',
odf: 'odf',
otf: 'odf',
csv: 'csv',
svg: 'svg',
markdown: 'markdown',
md: 'markdown',
pdf: 'pdf',
Expand Down