@onodocs/canvas 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +407 -219
- package/SDK.md +407 -219
- package/agreement-review.md +13 -0
- package/ai-report-demo.md +40 -0
- package/application-integration.md +87 -0
- package/document-collaboration.md +50 -0
- package/document-forms.md +84 -0
- package/document-modes.md +44 -0
- package/index.js +264 -39
- package/package.json +11 -3
- package/proposal.md +36 -0
- package/templates.md +71 -0
- package/types/canvas/index.d.ts +3 -0
- package/types/canvas/presentation.d.ts +7 -1
- package/types/canvas/text-selection.d.ts +10 -2
- package/types/foundation/page-interaction.d.ts +26 -0
- package/types/render-api/index.d.ts +1 -1
package/templates.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Word templates and document generation
|
|
2
|
+
|
|
3
|
+
Use `createTemplateEditor` from `@onodocs/sdk/editor` to design reusable DOCX templates. Run `npm run example:templates` in the source workspace for the invoice example at localhost port 5193. The designer uses the ordinary Word editor for layout, formatting and generated-document adjustments.
|
|
4
|
+
|
|
5
|
+
For a complete business-data-to-export journey, run `npm run example:proposal`. The [proposal studio guide](proposal.md) covers setup, repeating fee rows, wording edits and Word/PDF downloads.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { createTemplateEditor } from "@onodocs/sdk/editor";
|
|
9
|
+
|
|
10
|
+
const designer = createTemplateEditor({
|
|
11
|
+
container: document.querySelector("#templates"),
|
|
12
|
+
sampleData: { customer: "Willow Design", items: [{ name: "Review", price: 125 }] },
|
|
13
|
+
});
|
|
14
|
+
await designer.open(templateBytes);
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Select a placeholder and choose Text field, a data field and Apply binding. Selected text keeps the rest of the sentence intact. Use Selected paragraphs for whole paragraphs, Table row for repeating line items, or Whole table for a conditional table. Define an outer repeat or condition before adding fields inside it. Array-item choices in the data selector resolve against the current repeated item. Number, currency and date fields have format controls; image fields use point dimensions and supplied PNG/JPEG data. Existing bindings can be selected, updated or removed. Removing a binding preserves its placeholder content.
|
|
18
|
+
|
|
19
|
+
Reusable sections have a name and content. Define a section once, then choose Insert reusable section at each insertion point. Each insertion can select a different subrecord. Definitions do not appear in generated output. Sections are reused within their defining Word story part; cross-part insertion is not supported because package relationships belong to their source part. Section content can contain its own fields, repeats and conditions.
|
|
20
|
+
|
|
21
|
+
Preview document opens generated content in the editor. Adjust it with the ordinary editing controls and download Word or PDF. Back to template restores the design without incorporating those preview adjustments. Download template always saves the design. A JSON array in Sample data enables Generate batch, which downloads one DOCX for each record; browsers may ask to allow multiple downloads. The SDK batch iterator gives applications control over filenames and storage.
|
|
22
|
+
|
|
23
|
+
For generation in Node or a browser, use the default SDK entry. The browser entry exports the same template API.
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { openTemplate } from "@onodocs/sdk";
|
|
27
|
+
|
|
28
|
+
const template = await openTemplate(templateBytes, { licenseKey });
|
|
29
|
+
try {
|
|
30
|
+
const documentBytes = await template.generate(data, { locale: "en-US", signal });
|
|
31
|
+
for await (const bytes of template.batch(records, { locale: "en-US", signal })) {
|
|
32
|
+
await storeDocument(bytes);
|
|
33
|
+
}
|
|
34
|
+
} finally {
|
|
35
|
+
template.dispose();
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Generation starts from the original source each time. It neither edits the source template nor calls external services. Open the result through the existing Node/browser SDK or server renderer to query, render, edit or export it. Failed and cancelled generations leave the template available for another attempt. Consume batch results incrementally to avoid retaining a whole batch in memory.
|
|
40
|
+
|
|
41
|
+
Bindings are stored in ordinary Word content-control tags. Use `templateTag(binding)` with the editor's `template` command for programmatic authoring:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { templateTag } from "@onodocs/sdk";
|
|
45
|
+
|
|
46
|
+
await doc.edit({
|
|
47
|
+
kind: "template",
|
|
48
|
+
scope: "selection",
|
|
49
|
+
selection,
|
|
50
|
+
title: "Customer name",
|
|
51
|
+
tag: templateTag({ kind: "value", path: ["customer", "name"] }),
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The command supports `selection`, `paragraph`, `row` and `table` scopes. Inline selection stays within one paragraph and uses ordinary adjacent text runs; it cannot cross existing controls or marks. A collapsed selection inserts a placeholder using the title. `action: "update"` changes the selected control's tag and title; `action: "remove"` unwraps it. Supply `controlId` when choosing a specific control from `doc.query.contentControls()`. Use `editor.execute` for changes that must participate in the component's undo history.
|
|
56
|
+
|
|
57
|
+
| Binding | Required values | Result |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| `value` | `path` | String, finite number, boolean or null; null becomes empty text |
|
|
60
|
+
| `value` with `format` | `path`, `{ kind: "number", options }` or `{ kind: "date", options }` | `Intl.NumberFormat` or `Intl.DateTimeFormat` output |
|
|
61
|
+
| `image` | `path`, `width`, `height` | PNG/JPEG from `{ bytes: Uint8Array, mediaType }`; optional `description` |
|
|
62
|
+
| `repeat` | `path` | One copy for each array item; descendants use that item as their context |
|
|
63
|
+
| `if` | `path` | Included for truthy values or nonempty arrays |
|
|
64
|
+
| `section` | `name` | Reusable content definition, omitted from output |
|
|
65
|
+
| `include` | `name`, optional `path` | Section inserted with the current context or selected subrecord |
|
|
66
|
+
|
|
67
|
+
Paths are arrays of own-property names, not executable expressions. An empty path selects the current record. Missing data, wrong value types and recursive sections report an error. Currency options are ordinary `Intl.NumberFormatOptions`, for example `{ style: "currency", currency: "USD" }`. Date values can be a `Date`, timestamp or ISO date string; use an explicit offset for timestamps. The default locale is `en-US` and the default date time zone is UTC.
|
|
68
|
+
|
|
69
|
+
Formatting comes from the first run of a text placeholder. Unrelated Word content and package resources are preserved. Generation refreshes supported sequence and bookmark-reference fields. The browser template API also lays out the generated document to refresh page numbers, page references and supported tables of contents. Node callers can supply a `finalize` callback that opens the generated bytes with the server renderer and returns `document.save(options)`.
|
|
70
|
+
|
|
71
|
+
Unsupported fields retain their cached content. Use `onFieldStatus` to receive diagnostics, or `fields: "require-current"` to reject output containing unresolved fields. The default reports retained caches and completes generation. Locked fields retain their authored values. `fields: "preserve"` explicitly keeps all cached results. Existing signed-package, document-protection and editing restrictions still apply. Native DOTX/DOTM generation is not supported; save the template as DOCX. The reusable source is still a Word document and can be saved and opened by Word.
|
package/types/canvas/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Spec: pipeline.sdk.pdf-export */
|
|
1
2
|
/** Spec: pipeline.sdk.page-source */
|
|
2
3
|
import { type PageInteraction } from "../foundation/index.js";
|
|
3
4
|
import type { DocumentSource, PageSize } from "../render-api/index.js";
|
|
@@ -5,6 +6,7 @@ import type { DocumentView, ViewOptions } from "./presentation.js";
|
|
|
5
6
|
export { materializePageDisplayListToCanvas } from "./canvas-materializer.js";
|
|
6
7
|
export { encode, decode } from "./transport.js";
|
|
7
8
|
export type * from "../render-api/index.js";
|
|
9
|
+
export type { SelectionOverlay } from "./text-selection.js";
|
|
8
10
|
export type { DocumentView, ViewOptions, ViewAnchor, DocumentAttachment, AttachmentOptions, AttachmentPlacement } from "./presentation.js";
|
|
9
11
|
export interface DocumentPage {
|
|
10
12
|
readonly index: number;
|
|
@@ -12,6 +14,7 @@ export interface DocumentPage {
|
|
|
12
14
|
readonly interaction: PageInteraction;
|
|
13
15
|
render(canvas: HTMLCanvasElement, options?: Readonly<{
|
|
14
16
|
dpi?: number;
|
|
17
|
+
background?: "white" | "transparent";
|
|
15
18
|
signal?: AbortSignal;
|
|
16
19
|
}>): Promise<void>;
|
|
17
20
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/** Spec: pipeline.semantic.document-update */
|
|
2
2
|
/** Spec: pipeline.sdk.presentation */
|
|
3
|
-
import type { DocumentFragment, DocumentHit, DocumentPoint } from "../render-api/index.js";
|
|
3
|
+
import type { DocumentFragment, DocumentHit, DocumentPoint, DocumentSelection } from "../render-api/index.js";
|
|
4
4
|
import type { DocumentPage, PageSize } from "./index.js";
|
|
5
|
+
import { type SelectionOverlay } from "./text-selection.js";
|
|
5
6
|
export interface ViewOptions {
|
|
6
7
|
readonly zoom?: number | "fit-width";
|
|
7
8
|
readonly gap?: number;
|
|
8
9
|
readonly title?: string;
|
|
10
|
+
readonly input?: HTMLTextAreaElement;
|
|
11
|
+
readonly onSelectionChange?: (selection: DocumentSelection | undefined) => void;
|
|
9
12
|
}
|
|
10
13
|
export interface DocumentAttachment {
|
|
11
14
|
readonly element: HTMLElement;
|
|
@@ -42,6 +45,9 @@ export interface DocumentView {
|
|
|
42
45
|
point: DocumentPoint;
|
|
43
46
|
}> | undefined;
|
|
44
47
|
hitTest(point: DocumentPoint): DocumentHit | undefined;
|
|
48
|
+
readonly selection: DocumentSelection | undefined;
|
|
49
|
+
setSelection(selection: DocumentSelection): void;
|
|
50
|
+
setSelectionOverlays(selections: readonly SelectionOverlay[]): void;
|
|
45
51
|
scrollTo(anchor: ViewAnchor, options?: ScrollIntoViewOptions): boolean;
|
|
46
52
|
attach(element: HTMLElement, options: AttachmentOptions): DocumentAttachment;
|
|
47
53
|
dispose(): void;
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import type { PageTextLine } from "../render-api/index.js";
|
|
1
|
+
import type { DocumentSelection, PageTextLine } from "../render-api/index.js";
|
|
2
2
|
import type { DocumentPage } from "./index.js";
|
|
3
|
+
export interface SelectionOverlay {
|
|
4
|
+
readonly selection: DocumentSelection;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly color: string;
|
|
7
|
+
}
|
|
3
8
|
/** Spec: pipeline.sdk.presentation */
|
|
4
|
-
export declare function mountTextSelection(pageText: readonly PageTextLine[], viewport: HTMLElement, shells: readonly HTMLElement[], pageBounds: readonly DocumentPage["size"][], nearby: ReadonlySet<number>, signal: AbortSignal): {
|
|
9
|
+
export declare function mountTextSelection(pageText: readonly PageTextLine[], viewport: HTMLElement, shells: readonly HTMLElement[], pageBounds: readonly DocumentPage["size"][], nearby: ReadonlySet<number>, signal: AbortSignal, input?: HTMLTextAreaElement, onSelectionChange?: (selection: DocumentSelection | undefined) => void): {
|
|
5
10
|
paint: () => void;
|
|
11
|
+
setSelectionOverlays(values: readonly SelectionOverlay[]): void;
|
|
12
|
+
readonly selection: DocumentSelection | undefined;
|
|
13
|
+
setSelection(value: DocumentSelection): void;
|
|
6
14
|
};
|
|
7
15
|
//# sourceMappingURL=text-selection.d.ts.map
|
|
@@ -3,6 +3,14 @@ export interface DocumentPoint {
|
|
|
3
3
|
readonly x: number;
|
|
4
4
|
readonly y: number;
|
|
5
5
|
}
|
|
6
|
+
export interface ParagraphPosition {
|
|
7
|
+
readonly paragraphId: string;
|
|
8
|
+
readonly offset: number;
|
|
9
|
+
}
|
|
10
|
+
export interface DocumentSelection {
|
|
11
|
+
readonly start: ParagraphPosition;
|
|
12
|
+
readonly end: ParagraphPosition;
|
|
13
|
+
}
|
|
6
14
|
export interface PageRectangle extends DocumentPoint {
|
|
7
15
|
readonly width: number;
|
|
8
16
|
readonly height: number;
|
|
@@ -35,6 +43,7 @@ export interface DocumentHit {
|
|
|
35
43
|
}>;
|
|
36
44
|
}
|
|
37
45
|
export interface PageTextLine {
|
|
46
|
+
readonly ink?: PageRectangle;
|
|
38
47
|
readonly pageIndex: number;
|
|
39
48
|
readonly order: number;
|
|
40
49
|
readonly clip: PageRectangle | null;
|
|
@@ -44,6 +53,12 @@ export interface PageTextLine {
|
|
|
44
53
|
transform?: PageTransform;
|
|
45
54
|
}>[];
|
|
46
55
|
readonly selection: Readonly<{
|
|
56
|
+
storyId?: string;
|
|
57
|
+
generated?: readonly Readonly<{
|
|
58
|
+
text: string;
|
|
59
|
+
x: number;
|
|
60
|
+
width: number;
|
|
61
|
+
}>[];
|
|
47
62
|
transform?: PageTransform;
|
|
48
63
|
paragraphId: string;
|
|
49
64
|
sourceOrder?: bigint;
|
|
@@ -54,6 +69,7 @@ export interface PageTextLine {
|
|
|
54
69
|
carets: readonly Readonly<{
|
|
55
70
|
scalarOffset: number;
|
|
56
71
|
x: number;
|
|
72
|
+
paragraphOffset?: number;
|
|
57
73
|
}>[];
|
|
58
74
|
}>;
|
|
59
75
|
}
|
|
@@ -77,9 +93,19 @@ export interface PageHitLine {
|
|
|
77
93
|
readonly emptyParagraph: boolean;
|
|
78
94
|
}
|
|
79
95
|
export interface PageInteraction {
|
|
96
|
+
readonly readingOrder: readonly Readonly<{
|
|
97
|
+
text: string;
|
|
98
|
+
headingLevel?: number;
|
|
99
|
+
}>[];
|
|
100
|
+
/** Spec: pipeline.sdk.pdf-export */
|
|
101
|
+
readonly figures?: readonly Readonly<{
|
|
102
|
+
elementId: string;
|
|
103
|
+
fragment: DocumentFragment;
|
|
104
|
+
}>[];
|
|
80
105
|
readonly text: readonly PageTextLine[];
|
|
81
106
|
readonly lines: readonly PageHitLine[];
|
|
82
107
|
readonly areas: readonly Readonly<{
|
|
108
|
+
kind?: "image";
|
|
83
109
|
elementId: string;
|
|
84
110
|
fragment: DocumentFragment;
|
|
85
111
|
}>[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from "./page-display-list.js";
|
|
2
2
|
export * from "./page-source.js";
|
|
3
|
-
export type { DocumentFragment, DocumentHit, DocumentPoint, PageTextLine, PageInteraction, FontFaceResource, ImageResourceData } from "../foundation/index.js";
|
|
3
|
+
export type { DocumentFragment, DocumentHit, DocumentPoint, DocumentSelection, ParagraphPosition, PageTextLine, PageInteraction, FontFaceResource, ImageResourceData } from "../foundation/index.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|