@beyondwork/docx-react-component 1.0.57 → 1.0.59
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 +1 -1
- package/package.json +2 -1
- package/src/api/awareness-identity-types.ts +4 -2
- package/src/api/comment-negotiation-types.ts +4 -1
- package/src/api/external-custody-types.ts +16 -0
- package/src/api/internal/build-ref-projections.ts +108 -0
- package/src/api/package-version.ts +1 -1
- package/src/api/participants-types.ts +11 -1
- package/src/api/public-types.ts +1149 -8
- package/src/api/scope-metadata-resolver-types.ts +6 -0
- package/src/compare/diff-engine.ts +3 -0
- package/src/core/commands/formatting-commands.ts +1 -0
- package/src/core/commands/index.ts +225 -16
- package/src/core/commands/legacy-form-field-commands.ts +181 -0
- package/src/core/commands/table-structure-commands.ts +149 -31
- package/src/core/selection/mapping.ts +20 -0
- package/src/core/state/editor-state.ts +2 -1
- package/src/index.ts +28 -0
- package/src/io/docx-session.ts +22 -3
- package/src/io/export/export-session.ts +11 -7
- package/src/io/export/ooxml-namespaces.ts +47 -0
- package/src/io/export/reattach-preserved-parts.ts +4 -16
- package/src/io/export/serialize-comments.ts +3 -131
- package/src/io/export/serialize-ffdata.ts +89 -0
- package/src/io/export/serialize-headers-footers.ts +5 -0
- package/src/io/export/serialize-main-document.ts +224 -34
- package/src/io/export/serialize-numbering.ts +22 -2
- package/src/io/export/serialize-revisions.ts +99 -0
- package/src/io/export/serialize-tables.ts +9 -0
- package/src/io/export/split-review-boundaries.ts +1 -0
- package/src/io/export/table-properties-xml.ts +14 -0
- package/src/io/load-scheduler.ts +70 -28
- package/src/io/normalize/normalize-text.ts +13 -0
- package/src/io/ooxml/_mini-xml.ts +198 -0
- package/src/io/ooxml/canonicalize-payload.ts +1 -4
- package/src/io/ooxml/chart/chart-style-table.ts +4 -3
- package/src/io/ooxml/chart/parse-chart-space.ts +2 -4
- package/src/io/ooxml/chart/parse-series.ts +2 -1
- package/src/io/ooxml/chart/resolve-color.ts +2 -2
- package/src/io/ooxml/chart/types.ts +6 -434
- package/src/io/ooxml/comment-presentation-payload.ts +6 -5
- package/src/io/ooxml/highlight-colors.ts +8 -5
- package/src/io/ooxml/parse-anchor.ts +68 -53
- package/src/io/ooxml/parse-comments.ts +14 -142
- package/src/io/ooxml/parse-complex-content.ts +3 -106
- package/src/io/ooxml/parse-drawing.ts +100 -195
- package/src/io/ooxml/parse-ffdata.ts +93 -0
- package/src/io/ooxml/parse-fields.ts +7 -146
- package/src/io/ooxml/parse-fill.ts +88 -8
- package/src/io/ooxml/parse-font-table.ts +5 -105
- package/src/io/ooxml/parse-footnotes.ts +28 -152
- package/src/io/ooxml/parse-headers-footers.ts +106 -212
- package/src/io/ooxml/parse-inline-media.ts +3 -200
- package/src/io/ooxml/parse-main-document.ts +180 -217
- package/src/io/ooxml/parse-numbering.ts +154 -335
- package/src/io/ooxml/parse-object.ts +147 -0
- package/src/io/ooxml/parse-ole-relationship.ts +82 -0
- package/src/io/ooxml/parse-paragraph-formatting.ts +7 -10
- package/src/io/ooxml/parse-picture-sdt.ts +85 -0
- package/src/io/ooxml/parse-picture.ts +120 -39
- package/src/io/ooxml/parse-revisions.ts +285 -51
- package/src/io/ooxml/parse-settings.ts +6 -99
- package/src/io/ooxml/parse-shapes.ts +25 -140
- package/src/io/ooxml/parse-styles.ts +3 -218
- package/src/io/ooxml/parse-tables.ts +76 -256
- package/src/io/ooxml/parse-theme.ts +1 -4
- package/src/io/ooxml/property-grab-bag.ts +5 -47
- package/src/io/ooxml/xml-element-serialize.ts +32 -0
- package/src/io/ooxml/xml-parser.ts +183 -0
- package/src/legal/bookmarks.ts +1 -1
- package/src/legal/cross-references.ts +1 -1
- package/src/legal/defined-terms.ts +1 -1
- package/src/legal/{_document-root.ts → document-root.ts} +8 -0
- package/src/legal/signature-blocks.ts +1 -1
- package/src/model/canonical-document.ts +165 -6
- package/src/model/chart-types.ts +439 -0
- package/src/model/snapshot.ts +3 -1
- package/src/review/store/comment-remapping.ts +24 -11
- package/src/review/store/revision-actions.ts +482 -2
- package/src/review/store/revision-store.ts +15 -0
- package/src/review/store/revision-types.ts +76 -0
- package/src/runtime/collab/remote-cursor-awareness.ts +24 -0
- package/src/runtime/collab/runtime-collab-sync.ts +33 -0
- package/src/runtime/diagnostics/build-diagnostic.ts +151 -0
- package/src/runtime/diagnostics/code-metadata-table.ts +221 -0
- package/src/runtime/document-runtime.ts +544 -35
- package/src/runtime/document-search.ts +176 -0
- package/src/runtime/edit-ops/index.ts +18 -2
- package/src/runtime/footnote-resolver.ts +130 -0
- package/src/runtime/layout/layout-engine-instance.ts +31 -4
- package/src/runtime/layout/layout-engine-version.ts +37 -1
- package/src/runtime/layout/page-graph.ts +14 -1
- package/src/runtime/layout/resolved-formatting-state.ts +21 -0
- package/src/runtime/numbering-prefix.ts +17 -0
- package/src/runtime/query-scopes.ts +183 -0
- package/src/runtime/resolved-numbering-geometry.ts +37 -6
- package/src/runtime/revision-runtime.ts +27 -1
- package/src/runtime/scope-resolver.ts +60 -0
- package/src/runtime/selection/post-edit-validator.ts +60 -6
- package/src/runtime/structure-ops/index.ts +20 -4
- package/src/runtime/surface-projection.ts +293 -18
- package/src/runtime/table-schema.ts +6 -0
- package/src/runtime/theme-color-resolver.ts +2 -2
- package/src/runtime/units.ts +9 -0
- package/src/runtime/workflow-rail-segments.ts +4 -0
- package/src/ui/WordReviewEditor.tsx +258 -44
- package/src/ui/editor-runtime-boundary.ts +13 -0
- package/src/ui/editor-shell-view.tsx +4 -1
- package/src/ui/headless/chrome-registry.ts +53 -0
- package/src/ui/headless/selection-tool-resolver.ts +11 -1
- package/src/ui-tailwind/chrome/chrome-preset-model.ts +13 -0
- package/src/ui-tailwind/chrome/tw-command-palette-mount.tsx +96 -0
- package/src/ui-tailwind/chrome/tw-context-menu.tsx +2 -1
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +5 -4
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +6 -2
- package/src/ui-tailwind/chrome/use-container-breakpoint.ts +111 -0
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +23 -9
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +158 -0
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +6 -7
- package/src/ui-tailwind/editor-surface/pm-schema.ts +105 -17
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +13 -0
- package/src/ui-tailwind/editor-surface/shape-renderer.ts +76 -14
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +18 -1
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +2 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +18 -2
- package/src/ui-tailwind/index.ts +9 -0
- package/src/ui-tailwind/page-chrome-model.ts +77 -5
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +56 -1
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +2 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +116 -113
- package/src/ui-tailwind/review/tw-review-rail-footer.tsx +2 -2
- package/src/ui-tailwind/theme/tokens.ts +14 -0
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +5 -0
- package/src/ui-tailwind/tw-review-workspace.tsx +52 -87
- package/src/validation/diagnostics.ts +1 -0
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* and any future OOXML import path can share the same implementation.
|
|
17
17
|
*/
|
|
18
18
|
import type { XmlElementNode } from "./xml-element.ts";
|
|
19
|
+
import { localName } from "./xml-attr-helpers.ts";
|
|
19
20
|
|
|
20
21
|
const ROOT_TAG = "__root__";
|
|
21
22
|
|
|
@@ -112,6 +113,188 @@ export function parseXml(xml: string): XmlElementNode {
|
|
|
112
113
|
return root;
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Like `parseXml` but records byte-offset positions (`start`, `end`) on every
|
|
118
|
+
* produced element and text node. Required by parsers that need to re-slice the
|
|
119
|
+
* source string to extract raw XML fragments (e.g. `rawXml` preservation,
|
|
120
|
+
* `sourceXml.slice(node.start, node.end)` patterns).
|
|
121
|
+
*
|
|
122
|
+
* The canonical `parseXml` above is lighter and preferred when position
|
|
123
|
+
* information is not needed.
|
|
124
|
+
*/
|
|
125
|
+
export function parseXmlWithOffsets(xml: string): XmlElementNode {
|
|
126
|
+
const root: XmlElementNode = {
|
|
127
|
+
type: "element",
|
|
128
|
+
name: "__root__",
|
|
129
|
+
attributes: {},
|
|
130
|
+
children: [],
|
|
131
|
+
start: 0,
|
|
132
|
+
end: xml.length,
|
|
133
|
+
};
|
|
134
|
+
const stack: XmlElementNode[] = [root];
|
|
135
|
+
let cursor = 0;
|
|
136
|
+
|
|
137
|
+
while (cursor < xml.length) {
|
|
138
|
+
if (xml.startsWith("<!--", cursor)) {
|
|
139
|
+
const end = xml.indexOf("-->", cursor);
|
|
140
|
+
cursor = end >= 0 ? end + 3 : xml.length;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (xml.startsWith("<?", cursor)) {
|
|
145
|
+
const end = xml.indexOf("?>", cursor);
|
|
146
|
+
cursor = end >= 0 ? end + 2 : xml.length;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (xml.startsWith("<![CDATA[", cursor)) {
|
|
151
|
+
const end = xml.indexOf("]]>", cursor);
|
|
152
|
+
const textEnd = end >= 0 ? end : xml.length;
|
|
153
|
+
stack[stack.length - 1]?.children.push({
|
|
154
|
+
type: "text",
|
|
155
|
+
text: xml.slice(cursor + 9, textEnd),
|
|
156
|
+
start: cursor,
|
|
157
|
+
end: end >= 0 ? end + 3 : xml.length,
|
|
158
|
+
});
|
|
159
|
+
cursor = end >= 0 ? end + 3 : xml.length;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (xml[cursor] !== "<") {
|
|
164
|
+
const nextTag = xml.indexOf("<", cursor);
|
|
165
|
+
const end = nextTag >= 0 ? nextTag : xml.length;
|
|
166
|
+
const text = decodeXmlEntities(xml.slice(cursor, end));
|
|
167
|
+
if (text.length > 0) {
|
|
168
|
+
stack[stack.length - 1]?.children.push({ type: "text", text, start: cursor, end });
|
|
169
|
+
}
|
|
170
|
+
cursor = end;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (xml[cursor + 1] === "/") {
|
|
175
|
+
const end = xml.indexOf(">", cursor);
|
|
176
|
+
if (end < 0) {
|
|
177
|
+
throw new Error("Malformed XML: missing closing >.");
|
|
178
|
+
}
|
|
179
|
+
const name = xml.slice(cursor + 2, end).trim();
|
|
180
|
+
const current = stack.pop();
|
|
181
|
+
if (!current || localName(current.name) !== localName(name)) {
|
|
182
|
+
throw new Error(`Malformed XML: unexpected closing tag </${name}>.`);
|
|
183
|
+
}
|
|
184
|
+
current.end = end + 1;
|
|
185
|
+
cursor = end + 1;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const tagEnd = findTagEndWithOffsets(xml, cursor);
|
|
190
|
+
const tagBody = xml.slice(cursor + 1, tagEnd);
|
|
191
|
+
const selfClosing = /\/\s*$/.test(tagBody);
|
|
192
|
+
const { name, attributes: tagAttributes } = parseTagWithOffsets(
|
|
193
|
+
tagBody.replace(/\/\s*$/, "").trim(),
|
|
194
|
+
);
|
|
195
|
+
const element: XmlElementNode = {
|
|
196
|
+
type: "element",
|
|
197
|
+
name,
|
|
198
|
+
attributes: tagAttributes,
|
|
199
|
+
children: [],
|
|
200
|
+
start: cursor,
|
|
201
|
+
end: tagEnd + 1,
|
|
202
|
+
};
|
|
203
|
+
stack[stack.length - 1]?.children.push(element);
|
|
204
|
+
|
|
205
|
+
if (!selfClosing) {
|
|
206
|
+
stack.push(element);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
cursor = tagEnd + 1;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (stack.length !== 1) {
|
|
213
|
+
throw new Error("Malformed XML: unclosed element.");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return root;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
function parseTagWithOffsets(
|
|
221
|
+
tagBody: string,
|
|
222
|
+
): { name: string; attributes: Record<string, string> } {
|
|
223
|
+
let cursor = 0;
|
|
224
|
+
while (cursor < tagBody.length && /\s/.test(tagBody[cursor] ?? "")) {
|
|
225
|
+
cursor += 1;
|
|
226
|
+
}
|
|
227
|
+
const nameStart = cursor;
|
|
228
|
+
while (cursor < tagBody.length && !/\s/.test(tagBody[cursor] ?? "")) {
|
|
229
|
+
cursor += 1;
|
|
230
|
+
}
|
|
231
|
+
const name = tagBody.slice(nameStart, cursor);
|
|
232
|
+
const attributes: Record<string, string> = {};
|
|
233
|
+
|
|
234
|
+
while (cursor < tagBody.length) {
|
|
235
|
+
while (cursor < tagBody.length && /\s/.test(tagBody[cursor] ?? "")) {
|
|
236
|
+
cursor += 1;
|
|
237
|
+
}
|
|
238
|
+
if (cursor >= tagBody.length) break;
|
|
239
|
+
const keyStart = cursor;
|
|
240
|
+
while (cursor < tagBody.length && !/[\s=]/.test(tagBody[cursor] ?? "")) {
|
|
241
|
+
cursor += 1;
|
|
242
|
+
}
|
|
243
|
+
const key = tagBody.slice(keyStart, cursor);
|
|
244
|
+
while (cursor < tagBody.length && /\s/.test(tagBody[cursor] ?? "")) {
|
|
245
|
+
cursor += 1;
|
|
246
|
+
}
|
|
247
|
+
if (tagBody[cursor] !== "=") {
|
|
248
|
+
attributes[key] = "";
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
cursor += 1;
|
|
252
|
+
while (cursor < tagBody.length && /\s/.test(tagBody[cursor] ?? "")) {
|
|
253
|
+
cursor += 1;
|
|
254
|
+
}
|
|
255
|
+
const quote = tagBody[cursor];
|
|
256
|
+
if (quote !== `"` && quote !== `'`) {
|
|
257
|
+
throw new Error(`Malformed XML attribute ${key}.`);
|
|
258
|
+
}
|
|
259
|
+
cursor += 1;
|
|
260
|
+
const valueStart = cursor;
|
|
261
|
+
while (cursor < tagBody.length && tagBody[cursor] !== quote) {
|
|
262
|
+
cursor += 1;
|
|
263
|
+
}
|
|
264
|
+
attributes[key] = decodeXmlEntities(tagBody.slice(valueStart, cursor));
|
|
265
|
+
cursor += 1;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return { name, attributes };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function findTagEndWithOffsets(xml: string, start: number): number {
|
|
272
|
+
let cursor = start + 1;
|
|
273
|
+
let quote: string | null = null;
|
|
274
|
+
|
|
275
|
+
while (cursor < xml.length) {
|
|
276
|
+
const current = xml[cursor];
|
|
277
|
+
if (quote) {
|
|
278
|
+
if (current === quote) {
|
|
279
|
+
quote = null;
|
|
280
|
+
}
|
|
281
|
+
cursor += 1;
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
if (current === `"` || current === `'`) {
|
|
285
|
+
quote = current;
|
|
286
|
+
cursor += 1;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (current === ">") {
|
|
290
|
+
return cursor;
|
|
291
|
+
}
|
|
292
|
+
cursor += 1;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
throw new Error("Malformed XML: missing >.");
|
|
296
|
+
}
|
|
297
|
+
|
|
115
298
|
/** Decode the standard XML entity references plus numeric character references. */
|
|
116
299
|
export function decodeXmlEntities(text: string): string {
|
|
117
300
|
return text
|
package/src/legal/bookmarks.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
FieldRegistry,
|
|
8
8
|
FieldRegistryEntry,
|
|
9
9
|
} from "../model/canonical-document.ts";
|
|
10
|
-
import { resolveWalkableRoot } from "./
|
|
10
|
+
import { resolveWalkableRoot } from "./document-root.ts";
|
|
11
11
|
|
|
12
12
|
export interface LegalBookmark {
|
|
13
13
|
bookmarkId: string;
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
ParagraphNode,
|
|
13
13
|
TocEntry,
|
|
14
14
|
} from "../model/canonical-document.ts";
|
|
15
|
-
import { resolveWalkableRoot } from "./
|
|
15
|
+
import { resolveWalkableRoot } from "./document-root.ts";
|
|
16
16
|
|
|
17
17
|
export interface CrossReferencePattern {
|
|
18
18
|
kind: "section" | "clause" | "article" | "schedule" | "exhibit" | "appendix";
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
DocumentNode,
|
|
5
5
|
ParagraphNode,
|
|
6
6
|
} from "../model/canonical-document.ts";
|
|
7
|
-
import { resolveWalkableRoot } from "./
|
|
7
|
+
import { resolveWalkableRoot } from "./document-root.ts";
|
|
8
8
|
|
|
9
9
|
export interface DefinedTermOccurrence {
|
|
10
10
|
paragraphIndex: number;
|
|
@@ -4,6 +4,14 @@ import type {
|
|
|
4
4
|
DocumentRootNode,
|
|
5
5
|
} from "../model/canonical-document.ts";
|
|
6
6
|
|
|
7
|
+
// Compile-time guard: CanonicalDocument must never gain a `type` field,
|
|
8
|
+
// because resolveWalkableRoot uses `!("type" in document)` to distinguish
|
|
9
|
+
// a CanonicalDocument envelope from a DocumentNode union member.
|
|
10
|
+
type _CanonicalDocumentHasNoTypeField = "type" extends keyof CanonicalDocument
|
|
11
|
+
? never
|
|
12
|
+
: true;
|
|
13
|
+
const _: _CanonicalDocumentHasNoTypeField = true;
|
|
14
|
+
|
|
7
15
|
/**
|
|
8
16
|
* Accept either a full `CanonicalDocument` (or a Pick of it carrying `content`)
|
|
9
17
|
* or a raw `DocumentNode`, and return the node to walk.
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
DocumentNode,
|
|
5
5
|
ParagraphNode,
|
|
6
6
|
} from "../model/canonical-document.ts";
|
|
7
|
-
import { resolveWalkableRoot } from "./
|
|
7
|
+
import { resolveWalkableRoot } from "./document-root.ts";
|
|
8
8
|
|
|
9
9
|
export interface SignatureBlockCandidate {
|
|
10
10
|
startIndex: number;
|
|
@@ -16,10 +16,10 @@ import type {
|
|
|
16
16
|
ScopeMarkerStartNode,
|
|
17
17
|
ScopeMarkerEndNode,
|
|
18
18
|
} from "./scope-markers.ts";
|
|
19
|
-
import type { ChartModel } from "
|
|
19
|
+
import type { ChartModel } from "./chart-types.ts";
|
|
20
20
|
|
|
21
21
|
export type { ScopeMarkerStartNode, ScopeMarkerEndNode } from "./scope-markers.ts";
|
|
22
|
-
export type { ChartModel } from "
|
|
22
|
+
export type { ChartModel } from "./chart-types.ts";
|
|
23
23
|
|
|
24
24
|
const CANONICAL_DOCUMENT_TOP_LEVEL_KEYS = [
|
|
25
25
|
"schemaVersion",
|
|
@@ -284,6 +284,7 @@ export interface NumberingLevelOverrideDefinition {
|
|
|
284
284
|
paragraphGeometry?: NumberingLevelParagraphGeometry;
|
|
285
285
|
runProperties?: CanonicalRunFormatting;
|
|
286
286
|
restartAfterLevel?: number;
|
|
287
|
+
picBulletId?: string;
|
|
287
288
|
}
|
|
288
289
|
|
|
289
290
|
export interface NumberingInstance {
|
|
@@ -555,7 +556,8 @@ export type DocumentNode =
|
|
|
555
556
|
| ShapeNode
|
|
556
557
|
| WordArtNode
|
|
557
558
|
| VmlShapeNode
|
|
558
|
-
| DrawingFrameNode
|
|
559
|
+
| DrawingFrameNode
|
|
560
|
+
| OleEmbedNode;
|
|
559
561
|
|
|
560
562
|
export interface DocumentRootNode {
|
|
561
563
|
type: "doc";
|
|
@@ -833,6 +835,19 @@ export interface CellShading {
|
|
|
833
835
|
fill?: string;
|
|
834
836
|
color?: string;
|
|
835
837
|
val?: string;
|
|
838
|
+
/**
|
|
839
|
+
* SOW gap G3 — theme-shading references (§17.3.5). When `themeFill` is set
|
|
840
|
+
* and `fill` is absent or "auto", the runtime resolves the shading via
|
|
841
|
+
* `ThemeColorResolver.resolveWordThemeColor(themeFill, themeFillTint,
|
|
842
|
+
* themeFillShade)`. Fields are kept verbatim so export can round-trip the
|
|
843
|
+
* original `w:shd` element without re-encoding the resolved hex.
|
|
844
|
+
*/
|
|
845
|
+
themeFill?: string;
|
|
846
|
+
themeFillTint?: string;
|
|
847
|
+
themeFillShade?: string;
|
|
848
|
+
themeColor?: string;
|
|
849
|
+
themeColorTint?: string;
|
|
850
|
+
themeColorShade?: string;
|
|
836
851
|
}
|
|
837
852
|
|
|
838
853
|
export interface TableCellMargins {
|
|
@@ -1062,6 +1077,41 @@ export interface FieldNode {
|
|
|
1062
1077
|
includeNumbering?: boolean;
|
|
1063
1078
|
includeLevel?: boolean;
|
|
1064
1079
|
};
|
|
1080
|
+
/** Legacy form-field metadata from w:ffData (textInput, checkBox, ddList). Round-trip only; no UI for MVP. */
|
|
1081
|
+
legacyFormField?: LegacyFormFieldNode;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
export type LegacyFormFieldKind = "textInput" | "checkBox" | "ddList";
|
|
1085
|
+
|
|
1086
|
+
export interface LegacyFormFieldNode {
|
|
1087
|
+
kind: LegacyFormFieldKind;
|
|
1088
|
+
name?: string;
|
|
1089
|
+
enabled?: boolean;
|
|
1090
|
+
calcOnExit?: boolean;
|
|
1091
|
+
textInput?: {
|
|
1092
|
+
default?: string;
|
|
1093
|
+
maxLength?: number;
|
|
1094
|
+
format?: string;
|
|
1095
|
+
};
|
|
1096
|
+
checkBox?: {
|
|
1097
|
+
size?: number;
|
|
1098
|
+
default?: boolean;
|
|
1099
|
+
checked?: boolean;
|
|
1100
|
+
};
|
|
1101
|
+
ddList?: {
|
|
1102
|
+
default?: number;
|
|
1103
|
+
listEntry?: string[];
|
|
1104
|
+
};
|
|
1105
|
+
/** Verbatim <w:ffData>…</w:ffData> XML for lossless round-trip. */
|
|
1106
|
+
rawXml: string;
|
|
1107
|
+
/**
|
|
1108
|
+
* Phase V.a: set to `true` when typed fields have been mutated via
|
|
1109
|
+
* `setLegacyFormFieldValue` since parse. On serialize, the `rawXml` is
|
|
1110
|
+
* regenerated from the typed fields via `regenerateFFDataRawXml`.
|
|
1111
|
+
* Un-mutated nodes emit the preserved `rawXml` verbatim for lossless
|
|
1112
|
+
* round-trip.
|
|
1113
|
+
*/
|
|
1114
|
+
mutated?: boolean;
|
|
1065
1115
|
}
|
|
1066
1116
|
|
|
1067
1117
|
// ─── Field registry ─────────────────────────────────────────────────────────
|
|
@@ -1198,7 +1248,10 @@ export interface SectionProperties {
|
|
|
1198
1248
|
*/
|
|
1199
1249
|
export interface FootnoteProperties {
|
|
1200
1250
|
pos?: "pageBottom" | "beneathText" | "sectEnd" | "docEnd";
|
|
1201
|
-
numFmt?: "decimal" | "upperRoman" | "lowerRoman" | "upperLetter" | "lowerLetter"
|
|
1251
|
+
numFmt?: "decimal" | "upperRoman" | "lowerRoman" | "upperLetter" | "lowerLetter"
|
|
1252
|
+
| "ordinal" | "cardinalText" | "ordinalText" | "hex" | "chicago" | "bullet"
|
|
1253
|
+
| "ideographDigital" | "japaneseCounting" | "arabicAbjad" | "arabicAlpha"
|
|
1254
|
+
| "none";
|
|
1202
1255
|
numStart?: number;
|
|
1203
1256
|
numRestart?: "continuous" | "eachSect" | "eachPage";
|
|
1204
1257
|
}
|
|
@@ -1289,7 +1342,8 @@ export type InlineNode =
|
|
|
1289
1342
|
| ShapeNode
|
|
1290
1343
|
| WordArtNode
|
|
1291
1344
|
| VmlShapeNode
|
|
1292
|
-
| DrawingFrameNode
|
|
1345
|
+
| DrawingFrameNode
|
|
1346
|
+
| OleEmbedNode;
|
|
1293
1347
|
|
|
1294
1348
|
export interface TextNode {
|
|
1295
1349
|
type: "text";
|
|
@@ -1450,10 +1504,50 @@ export interface VmlShapeNode {
|
|
|
1450
1504
|
rawXml: string;
|
|
1451
1505
|
}
|
|
1452
1506
|
|
|
1507
|
+
/**
|
|
1508
|
+
* Preserve-only OLE embedded object (Lane 7c Slice 7c.1).
|
|
1509
|
+
*
|
|
1510
|
+
* Captures `<w:object>` subtrees whose child is `<o:OLEObject>` — Excel
|
|
1511
|
+
* ranges, PowerPoint slides, and other OLE-packaged payloads embedded in
|
|
1512
|
+
* the document via an OPC relationship. The original object XML is
|
|
1513
|
+
* retained in `rawXml` and re-emitted verbatim on export; the binary
|
|
1514
|
+
* package part is preserved through the opaque-fragment / package-part
|
|
1515
|
+
* store reached via `relationshipId`.
|
|
1516
|
+
*
|
|
1517
|
+
* Native render is out of scope: this node models the preservation
|
|
1518
|
+
* contract only. Placeholder badge chrome (Lane 6b post-v2.0) will hang
|
|
1519
|
+
* off `{progId, relationshipId}` when the chrome slice activates.
|
|
1520
|
+
*
|
|
1521
|
+
* Non-OLE `<w:object>` elements (legacy VML-wrapped objects without
|
|
1522
|
+
* `<o:OLEObject>`) continue to flow through the generic opaque-fragment
|
|
1523
|
+
* path and do NOT materialize as `OleEmbedNode` — parsers must fall
|
|
1524
|
+
* through when `<o:OLEObject>` is absent.
|
|
1525
|
+
*/
|
|
1526
|
+
export interface OleEmbedNode {
|
|
1527
|
+
type: "ole_embed";
|
|
1528
|
+
id: string;
|
|
1529
|
+
progId?: string;
|
|
1530
|
+
embedType: "oleObject";
|
|
1531
|
+
relationshipId: string;
|
|
1532
|
+
metadata: {
|
|
1533
|
+
originalFilename?: string;
|
|
1534
|
+
classId?: string;
|
|
1535
|
+
shapeId?: string;
|
|
1536
|
+
};
|
|
1537
|
+
rawXml: string;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1453
1540
|
export interface AnchorGeometry {
|
|
1454
1541
|
display: "inline" | "floating";
|
|
1455
1542
|
extent: { widthEmu: number; heightEmu: number };
|
|
1456
1543
|
wrapMode: "none" | "square" | "tight" | "through" | "topAndBottom";
|
|
1544
|
+
/**
|
|
1545
|
+
* Polygon coords (in OOXML's 21600ths-of-image units) when wrapMode is
|
|
1546
|
+
* "tight" or "through" and `wp:wrapPolygon` is present. First point from
|
|
1547
|
+
* `wp:start`; subsequent points from sequential `wp:lineTo`. Consumed by
|
|
1548
|
+
* Lane 6 P7 float-wrap for proper polygon text flow.
|
|
1549
|
+
*/
|
|
1550
|
+
wrapPolygon?: Array<{ x: number; y: number }>;
|
|
1457
1551
|
positionH?: { relativeFrom: string; align?: string; offset?: number };
|
|
1458
1552
|
positionV?: { relativeFrom: string; align?: string; offset?: number };
|
|
1459
1553
|
distMargins?: { top?: number; bottom?: number; left?: number; right?: number };
|
|
@@ -1462,22 +1556,66 @@ export interface AnchorGeometry {
|
|
|
1462
1556
|
layoutInCell?: boolean;
|
|
1463
1557
|
allowOverlap?: boolean;
|
|
1464
1558
|
simplePos?: boolean;
|
|
1465
|
-
docPr?: {
|
|
1559
|
+
docPr?: {
|
|
1560
|
+
id: string;
|
|
1561
|
+
name?: string;
|
|
1562
|
+
descr?: string;
|
|
1563
|
+
/** `wp:docPr hidden="1"` — Word UI hides the frame from the user. */
|
|
1564
|
+
hidden?: boolean;
|
|
1565
|
+
};
|
|
1566
|
+
/**
|
|
1567
|
+
* `wp:cNvGraphicFramePr/a:graphicFrameLocks` — object-manipulation locks
|
|
1568
|
+
* consumed by Lane 6 object chrome (disable resize handles / move, etc.).
|
|
1569
|
+
*/
|
|
1570
|
+
frameLocks?: {
|
|
1571
|
+
noChangeAspect?: boolean;
|
|
1572
|
+
noResize?: boolean;
|
|
1573
|
+
noMove?: boolean;
|
|
1574
|
+
noRot?: boolean;
|
|
1575
|
+
noSelect?: boolean;
|
|
1576
|
+
noGrp?: boolean;
|
|
1577
|
+
};
|
|
1466
1578
|
}
|
|
1467
1579
|
|
|
1468
1580
|
export interface PictureContent {
|
|
1469
1581
|
type: "picture";
|
|
1470
1582
|
blipRef: string;
|
|
1583
|
+
/**
|
|
1584
|
+
* Phase 4.4 G4 — true when the image references an external URL via
|
|
1585
|
+
* `a:blip r:link` (bytes not in the .docx package) rather than embedded
|
|
1586
|
+
* via `r:embed`. External-linked images can't resolve to mediaId;
|
|
1587
|
+
* `state: "missing"` in surface projection.
|
|
1588
|
+
*/
|
|
1589
|
+
isLinked?: boolean;
|
|
1471
1590
|
/** Resolved media catalog ID (e.g. "media:word/media/image1.png"), populated by parse-drawing. */
|
|
1472
1591
|
mediaId?: string;
|
|
1473
1592
|
/** Absolute package path for media catalog lookup. */
|
|
1474
1593
|
packagePartName?: string;
|
|
1475
1594
|
srcRect?: { top: number; bottom: number; left: number; right: number };
|
|
1476
1595
|
stretch?: boolean;
|
|
1596
|
+
/**
|
|
1597
|
+
* Phase 4.5 G7 — `pic:blipFill/a:tile` (tiled image repeat). Mutually
|
|
1598
|
+
* exclusive with `stretch`. tx/ty = offset (EMUs), sx/sy = scale ×1000,
|
|
1599
|
+
* flip = "x"|"y"|"xy", algn = alignment token.
|
|
1600
|
+
*/
|
|
1601
|
+
tile?: {
|
|
1602
|
+
tx?: number;
|
|
1603
|
+
ty?: number;
|
|
1604
|
+
sx?: number;
|
|
1605
|
+
sy?: number;
|
|
1606
|
+
flip?: "x" | "y" | "xy";
|
|
1607
|
+
algn?: string;
|
|
1608
|
+
};
|
|
1477
1609
|
rotation?: number;
|
|
1478
1610
|
flipH?: boolean;
|
|
1479
1611
|
flipV?: boolean;
|
|
1480
1612
|
presetGeom?: string;
|
|
1613
|
+
/** N11.b — DrawingML a:softEdge feather radius in EMU. */
|
|
1614
|
+
softEdgeRadius?: number;
|
|
1615
|
+
/** N11.b — DrawingML a:outerShdw attributes. `dir` is in 60000ths of a degree; `blurRad`/`dist` in EMU. */
|
|
1616
|
+
outerShadow?: { blurRad: number; dist: number; dir: number; color: string; colorType: "srgbClr" | "schemeClr" };
|
|
1617
|
+
/** N11.b — DrawingML a:glow radius in EMU + color. */
|
|
1618
|
+
glow?: { radius: number; color: string; colorType: "srgbClr" | "schemeClr" };
|
|
1481
1619
|
/** Original w:drawing XML slice, preserved for lossless round-trip serialization. */
|
|
1482
1620
|
rawXml?: string;
|
|
1483
1621
|
}
|
|
@@ -2264,6 +2402,27 @@ function validateDocumentNode(
|
|
|
2264
2402
|
}
|
|
2265
2403
|
return;
|
|
2266
2404
|
}
|
|
2405
|
+
case "ole_embed":
|
|
2406
|
+
expectString(record.id, `${path}.id`, issues);
|
|
2407
|
+
expectString(record.relationshipId, `${path}.relationshipId`, issues);
|
|
2408
|
+
expectString(record.rawXml, `${path}.rawXml`, issues);
|
|
2409
|
+
if (record.embedType !== "oleObject") {
|
|
2410
|
+
issues.push({
|
|
2411
|
+
path: `${path}.embedType`,
|
|
2412
|
+
message: "embedType must be 'oleObject'.",
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
if (record.progId !== undefined) {
|
|
2416
|
+
expectString(record.progId, `${path}.progId`, issues);
|
|
2417
|
+
}
|
|
2418
|
+
if (record.metadata === undefined || record.metadata === null ||
|
|
2419
|
+
typeof record.metadata !== "object") {
|
|
2420
|
+
issues.push({
|
|
2421
|
+
path: `${path}.metadata`,
|
|
2422
|
+
message: "metadata must be an object.",
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
return;
|
|
2267
2426
|
default:
|
|
2268
2427
|
issues.push({
|
|
2269
2428
|
path: `${path}.type`,
|