# word-editor API

`word-editor` exposes the DOCX editor as a native Web Component. The component can be embedded in any browser application, independent of React, Vue, Angular, Svelte, or a server-rendered host.

中文说明：本文档以当前代码实现为准，覆盖生产集成所需的元素属性、方法、命令、事件、字体网关、授权和部署注意事项。

## Installation

Build the runtime and import the generated browser module:

```bash
npm run build
```

```html
<word-editor id="editor" mode="edit" zoom="1"></word-editor>

<script type="module">
  import "/packages/word-editor/dist/index.js";

  const editor = document.querySelector("#editor");
  await editor.load(file, file.name);
</script>
```

The default package entry registers `<word-editor>` automatically. Advanced hosts can import and call `defineWordEditorElement(tagName)` if they need a custom tag name.

```ts
import { WordEditorElement, defineWordEditorElement } from "./packages/word-editor/dist/index.js";

defineWordEditorElement("acme-word-editor");
```

## Lifecycle

The element must be connected to the DOM before `load()`, `loadBlank()`, `save()`, or command methods are called. A typical production lifecycle is:

1. Render `<word-editor>`.
2. Wait for `ready` or call `load()` after the next microtask once the element is connected.
3. Subscribe to `loaded`, `changed`, `saved`, and `error`.
4. Keep host-side dirty state in sync with `changed`.
5. Upload or persist the Blob returned by `save()`.
6. Call `destroy()` only when the host intentionally tears down the editor instance.

```ts
const editor = document.querySelector("word-editor");

editor.addEventListener("ready", () => {
  console.log("editor mounted");
});

editor.addEventListener("changed", (event) => {
  console.log("dirty:", event.detail.dirty);
});

editor.addEventListener("error", (event) => {
  console.error(event.detail.code, event.detail.message);
});

await editor.load(file, file.name);
const docx = await editor.save();
```

## Element Attributes

| Attribute | Values | Default | Description |
| --- | --- | --- | --- |
| `mode` | `edit`, `view` | `edit` | Editing or view mode. Mirrors `setMode()`. |
| `engine` | `ts` | `ts` | Current production engine. The public property is `engineKind`. |
| `zoom` | positive number | `1` | Page zoom ratio. Mirrors `setZoom()`. |
| `auto-font-gateway` | boolean attribute | disabled | Enables background font loading from a manifest. |
| `font-gateway-url` | URL | default gateway when auto loading is enabled | Font gateway manifest URL. |
| `font-gateway-limit` | positive integer | default auto limit | Maximum number of gateway fonts to load automatically. |
| `license-required` | boolean attribute | disabled | Requires runtime license validation before mounting. |
| `license-feature` | string | runtime default | Feature name used by the license gate. |

Example:

```html
<word-editor
  mode="edit"
  zoom="1"
  auto-font-gateway
  font-gateway-url="https://font.flyfish.group/manifest.json"
  font-gateway-limit="32"
  license-required
  license-feature="word-editor-production">
</word-editor>
```

## Constructor Options

`new WordEditorElement(options)` accepts the same core configuration for programmatic mounting.

```ts
const editor = new WordEditorElement({
  mode: "edit",
  engine: "ts",
  zoom: 1,
  fonts: [
    {
      family: "Aptos",
      src: 'local("Aptos")',
      display: "swap",
    },
  ],
  fontGateway: {
    autoLoad: true,
    manifestUrl: "https://font.flyfish.group/manifest.json",
    limit: 32,
    background: true,
    awaitFontFaces: false,
  },
});

document.body.append(editor);
```

## Methods

### `load(input, name?)`

Loads a DOCX file into the editor.

```ts
await editor.load(file, file.name);
await editor.load(blob, "contract.docx");
await editor.load(arrayBuffer, "template.docx");
```

Parameters:

| Name | Type | Description |
| --- | --- | --- |
| `input` | `File \| Blob \| ArrayBuffer` | DOCX payload. |
| `name` | `string \| undefined` | Display and save name. |

Resolves when the document is available in the editor. On success, the editor emits `loaded` and resets dirty state with `changed`.

### `loadBlank(name?)`

Creates a blank document.

```ts
await editor.loadBlank("blank.docx");
```

If the current engine does not support blank documents, the method rejects with an error.

### `save()`

Serializes the current document to a DOCX Blob.

```ts
const blob = await editor.save();
await uploadDocument(blob);
```

The method emits `saved` and then updates dirty state with `changed`.

### `exec(command, value?)`

Executes a ribbon/API command.

```ts
await editor.exec("bold");
await editor.exec("fontName", "Aptos");
await editor.exec("fontSizePt", "12");
await editor.exec("foreColor", "#185abd");
await editor.exec("toggleRuler");
```

Formatting commands act on the current selection where supported. View commands update the editor UI state.

### `insertTable(rows?, columns?)`

Inserts a table at the current selection.

```ts
await editor.insertTable(3, 4);
```

Defaults to `2 x 2`.

### `insertImage(input, options?)`

Inserts an image at the current selection.

```ts
await editor.insertImage(file, {
  name: file.name,
  mimeType: file.type,
  alt: "Approved contract stamp",
  maxWidthPx: 640,
});
```

Options:

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | Image name for metadata. |
| `mimeType` | `string` | Image MIME type. |
| `alt` | `string` | Alternative text. |
| `maxWidthPx` | `number` | Optional display width cap. |

### Font Methods

```ts
await editor.registerFont({
  family: "Source Han Sans SC",
  src: "url(/fonts/SourceHanSansSC.woff2)",
  display: "swap",
  license: "licensed",
});

await editor.registerFonts(fonts);
const imported = await editor.importFont(file, { family: "Custom Sans", license: "tenant" });
const loaded = await editor.loadFontGatewayFonts({ manifestUrl, limit: 32, background: true });
const repositoryFonts = await editor.loadRepositoryFonts(manifestUrl, true, { families: ["Aptos"] });
const persisted = await editor.listPersistedFonts();
await editor.clearPersistedFonts();
```

Available font APIs:

| Method | Description |
| --- | --- |
| `registerFont(font)` | Registers one font source with the active engine. |
| `registerFonts(fonts)` | Registers multiple font sources. |
| `importFont(input, options?)` | Imports a font file and returns a `WordEditorFontSource`. |
| `loadPersistedFonts()` | Loads browser-persisted fonts. |
| `listPersistedFonts()` | Lists browser-persisted font records. |
| `clearPersistedFonts()` | Clears browser-persisted font records. |
| `loadRepositoryFonts(manifestUrl?, persist?, options?)` | Loads fonts from a custom manifest. |
| `loadFontGatewayFonts(options?)` | Loads fonts through the configured gateway. |

### View and Runtime Methods

```ts
editor.setMode("view");
editor.setMode("edit");
editor.setZoom(1.1);
editor.reflowPages();

const status = await editor.getRuntimeStatus();
console.log(status?.pageCount, status?.dirty, status?.fonts);
```

| Method / Property | Description |
| --- | --- |
| `setMode(mode)` | Sets `edit` or `view` mode. |
| `setEngine(engine)` | Sets the engine attribute. Current valid value is `ts`. |
| `setZoom(value)` | Sets the page zoom ratio. |
| `reflowPages()` | Requests pagination/layout refresh. |
| `getRuntimeStatus()` | Reads runtime status including engine, document name, dirty flag, page count, fonts, persisted fonts, layout and feature metadata. |
| `dirty` | Boolean dirty state. |
| `documentName` | Current document name if a document is loaded. |
| `mode` | Current mode. |
| `engineKind` | Current engine kind. |
| `zoom` | Current zoom ratio. |
| `destroy()` | Destroys the engine and clears the component host. |

## Commands

Commands are accepted by `exec(command, value?)`. The `WordEditorCommand` type currently includes:

### Formatting

`bold`, `italic`, `underline`, `strikeThrough`, `fontName`, `fontSize`, `fontSizePt`, `foreColor`, `hiliteColor`, `removeFormat`, `increaseFont`, `decreaseFont`, `subscript`, `superscript`, `textEffects`.

### Paragraph and Lists

`justifyLeft`, `justifyCenter`, `justifyRight`, `justifyFull`, `insertUnorderedList`, `insertOrderedList`, `multilevelList`, `increaseIndent`, `decreaseIndent`, `sortParagraphs`, `lineSpacing`, `toggleBorders`, `toggleShading`, `formatBlock`.

### Page Layout and View

`pageBreak`, `setPageSize`, `setMargins`, `setOrientation`, `toggleNavigation`, `toggleRuler`, `togglePageEnds`, `toggleGridlines`, `toggleSnapToGrid`, `toggleColumns`, `toggleLineNumbers`, `togglePageBorder`, `togglePageColor`, `toggleDarkMode`.

### Tables

`insertTable`, `insertTableRow`, `insertTableColumn`, `deleteTableRow`, `deleteTableColumn`, `mergeCellRight`, `splitCell`, `sortTableAscending`, `sortTableDescending`, `autoFitTable`.

### Insert Objects

`insertEquation`, `insertFraction`, `insertRadical`, `insertScript`, `insertIntegral`, `insertMatrix`, `insertShape`, `insertTextBox`, `insertWordArt`, `insertInkStroke`, `insertSmartArt`, `insertChart`, `insertHyperlink`, `insertOnlineVideo`, `insertPageNumber`, `insertSymbol`, `insertEmoji`.

### References, Review, and Collaboration

`insertComment`, `insertFootnote`, `insertEndnote`, `insertToc`, `deleteToc`, `insertCitation`, `insertBibliography`, `insertTableOfFigures`, `insertCaption`, `insertCrossReference`, `insertBookmark`, `toggleTrackChanges`, `toggleHeaderFooterEditing`, `acceptRevision`, `rejectRevision`, `acceptAllRevisions`, `rejectAllRevisions`, `previousComment`, `nextComment`, `previousRevision`, `nextRevision`, `deleteComment`, `toggleMarkupView`, `toggleRevisionFilter`, `updateFields`, `showNotes`.

### Search and History

`undo`, `redo`, `find`, `replace`, `replaceAll`.

## Events

Subscribe with `addEventListener`.

| Event | Detail | Description |
| --- | --- | --- |
| `ready` | none | Engine mounted and editor surface is available. |
| `loaded` | `WordEditorLoadResult` | Document loaded. Includes name, engine, optional page count, fonts, persisted fonts, font fallback and coverage data. |
| `changed` | `{ dirty: boolean }` | Dirty state changed. |
| `saved` | `WordEditorSaveResult` | Save completed. Includes document name and DOCX Blob. |
| `error` | `WordEditorErrorDetail` | License, loading, saving, command, or runtime error. |
| `word-editor-operation` | operation commit | Bubbled composed event from the internal editing surface for audit/collaboration integrations. |
| `word-editor-action` | `{ action, ...detail }` | Bubbled composed host action event for integrations such as sharing, plugins, or external workflows. |
| `word-editor-semantic-paste` | semantic paste payload | Bubbled composed event with structured paste summary and operations. |

Example:

```ts
editor.addEventListener("loaded", (event) => {
  const { name, pageCount, fonts } = event.detail;
  updateTitle(name);
  updateStatus(`${pageCount ?? 0} pages, ${fonts?.length ?? 0} fonts`);
});

editor.addEventListener("saved", async (event) => {
  await uploadDocument(event.detail.blob);
});

editor.addEventListener("error", (event) => {
  showToast(event.detail.message);
});
```

## TypeScript Types

The package exports the public types from `core/types.ts`:

```ts
import type {
  WordEditorCommand,
  WordEditorEngineKind,
  WordEditorErrorDetail,
  WordEditorFontGatewayAutoOptions,
  WordEditorFontGatewayOptions,
  WordEditorFontRepositoryLoadOptions,
  WordEditorFontSource,
  WordEditorInsertImageOptions,
  WordEditorLoadResult,
  WordEditorMode,
  WordEditorOptions,
  WordEditorRuntimeStatus,
  WordEditorSaveResult,
} from "./packages/word-editor/dist/index.js";
```

Key shapes:

```ts
type WordEditorMode = "view" | "edit";
type WordEditorEngineKind = "ts";

interface WordEditorFontSource {
  family: string;
  src?: string;
  source?: string;
  blob?: Blob | ArrayBuffer;
  descriptors?: FontFaceDescriptors;
  weight?: string;
  style?: string;
  display?: "auto" | "block" | "swap" | "fallback" | "optional";
  license?: string;
  fileName?: string;
  id?: string;
  persisted?: boolean;
  persist?: boolean;
}

interface WordEditorErrorDetail {
  code: string;
  message: string;
  detail?: unknown;
}
```

## Font Gateway

The font gateway should be asynchronous for best first-screen performance. The editor can render the document first, load fonts in the background, then reflow pages when fonts become available.

```html
<word-editor
  auto-font-gateway
  font-gateway-url="https://font.flyfish.group/manifest.json"
  font-gateway-limit="32">
</word-editor>
```

Programmatic loading:

```ts
await editor.loadFontGatewayFonts({
  manifestUrl: "https://font.flyfish.group/manifest.json",
  families: ["Aptos", "SimSun", "Microsoft YaHei"],
  limit: 32,
  persist: true,
  background: true,
  awaitFontFaces: false,
});

editor.reflowPages();
```

Production guidance:

- Keep `awaitFontFaces: false` for automatic entry-time loading unless the host intentionally wants to block.
- Set a conservative `limit` to avoid excessive memory and network use.
- Persist only fonts that your license and tenant policy allow.
- Surface progress in host UI if the host triggers manual font loading.

## Licensing

The runtime supports an explicit license gate. When `license-required` is present, the component validates the configured license before creating the engine. If validation fails, it:

- Sets `data-license-error`.
- Renders a license error panel.
- Dispatches an `error` event with a `WordEditorErrorDetail`.

```html
<word-editor
  license-required
  license-feature="word-editor-production">
</word-editor>
```

Production deployments should include:

- `office-preview-license.json`
- `auth/word-editor-license-runtime.mjs`
- `wasm/office-parser-core.wasm`
- Cloudflare Pages headers that serve WASM as `application/wasm`
- A release metadata file such as `word-editor-release.json`

## Cloudflare Pages Deployment

Current production origin:

```txt
https://docx-editor.pages.dev
```

Build and deploy:

```bash
npm run build:cloudflare
npm run deploy:cloudflare
```

The Cloudflare Pages artifact includes:

- `/` product homepage
- `/docs/` documentation site
- `/docs/*.md` source documentation
- `/examples/demo/` production demo/editor
- `/packages/word-editor/dist/*.js` runtime modules
- `/auth/*` license runtime
- `/wasm/office-parser-core.wasm`
- `/word-editor-release.json`

## Error Handling

Use the `error` event as the single host-facing error channel.

```ts
editor.addEventListener("error", (event) => {
  const detail = event.detail;
  logEditorError(detail.code, detail.message, detail.detail);
  showDocumentError(detail.message);
});
```

Recommended host behavior:

- Show user-safe messages for load/save failures.
- Keep technical detail in logs.
- Disable destructive actions while `save()` is pending.
- Preserve the original file until the new Blob is successfully stored.

## Production Checklist

- Root page loads from `/`.
- Documentation loads from `/docs/`.
- Demo loads from `/examples/demo/`.
- `office-preview-license.json` returns `Cache-Control: no-store`.
- WASM returns `Content-Type: application/wasm`.
- `word-editor-release.json` identifies `product: "word-editor"` and the deploy origin.
- Web Component emits `ready`, `loaded`, `changed`, `saved`, and `error` as expected.
- Font gateway loading does not block the first visible document render.
- Host app handles dirty state before navigation.
- Only affected tests are run during iteration; broader browser gates are run before release.
