diff --git a/.github/workflows/ci-superdoc.yml b/.github/workflows/ci-superdoc.yml index 3860946284..cdb9b23734 100644 --- a/.github/workflows/ci-superdoc.yml +++ b/.github/workflows/ci-superdoc.yml @@ -39,6 +39,7 @@ jobs: - 'packages/document-api/**' - 'packages/collaboration-yjs/**' - 'packages/docx-evidence-contracts/**' + - 'packages/fonts/**' - 'shared/**' - 'tests/**' - 'scripts/**' @@ -131,6 +132,13 @@ jobs: # Local equivalent: `pnpm check:public:superdoc` (with build). run: pnpm check:public:superdoc --skip-build + - name: Font curation list drift check + # Fails if the committed packages/fonts/src/bundled-families.ts no longer matches the + # font-system curation set, so a font-offerings change that is not regenerated cannot merge + # stale (guards the Verdana-bug class). Runs here because the job's path filter covers both + # the font offerings (shared/**) and the fonts package (packages/fonts/**). + run: pnpm --filter @superdoc-dev/fonts run check:families + unit-tests: needs: build runs-on: ubuntu-latest diff --git a/.github/workflows/release-fonts.yml b/.github/workflows/release-fonts.yml new file mode 100644 index 0000000000..6ebb7f42d3 --- /dev/null +++ b/.github/workflows/release-fonts.yml @@ -0,0 +1,94 @@ +# Auto-releases on push to main (@next). +# Stable releases are orchestrated centrally by release-stable.yml so that +# every stable release shares one concurrency slot and one git push lane. +name: 📦 Release fonts + +on: + push: + branches: + - main + paths: + - 'packages/fonts/**' + - 'shared/**' + - 'pnpm-workspace.yaml' + - '!**/*.md' + workflow_dispatch: + +permissions: + contents: write + packages: write + +concurrency: + # Stable releases share the `release-stable` group so @semantic-release/git + # pushes to `stable` serialize across workflows; per-workflow groups would + # let releases race on `git push origin stable`. queue: max keeps GitHub + # from dropping older pending stable releases when a stable push touches + # multiple wrapper packages; default queue: single only allows one pending. + # queue: max requires cancel-in-progress: false (cannot be combined with true). + group: ${{ github.ref_name == 'stable' && 'release-stable' || format('{0}-{1}', github.workflow, github.ref) }} + cancel-in-progress: false + queue: max + +jobs: + release: + # Stable publishes must go through release-stable.yml. + if: ${{ github.event_name != 'workflow_dispatch' || github.ref_name != 'stable' }} + runs-on: ubuntu-24.04 + steps: + - name: Generate token + id: generate_token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ steps.generate_token.outputs.token }} + + - name: Refresh branch head + # Queued release runs may start against a stale checkout (queue: max + # plus cancel-in-progress: false). Refresh to the current branch head + # so @semantic-release/git pushes fast-forward; semantic-release no-ops + # if no new commits were added since the previous queued run released. + run: | + git fetch origin "${{ github.ref_name }}" --tags + git checkout -B "${{ github.ref_name }}" "origin/${{ github.ref_name }}" + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + cache: pnpm + registry-url: 'https://registry.npmjs.org' + + - name: Verify 0.1.0 bootstrap + run: | + if ! git ls-remote --exit-code --tags origin "fonts-v0.1.0" >/dev/null 2>&1; then + echo "::error::Missing fonts-v0.1.0 tag. Publish @superdoc-dev/fonts@0.1.0 and push fonts-v0.1.0 before automated fonts releases run." + exit 1 + fi + if ! npm view @superdoc-dev/fonts@0.1.0 version >/dev/null 2>&1; then + echo "::error::@superdoc-dev/fonts@0.1.0 is not published. Publish it before automated fonts releases run." + exit 1 + fi + + - uses: oven-sh/setup-bun@v2 + + - name: Install dependencies + run: pnpm install + + - name: Build fonts package + run: pnpm --filter @superdoc-dev/fonts build + + - name: Release + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + LINEAR_TOKEN: ${{ secrets.LINEAR_TOKEN }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + working-directory: packages/fonts + run: pnpx semantic-release diff --git a/.github/workflows/release-stable.yml b/.github/workflows/release-stable.yml index 61175611f9..14c4d154d4 100644 --- a/.github/workflows/release-stable.yml +++ b/.github/workflows/release-stable.yml @@ -182,6 +182,13 @@ jobs: packages-dir: ${{ steps.stage_recovered_python.outputs.main_dir }} skip-existing: true + # build-python-sdk.mjs requires packages/sdk/tools/catalog.json, a + # generated (gitignored) artifact. `pnpm run build` does not produce it, + # so generate the SDK tool catalog/clients before the Python build. + - name: Generate SDK artifacts (tool catalog) + if: steps.stable_release.outputs.sdk_release_present == 'true' + run: pnpm run generate:all + - name: Build and verify Python SDK if: steps.stable_release.outputs.sdk_release_present == 'true' run: node packages/sdk/scripts/build-python-sdk.mjs diff --git a/apps/docs/advanced/headless-toolbar.mdx b/apps/docs/advanced/headless-toolbar.mdx index 67c744488b..f0f3df8d6f 100644 --- a/apps/docs/advanced/headless-toolbar.mdx +++ b/apps/docs/advanced/headless-toolbar.mdx @@ -329,8 +329,6 @@ Snapshot values match the format you pass to `execute()`. What you read is what For a font dropdown that also includes fonts used by the active document, use `useSuperDocFontOptions()` from `superdoc/ui/react` or `ui.fonts` from `superdoc/ui`. -`DEFAULT_FONT_FAMILY_OPTIONS` mirrors the built-in picker list. It can include bundled font choices beyond the core defaults; use the font report when you need per-font rendering details. - For font family, font size, and other commands that apply to selected text, prefer a button menu or popover that prevents `mousedown` from moving focus out of the editor. Native selects can visually clear the editor selection while their menu is open. @@ -361,7 +359,7 @@ const { | Constant | Contents | |----------|----------| -| `DEFAULT_FONT_FAMILY_OPTIONS` | Built-in picker list. Includes strict defaults plus explicitly advertised bundled fallback choices. | +| `DEFAULT_FONT_FAMILY_OPTIONS` | Conservative no-pack baseline: one font per CSS generic (Arial, Times New Roman, Courier New). Configure the pack for the full list, or use `useSuperDocFontOptions()` / `ui.fonts`. | | `DEFAULT_FONT_SIZE_OPTIONS` | 8pt through 96pt (14 sizes) | | `DEFAULT_TEXT_ALIGN_OPTIONS` | left, center, right, justify | | `DEFAULT_LINE_HEIGHT_OPTIONS` | 1.00, 1.15, 1.50, 2.00, 2.50, 3.00 | diff --git a/apps/docs/editor/custom-ui/toolbar-and-commands.mdx b/apps/docs/editor/custom-ui/toolbar-and-commands.mdx index 0fe7bf225e..84140402bd 100644 --- a/apps/docs/editor/custom-ui/toolbar-and-commands.mdx +++ b/apps/docs/editor/custom-ui/toolbar-and-commands.mdx @@ -101,7 +101,7 @@ function FontSizePicker() { ## Font family picker -Use `useSuperDocFontOptions()` for a custom font dropdown. It returns the built-in defaults plus fonts used by the active document, sorted alphabetically. +Use `useSuperDocFontOptions()` for a custom font dropdown. It returns the fonts SuperDoc can render plus fonts used by the active document, sorted alphabetically. Without a configured font pack that is the conservative baseline; configure the pack (`@superdoc-dev/fonts`, or `fonts.assetBaseUrl`) and it returns the full set, minus anything curated with `createSuperDocFonts`. `label` is what you show. `value` is what you pass to the `font-family` command. `previewFamily` is only for rendering the option row. diff --git a/apps/docs/getting-started/fonts.mdx b/apps/docs/getting-started/fonts.mdx index c0008cad91..840b1a64a6 100644 --- a/apps/docs/getting-started/fonts.mdx +++ b/apps/docs/getting-started/fonts.mdx @@ -6,23 +6,136 @@ keywords: 'fonts, font loading, calibri, cambria, aptos, font fallback, custom f SuperDoc keeps the font name from the Word document. When SuperDoc ships an approved fallback for that font, it renders with the fallback but keeps the original name for export. When no fallback is available, load the real font in your app. -## Load fonts in your app +## Bundled fallback fonts -Fonts are your host page's responsibility. `@font-face`, a hosted stylesheet, or a font CDN: anything the browser can resolve. +A Word document asks for fonts like Calibri, Cambria, and Times New Roman. Most are proprietary, or not installed on every machine. SuperDoc renders them with reviewed open substitutes that match the metrics: Carlito for Calibri, Liberation Serif for Times New Roman, and more. The original name is kept for export. + +Without the pack, the toolbar lists one widely available font per CSS generic: Arial for sans-serif, Times New Roman for serif, Courier New for monospace. Each is applied with that generic as a fallback, so it renders acceptably even where the exact font is absent - a readable floor, not an exact-typography guarantee. Wire the pack and the toolbar lists the full reviewed set, and SuperDoc renders the substitutes everywhere. Either way, the Word font name is kept for export. + +These substitutes are real `.woff2` files the browser fetches from a URL. The `superdoc` core does not ship them; the optional `@superdoc-dev/fonts` package does. Pick one path below. + +### Recommended: the `@superdoc-dev/fonts` package + +Install the optional pack and pass it. Your bundler (Vite, Webpack, Next, Nuxt) emits the files and rewrites the URLs. No copy step. No path config. + +```bash +npm install @superdoc-dev/fonts +``` + +```js +import { SuperDoc } from 'superdoc'; +import { superdocFonts } from '@superdoc-dev/fonts'; + +new SuperDoc({ + selector: '#editor', + document: 'contract.docx', + fonts: superdocFonts, +}); +``` + +### Choose which bundled fonts + +By default the pack enables every reviewed font. To narrow it, use `createSuperDocFonts` and name the families. Think in Word names (`Calibri`, not the substitute `Carlito`). + +Drop a few: + +```js +import { createSuperDocFonts } from '@superdoc-dev/fonts'; + +new SuperDoc({ + selector: '#editor', + document: 'contract.docx', + fonts: createSuperDocFonts({ exclude: ['Cooper Black', 'Brush Script MT'] }), +}); +``` + +Or allow only a set: + +```js +fonts: createSuperDocFonts({ include: ['Calibri', 'Cambria', 'Arial'] }), +``` + +Curation changes the toolbar list and which families SuperDoc substitutes. It does not touch your own licensed fonts (see [Load your own fonts](#load-your-own-fonts)). A curated-out family a document still uses keeps its Word name for export and renders with a system font. + +### Alternative: host the files yourself + +Serve the `.woff2` from your own path or a CDN, then point SuperDoc at them. The files ship in the `@superdoc-dev/fonts` package at `node_modules/@superdoc-dev/fonts/assets/`; copy them into your served folder. + +```js +new SuperDoc({ + selector: '#editor', + document: 'contract.docx', + fonts: { assetBaseUrl: '/fonts/' }, +}); +``` + +Use `fonts.resolveAssetUrl` instead for signed or versioned URLs. + +### CDN script build + +The `superdoc` CDN build ships no fonts: by default the toolbar shows the baseline and documents render with system fonts. To load the reviewed pack, add the `@superdoc-dev/fonts` browser build and pass the `SuperDocFonts` global. + +```html + + + +``` + +From a public CDN (jsDelivr or unpkg) the faces resolve automatically, relative to `superdoc-fonts.min.js`. If you self-host it, keep the package's `dist/` and `assets/` folders in their relative layout. + +### Skipping the pack + +The pack is optional. Skip it if you load your own fonts for every family, or only need fonts the user's OS already has. With no pack configured the toolbar shows the baseline and documents render with system fonts, quietly. If you do wire the pack but the `.woff2` cannot be fetched, SuperDoc logs a one-time warning that names the fix; until then text falls back to the original font name, so it can look unchanged on a machine that lacks it. + +## Load your own fonts + +For a brand font, a licensed font, or any family SuperDoc does not ship a fallback for, load the real file yourself. Use `@font-face`, a hosted stylesheet, or a font CDN. Anything the browser can resolve. ```css @font-face { - font-family: 'Calibri'; - src: url('/fonts/Carlito-Regular.woff2') format('woff2'); + font-family: 'Inter'; + src: url('/fonts/Inter-Regular.woff2') format('woff2'); font-display: swap; } ``` -For custom or licensed fonts, load the real file yourself. SuperDoc's built-in fallbacks cover only the fonts it ships and verifies. +SuperDoc's built-in fallbacks cover only the fonts it ships and verifies. For everything else, the real file is yours to provide. + +To register a font through SuperDoc instead of CSS, pass it in `fonts.families` (which composes with `@superdoc-dev/fonts`). Give one file per face so bold and italic resolve correctly: + +```js +new SuperDoc({ + selector: '#editor', + document: 'contract.docx', + fonts: { + families: [ + { + family: 'Brand Sans', + faces: [ + { source: '/fonts/BrandSans-Regular.woff2' }, + { source: '/fonts/BrandSans-Italic.woff2', style: 'italic' }, + { source: '/fonts/BrandSans-Bold.woff2', weight: 700 }, + { source: '/fonts/BrandSans-BoldItalic.woff2', weight: 700, style: 'italic' }, + ], + }, + ], + }, +}); +``` + +SuperDoc passes each `source` URL to the browser; it does not read the font file, so register one file per weight and style you use. `weight` defaults to 400 and `style` to `normal`. Use WOFF2 for the widest browser support. + +Registering a family makes it render wherever a document uses it. It does not add the font to the toolbar; to offer it there, list it in `modules.toolbar.fonts` (see [Toolbar font list](#toolbar-font-list)). ## Toolbar font list -The built-in toolbar lists SuperDoc's defaults plus fonts used by the active document, sorted alphabetically. If you pass `modules.toolbar.fonts`, that custom list replaces the default list. +The built-in toolbar lists the fonts SuperDoc can render, plus the fonts the active document uses, sorted alphabetically. With no pack configured that is the baseline of one font per CSS generic (Arial, Times New Roman, Courier New); with the pack it is the full reviewed set, minus anything you curated out with `createSuperDocFonts`. If you pass `modules.toolbar.fonts`, that custom list replaces it entirely. Each custom entry is a `{ label, key }` pair where `key` is the CSS `font-family` value: @@ -61,6 +174,7 @@ editor.doc.format.apply({ - **Font name preserved, browser falls back.** SuperDoc keeps the DOCX font name. If no bundled fallback or loaded real font exists, the browser chooses its own fallback. - **Custom toolbar list hides document fonts.** Passing `modules.toolbar.fonts` replaces the built-in list. Include every option you want users to pick. +- **Not every bundled family ships every weight and style.** A few substitutes are a single face. For a bold or italic run the substitute lacks, SuperDoc renders the faces it has and leaves the missing ones to the browser's fallback rather than synthesizing a face, so spacing stays predictable. - **Office font licensing.** Calibri, Cambria, and Aptos are licensed Microsoft fonts. Self-hosting the real files requires a license. ## Where to next diff --git a/apps/docs/getting-started/frameworks/angular.mdx b/apps/docs/getting-started/frameworks/angular.mdx index 6a0f232b43..c7d7294064 100644 --- a/apps/docs/getting-started/frameworks/angular.mdx +++ b/apps/docs/getting-started/frameworks/angular.mdx @@ -11,7 +11,7 @@ Requires Angular 17.2+. `viewChild()` and `input()` are stable from Angular 19; ## Install ```bash -npm install superdoc +npm install superdoc @superdoc-dev/fonts ``` ## Basic setup @@ -19,6 +19,7 @@ npm install superdoc ```typescript import { Component, ElementRef, viewChild, AfterViewInit, inject, DestroyRef } from '@angular/core'; import { SuperDoc } from 'superdoc'; +import { superdocFonts } from '@superdoc-dev/fonts'; import 'superdoc/style.css'; @Component({ @@ -38,6 +39,7 @@ export class EditorComponent implements AfterViewInit { selector: this.editorRef().nativeElement, document: 'contract.docx', documentMode: 'editing', + fonts: superdocFonts, }); } } diff --git a/apps/docs/getting-started/frameworks/laravel.mdx b/apps/docs/getting-started/frameworks/laravel.mdx index 47e824ca5e..b003b9cbf6 100644 --- a/apps/docs/getting-started/frameworks/laravel.mdx +++ b/apps/docs/getting-started/frameworks/laravel.mdx @@ -11,6 +11,7 @@ SuperDoc works with Laravel + Blade + Vite. Laravel serves the Blade template wi ```bash composer install npm install +npm install superdoc @superdoc-dev/fonts ``` ## Vite config @@ -55,9 +56,10 @@ Create a Blade view that loads the Vite-bundled script and mounts the editor: ```js resources/js/app.js import { SuperDoc } from 'superdoc'; +import { superdocFonts } from '@superdoc-dev/fonts'; import 'superdoc/style.css'; -let superdoc = new SuperDoc({ selector: '#editor' }); +let superdoc = new SuperDoc({ selector: '#editor', fonts: superdocFonts }); document.getElementById('file-input').addEventListener('change', (e) => { const file = e.target.files[0]; diff --git a/apps/docs/getting-started/frameworks/nextjs.mdx b/apps/docs/getting-started/frameworks/nextjs.mdx index d2d6431961..086ab7cf94 100644 --- a/apps/docs/getting-started/frameworks/nextjs.mdx +++ b/apps/docs/getting-started/frameworks/nextjs.mdx @@ -10,7 +10,7 @@ SuperDoc works seamlessly with Next.js. The recommended approach is using `@supe The React wrapper is the simplest way to integrate SuperDoc with Next.js: ```bash -npm install @superdoc-dev/react +npm install @superdoc-dev/react @superdoc-dev/fonts ``` ### App Router (Next.js 13+) @@ -20,12 +20,14 @@ npm install @superdoc-dev/react 'use client'; import { SuperDocEditor } from '@superdoc-dev/react'; +import { superdocFonts } from '@superdoc-dev/fonts'; import '@superdoc-dev/react/style.css'; export default function EditorPage() { return ( console.log('Editor ready!')} style={{ height: '100vh' }} diff --git a/apps/docs/getting-started/frameworks/nuxt.mdx b/apps/docs/getting-started/frameworks/nuxt.mdx index 404989f5db..029f9c6549 100644 --- a/apps/docs/getting-started/frameworks/nuxt.mdx +++ b/apps/docs/getting-started/frameworks/nuxt.mdx @@ -9,7 +9,7 @@ SuperDoc works with Nuxt 4+ as a client-side Vue component. Set `ssr: false` in ## Install ```bash -npm install superdoc +npm install superdoc @superdoc-dev/fonts ``` ## Configure Nuxt @@ -33,6 +33,7 @@ Nuxt auto-imports Vue's `ref`, `watch`, and lifecycle hooks: no manual imports n ```vue app/pages/index.vue ``` @@ -51,10 +57,11 @@ By the end of this page you'll have a working DOCX editor in your app: load a Wo ```jsx import { SuperDocEditor } from '@superdoc-dev/react'; + import { superdocFonts } from '@superdoc-dev/fonts'; import '@superdoc-dev/react/style.css'; export default function App() { - return ; + return ; } ``` diff --git a/apps/docs/scripts/validate-code-imports.ts b/apps/docs/scripts/validate-code-imports.ts index f5d0a9c93b..4470d341de 100644 --- a/apps/docs/scripts/validate-code-imports.ts +++ b/apps/docs/scripts/validate-code-imports.ts @@ -36,6 +36,7 @@ const EXACT_SUPERDOC_IMPORTS = new Set([ '@superdoc-dev/template-builder/defaults', '@superdoc-dev/template-builder/field-types.css', '@superdoc-dev/superdoc-yjs-collaboration', + '@superdoc-dev/fonts', ]); const EXACT_EXTERNAL_IMPORTS = new Set([ diff --git a/demos/contract-templates/package.json b/demos/contract-templates/package.json index 42ce1e50bb..149f7377a8 100644 --- a/demos/contract-templates/package.json +++ b/demos/contract-templates/package.json @@ -3,7 +3,6 @@ "private": true, "type": "module", "scripts": { - "predev": "pnpm --filter superdoc build", "dev": "vite", "build": "tsc --noEmit && vite build", "preview": "vite preview" diff --git a/demos/nextjs-ssr/copy-fonts.mjs b/demos/nextjs-ssr/copy-fonts.mjs index 7131366e61..fd12b5cdfc 100644 --- a/demos/nextjs-ssr/copy-fonts.mjs +++ b/demos/nextjs-ssr/copy-fonts.mjs @@ -1,21 +1,21 @@ -// Copy SuperDoc's bundled metric-compatible font substitutes into public/fonts/ so they -// are served at /fonts/ (the default asset base). Without this, the bundled .woff2 404 -// and SuperDoc paginates against a browser fallback. Runs as `predev`/`prebuild`. +// Copy the bundled metric-compatible font substitutes into public/fonts/ so they are served at +// /fonts/ (the asset base set on the editor). Without this, the bundled .woff2 404 and SuperDoc +// paginates against a browser fallback. Runs as `predev`/`prebuild`. // -// A real Next.js consumer would copy from `node_modules/@superdoc/font-system/assets/` -// (or set `fonts.assetBaseUrl` to wherever they serve them); this example copies from the -// workspace build for a self-contained demo. +// A real Next.js consumer would copy from `node_modules/@superdoc-dev/fonts/assets/` (or set +// `fonts.assetBaseUrl` to wherever they serve them); this example copies from the workspace package +// for a self-contained demo. import { cpSync, existsSync } from 'node:fs'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; const here = dirname(fileURLToPath(import.meta.url)); -const src = resolve(here, '../../packages/superdoc/dist/fonts'); +const src = resolve(here, '../../packages/fonts/assets'); const dst = resolve(here, 'public/fonts'); if (existsSync(src)) { cpSync(src, dst, { recursive: true }); console.log('[nextjs-ssr] copied bundled fonts -> public/fonts/'); } else { - console.warn(`[nextjs-ssr] bundled fonts not found at ${src}; run \`pnpm build:superdoc\` first`); + console.warn(`[nextjs-ssr] bundled fonts not found at ${src}; run \`pnpm --filter @superdoc-dev/fonts sync\` first`); } diff --git a/demos/nextjs-ssr/src/app/SuperDoc/superdoc.js b/demos/nextjs-ssr/src/app/SuperDoc/superdoc.js index 0eba0da867..585e5b2c65 100644 --- a/demos/nextjs-ssr/src/app/SuperDoc/superdoc.js +++ b/demos/nextjs-ssr/src/app/SuperDoc/superdoc.js @@ -19,6 +19,8 @@ export default function SuperDocEditor() { const { SuperDoc } = await import('superdoc'); const config = { selector: superdocContainerRef.current, + // Self-hosted bundled fallback fonts (copied to public/fonts/ by copy-fonts.mjs). + fonts: { assetBaseUrl: '/fonts/' }, modules: { toolbar: { selector: '#toolbar', diff --git a/examples/getting-started/README.md b/examples/getting-started/README.md index f80c9e25cb..a6d158b4fd 100644 --- a/examples/getting-started/README.md +++ b/examples/getting-started/README.md @@ -11,6 +11,8 @@ Minimal examples for integrating SuperDoc into your project. Each example loads | [vanilla](./vanilla) | Plain JavaScript with Vite | [Guide](https://docs.superdoc.dev/getting-started/quickstart) | | [cdn](./cdn) | Zero build tools — just an HTML file | [Guide](https://docs.superdoc.dev/getting-started/quickstart) | +The bundler examples pass [`@superdoc-dev/fonts`](https://docs.superdoc.dev/getting-started/fonts), so SuperDoc's bundled fallback fonts (Carlito for Calibri, and more) render without copying any assets. The CDN example loads them from the script's path; the Laravel example copies them into `public/fonts/`. + ## Running ```bash diff --git a/examples/getting-started/angular/package.json b/examples/getting-started/angular/package.json index c29ff8b8b1..7407cefe15 100644 --- a/examples/getting-started/angular/package.json +++ b/examples/getting-started/angular/package.json @@ -11,6 +11,7 @@ "@angular/core": "^21.1.4", "@angular/platform-browser": "^21.1.4", "@angular/platform-browser-dynamic": "^21.1.4", + "@superdoc-dev/fonts": "workspace:*", "rxjs": "~7.8.2", "superdoc": "latest", "tslib": "^2.8.1", diff --git a/examples/getting-started/angular/src/app/app.component.ts b/examples/getting-started/angular/src/app/app.component.ts index 105196b5b0..505f29bed4 100644 --- a/examples/getting-started/angular/src/app/app.component.ts +++ b/examples/getting-started/angular/src/app/app.component.ts @@ -1,5 +1,6 @@ import { Component, ElementRef, ViewChild, OnDestroy } from '@angular/core'; import { SuperDoc } from 'superdoc'; +import { superdocFonts } from '@superdoc-dev/fonts'; @Component({ selector: 'app-root', @@ -24,6 +25,7 @@ export class AppComponent implements OnDestroy { selector: this.editorRef.nativeElement, documentMode: 'editing', document: file, + fonts: superdocFonts, }); } diff --git a/examples/getting-started/cdn/.gitignore b/examples/getting-started/cdn/.gitignore index 66a264a5fc..867f62031b 100644 --- a/examples/getting-started/cdn/.gitignore +++ b/examples/getting-started/cdn/.gitignore @@ -1,3 +1,6 @@ superdoc.min.js +superdoc-fonts.min.js style.css test_file.docx +assets/ +fonts/ diff --git a/examples/getting-started/cdn/README.md b/examples/getting-started/cdn/README.md index 8cd8fd27b0..f04f6bbaf0 100644 --- a/examples/getting-started/cdn/README.md +++ b/examples/getting-started/cdn/README.md @@ -5,12 +5,13 @@ Zero build tools. A single HTML file plus the SuperDoc global bundle. ## Run locally ```bash -pnpm --filter superdoc build # one-time, builds the CDN bundle -pnpm setup # copies the bundle + sample DOCX in +pnpm --filter superdoc build # builds superdoc.min.js +pnpm --filter @superdoc-dev/fonts build # builds superdoc-fonts.min.js + the font faces +pnpm setup # copies both bundles + fonts + sample DOCX in npx serve . ``` -`pnpm setup` copies the built `superdoc.min.js`, `style.css`, and a sample `test_file.docx` into this directory so the example is self-contained. +`pnpm setup` copies the built `superdoc.min.js`, `superdoc-fonts.min.js`, `style.css`, the font `assets/`, and a sample `test_file.docx` into this directory so the example is self-contained. ## Use from the public CDN @@ -19,10 +20,21 @@ Replace the local ` + ``` Pin to a specific version (e.g. `superdoc@1.26.0`) in production and add [SRI hashes](https://developer.mozilla.org/docs/Web/Security/Subresource_Integrity) for integrity. +## Fonts + +The `superdoc` CDN build ships no fonts: by default the toolbar shows the baseline (one font per CSS generic) and documents render with system fonts. The reviewed fallback pack comes from the optional `@superdoc-dev/fonts` browser build, loaded as a second ` + +