import { Extension, Command, Mark, Editor } from '@tiptap/core'; import { a as PageDimensionsTwips, C as CommentThread, P as PageSetup, W as WatermarkConfig } from './watermark-DNRzAyyP.cjs'; import { Node } from '@tiptap/pm/model'; import { BlockDiffResult } from './diff.cjs'; /** * A DocxEditorExtension is the public unit of customization. * * Users can register extensions to: * - add new node/mark types (via `tiptapExtension`) * - add toolbar buttons (via `toolbar`) * - add slash-command menu items (via `slashCommands`) * - hook into editor lifecycle (via `onInit`, `onDestroy`) * - contribute custom commands on the editor API (via `commands`) */ interface DocxEditorExtension { /** Unique id, e.g. "my-extension". Used for lookup and dedupe. */ id: string; /** Optional human-readable name. */ name?: string; /** The TipTap Extension(s) to install. Can be a single Extension or an array. */ tiptapExtensions?: Extension | Extension[]; /** * Toolbar buttons contributed by this extension. * The toolbar UI will render these in registration order. */ toolbar?: ToolbarButton[]; /** * Slash-command menu items contributed by this extension. * Triggered when the user types "/" in the editor. */ slashCommands?: SlashCommand[]; /** Custom commands added to the editor API under `editor.commands.`. */ commands?: Record Command>; /** Called once after the editor is mounted. */ onInit?: (ctx: ExtensionContext) => void; /** Called when the editor is destroyed. */ onDestroy?: (ctx: ExtensionContext) => void; } interface ToolbarButton { id: string; label: string; icon?: string; tooltip?: string; /** Returns true if the button should appear "active" given current selection state. */ isActive?: (ctx: ExtensionContext) => boolean; /** Returns true if the button should be disabled given current selection state. */ isDisabled?: (ctx: ExtensionContext) => boolean; /** Click handler. Receives the extension context. */ onClick: (ctx: ExtensionContext) => void; } interface SlashCommand { id: string; label: string; description?: string; icon?: string; /** Keyword aliases that trigger this command when typed after "/". */ keywords?: string[]; /** Execute the command at the current selection. */ execute: (ctx: ExtensionContext) => void; } /** * Context passed to extension callbacks. * Gives access to the underlying TipTap editor + helpers. */ interface ExtensionContext { /** The underlying TipTap Editor instance. */ editor: any; /** Insert HTML at the current selection. */ insertHTML: (html: string) => void; /** Insert plain text at the current selection. */ insertText: (text: string) => void; /** Focus the editor. */ focus: () => void; /** Read the current document as JSON. */ getJSON: () => any; /** Read the current document as HTML. */ getHTML: () => string; /** Replace the entire document with the given JSON. */ setJSON: (json: any) => void; /** Replace the entire document with the given HTML. */ setHTML: (html: string) => void; } /** * ExtensionRegistry holds all registered DocxEditorExtensions. * * - Order of registration is preserved (insertion order). * - Duplicate ids are rejected (throws). * - Extensions are immutable once registered (cannot be removed in v0.1; * we may add removal in a future version). */ declare class ExtensionRegistry { private readonly _extensions; private readonly _order; register(ext: DocxEditorExtension): void; has(id: string): boolean; get(id: string): DocxEditorExtension | undefined; /** Returns all registered extensions in registration order. */ list(): DocxEditorExtension[]; /** Returns the total number of registered extensions. */ get size(): number; } /** * Comments — text-anchored comment threads, independent of "Suggesting" * mode track changes (`track-changes.ts`). This file only owns the * in-document *anchor*: a `comment` mark wrapping the commented text plus * two ProseMirror commands to add/remove that anchor. * * Thread content (author, messages, @mentions, resolved state) deliberately * does NOT live in the mark's attrs — only the `id` does, matching * `insertion`/`deletion`'s `{ id, author, date }` pattern but trimmed down * further, since here the thread data is owned by the React `CommentsLayer` * + a pluggable `CommentsStorageAdapter` (see `comments-types.ts`), not by * the document itself. This keeps the mark cheap to keep around even after * a thread is resolved (resolution only changes app-level state, so the * highlight never needs to flicker on/off from an `appendTransaction`). */ declare const CommentMark: Mark; interface CommentAnchor { id: string; from: number; to: number; text: string; } /** * Current position + text of every comment anchor in the doc, in doc order. * A mark can be split across several text nodes (e.g. part of the commented * range was later made bold), so fragments sharing an id are merged into one * span covering their full min..max range. */ declare function listCommentAnchors(doc: Node): CommentAnchor[]; /** Read-only helper: does the doc currently anchor any comments? */ declare function hasComments(doc: Node): boolean; declare module '@tiptap/core' { interface Commands { commentsCore: { addCommentMark: (id: string, from: number, to: number) => ReturnType; removeCommentMark: (id: string) => ReturnType; }; } } declare const CommentsCore: Extension; /** * Types for the edit-history feature. Framework-agnostic (no React, no * storage implementation) because both the core `DocxEditor` class * (`editor.ts`) and `packages/agent`'s `DocxAgent` (`packages/agent/src/agent/core.ts`) * need to reference `HistoryCheckpointMeta` without pulling in the * React-only adapter/manager code in `react/history.ts`. */ /** Who triggered a history checkpoint. */ type HistorySource = 'user' | 'agent' | 'restore'; /** * Fired through `DocxEditor.recordCheckpoint()` — describes *why* a * checkpoint is being recorded. Carries no document content; the listener * (typically `HistoryManager`) is responsible for snapshotting * `editor.getJSON()` and persisting it. */ interface HistoryCheckpointMeta { source: HistorySource; /** Short human-readable label, e.g. "Manual save" or "AI agent edit: insert_table". */ label: string; /** Agent checkpoints only — the tool(s) that mutated the document this turn. */ toolNames?: string[]; /** Restore checkpoints only — id of the history entry that was restored. */ restoredFromId?: string; } /** List-view shape: everything except the document snapshot. Cheap to fetch in bulk. */ interface HistoryEntryMeta extends HistoryCheckpointMeta { id: string; timestamp: number; } /** Full entry, including the document snapshot — fetched lazily via `get(id)`. */ interface HistoryEntry extends HistoryEntryMeta { /** Full TipTap JSON document (`editor.getJSON()`) at the time of the checkpoint. */ content: any; format?: 'json'; } /** * Pluggable persistence for history entries. Unlike `StorageAdapter` * (auto-save.ts), which holds a single "latest draft," this holds an * append-only *list* of versions — so `list()` and `get()` are split to let * the drawer render a version list without transferring every version's * full document content. */ interface HistoryStorageAdapter { append(entry: Omit): Promise; /** Newest first. Must not include `content` — use `get(id)` for that. */ list(): Promise; get(id: string): Promise; prune?(opts?: { maxEntries?: number; maxAgeMs?: number; }): Promise; /** Permanently delete one entry. Optional — all 4 built-in adapters implement it. */ remove?(id: string): Promise; } /** * Theme tokens for the editor. All tokens are CSS custom properties, so users * can override them at runtime by setting them on a parent element. * * The default values match a Word/Google-Docs style page (A4, 1" margins, * 11pt body text). See `page-setup.ts` for the higher-level `PageSetup` API * (size presets, custom dimensions, orientation) that resolves into these * `pageWidth`/`pageHeight`/`pageMarginX`/`pageMarginY` fields. */ interface DocxEditorTheme { /** Page background (the gray area around the page). */ background?: string; /** Default text color on the page. */ text?: string; /** Accent color for selection, active toolbar button, link underline. */ accent?: string; /** Border color for tables, blockquote borders, hr, etc. */ border?: string; /** Font family for body text. */ fontFamily?: string; /** Font size for body text (any CSS length, e.g. "11pt" or "14px"). */ fontSize?: string; /** Page width (in any CSS length, e.g. "816px" or "21cm"). */ pageWidth?: string; /** Page height (any CSS length). */ pageHeight?: string; /** Page horizontal margin (any CSS length, e.g. "96px" = 1in). */ pageMarginX?: string; /** Page vertical margin. */ pageMarginY?: string; /** Gap between pages when multi-page. */ pageGap?: string; /** Line height. */ lineHeight?: number | string; } /** * Font stacks for non-Latin script rendering (Phase 6 multi-language * scaffold — see `@shashimadushan/docx-editor-legal-templates`'s * `titleSi`/`titleTa`/`labelSi`/`labelTa` fields). Pass one of these as * `theme.fontFamily` when displaying/editing a Sinhala or Tamil document — * `fontFamily` is a plain CSS custom property, so no editor code change is * needed to switch scripts, only a font stack + (if the host page doesn't * already load the web font) a `@font-face`/Google Fonts `` for * "Noto Sans Sinhala" / "Noto Sans Tamil". */ declare const SINHALA_FONT_STACK = "\"Noto Sans Sinhala\", \"Iskoola Pota\", \"Nirmala UI\", sans-serif"; declare const TAMIL_FONT_STACK = "\"Noto Sans Tamil\", \"Latha\", \"Nirmala UI\", sans-serif"; declare const defaultTheme: Required; /** * Convert a theme object into a `style` string of CSS custom properties * applied to the editor host element. */ declare function themeToCSSVars(theme: DocxEditorTheme): string; /** * Convert a TipTap JSON document (the format produced by `editor.getJSON()`) * into a .docx Blob, ready to download or save. * * This is the "no original file to patch" path — a document created in the * editor rather than opened from disk. It runs the *same* OOXML serializer * the selective-save path uses (`serializeTipTapToOOXML`) and wraps the result * in a generated package (`./docx-package`) whose `styles.xml` is derived from * the editor's own theme/stylesheet. * * It used to rebuild the document with the `docx` library instead, which is * why an exported file never matched the screen: that path had no access to * the editor's typography (so Word applied its own Calibri/Heading defaults), * dropped `fontFamily`, letter spacing, indentation and per-paragraph line * height, wrote lists as literal "• "/"1. " text rather than real numbering, * and emitted headings as Word's built-in blue heading styles. Routing both * save paths through one serializer means a given document exports the same * way whether or not it happens to have an original .docx behind it. * * Supported node types: doc, paragraph, heading, bulletList/orderedList * (incl. nesting), listItem, codeBlock, blockquote, horizontalRule, * pageBreak, table (widths/merges/shading/borders), image. * * Supported marks: bold, italic, underline, strike, superscript, subscript, * link (as a real external relationship), textStyle (color, fontSize, * fontFamily, letterSpacing, backgroundColor), textTransform (uppercase), * highlight. */ interface SaveDocxOptions { /** Document title (used in core properties). */ title?: string; /** Author name (used in core properties). */ creator?: string; /** * Page size/margins in twips, from `resolvePageDimensionsTwips()` * (`../page-setup`). Falls back to US Letter with 1in margins when omitted. */ pageDimensions?: PageDimensionsTwips; /** * The editor's resolved theme. Drives the generated `styles.xml` document * defaults (font family/size, text color, line height) so the exported file * opens with the typography the document was edited in. Falls back to * `defaultTheme` when omitted. */ theme?: DocxEditorTheme; /** Comment threads to write to word/comments.xml, matched to `comment` * marks in `json` by id. From a `CommentsStorageAdapter.list()` call. */ commentThreads?: CommentThread[]; /** Header/footer content as HTML paragraphs (plain text, v1) — from * `DocxEditor.getHeaderHTML()`/`getFooterHTML()`. */ headerHTML?: string; footerHTML?: string; } declare function saveDocxFromJSON(json: any, options?: SaveDocxOptions): Promise; interface HeaderFooterConfig { /** HTML content for the header (top of every page). */ headerHTML?: string; /** HTML content for the footer (bottom of every page). */ footerHTML?: string; /** Show "Page X" in the footer. Default: false. */ showPageNumber?: boolean; } /** Everything `io/pdf.ts`'s `renderHtmlToPdf` needs — see `DocxEditor.getExportSnapshot()`. */ interface DocxEditorExportSnapshot { /** The document's real HTML, from TipTap's own schema-aware serializer. */ html: string; /** CSS custom properties (page geometry, typography) — from `themeToCSSVars(theme)`. */ themeCSSVars: string; /** Current watermark config, or null if none is set. */ watermark: WatermarkConfig | null; /** Header HTML (top of every page), or '' if none. */ headerHTML: string; /** Footer HTML (bottom of every page), or '' if none. */ footerHTML: string; } /** * ViewMode — how the document surface is rendered. * * - `'pageless'` (default): one continuous flowing surface, like Google * Docs' "Pageless" format. Page breaks are visually disabled — they no * longer simulate a page gap/shadow — and instead collapse into a thin * section divider. There is no fixed page height, so content never gets * chopped into simulated pages. * - `'paged'`: the classic Word/Google-Docs paginated layout. Page breaks * render as real page-separation gaps and the surface is laid out into * discrete pages (see `_layoutPagination()`). */ type ViewMode = 'pageless' | 'paged'; /** * EditorMode — the Editing / Suggesting / Viewing switcher (matches Google * Docs' mode dropdown): * - `'editing'` (default): normal editing, changes apply directly. * - `'suggesting'`: still editable, but edits are tracked as suggestions * (insertions underlined, deletions struck through, kept in the * document) instead of applied directly — see `track-changes.ts`. * - `'viewing'`: read-only; the formatting toolbar is disabled too. */ type EditorMode = 'editing' | 'suggesting' | 'viewing'; /** * A snapshot of what's around the cursor — see `DocxEditor.getCursorContext()`. */ interface CursorContext { /** Plain text immediately before the cursor (up to `contextChars` chars). */ before: string; /** Plain text immediately after the cursor (up to `contextChars` chars). */ after: string; /** 1-based page number containing the cursor (pageBreak nodes before it, +1). */ page: number; /** Total number of pages in the document. */ totalPages: number; /** 1-based index of the top-level block (paragraph/heading/etc.) containing the cursor. */ line: number; /** Total number of top-level blocks in the document. */ totalLines: number; /** * Human-readable type of the block the cursor is in — e.g. "heading * (title), level 2", "bulleted list item", "paragraph". This is the piece * that used to be missing entirely: the agent knew *where* the cursor was * but not *what kind of content* it was sitting in. */ blockType: string; /** The block's alignment ('left'/'center'/'right'/'justify'), if set. */ alignment?: string; /** * Character-level marks active AT THE CARET (bold/italic/underline/ * strike/code/highlight/subscript/superscript/link) — i.e. what typing * right now would inherit, or what "make this bold" needs to check before * deciding whether to toggle on or off. Empty array means plain text. */ activeMarks: string[]; /** * The cursor's entire block rendered with marks made visible as * lightweight markdown (**bold**, *italic*, __underline__, ~~strike~~, * `code`, ==highlight==) and structural prefixes for headings/lists/ * quotes (# / - / 1. / >) — see `annotateNode`. This lets the model see * "this is a bold, centered H2" at a glance instead of inferring it from * plain, unmarked text. */ blockAnnotated: string; } /** * Render a `CursorContext` into a compact block of text suitable for * injecting into an LLM prompt, so an AI agent knows what's around the * cursor (and where the user is in the document) without needing the * whole document. */ declare function formatCursorContext(ctx: CursorContext): string; interface DocxEditorOptions { /** DOM element to mount into. If omitted, call `mount(el)` later. */ element?: HTMLElement; /** Initial HTML content. */ content?: string; /** Theme tokens. */ theme?: DocxEditorTheme; /** * Page size/orientation/margins. Default: A4 portrait, 1in margins * (`DEFAULT_PAGE_SETUP`). Resolved into `theme.pageWidth`/`pageHeight`/ * `pageMarginX`/`pageMarginY` before the initial paint — an explicit * `theme.pageWidth` etc. still wins over this if both are given. */ pageSetup?: PageSetup; /** Editable flag. Default: true. */ editable?: boolean; /** Document filename (shown in title bar). */ filename?: string; /** Header/footer configuration. */ headerFooter?: HeaderFooterConfig; /** Initial watermark. */ watermark?: WatermarkConfig; /** * Initial view mode — `'pageless'` (default, one continuous flowing * surface) or `'paged'` (classic Word/Google-Docs pagination). */ viewMode?: ViewMode; /** * Builtin extension ids to disable. Use this to remove default toolbar * buttons / slash commands without writing your own replacement. * Example: `disableBuiltins: ['bold', 'italic']` * Pass `'*'` to disable ALL builtins. */ disableBuiltins?: string[] | '*'; /** * Custom extensions to register (in addition to builtins). * If you want to fully replace builtins, pass `disableBuiltins: '*'`. */ extensions?: DocxEditorExtension[]; /** * Pass your own TipTap Extension array to fully control the schema. * Defaults to `defaultTipTapExtensions()`. */ tiptapExtensions?: any[]; /** Placeholder text when the document is empty. */ placeholder?: string; /** Called whenever the document content changes. */ onUpdate?: (ctx: { editor: DocxEditor; json: any; html: string; }) => void; /** Called when the editor is created. */ onCreate?: (ctx: { editor: DocxEditor; }) => void; } /** * DocxEditor — the public class. * * Wraps a TipTap Editor and adds: * - .docx load/save (via mammoth + docx lib) * - extension registry with toolbar + slash commands * - paged paper-like layout (Word / Google Docs style) * - theme tokens * * The editor surface is rendered as a "page" — a white card with shadow, * centered in a gray scrolling container. The page width and margins come * from the theme (default: 8.5×11" with 1" margins, matching Word). */ declare class DocxEditor { readonly registry: ExtensionRegistry; readonly editor: Editor; readonly theme: Required; readonly filename: string; private readonly _host; private readonly _surface; private readonly _page; private readonly _content; private readonly _headerEl; private readonly _footerEl; private readonly _addPageBtn; private readonly _ctx; private _watermark; private _watermarkEl; private _headerFooter; private _viewMode; private _mode; private _pageSetup; private _destroyed; private _isLoading; private _originalDocxBuffer; private _useOOXMLParser; private _layoutRaf; private _checkpointListeners; constructor(opts?: DocxEditorOptions); /** Mount the editor into a DOM element. */ mount(el: HTMLElement): void; /** Destroy the editor and free resources. */ destroy(): void; /** Returns true if `destroy()` has been called. */ get destroyed(): boolean; /** Load a .docx file (ArrayBuffer) into the editor. */ loadDocx(buffer: ArrayBuffer): Promise; /** * Save the current document as a .docx Blob. The live page setup (size/ * orientation/margins — see `setPageSetup()`) is exported by default, so * the saved file matches what's shown on screen; pass `options.pageDimensions` * explicitly to override it. */ saveDocx(options?: SaveDocxOptions): Promise; /** * Save the current document using selective XML patching. * If the document was loaded from a .docx file, this patches only the * changed paragraphs in the original XML — preserving unchanged content * byte-for-byte for Word Compare compatibility. * * Falls back to saveDocx() if no original buffer is available. */ saveDocxWithSelectivePatch(): Promise; /** Trigger a browser download of the current document as a .docx file. */ downloadDocx(filename?: string, options?: SaveDocxOptions): Promise; /** * Open the browser's native print dialog, scoped to just the document * content — the surrounding chrome (title/menu/toolbar/status bars, the * agent panel) is hidden via a `@media print` stylesheet, and explicit * page breaks are honored via `break-after: page`. Choosing "Save as * PDF" there is a zero-setup export: no server, no extra dependency. * * This is the lower-fidelity, no-network sibling of `renderHtmlToPdf()` * (`@shashimadushan/docx-editor-editor/headless`), which needs a Node/Puppeteer (or * Playwright) server round trip but produces a file with no user * interaction and doesn't depend on the browser's own print * implementation. `` lets a host app swap in * that server-rendered path later without changing the toolbar button. */ printToPdf(): void; getJSON(): any; getHTML(): string; /** * Load JSON as the initial/loaded document: suppresses `onUpdate` and * dirty-tracking, since this represents a fresh load rather than an edit * (used by `loadDocx()` and draft-restore). For programmatic edits that * should behave like something the user did — including everything the * agent package does — use `replaceContent()` instead. */ setJSON(json: any): void; /** * Replace the whole document with `json` as a normal edit: it fires * `onUpdate` (so autosave/dirty-tracking sees it) and participates in * undo/redo like anything the user could have typed — unlike `setJSON()`, * which is reserved for the initial-load path and deliberately suppresses * both. * * This is what the agent package's tools mutate through (via * `AgentToolContext.setDoc`), since an agent edit should be undoable and * visible to autosave exactly like a manual edit. */ replaceContent(json: any): void; /** * Core document-replace primitive shared by `setJSON()` and * `replaceContent()`: builds ONE ProseMirror transaction that swaps in * `json` as the new document (the same `tr.replaceWith(0, size, node)` * technique TipTap's own `setContent` command uses internally), then * remaps the caret through that same transaction and clamps it into the * new document. * * Plain `editor.commands.setContent()` does the replace but never * restores the selection afterward, so every full-document replace (every * agent tool call, since tools mutate a JSON copy and write it back * wholesale) silently dropped the user's cursor. Doing the replace * ourselves lets us carry the caret through in the same transaction. */ private _replaceDoc; /** * Subscribe to checkpoint events (manual saves, agent turns, reverts). * `DocxEditor` itself holds no history storage — this is a plain pub/sub * bus; `HistoryManager` (`react/history.ts`) is what subscribes, snapshots * `getJSON()`, and persists it via a `HistoryStorageAdapter`. Returns an * unsubscribe function. */ onCheckpoint(listener: (meta: HistoryCheckpointMeta) => void): () => void; /** * Announce that a checkpoint-worthy moment happened (a manual save, or — * from `packages/agent`'s `DocxAgent.editor.recordCheckpoint(...)` — a * completed agent turn that mutated the document). Fires `onCheckpoint` * listeners; does not itself read or store document content. */ recordCheckpoint(meta: HistoryCheckpointMeta): void; setHTML(html: string): void; getText(): string; setEditable(editable: boolean): void; getEditable(): boolean; /** Get the current mode. Default: 'editing'. */ getMode(): EditorMode; /** * Switch between 'editing' (normal), 'suggesting' (edits are tracked as * insertions/deletions instead of applied directly), and 'viewing' * (read-only). See `EditorMode`. */ setMode(mode: EditorMode): void; /** Set the display name attached to suggestions made from now on. Default: 'You'. */ setSuggestionAuthor(author: string): void; /** Does the document currently have any pending (unresolved) suggestions? */ hasPendingSuggestions(): boolean; /** Ids of all pending suggestions, in document order. */ listPendingSuggestionIds(): string[]; /** Accept every pending suggestion (insertions kept, deletions applied). */ acceptAllSuggestions(): void; /** Reject every pending suggestion (insertions discarded, deletions undone). */ rejectAllSuggestions(): void; /** Accept a single suggestion (all marks sharing this change id). */ acceptSuggestion(id: string): void; /** Reject a single suggestion (all marks sharing this change id). */ rejectSuggestion(id: string): void; /** * Highlight the blocks that changed between `diff` (from * `diffHistoryBlocks()` in `react/history/historyDiff.ts`) and the current * document — decoration-only, never edits content or participates in * undo/redo. Called from the History drawer's `onMouseEnter`; pair with * `clearHistoryDiffPreview()` on `onMouseLeave`. */ previewHistoryDiff(diff: BlockDiffResult): void; /** Clear the hover-diff highlight set by `previewHistoryDiff()`. */ clearHistoryDiffPreview(): void; /** Anchor a new comment thread's highlight over `[from, to)`, keyed by `id`. */ addCommentAnchor(id: string, from: number, to: number): void; /** Remove a comment thread's highlight (all marks sharing this id). */ removeCommentAnchor(id: string): void; /** Current position + text of every comment anchor in the doc, in doc order. */ listCommentAnchors(): CommentAnchor[]; /** Does the document currently anchor any comments? */ hasComments(): boolean; registerExtension(ext: DocxEditorExtension): void; getToolbarButtons(): { extensionId: string; button: any; }[]; getSlashCommands(): { extensionId: string; command: any; }[]; getExtensionContext(): ExtensionContext; /** Returns the host element (root of the editor DOM). For advanced UIs. */ getHost(): HTMLElement | null; /** Returns the page element (the white "paper"). */ getPage(): HTMLElement; /** Returns the surface element (the scroll container around pages). */ getSurface(): HTMLElement; /** Set a loading indicator overlay on the editor surface. */ setLoading(loading: boolean, message?: string): void; /** Get the current view mode ('pageless' | 'paged'). Default: 'pageless'. */ getViewMode(): ViewMode; /** * Switch between 'pageless' (one continuous flowing surface — the * default) and 'paged' (classic Word/Google-Docs pagination). * * In 'pageless' mode, page breaks are visually disabled: they stop * simulating a page gap/shadow and collapse into a thin section divider, * and the page surface grows/shrinks with its content instead of being * locked to fixed page-height increments. */ setViewMode(mode: ViewMode): void; /** Get the current page setup. Default: A4 portrait, 1in margins. */ getPageSetup(): PageSetup; /** * Apply a new page size/orientation/margins. Updates the page geometry * live (both 'pageless' and 'paged' view modes) and re-runs pagination. */ setPageSetup(setup: PageSetup): void; /** Get the current watermark config (or null if none). */ getWatermark(): WatermarkConfig | null; /** * Set a watermark. Pass null to remove. * * Renders as a single tiled overlay (repeating SVG background) covering * the whole page, so it reads consistently down the entire document in * both view modes — no per-mode branching needed here. */ setWatermark(config: WatermarkConfig | null): void; /** Get the list of preset watermarks. */ getWatermarkPresets(): { label: string; config: WatermarkConfig; }[]; /** * Capture a snapshot of what's around the cursor right now: the text * immediately before and after it, its page number, and its "line" * (the 1-based index of the top-level block — paragraph, heading, * list item, etc. — it's in). Used to give the AI agent situational * awareness ("what's near, what page/line the user is on") without * shipping the whole document on every request. */ getCursorContext(contextChars?: number): CursorContext; /** Get the current header/footer config. */ getHeaderFooter(): HeaderFooterConfig; /** Get the header DOM element (or null if no header region). */ getHeaderElement(): HTMLElement | null; /** Get the footer DOM element (or null if no footer region). */ getFooterElement(): HTMLElement | null; /** Get the header HTML content. */ getHeaderHTML(): string; /** Get the footer HTML content. */ getFooterHTML(): string; /** Set the header HTML content. Creates the header region if it doesn't exist. */ setHeaderHTML(html: string): void; /** Set the footer HTML content. Creates the footer region if it doesn't exist. */ setFooterHTML(html: string): void; /** Toggle page number visibility in the footer. */ setShowPageNumber(show: boolean): void; /** * Gather everything a PDF export needs, in one call: the document's real * HTML (via TipTap's own schema-aware serializer, not a hand-rolled * JSON→HTML walker — so exported PDFs stay faithful to marks/attributes * the same way .docx round-tripping already relies on `getHTML()`), plus * the page-level extras that live outside the document JSON (watermark, * header/footer, theme/page geometry). * * PDF rendering itself (`renderHtmlToPdf` in `io/pdf.ts`) runs in Node via * a headless browser, which can't reach into this live editor instance — * so the browser side calls `getExportSnapshot()` and sends the result to * wherever `renderHtmlToPdf` runs (typically a server endpoint). */ getExportSnapshot(): DocxEditorExportSnapshot; /** * Lay out the document into Word/Google-Docs-style pages. * * This editor keeps ONE continuous contenteditable region (splitting a * live ProseMirror doc across separate DOM nodes would break editing), * so "pages" are simulated: * * 1. Each `pageBreak` node is dynamically sized so that whatever comes * after it always lands exactly on the top margin of the next * simulated page — never leaving a big stray blank rectangle and * never bunching two pages together. * 2. The overall page container's min-height is grown to fit * `pageBreaks + 1` full pages (with a page-gap between each), so an * empty trailing page still renders at full page height, like Word. * * Runs after every content change (typing, paste, insert/delete page * break, image load, font load, .docx load). */ private _layoutPagination; /** * Clear per-page-break pagination sizing and give the page/content a * single default page-sized min-height — used in 'pageless' mode. * * Unlike 'paged' mode (which grows the page in whole-page increments to * fit `pageBreaks + 1` simulated pages), pageless mode never adds extra * height for page breaks — they're just thin dividers now — but the * page still starts out looking like a normal sheet of paper (one full * page tall) instead of collapsing to whatever little content exists. * Content simply keeps flowing past that height once it grows beyond it * (min-height, not height). */ private _resetPagination; /** Schedule a pagination layout pass on the next animation frame (coalesces bursts of updates). */ private _scheduleLayoutPagination; private _ensureHeaderFooter; } export { type CommentAnchor as C, type DocxEditorExtension as D, type EditorMode as E, type HeaderFooterConfig as H, SINHALA_FONT_STACK as S, TAMIL_FONT_STACK as T, type ViewMode as V, CommentMark as a, CommentsCore as b, type CursorContext as c, DocxEditor as d, type DocxEditorExportSnapshot as e, type DocxEditorOptions as f, type DocxEditorTheme as g, type ExtensionContext as h, ExtensionRegistry as i, type HistoryCheckpointMeta as j, type HistoryEntry as k, type HistoryEntryMeta as l, type HistorySource as m, type HistoryStorageAdapter as n, type SaveDocxOptions as o, type SlashCommand as p, type ToolbarButton as q, defaultTheme as r, formatCursorContext as s, hasComments as t, listCommentAnchors as u, saveDocxFromJSON as v, themeToCSSVars as w };