@stll/folio-core 0.40.0 → 0.42.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 +16 -0
- package/dist/ai-edits/clean-text.d.ts +28 -6
- package/dist/ai-edits/clean-text.js +28 -13
- package/dist/ai-edits/headless.d.ts +12 -0
- package/dist/ai-edits/headless.js +26 -3
- package/dist/ai-edits/snapshot.d.ts +6 -1
- package/dist/ai-edits/snapshot.js +15 -10
- package/dist/ai-suggestions/text-positions.js +15 -3
- package/dist/compare/inline-atoms.js +2 -2
- package/dist/compat/eigenpal.d.ts +4 -3
- package/dist/compat/eigenpal.js +2 -1
- package/dist/display-list/primitives.d.ts +2 -1
- package/dist/document-operations.d.ts +3 -2
- package/dist/docx/blockPlainText.d.ts +8 -0
- package/dist/docx/blockPlainText.js +40 -0
- package/dist/docx/compatibility.d.ts +16 -2
- package/dist/docx/compatibility.js +30 -9
- package/dist/docx/footnoteParser.js +4 -23
- package/dist/docx/graphicFrameLocks.d.ts +22 -0
- package/dist/docx/graphicFrameLocks.js +55 -0
- package/dist/docx/groupDrawingParser.d.ts +7 -1
- package/dist/docx/groupDrawingParser.js +11 -2
- package/dist/docx/headerFooterParser.d.ts +5 -1
- package/dist/docx/headerFooterParser.js +7 -21
- package/dist/docx/imageParser.js +5 -0
- package/dist/docx/imageRawXml.d.ts +33 -1
- package/dist/docx/imageRawXml.js +56 -1
- package/dist/docx/rezip.d.ts +20 -3
- package/dist/docx/rezip.js +24 -13
- package/dist/docx/runParser.js +43 -21
- package/dist/docx/serializer/runSerializer.js +4 -2
- package/dist/docx/server/createBilingualDocument.js +31 -5
- package/dist/docx/shapeParser.js +32 -6
- package/dist/docx/vmlImageParser.d.ts +11 -1
- package/dist/docx/vmlImageParser.js +29 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/internal/compare/inline-presentation.d.ts +11 -3
- package/dist/internal/compare/inline-presentation.js +8 -1
- package/dist/prosemirror/attrs/index.js +33 -3
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +13 -2
- package/dist/prosemirror/conversion/fromProseDoc.js +80 -27
- package/dist/prosemirror/conversion/index.d.ts +2 -2
- package/dist/prosemirror/conversion/toProseDoc.js +10 -2
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +6 -0
- package/dist/prosemirror/imageCommit.js +7 -3
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +16 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +20 -1
- package/dist/prosemirror/schema/nodes.d.ts +20 -0
- package/dist/server.d.ts +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -46,6 +46,22 @@ const document = createEmptyDocument({
|
|
|
46
46
|
const docx = await createDocx(document);
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
A document built from scratch states no author and no application unless the
|
|
50
|
+
host names them. Pass either to write it:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
const docx = await createDocx(document, {
|
|
54
|
+
creator: "Marie Nováková",
|
|
55
|
+
application: "Example Host",
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`creator` becomes `dc:creator` in `docProps/core.xml`; `application` becomes
|
|
60
|
+
`Application` in `docProps/app.xml`, alongside the `AppVersion` the schema
|
|
61
|
+
form requires. An omitted value writes no element at all. Both are ignored for
|
|
62
|
+
a document that carries a source package: that package keeps the properties it
|
|
63
|
+
already states.
|
|
64
|
+
|
|
49
65
|
Style sets are content-free JSON values. Inspect a source file before presenting
|
|
50
66
|
styles for selection, extract the selected dependency closure, persist the
|
|
51
67
|
result, and load it into any later document:
|
|
@@ -44,6 +44,18 @@ type CleanTextStructuralBoundary = {
|
|
|
44
44
|
clear?: PageBreakRunAttrs["clear"];
|
|
45
45
|
/** Whether the post-tracked-changes projection retains this carrier. */
|
|
46
46
|
presentInCleanView: boolean;
|
|
47
|
+
} | {
|
|
48
|
+
/**
|
|
49
|
+
* A field result: several clean-text characters over a single PM
|
|
50
|
+
* position. Only the whole span is addressable, so a text range may
|
|
51
|
+
* start or end at its edges but never inside it.
|
|
52
|
+
*/
|
|
53
|
+
type: "field";
|
|
54
|
+
offset: number;
|
|
55
|
+
/** Characters the result contributes; always greater than one. */
|
|
56
|
+
length: number;
|
|
57
|
+
from: number;
|
|
58
|
+
to: number;
|
|
47
59
|
};
|
|
48
60
|
type ResolveCleanTextRangeOptions = {
|
|
49
61
|
cleanBlock: CleanBlockText;
|
|
@@ -51,17 +63,27 @@ type ResolveCleanTextRangeOptions = {
|
|
|
51
63
|
endOffset: number;
|
|
52
64
|
};
|
|
53
65
|
/**
|
|
54
|
-
* Resolve clean-text offsets without selecting a
|
|
66
|
+
* Resolve clean-text offsets without selecting a structural atom.
|
|
55
67
|
*
|
|
56
|
-
* A range wholly on one side of a boundary is biased away from the
|
|
57
|
-
* range spanning both sides
|
|
58
|
-
* and returns `null`; a structural
|
|
68
|
+
* A range wholly on one side of a zero-width boundary is biased away from the
|
|
69
|
+
* atom. A range spanning both sides, or cutting into a field result, is
|
|
70
|
+
* unrepresentable as a generic text selection and returns `null`; a structural
|
|
71
|
+
* operation must own that mutation instead.
|
|
59
72
|
*/
|
|
60
73
|
declare const resolveCleanTextRange: ({ cleanBlock, startOffset, endOffset }: ResolveCleanTextRangeOptions) => {
|
|
61
74
|
from: number;
|
|
62
75
|
to: number;
|
|
63
76
|
} | null;
|
|
64
|
-
|
|
77
|
+
type BuildCleanBlockTextOptions = {
|
|
78
|
+
/**
|
|
79
|
+
* `"text"` reads a field as the result Word shows, which is the view a reader
|
|
80
|
+
* and the AI reason against. `"omitted"` drops it, which is what an alignment
|
|
81
|
+
* coordinate needs: an atom present on only one side must not shift the
|
|
82
|
+
* offsets that locate it.
|
|
83
|
+
*/
|
|
84
|
+
fieldResults: "text" | "omitted";
|
|
85
|
+
};
|
|
86
|
+
declare const buildCleanBlockText: (blockNode: Node, blockFrom: number, { fieldResults }?: BuildCleanBlockTextOptions) => CleanBlockText;
|
|
65
87
|
/**
|
|
66
88
|
* A "redline-aware" view of a textblock: the same left-to-right traversal as
|
|
67
89
|
* {@link buildCleanBlockText}, but every tracked change and comment anchor is
|
|
@@ -83,4 +105,4 @@ declare const buildCleanBlockText: (blockNode: Node, blockFrom: number) => Clean
|
|
|
83
105
|
*/
|
|
84
106
|
declare const buildAnnotatedBlockText: (blockNode: Node) => string;
|
|
85
107
|
//#endregion
|
|
86
|
-
export { CleanBlockText, CleanTextStructuralBoundary, buildAnnotatedBlockText, buildCleanBlockText, resolveCleanTextRange };
|
|
108
|
+
export { BuildCleanBlockTextOptions, CleanBlockText, CleanTextStructuralBoundary, buildAnnotatedBlockText, buildCleanBlockText, resolveCleanTextRange };
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { expectPageBreakRunAttrs } from "../prosemirror/attrs/index.js";
|
|
2
|
-
import { runFormattingInlineControlCharacter } from "../prosemirror/runFormattingInlineCarriers.js";
|
|
2
|
+
import { runFormattingInlineAtomCleanText, runFormattingInlineControlCharacter } from "../prosemirror/runFormattingInlineCarriers.js";
|
|
3
3
|
//#region src/ai-edits/clean-text.ts
|
|
4
4
|
const EMPTY_CLEAN_TEXT_STRUCTURAL_BOUNDARIES = Object.freeze([]);
|
|
5
|
+
const cutsIntoSpan = ({ offset, length }, boundaryOffset) => boundaryOffset > offset && boundaryOffset < offset + length;
|
|
5
6
|
/**
|
|
6
|
-
* Resolve clean-text offsets without selecting a
|
|
7
|
+
* Resolve clean-text offsets without selecting a structural atom.
|
|
7
8
|
*
|
|
8
|
-
* A range wholly on one side of a boundary is biased away from the
|
|
9
|
-
* range spanning both sides
|
|
10
|
-
* and returns `null`; a structural
|
|
9
|
+
* A range wholly on one side of a zero-width boundary is biased away from the
|
|
10
|
+
* atom. A range spanning both sides, or cutting into a field result, is
|
|
11
|
+
* unrepresentable as a generic text selection and returns `null`; a structural
|
|
12
|
+
* operation must own that mutation instead.
|
|
11
13
|
*/
|
|
12
14
|
const resolveCleanTextRange = ({ cleanBlock, startOffset, endOffset }) => {
|
|
13
15
|
if (!Number.isInteger(startOffset) || !Number.isInteger(endOffset) || startOffset < 0 || endOffset < startOffset || endOffset > cleanBlock.text.length) return null;
|
|
@@ -22,6 +24,10 @@ const resolveCleanTextRange = ({ cleanBlock, startOffset, endOffset }) => {
|
|
|
22
24
|
let from = baseFrom;
|
|
23
25
|
let to = baseTo;
|
|
24
26
|
for (const boundary of structuralBoundaries) {
|
|
27
|
+
if (boundary.type === "field") {
|
|
28
|
+
if (cutsIntoSpan(boundary, startOffset) || cutsIntoSpan(boundary, endOffset)) return null;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
25
31
|
if (boundary.offset > startOffset && boundary.offset < endOffset) return null;
|
|
26
32
|
if (boundary.offset === startOffset) from = Math.max(from, boundary.to);
|
|
27
33
|
if (startOffset !== endOffset && boundary.offset === endOffset) to = Math.min(to, boundary.from);
|
|
@@ -40,7 +46,8 @@ const INSERTION_MARK = "insertion";
|
|
|
40
46
|
const COMMENT_MARK = "comment";
|
|
41
47
|
const HIDDEN_MARK = "hidden";
|
|
42
48
|
const isOmittedFromCleanView = (node) => node.marks.some((mark) => mark.type.name === DELETION_MARK || mark.type.name === HIDDEN_MARK);
|
|
43
|
-
const
|
|
49
|
+
const DEFAULT_BUILD_CLEAN_BLOCK_TEXT_OPTIONS = { fieldResults: "text" };
|
|
50
|
+
const buildCleanBlockText = (blockNode, blockFrom, { fieldResults } = DEFAULT_BUILD_CLEAN_BLOCK_TEXT_OPTIONS) => {
|
|
44
51
|
let text = "";
|
|
45
52
|
const offsets = [];
|
|
46
53
|
let structuralBoundaries;
|
|
@@ -59,12 +66,19 @@ const buildCleanBlockText = (blockNode, blockFrom) => {
|
|
|
59
66
|
});
|
|
60
67
|
return false;
|
|
61
68
|
}
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
69
|
+
const atomText = fieldResults === "omitted" ? runFormattingInlineControlCharacter(node) : runFormattingInlineAtomCleanText(node);
|
|
70
|
+
if (atomText !== null) {
|
|
64
71
|
if (isOmittedFromCleanView(node)) return false;
|
|
65
72
|
const startPos = blockFrom + 1 + pos;
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
if (atomText.length > 1) (structuralBoundaries ??= []).push({
|
|
74
|
+
type: "field",
|
|
75
|
+
offset: text.length,
|
|
76
|
+
length: atomText.length,
|
|
77
|
+
from: startPos,
|
|
78
|
+
to: startPos + node.nodeSize
|
|
79
|
+
});
|
|
80
|
+
for (let index = 0; index < atomText.length; index++) offsets.push(startPos);
|
|
81
|
+
text += atomText;
|
|
68
82
|
lastEnd = startPos + node.nodeSize;
|
|
69
83
|
return false;
|
|
70
84
|
}
|
|
@@ -105,16 +119,17 @@ const buildCleanBlockText = (blockNode, blockFrom) => {
|
|
|
105
119
|
const buildAnnotatedBlockText = (blockNode) => {
|
|
106
120
|
const segments = [];
|
|
107
121
|
blockNode.descendants((node) => {
|
|
108
|
-
|
|
122
|
+
const text = node.isText ? node.text : runFormattingInlineAtomCleanText(node);
|
|
123
|
+
if (text === void 0 || text === null) return true;
|
|
109
124
|
const annotation = annotationOf(node.marks);
|
|
110
125
|
const previous = segments.at(-1);
|
|
111
126
|
if (previous && sameAnnotation(previous.annotation, annotation)) {
|
|
112
|
-
previous.text +=
|
|
127
|
+
previous.text += text;
|
|
113
128
|
return false;
|
|
114
129
|
}
|
|
115
130
|
segments.push({
|
|
116
131
|
annotation,
|
|
117
|
-
text
|
|
132
|
+
text
|
|
118
133
|
});
|
|
119
134
|
return false;
|
|
120
135
|
});
|
|
@@ -514,6 +514,18 @@ declare class FolioDocxReviewer {
|
|
|
514
514
|
private createComparisonHeaderFooter;
|
|
515
515
|
private canImportHeaderFooterContent;
|
|
516
516
|
private getNoteStory;
|
|
517
|
+
/**
|
|
518
|
+
* A loaded story's blocks, so its text comes from the same walk an unloaded
|
|
519
|
+
* one uses.
|
|
520
|
+
*
|
|
521
|
+
* The two used to be separate walks and disagreed: the model walk separates
|
|
522
|
+
* paragraphs, joins table cells with a tab and reads the accepted
|
|
523
|
+
* tracked-change view, while the editor walk concatenated text nodes and saw
|
|
524
|
+
* none of that. The same note therefore read one way before it was loaded and
|
|
525
|
+
* another after. This is the conversion the save path already performs on the
|
|
526
|
+
* same states, so the text now describes exactly what a save would write.
|
|
527
|
+
*/
|
|
528
|
+
private storyBlocks;
|
|
517
529
|
private getHeaderFooterStoryText;
|
|
518
530
|
private getNoteStoryText;
|
|
519
531
|
private getStoryText;
|
|
@@ -1530,14 +1530,37 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
1530
1530
|
if (story.type === "footnote") return this.baseDocument.package.footnotes?.find((note) => note.id === story.noteId && !isSeparatorFootnote(note));
|
|
1531
1531
|
return this.baseDocument.package.endnotes?.find((note) => note.id === story.noteId && !isSeparatorEndnote(note));
|
|
1532
1532
|
}
|
|
1533
|
+
/**
|
|
1534
|
+
* A loaded story's blocks, so its text comes from the same walk an unloaded
|
|
1535
|
+
* one uses.
|
|
1536
|
+
*
|
|
1537
|
+
* The two used to be separate walks and disagreed: the model walk separates
|
|
1538
|
+
* paragraphs, joins table cells with a tab and reads the accepted
|
|
1539
|
+
* tracked-change view, while the editor walk concatenated text nodes and saw
|
|
1540
|
+
* none of that. The same note therefore read one way before it was loaded and
|
|
1541
|
+
* another after. This is the conversion the save path already performs on the
|
|
1542
|
+
* same states, so the text now describes exactly what a save would write.
|
|
1543
|
+
*/
|
|
1544
|
+
storyBlocks(state, source) {
|
|
1545
|
+
return state ? proseDocToBlocks(state.doc, source.content, this.baseDocument.package.styles, { emptyFieldResult: "authored" }) : source.content;
|
|
1546
|
+
}
|
|
1533
1547
|
getHeaderFooterStoryText(story, source) {
|
|
1534
1548
|
const state = this.secondaryStoryStates.get(headerFooterStoryKey(story))?.state;
|
|
1535
|
-
return normalizeFolioAIBlockText(
|
|
1549
|
+
return normalizeFolioAIBlockText(getHeaderFooterText({
|
|
1550
|
+
...source,
|
|
1551
|
+
content: this.storyBlocks(state, source)
|
|
1552
|
+
}));
|
|
1536
1553
|
}
|
|
1537
1554
|
getNoteStoryText(story, source) {
|
|
1538
1555
|
const state = this.secondaryStoryStates.get(noteStoryKey(story))?.state;
|
|
1539
|
-
const
|
|
1540
|
-
return normalizeFolioAIBlockText(
|
|
1556
|
+
const content = this.storyBlocks(state, source);
|
|
1557
|
+
return normalizeFolioAIBlockText(source.type === "footnote" ? getFootnoteText({
|
|
1558
|
+
...source,
|
|
1559
|
+
content
|
|
1560
|
+
}) : getEndnoteText({
|
|
1561
|
+
...source,
|
|
1562
|
+
content
|
|
1563
|
+
}));
|
|
1541
1564
|
}
|
|
1542
1565
|
getStoryText(story) {
|
|
1543
1566
|
if (story.type === "main") return this.getContentAsText();
|
|
@@ -66,7 +66,12 @@ declare const isFolioAIContentBlock: ({ text }: Pick<FolioAIBlock, "text">) => b
|
|
|
66
66
|
*/
|
|
67
67
|
declare const trailingBodyBlockId: ({ blocks }: FolioAIEditSnapshot) => string | null;
|
|
68
68
|
declare const hashFolioAIBlockText: (text: string) => string;
|
|
69
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Canonical public projection of the clean view's zero-width structure.
|
|
71
|
+
*
|
|
72
|
+
* A field boundary stays internal: it marks text the reader already sees, so it
|
|
73
|
+
* belongs to range resolution rather than to a block's published structure.
|
|
74
|
+
*/
|
|
70
75
|
declare const projectFolioAIBlockStructuralBoundaries: ({ structuralBoundaries }: Pick<CleanBlockText, "structuralBoundaries">) => readonly FolioAIBlockStructuralBoundary[];
|
|
71
76
|
/** Stable precondition fingerprint for a block's zero-width structure. */
|
|
72
77
|
declare const hashFolioAIBlockStructuralBoundaries: (cleanBlock: Pick<CleanBlockText, "structuralBoundaries">) => string;
|
|
@@ -4,7 +4,7 @@ import { marksToTextFormatting } from "../prosemirror/conversion/fromProseDoc.js
|
|
|
4
4
|
import { directParagraphAlignment } from "../prosemirror/paragraphAlignment.js";
|
|
5
5
|
import { directParagraphIndentation } from "../prosemirror/paragraphIndentation.js";
|
|
6
6
|
import { directParagraphSpacing } from "../prosemirror/paragraphSpacing.js";
|
|
7
|
-
import {
|
|
7
|
+
import { runFormattingInlineAtomCleanText } from "../prosemirror/runFormattingInlineCarriers.js";
|
|
8
8
|
import { authoredRunFormattingFromAttrs } from "../prosemirror/runFormattingProvenance.js";
|
|
9
9
|
import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "../prosemirror/runFormattingReconciliation.js";
|
|
10
10
|
import { paragraphRunStyleContext } from "../prosemirror/runStyleFormatting.js";
|
|
@@ -231,15 +231,20 @@ const hashFolioAIBlockText = (text) => {
|
|
|
231
231
|
};
|
|
232
232
|
const EMPTY_FOLIO_AI_BLOCK_STRUCTURAL_BOUNDARIES = Object.freeze([]);
|
|
233
233
|
const EMPTY_FOLIO_AI_BLOCK_STRUCTURAL_BOUNDARY_HASH = hashFolioAIBlockText(JSON.stringify(EMPTY_FOLIO_AI_BLOCK_STRUCTURAL_BOUNDARIES));
|
|
234
|
-
/**
|
|
234
|
+
/**
|
|
235
|
+
* Canonical public projection of the clean view's zero-width structure.
|
|
236
|
+
*
|
|
237
|
+
* A field boundary stays internal: it marks text the reader already sees, so it
|
|
238
|
+
* belongs to range resolution rather than to a block's published structure.
|
|
239
|
+
*/
|
|
235
240
|
const projectFolioAIBlockStructuralBoundaries = ({ structuralBoundaries }) => {
|
|
236
241
|
let projected;
|
|
237
|
-
for (const
|
|
238
|
-
if (!presentInCleanView) continue;
|
|
242
|
+
for (const boundary of structuralBoundaries) {
|
|
243
|
+
if (boundary.type !== "pageBreakRun" || !boundary.presentInCleanView) continue;
|
|
239
244
|
(projected ??= []).push({
|
|
240
245
|
type: "pageBreak",
|
|
241
|
-
offset,
|
|
242
|
-
...clear !== void 0 ? { clear } : {}
|
|
246
|
+
offset: boundary.offset,
|
|
247
|
+
...boundary.clear !== void 0 ? { clear: boundary.clear } : {}
|
|
243
248
|
});
|
|
244
249
|
}
|
|
245
250
|
return projected ?? EMPTY_FOLIO_AI_BLOCK_STRUCTURAL_BOUNDARIES;
|
|
@@ -531,13 +536,13 @@ const getPreviewRuns = ({ node, nodeFrom, cleanBlock, styleResolver }) => {
|
|
|
531
536
|
let paragraphStyleContext;
|
|
532
537
|
let cleanOffset = 0;
|
|
533
538
|
node.descendants((child, relativePosition) => {
|
|
534
|
-
const text = child.isText ? child.text :
|
|
535
|
-
if (text === void 0 || text === null) return true;
|
|
539
|
+
const text = child.isText ? child.text : runFormattingInlineAtomCleanText(child);
|
|
540
|
+
if (text === void 0 || text === null || text.length === 0) return true;
|
|
536
541
|
if (child.marks.some((mark) => mark.type.name === DELETION_MARK || mark.type.name === HIDDEN_MARK)) return false;
|
|
537
542
|
const start = nodeFrom + 1 + relativePosition;
|
|
538
543
|
while ((cleanBlock.offsets[cleanOffset] ?? Number.POSITIVE_INFINITY) < start) cleanOffset++;
|
|
539
|
-
const
|
|
540
|
-
if (cleanBlock.offsets[cleanOffset] !== start || cleanBlock.offsets[
|
|
544
|
+
const lastCharacterPosition = child.isText ? start + text.length - 1 : start;
|
|
545
|
+
if (cleanBlock.offsets[cleanOffset] !== start || cleanBlock.offsets[cleanOffset + text.length - 1] !== lastCharacterPosition) return false;
|
|
541
546
|
cleanOffset += text.length;
|
|
542
547
|
const style = getPreviewRunStyle(child.marks, defaultStyle);
|
|
543
548
|
const hasAuthorshipCarrier = child.marks.some(({ type }) => type.name === RUN_FORMATTING_OVERRIDE_MARK || type.name === CHARACTER_STYLE_MARK);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runFormattingInlineAtomResultText } from "../prosemirror/runFormattingInlineCarriers.js";
|
|
1
2
|
//#region src/ai-suggestions/text-positions.ts
|
|
2
3
|
const BLOCK_SEPARATOR = "\n";
|
|
3
4
|
/**
|
|
@@ -15,11 +16,22 @@ function buildPositionalText(doc, from = 0, to = doc.content.size) {
|
|
|
15
16
|
if (node.type.name === "pageBreakRun") {
|
|
16
17
|
structuralBoundaries.push({
|
|
17
18
|
textOffset: textLength,
|
|
18
|
-
|
|
19
|
-
to: pos + node.nodeSize
|
|
19
|
+
length: 0
|
|
20
20
|
});
|
|
21
21
|
return false;
|
|
22
22
|
}
|
|
23
|
+
const resultText = runFormattingInlineAtomResultText(node);
|
|
24
|
+
if (resultText !== null) {
|
|
25
|
+
if (resultText.length === 0 || pos < from || pos + node.nodeSize > to) return false;
|
|
26
|
+
structuralBoundaries.push({
|
|
27
|
+
textOffset: textLength,
|
|
28
|
+
length: resultText.length
|
|
29
|
+
});
|
|
30
|
+
chunks.push(resultText);
|
|
31
|
+
for (let index = 0; index < resultText.length; index++) offsets.push(pos);
|
|
32
|
+
textLength += resultText.length;
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
23
35
|
if (node.isText) {
|
|
24
36
|
const text = node.text ?? "";
|
|
25
37
|
const startInNode = Math.max(from, pos);
|
|
@@ -54,7 +66,7 @@ function buildPositionalText(doc, from = 0, to = doc.content.size) {
|
|
|
54
66
|
text,
|
|
55
67
|
pmPositionAt,
|
|
56
68
|
pmRangeAt: (startTextIndex, endTextIndex) => {
|
|
57
|
-
if (!Number.isInteger(startTextIndex) || !Number.isInteger(endTextIndex) || startTextIndex < 0 || endTextIndex <= startTextIndex || endTextIndex > text.length || structuralBoundaries.some(({ textOffset }) => textOffset > startTextIndex && textOffset < endTextIndex)) return null;
|
|
69
|
+
if (!Number.isInteger(startTextIndex) || !Number.isInteger(endTextIndex) || startTextIndex < 0 || endTextIndex <= startTextIndex || endTextIndex > text.length || structuralBoundaries.some(({ textOffset, length }) => length === 0 ? textOffset > startTextIndex && textOffset < endTextIndex : startTextIndex > textOffset && startTextIndex < textOffset + length || endTextIndex > textOffset && endTextIndex < textOffset + length)) return null;
|
|
58
70
|
const rangeFrom = pmPositionAt(startTextIndex);
|
|
59
71
|
const finalCharacter = offsets[endTextIndex - 1];
|
|
60
72
|
if (finalCharacter === void 0) return null;
|
|
@@ -46,7 +46,7 @@ const atomKey = (node) => canonicalJson({
|
|
|
46
46
|
content: node.content.toJSON()
|
|
47
47
|
});
|
|
48
48
|
const atomBlockOf = ({ node, from }) => {
|
|
49
|
-
const clean = buildCleanBlockText(node, from);
|
|
49
|
+
const clean = buildCleanBlockText(node, from, { fieldResults: "omitted" });
|
|
50
50
|
const supported = [];
|
|
51
51
|
const unsupportedTopology = [];
|
|
52
52
|
let unalignable = false;
|
|
@@ -237,7 +237,7 @@ const sameParagraphSourcePosition = ({ sourceBlocks, reviewed, offset }) => {
|
|
|
237
237
|
if (typeof paraId !== "string" || paraId.length === 0) return null;
|
|
238
238
|
const source = sourceBlocks.get(paraId);
|
|
239
239
|
if (!source || source.node.type !== reviewed.node.type) return null;
|
|
240
|
-
const clean = buildCleanBlockText(source.node, source.from);
|
|
240
|
+
const clean = buildCleanBlockText(source.node, source.from, { fieldResults: "omitted" });
|
|
241
241
|
return clean.text === reviewed.cleanText ? clean.offsets[offset] ?? null : null;
|
|
242
242
|
};
|
|
243
243
|
/**
|
|
@@ -19,8 +19,9 @@ import { CreateEmptyDocumentOptions, createEmptyDocument } from "../utils/create
|
|
|
19
19
|
import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
|
|
20
20
|
import { DocumentStyleCatalog, DocumentStyleCatalogEntry, ExtractDocumentStyleSetOptions, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, inspectDocumentStyles, inspectDocumentStylesFromDocx } from "../style-sets/extract.js";
|
|
21
21
|
import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet } from "../style-sets/stellaStyle.js";
|
|
22
|
-
import { createDocx } from "../docx/rezip.js";
|
|
23
|
-
import {
|
|
22
|
+
import { DocumentPropertiesOptions, createDocx } from "../docx/rezip.js";
|
|
23
|
+
import { DRAWING_SAFETY_CLASSES, DrawingSafetyClass } from "../docx/imageRawXml.js";
|
|
24
|
+
import { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, DocxDrawingClassification, FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, InspectDocxCompatibilityOptions, inspectDocxCompatibility } from "../docx/compatibility.js";
|
|
24
25
|
import { BlockRect } from "../paged-layout/blockGeometry.js";
|
|
25
26
|
import { setAISuggestionsMeta, setFocusedSuggestionMeta } from "../prosemirror/plugins/aiSuggestionDecorations.js";
|
|
26
27
|
import { scrollFolioPositionIntoView } from "../paged-layout/scrollToPmPosition.js";
|
|
@@ -39,4 +40,4 @@ import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled
|
|
|
39
40
|
import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
|
|
40
41
|
type Document = document_d_exports.Document;
|
|
41
42
|
type DocxConformanceClass = document_d_exports.DocxConformanceClass;
|
|
42
|
-
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
43
|
+
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
package/dist/compat/eigenpal.js
CHANGED
|
@@ -11,6 +11,7 @@ import { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, CompareDocxApply
|
|
|
11
11
|
import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS } from "../compare/verification.js";
|
|
12
12
|
import { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
13
13
|
import { inspectDocxCompatibility } from "../docx/compatibility.js";
|
|
14
|
+
import { DRAWING_SAFETY_CLASSES } from "../docx/imageRawXml.js";
|
|
14
15
|
import { createDocx } from "../docx/rezip.js";
|
|
15
16
|
import { buildEmbeddedFontFamilyMap, extractEmbeddedFonts, getEmbeddedFontFaces, scopeEmbeddedFontFamily } from "../fonts/embeddedFonts.js";
|
|
16
17
|
import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
|
|
@@ -32,4 +33,4 @@ import { currentFolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioB
|
|
|
32
33
|
import { createEmptyDocument } from "../utils/createDocument.js";
|
|
33
34
|
import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "../utils/fontResolver.js";
|
|
34
35
|
import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
|
|
35
|
-
export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioContentComparisonLimitError, FolioContentInlinePresentationProjectionError, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
36
|
+
export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioContentComparisonLimitError, FolioContentInlinePresentationProjectionError, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
@@ -2,6 +2,7 @@ import { DisplayColor, DisplayGlyphRun, DisplayHitRegion, DisplayPrimitive } fro
|
|
|
2
2
|
import { hasCursiveLetter, joinsAcrossBoundary } from "../utils/cursiveJoining.js";
|
|
3
3
|
import { hasComplexScript, isComplexScriptCodePoint } from "../utils/scriptSegments.js";
|
|
4
4
|
//#region src/display-list/primitives.d.ts
|
|
5
|
+
type PrimitiveKind = DisplayPrimitive["kind"];
|
|
5
6
|
/**
|
|
6
7
|
* Left edge of every code point of a run, as an offset from the run's `xPx`.
|
|
7
8
|
*
|
|
@@ -15,7 +16,7 @@ import { hasComplexScript, isComplexScriptCodePoint } from "../utils/scriptSegme
|
|
|
15
16
|
* advances rightward from its origin whatever the paragraph does.
|
|
16
17
|
*/
|
|
17
18
|
declare const glyphCellOffsetsPx: (run: DisplayGlyphRun) => readonly number[];
|
|
18
|
-
declare const DISPLAY_PRIMITIVE_KINDS:
|
|
19
|
+
declare const DISPLAY_PRIMITIVE_KINDS: readonly PrimitiveKind[];
|
|
19
20
|
/**
|
|
20
21
|
* Dash geometry of each stroke pattern, as multiples of the stroke thickness.
|
|
21
22
|
*
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { document_d_exports } from "./types/document.js";
|
|
1
2
|
import { FolioTableTemplates } from "./ai-edits/table-template.js";
|
|
2
3
|
import { FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditNormalization, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAITextRangeHandle } from "./ai-edits/types.js";
|
|
3
4
|
import { FolioAIEditView, FolioRevisionStamp, FolioWordDiffOptions } from "./ai-edits/apply.js";
|
|
4
5
|
//#region src/document-operations.d.ts
|
|
5
6
|
declare const FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION: 1;
|
|
6
7
|
/** Direct paragraph-alignment values accepted by the operation contract. */
|
|
7
|
-
declare const FOLIO_PARAGRAPH_ALIGNMENT_VALUES: readonly
|
|
8
|
+
declare const FOLIO_PARAGRAPH_ALIGNMENT_VALUES: readonly document_d_exports.ParagraphAlignment[];
|
|
8
9
|
/** `w:spacing/@w:lineRule` values accepted by the operation contract. */
|
|
9
|
-
declare const FOLIO_LINE_SPACING_RULE_VALUES: readonly
|
|
10
|
+
declare const FOLIO_LINE_SPACING_RULE_VALUES: readonly document_d_exports.LineSpacingRule[];
|
|
10
11
|
/** `w:br/@w:clear` values accepted on an authored hard page break. */
|
|
11
12
|
declare const FOLIO_PAGE_BREAK_CLEAR_VALUES: readonly ["none", "left", "right", "all"];
|
|
12
13
|
declare const FOLIO_DOCUMENT_OPERATION_TYPES: readonly ["replaceInBlock", "replaceRange", "commentOnRange", "formatRange", "insertAfterBlock", "insertBeforeBlock", "replaceBlock", "deleteBlock", "splitBlock", "mergeBlockWithNext", "setBlockParagraphProperties", "insertTable", "deleteTable", "commentOnBlock", "insertSignatureTable", "insertTableRow", "deleteTableRow", "insertTableColumn", "deleteTableColumn", "mergeTableCells", "splitTableCell"];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/blockPlainText.d.ts
|
|
3
|
+
type PlainTextBlock = document_d_exports.Paragraph | document_d_exports.Table | document_d_exports.BlockSdt;
|
|
4
|
+
/** One entry per block, so callers can join or count lines as they need. */
|
|
5
|
+
declare const collectBlockTexts: (blocks: readonly PlainTextBlock[]) => string[];
|
|
6
|
+
declare const blockPlainText: (blocks: readonly PlainTextBlock[]) => string;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { PlainTextBlock, blockPlainText, collectBlockTexts };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { getParagraphText } from "./paragraphParser.js";
|
|
2
|
+
import { panic } from "better-result";
|
|
3
|
+
//#region src/docx/blockPlainText.ts
|
|
4
|
+
/**
|
|
5
|
+
* The one plain-text projection of a block sequence.
|
|
6
|
+
*
|
|
7
|
+
* Every story — body, header, footer, footnote, endnote — reads through here,
|
|
8
|
+
* so a reader, a hash and a comparison all see the same string for the same
|
|
9
|
+
* content. Header and footer text used to come from a separate walk that
|
|
10
|
+
* handled only text runs, silently dropping fields, hyperlinks, tabs, breaks
|
|
11
|
+
* and tracked changes, so the same paragraph read one way in a note and another
|
|
12
|
+
* in a header.
|
|
13
|
+
*
|
|
14
|
+
* Separators carry the structure a reader needs: paragraphs and table rows are
|
|
15
|
+
* newline-separated, cells within a row tab-separated. `getParagraphText` owns
|
|
16
|
+
* everything below block level and reads the accepted tracked-change view.
|
|
17
|
+
*/
|
|
18
|
+
/** One entry per block, so callers can join or count lines as they need. */
|
|
19
|
+
const collectBlockTexts = (blocks) => {
|
|
20
|
+
const texts = [];
|
|
21
|
+
for (const block of blocks) switch (block.type) {
|
|
22
|
+
case "paragraph":
|
|
23
|
+
texts.push(getParagraphText(block));
|
|
24
|
+
break;
|
|
25
|
+
case "table":
|
|
26
|
+
for (const row of block.rows) {
|
|
27
|
+
if (row.formatting?.hidden === true) continue;
|
|
28
|
+
texts.push(row.cells.map((cell) => collectBlockTexts(cell.content).join("\n")).join(" "));
|
|
29
|
+
}
|
|
30
|
+
break;
|
|
31
|
+
case "blockSdt":
|
|
32
|
+
texts.push(...collectBlockTexts(block.content));
|
|
33
|
+
break;
|
|
34
|
+
default: panic(`Unsupported block in plain-text extraction: ${JSON.stringify(block)}`);
|
|
35
|
+
}
|
|
36
|
+
return texts;
|
|
37
|
+
};
|
|
38
|
+
const blockPlainText = (blocks) => collectBlockTexts(blocks).join("\n");
|
|
39
|
+
//#endregion
|
|
40
|
+
export { blockPlainText, collectBlockTexts };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { DrawingSafetyClass } from "./imageRawXml.js";
|
|
2
3
|
//#region src/docx/compatibility.d.ts
|
|
3
4
|
type DocxCompatibilityReason = "opaqueDrawing";
|
|
4
5
|
type FolioDocxCompatibilityHost = "browser" | "server" | "unknown";
|
|
@@ -26,14 +27,27 @@ type DocxCompatibilityIssue = {
|
|
|
26
27
|
code: DocxCompatibilityReason;
|
|
27
28
|
location: DocxCompatibilityLocation;
|
|
28
29
|
};
|
|
30
|
+
/** A drawing and the fate the run serializer holds for it. */
|
|
31
|
+
type DocxDrawingClassification = {
|
|
32
|
+
class: DrawingSafetyClass;
|
|
33
|
+
location: DocxCompatibilityLocation;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Schema 2 replaced the per-drawing boolean judgement with
|
|
37
|
+
* {@link DocxDrawingClassification} and stopped reporting a replayable drawing
|
|
38
|
+
* as an issue; `issues` now holds opaque drawings only.
|
|
39
|
+
*/
|
|
29
40
|
type DocxCompatibility = {
|
|
30
|
-
schemaVersion:
|
|
41
|
+
schemaVersion: 2;
|
|
31
42
|
context: DocxCompatibilityContext;
|
|
32
43
|
canSafelyEdit: boolean;
|
|
44
|
+
/** Every drawing the walk reached, classified. */
|
|
45
|
+
drawings: DocxDrawingClassification[];
|
|
46
|
+
/** The blocking subset: drawings a save can neither replay nor regenerate. */
|
|
33
47
|
issues: DocxCompatibilityIssue[];
|
|
34
48
|
reasons: DocxCompatibilityReason[];
|
|
35
49
|
unsupportedContentCount: number;
|
|
36
50
|
};
|
|
37
51
|
declare const inspectDocxCompatibility: (doc: document_d_exports.Document, options?: InspectDocxCompatibilityOptions) => DocxCompatibility;
|
|
38
52
|
//#endregion
|
|
39
|
-
export { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, DocxCompatibilityReason, FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, InspectDocxCompatibilityOptions, inspectDocxCompatibility };
|
|
53
|
+
export { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, DocxCompatibilityReason, DocxDrawingClassification, FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, InspectDocxCompatibilityOptions, inspectDocxCompatibility };
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DRAWING_SAFETY_CLASSES, classifyDrawingSafety } from "./imageRawXml.js";
|
|
2
|
+
import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
|
|
2
3
|
//#region src/docx/compatibility.ts
|
|
4
|
+
/**
|
|
5
|
+
* Whether a parsed package can be edited without losing content on save.
|
|
6
|
+
*
|
|
7
|
+
* Every part walked here is re-serialized from the model at some point: the
|
|
8
|
+
* repack always rebuilds `word/document.xml`, headers and footers replay their
|
|
9
|
+
* captured bytes only while their content fingerprint is unchanged, and note
|
|
10
|
+
* parts are preserved except for edited paragraphs spliced back by `w:paraId`.
|
|
11
|
+
* So an opaque drawing anywhere in this walk is a real risk, while a drawing the
|
|
12
|
+
* serializer replays verbatim is not, whichever part holds it.
|
|
13
|
+
*/
|
|
3
14
|
const resolveCompatibilityContext = (doc, options) => ({
|
|
4
15
|
host: options.host ?? "unknown",
|
|
5
16
|
profile: options.profile ?? doc.package.conformanceClass ?? DOCX_CONFORMANCE_CLASSES.UNKNOWN
|
|
@@ -7,13 +18,16 @@ const resolveCompatibilityContext = (doc, options) => ({
|
|
|
7
18
|
const inspectDocxCompatibility = (doc, options = {}) => {
|
|
8
19
|
const context = resolveCompatibilityContext(doc, options);
|
|
9
20
|
const reasons = /* @__PURE__ */ new Set();
|
|
21
|
+
const drawings = [];
|
|
10
22
|
const issues = [];
|
|
11
|
-
const record = (
|
|
23
|
+
const record = (drawing) => {
|
|
24
|
+
drawings.push(drawing);
|
|
25
|
+
if (drawing.class !== DRAWING_SAFETY_CLASSES.OPAQUE) return;
|
|
12
26
|
const code = "opaqueDrawing";
|
|
13
27
|
reasons.add(code);
|
|
14
28
|
issues.push({
|
|
15
29
|
code,
|
|
16
|
-
location
|
|
30
|
+
location: drawing.location
|
|
17
31
|
});
|
|
18
32
|
};
|
|
19
33
|
inspectBlocks(doc.package.document.content, {
|
|
@@ -54,9 +68,10 @@ const inspectDocxCompatibility = (doc, options = {}) => {
|
|
|
54
68
|
record
|
|
55
69
|
});
|
|
56
70
|
return {
|
|
57
|
-
schemaVersion:
|
|
71
|
+
schemaVersion: 2,
|
|
58
72
|
context,
|
|
59
73
|
canSafelyEdit: issues.length === 0,
|
|
74
|
+
drawings,
|
|
60
75
|
issues,
|
|
61
76
|
reasons: Array.from(reasons),
|
|
62
77
|
unsupportedContentCount: issues.length
|
|
@@ -146,11 +161,17 @@ function inspectHyperlink(hyperlink, context) {
|
|
|
146
161
|
});
|
|
147
162
|
}
|
|
148
163
|
function inspectRun(run, context) {
|
|
149
|
-
for (const [contentIndex, content] of run.content.entries())
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
for (const [contentIndex, content] of run.content.entries()) {
|
|
165
|
+
if (content.type !== "drawing") continue;
|
|
166
|
+
context.record({
|
|
167
|
+
class: classifyDrawingSafety(content),
|
|
168
|
+
location: {
|
|
169
|
+
...context.blockId === void 0 ? {} : { blockId: context.blockId },
|
|
170
|
+
part: context.part,
|
|
171
|
+
path: `${context.path}.content[${contentIndex}]`
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
154
175
|
}
|
|
155
176
|
//#endregion
|
|
156
177
|
export { inspectDocxCompatibility };
|