Skip to content
Closed
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
8 changes: 8 additions & 0 deletions .github/workflows/ci-superdoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
- 'packages/document-api/**'
- 'packages/collaboration-yjs/**'
- 'packages/docx-evidence-contracts/**'
- 'packages/fonts/**'
- 'shared/**'
- 'tests/**'
- 'scripts/**'
Expand Down Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions apps/docs/advanced/headless-toolbar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<CodeGroup>
Expand Down Expand Up @@ -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 |
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/editor/custom-ui/toolbar-and-commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
39 changes: 33 additions & 6 deletions apps/docs/getting-started/fonts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@ SuperDoc keeps the font name from the Word document. When SuperDoc ships an appr

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 them from a URL. Installing SuperDoc from npm puts them in `node_modules`, which does not serve them to the browser. So you tell your app where they live. Pick one path.

### Recommended: the `@superdoc/fonts` package
### 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/fonts
npm install @superdoc-dev/fonts
```

```js
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';

new SuperDoc({
selector: '#editor',
Expand All @@ -31,6 +33,30 @@ new SuperDoc({
});
```

### 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 package at `node_modules/superdoc/dist/fonts/`.
Expand All @@ -51,7 +77,7 @@ The CDN build loads the fonts from a path relative to the script. Loading from a

### 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. When the bundled `.woff2` cannot be fetched, SuperDoc logs a one-time warning and falls back to the original font name. On a machine without that font, the text renders in a system fallback, so it can look unchanged.
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

Expand All @@ -65,11 +91,11 @@ For a brand font, a licensed font, or any family SuperDoc does not ship a fallba
}
```

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 it through SuperDoc instead of CSS, pass it in `fonts.families` (which composes with `@superdoc/fonts`).
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 it through SuperDoc instead of CSS, pass it in `fonts.families` (which composes with `@superdoc-dev/fonts`).

## 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:

Expand Down Expand Up @@ -108,6 +134,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
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/getting-started/frameworks/angular.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ Requires Angular 17.2+. `viewChild()` and `input()` are stable from Angular 19;
## Install

```bash
npm install superdoc @superdoc/fonts
npm install superdoc @superdoc-dev/fonts
```

## Basic setup

```typescript
import { Component, ElementRef, viewChild, AfterViewInit, inject, DestroyRef } from '@angular/core';
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import 'superdoc/style.css';

@Component({
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/getting-started/frameworks/laravel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SuperDoc works with Laravel + Blade + Vite. Laravel serves the Blade template wi
```bash
composer install
npm install
npm install superdoc @superdoc/fonts
npm install superdoc @superdoc-dev/fonts
```

## Vite config
Expand Down Expand Up @@ -56,7 +56,7 @@ 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/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import 'superdoc/style.css';

let superdoc = new SuperDoc({ selector: '#editor', fonts: superdocFonts });
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/getting-started/frameworks/nextjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 @superdoc/fonts
npm install @superdoc-dev/react @superdoc-dev/fonts
```

### App Router (Next.js 13+)
Expand All @@ -20,7 +20,7 @@ npm install @superdoc-dev/react @superdoc/fonts
'use client';

import { SuperDocEditor } from '@superdoc-dev/react';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import '@superdoc-dev/react/style.css';

export default function EditorPage() {
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/getting-started/frameworks/nuxt.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ SuperDoc works with Nuxt 4+ as a client-side Vue component. Set `ssr: false` in
## Install

```bash
npm install superdoc @superdoc/fonts
npm install superdoc @superdoc-dev/fonts
```

## Configure Nuxt
Expand All @@ -33,7 +33,7 @@ Nuxt auto-imports Vue's `ref`, `watch`, and lifecycle hooks: no manual imports n
```vue app/pages/index.vue
<script setup lang="ts">
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';

const container = ref<HTMLDivElement | null>(null);
const file = ref<File | null>(null);
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/getting-started/frameworks/react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ SuperDoc provides `@superdoc-dev/react`: a first-party wrapper with lifecycle ma
## Install

```bash
npm install @superdoc-dev/react @superdoc/fonts
npm install @superdoc-dev/react @superdoc-dev/fonts
```

<Note>
Expand All @@ -20,7 +20,7 @@ npm install @superdoc-dev/react @superdoc/fonts

```jsx
import { SuperDocEditor } from '@superdoc-dev/react';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import '@superdoc-dev/react/style.css';

function App() {
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/getting-started/frameworks/solid.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ SuperDoc does not ship a first-party Solid wrapper. Use the core `superdoc` pack
## Install

```bash
npm install superdoc @superdoc/fonts
npm install superdoc @superdoc-dev/fonts
```

## Quick start

```tsx
import { onCleanup, onMount } from 'solid-js';
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import 'superdoc/style.css';

export default function App() {
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/getting-started/frameworks/vanilla-js.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ SuperDoc works with plain JavaScript. No framework required.

```javascript NPM/Bundler
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import 'superdoc/style.css';

const superdoc = new SuperDoc({
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/getting-started/frameworks/vue.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ SuperDoc works with Vue 3.0+ using Composition API, Options API, or `<script set
## Install

```bash
npm install superdoc @superdoc/fonts
npm install superdoc @superdoc-dev/fonts
```

## Basic setup
Expand All @@ -23,7 +23,7 @@ npm install superdoc @superdoc/fonts
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import 'superdoc/style.css';

const container = ref(null);
Expand Down
10 changes: 5 additions & 5 deletions apps/docs/getting-started/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ By the end of this page you'll have a working DOCX editor in your app: load a Wo
<Tabs>
<Tab title="npm">
```bash
npm install superdoc @superdoc/fonts
npm install superdoc @superdoc-dev/fonts
```
</Tab>
<Tab title="React">
```bash
npm install @superdoc-dev/react @superdoc/fonts
npm install @superdoc-dev/react @superdoc-dev/fonts
```
</Tab>
<Tab title="CDN">
Expand All @@ -32,7 +32,7 @@ By the end of this page you'll have a working DOCX editor in your app: load a Wo
</Tabs>

<Info>
`@superdoc/fonts` serves SuperDoc's bundled fallback fonts so Word fonts render without copying assets. It's optional. See [Font support](/getting-started/fonts).
`@superdoc-dev/fonts` serves SuperDoc's bundled fallback fonts so Word fonts render without copying assets. It's optional. See [Font support](/getting-started/fonts).
</Info>

## 2. Render the editor
Expand All @@ -44,7 +44,7 @@ By the end of this page you'll have a working DOCX editor in your app: load a Wo

<script type="module">
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import 'superdoc/style.css';

const superdoc = new SuperDoc({
Expand All @@ -57,7 +57,7 @@ By the end of this page you'll have a working DOCX editor in your app: load a Wo
<Tab title="React">
```jsx
import { SuperDocEditor } from '@superdoc-dev/react';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import '@superdoc-dev/react/style.css';

export default function App() {
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/scripts/validate-code-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +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/fonts',
'@superdoc-dev/fonts',
]);

const EXACT_EXTERNAL_IMPORTS = new Set([
Expand Down
2 changes: 1 addition & 1 deletion examples/getting-started/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ 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/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/`.
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

Expand Down
2 changes: 1 addition & 1 deletion examples/getting-started/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@angular/core": "^21.1.4",
"@angular/platform-browser": "^21.1.4",
"@angular/platform-browser-dynamic": "^21.1.4",
"@superdoc/fonts": "workspace:*",
"@superdoc-dev/fonts": "workspace:*",
"rxjs": "~7.8.2",
"superdoc": "latest",
"tslib": "^2.8.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, ElementRef, ViewChild, OnDestroy } from '@angular/core';
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';

@Component({
selector: 'app-root',
Expand Down
2 changes: 1 addition & 1 deletion examples/getting-started/laravel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ Open **http://localhost:8000** — pick a `.docx` file and SuperDoc renders it.

## Fonts

SuperDoc's bundled fallback fonts (Carlito for Calibri, and more) are served from `public/fonts/`. `copy-fonts.mjs` copies them out of the installed package before the Vite build. That's the self-host approach. A simpler option for a Vite app is to install [`@superdoc/fonts`](https://docs.superdoc.dev/getting-started/fonts) and pass `fonts: superdocFonts`, which lets Vite emit the fonts with no copy step.
SuperDoc's bundled fallback fonts (Carlito for Calibri, and more) are served from `public/fonts/`. `copy-fonts.mjs` copies them out of the installed package before the Vite build. That's the self-host approach. A simpler option for a Vite app is to install [`@superdoc-dev/fonts`](https://docs.superdoc.dev/getting-started/fonts) and pass `fonts: superdocFonts`, which lets Vite emit the fonts with no copy step.
2 changes: 1 addition & 1 deletion examples/getting-started/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"dependencies": {
"@superdoc-dev/react": "^1.0.0-rc.1",
"@superdoc/fonts": "workspace:*",
"@superdoc-dev/fonts": "workspace:*",
"next": "16.1.6",
"react": "^19.2.0",
"react-dom": "^19.2.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/getting-started/nextjs/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useState, useRef } from 'react';
import { SuperDocEditor, SuperDocRef, DocumentMode } from '@superdoc-dev/react';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';
import '@superdoc-dev/react/style.css';

export default function Home() {
Expand Down
2 changes: 1 addition & 1 deletion examples/getting-started/nuxt/app/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { SuperDoc } from 'superdoc';
import { superdocFonts } from '@superdoc/fonts';
import { superdocFonts } from '@superdoc-dev/fonts';

const editor = ref<HTMLDivElement | null>(null);
const file = ref<File | null>(null);
Expand Down
2 changes: 1 addition & 1 deletion examples/getting-started/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@superdoc/fonts": "workspace:*",
"@superdoc-dev/fonts": "workspace:*",
"nuxt": "^4.3.1",
"superdoc": "latest",
"vue": "^3.5.28"
Expand Down
2 changes: 1 addition & 1 deletion examples/getting-started/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"dependencies": {
"@superdoc-dev/react": "^1.0.0-rc.1",
"@superdoc/fonts": "workspace:*",
"@superdoc-dev/fonts": "workspace:*",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
Expand Down
Loading
Loading