@stll/folio-core 0.33.0 → 0.33.1
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/dist/ai-edits/apply.js +4 -2
- package/dist/compare/__fixtures__/body-sequence.d.ts +26 -3
- package/dist/compare/__fixtures__/body-sequence.js +81 -12
- package/dist/compare/compare.d.ts +2 -2
- package/dist/compare/compare.js +8 -2
- package/dist/compare/plan.js +82 -0
- package/dist/compare/reproducible-package.d.ts +7 -3
- package/dist/compare/reproducible-package.js +20 -3
- package/dist/compare/types.d.ts +18 -3
- package/dist/compare/types.js +11 -1
- package/dist/compare/verification.d.ts +29 -1
- package/dist/compare/verification.js +44 -1
- package/dist/compat/eigenpal.d.ts +3 -3
- package/dist/compat/eigenpal.js +2 -2
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/docx/hyperlinkParser.d.ts +9 -1
- package/dist/docx/hyperlinkParser.js +19 -13
- package/dist/docx/paraIdRangeNormalization.d.ts +40 -0
- package/dist/docx/paraIdRangeNormalization.js +64 -0
- package/dist/docx/paragraphParser.js +79 -4
- package/dist/docx/revisionIdNormalization.d.ts +15 -1
- package/dist/docx/revisionIdNormalization.js +22 -4
- package/dist/docx/rezip.d.ts +6 -0
- package/dist/docx/rezip.js +31 -8
- package/dist/docx/serializer/paragraphSerializer.js +42 -18
- package/dist/docx/serializer/tableSerializer.js +24 -9
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/prosemirror/commands/comments.js +7 -2
- package/package.json +1 -1
package/dist/ai-edits/apply.js
CHANGED
|
@@ -1171,7 +1171,8 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations, mode =
|
|
|
1171
1171
|
}
|
|
1172
1172
|
case "deleteBlock":
|
|
1173
1173
|
if (mode === "direct") {
|
|
1174
|
-
|
|
1174
|
+
const at = tr.doc.resolve(item.blockFrom);
|
|
1175
|
+
tr = !(at.index() === at.parent.childCount - 1) || at.nodeBefore?.type.name === item.blockNode.type.name ? tr.delete(item.blockFrom, item.blockTo) : tr.delete(item.blockFrom + 1, item.blockTo - 1);
|
|
1175
1176
|
break;
|
|
1176
1177
|
}
|
|
1177
1178
|
if (deletionType) {
|
|
@@ -1189,7 +1190,8 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations, mode =
|
|
|
1189
1190
|
const inlineRevisionApplied = item.from < item.to || atomRanges.length > 0;
|
|
1190
1191
|
appliedRevisionIds = inlineRevisionApplied ? [revisionId] : [];
|
|
1191
1192
|
const markPosition = tr.mapping.map(item.blockFrom);
|
|
1192
|
-
|
|
1193
|
+
const markPlace = tr.doc.resolve(markPosition);
|
|
1194
|
+
if (!(markPlace.index() === markPlace.parent.childCount - 1) && tr.doc.nodeAt(markPosition)?.attrs["pPrMark"] == null) {
|
|
1193
1195
|
const markRevisionId = revisionSeed++;
|
|
1194
1196
|
tr = tr.setNodeAttribute(markPosition, "pPrMark", {
|
|
1195
1197
|
kind: isPairedMove(item.operation.moveId) ? "moveFrom" : "del",
|
|
@@ -13,11 +13,26 @@
|
|
|
13
13
|
* gets written.
|
|
14
14
|
*/
|
|
15
15
|
type CellContent = string | readonly BodyItem[];
|
|
16
|
+
/**
|
|
17
|
+
* One inline of a paragraph: plain text, or text carrying an external
|
|
18
|
+
* hyperlink. A link is the case where a revision wrapper and the linked runs
|
|
19
|
+
* have to nest one inside the other, so the fixture has to be able to author
|
|
20
|
+
* one.
|
|
21
|
+
*/
|
|
22
|
+
type ParagraphInline = string | {
|
|
23
|
+
text: string;
|
|
24
|
+
href: string;
|
|
25
|
+
};
|
|
16
26
|
/** One body-level item: a paragraph, or a table given row by row. */
|
|
17
27
|
type BodyItem = {
|
|
18
28
|
kind: "paragraph";
|
|
19
|
-
text: string;
|
|
29
|
+
text: string | readonly ParagraphInline[];
|
|
20
30
|
styleId?: string;
|
|
31
|
+
/**
|
|
32
|
+
* An authored `w14:paraId`, for a package whose ids a producer wrote
|
|
33
|
+
* without respecting the 31-bit bound the schema puts on them.
|
|
34
|
+
*/
|
|
35
|
+
paraId?: string;
|
|
21
36
|
} | {
|
|
22
37
|
kind: "table";
|
|
23
38
|
rows: readonly (readonly CellContent[])[];
|
|
@@ -28,6 +43,14 @@ type BodyItem = {
|
|
|
28
43
|
*/
|
|
29
44
|
hiddenRows?: readonly number[];
|
|
30
45
|
};
|
|
31
|
-
|
|
46
|
+
type BodySequenceOptions = {
|
|
47
|
+
/**
|
|
48
|
+
* A default header part, written as its own sequence. A header is a story of
|
|
49
|
+
* its own: it ends with its own paragraph, and a comparison writes it with
|
|
50
|
+
* its own revision ids.
|
|
51
|
+
*/
|
|
52
|
+
header?: readonly BodyItem[];
|
|
53
|
+
};
|
|
54
|
+
declare const buildBodySequenceDocx: (items: readonly BodyItem[], { header }?: BodySequenceOptions) => Promise<ArrayBuffer>;
|
|
32
55
|
//#endregion
|
|
33
|
-
export { BodyItem, CellContent, buildBodySequenceDocx };
|
|
56
|
+
export { BodyItem, BodySequenceOptions, CellContent, ParagraphInline, buildBodySequenceDocx };
|
|
@@ -12,6 +12,10 @@ const NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
|
12
12
|
const RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
13
13
|
const OFFICE_RELATIONSHIPS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
14
14
|
const WORDPROCESSING = "application/vnd.openxmlformats-officedocument.wordprocessingml";
|
|
15
|
+
const MARKUP_COMPATIBILITY = "http://schemas.openxmlformats.org/markup-compatibility/2006";
|
|
16
|
+
const PACKAGE_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006";
|
|
17
|
+
const CORE_PROPERTIES_TYPE = "application/vnd.openxmlformats-package.core-properties+xml";
|
|
18
|
+
const WORDML_2010 = "http://schemas.microsoft.com/office/word/2010/wordml";
|
|
15
19
|
/**
|
|
16
20
|
* `createFolders: false` because JSZip stamps the folder entries it
|
|
17
21
|
* synthesizes with `new Date()`, which the fixed date above does not reach.
|
|
@@ -21,13 +25,52 @@ const ZIP_ENTRY_OPTIONS = {
|
|
|
21
25
|
createFolders: false
|
|
22
26
|
};
|
|
23
27
|
/**
|
|
28
|
+
* A paragraph's id is derived from its own content, not from its position.
|
|
29
|
+
*
|
|
30
|
+
* Two packages authored from two descriptions are a base and a target, and a
|
|
31
|
+
* paragraph that appears in both is the same paragraph. Numbering the ids in
|
|
32
|
+
* document order would instead give the same id to the paragraph that happens
|
|
33
|
+
* to sit at the same index, which is how the fixture would tell a comparison
|
|
34
|
+
* that a removed paragraph was a rewrite of the one after it.
|
|
35
|
+
*/
|
|
36
|
+
const createParaIdAllocator = () => {
|
|
37
|
+
const taken = /* @__PURE__ */ new Set();
|
|
38
|
+
return (content) => {
|
|
39
|
+
let hash = 2166136261;
|
|
40
|
+
for (let index = 0; index < content.length; index += 1) hash = Math.imul(hash ^ content.charCodeAt(index), 16777619) >>> 0;
|
|
41
|
+
let candidate = hash % 2147483646;
|
|
42
|
+
while (taken.has((candidate + 1).toString(16).toUpperCase().padStart(8, "0"))) candidate = (candidate + 1) % 2147483646;
|
|
43
|
+
const paraId = (candidate + 1).toString(16).toUpperCase().padStart(8, "0");
|
|
44
|
+
taken.add(paraId);
|
|
45
|
+
return paraId;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
const run = (text) => `<w:r><w:t xml:space="preserve">${text}</w:t></w:r>`;
|
|
49
|
+
const inlineXml = (inline, { links }) => typeof inline === "string" ? run(inline) : `<w:hyperlink r:id="${links.get(inline.href) ?? ""}">${run(inline.text)}</w:hyperlink>`;
|
|
50
|
+
/**
|
|
24
51
|
* An empty paragraph is a `w:p` with no run at all, which is what a package
|
|
25
52
|
* holds for a blank line or an empty cell. It is not the same thing as a
|
|
26
53
|
* paragraph whose run carries an empty string, and both shapes occur.
|
|
27
54
|
*/
|
|
28
|
-
|
|
55
|
+
/** A blank line carries no run at all, so an empty string is no inline. */
|
|
56
|
+
const nonEmptyInlines = (text) => text.length === 0 ? [] : [text];
|
|
57
|
+
const paragraph = (text, context, { styleId, paraId } = {}) => {
|
|
29
58
|
const properties = styleId === void 0 ? "" : `<w:pPr><w:pStyle w:val="${styleId}"/></w:pPr>`;
|
|
30
|
-
|
|
59
|
+
const inlines = typeof text === "string" ? nonEmptyInlines(text) : text;
|
|
60
|
+
const content = inlines.map((inline) => typeof inline === "string" ? inline : inline.text).join("");
|
|
61
|
+
const id = paraId ?? context.paraId(`${styleId ?? ""}|${content}`);
|
|
62
|
+
return `<w:p w14:paraId="${id}" w14:textId="${id}">${properties}${inlines.map((inline) => inlineXml(inline, context)).join("")}</w:p>`;
|
|
63
|
+
};
|
|
64
|
+
/** Every href the body carries, in document order, so the ids are stable. */
|
|
65
|
+
const collectHrefs = (items, hrefs) => {
|
|
66
|
+
for (const item of items) {
|
|
67
|
+
if (item.kind === "paragraph") {
|
|
68
|
+
if (typeof item.text === "string") continue;
|
|
69
|
+
for (const inline of item.text) if (typeof inline !== "string" && !hrefs.includes(inline.href)) hrefs.push(inline.href);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
for (const row of item.rows) for (const cell of row) if (typeof cell !== "string") collectHrefs(cell, hrefs);
|
|
73
|
+
}
|
|
31
74
|
};
|
|
32
75
|
const EMPTY_PARAGRAPH = {
|
|
33
76
|
kind: "paragraph",
|
|
@@ -44,20 +87,46 @@ const closedSequence = (items) => {
|
|
|
44
87
|
return last === void 0 || last.kind === "table" ? [...items, EMPTY_PARAGRAPH] : items;
|
|
45
88
|
};
|
|
46
89
|
/** A cell must also contain a paragraph, which the empty sequence supplies. */
|
|
47
|
-
const cellXml = (content) => typeof content === "string" ? paragraph(content) : itemsXml(closedSequence(content));
|
|
48
|
-
|
|
90
|
+
const cellXml = (content, context) => typeof content === "string" ? paragraph(content, context) : itemsXml(closedSequence(content), context);
|
|
91
|
+
/** `w:tbl` is `w:tblPr, w:tblGrid, rows`: a fixture without the grid is not one. */
|
|
92
|
+
const tableGrid = (rows) => {
|
|
93
|
+
let columns = 0;
|
|
94
|
+
for (const cells of rows) columns = Math.max(columns, cells.length);
|
|
95
|
+
return `<w:tblGrid>${`<w:gridCol w:w="2000"/>`.repeat(columns)}</w:tblGrid>`;
|
|
96
|
+
};
|
|
97
|
+
const table = (item, context) => {
|
|
49
98
|
const hidden = new Set(item.hiddenRows ?? []);
|
|
50
|
-
return `<w:tbl><w:tblPr><w:tblW w:w="0" w:type="auto"/></w:tblPr>` + item.rows.map((cells, rowIndex) => `<w:tr>${hidden.has(rowIndex) ? `<w:trPr><w:hidden/></w:trPr>` : ""}${cells.map((content) => `<w:tc><w:tcPr><w:tcW w:w="2000" w:type="dxa"/></w:tcPr>${cellXml(content)}</w:tc>`).join("")}</w:tr>`).join("") + `</w:tbl>`;
|
|
99
|
+
return `<w:tbl><w:tblPr><w:tblW w:w="0" w:type="auto"/></w:tblPr>` + tableGrid(item.rows) + item.rows.map((cells, rowIndex) => `<w:tr>${hidden.has(rowIndex) ? `<w:trPr><w:hidden/></w:trPr>` : ""}${cells.map((content) => `<w:tc><w:tcPr><w:tcW w:w="2000" w:type="dxa"/></w:tcPr>${cellXml(content, context)}</w:tc>`).join("")}</w:tr>`).join("") + `</w:tbl>`;
|
|
51
100
|
};
|
|
52
|
-
const itemsXml = (items) => items.map((item) => item.kind === "paragraph" ? paragraph(item.text,
|
|
53
|
-
|
|
54
|
-
|
|
101
|
+
const itemsXml = (items, context) => items.map((item) => item.kind === "paragraph" ? paragraph(item.text, context, {
|
|
102
|
+
...item.styleId === void 0 ? {} : { styleId: item.styleId },
|
|
103
|
+
...item.paraId === void 0 ? {} : { paraId: item.paraId }
|
|
104
|
+
}) : table(item, context)).join("");
|
|
105
|
+
const bodyXml = (items, context) => itemsXml(closedSequence(items), context);
|
|
106
|
+
/** The relationship id the default header takes when a fixture asks for one. */
|
|
107
|
+
const HEADER_RELATIONSHIP_ID = "rId2";
|
|
108
|
+
const buildBodySequenceDocx = async (items, { header } = {}) => {
|
|
109
|
+
const hrefs = [];
|
|
110
|
+
collectHrefs(closedSequence(items), hrefs);
|
|
111
|
+
collectHrefs(closedSequence(header ?? []), hrefs);
|
|
112
|
+
const firstLinkRelationship = header ? 3 : 2;
|
|
113
|
+
const links = new Map(hrefs.map((href, index) => [href, `rId${index + firstLinkRelationship}`]));
|
|
114
|
+
const linkRelationships = hrefs.map((href, index) => `<Relationship Id="rId${index + firstLinkRelationship}" Type="${OFFICE_RELATIONSHIPS}/hyperlink" Target="${href}" TargetMode="External"/>`).join("");
|
|
115
|
+
const paraId = createParaIdAllocator();
|
|
55
116
|
const parts = {
|
|
56
|
-
"[Content_Types].xml": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="${WORDPROCESSING}.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="${WORDPROCESSING}.styles+xml"/></Types>`,
|
|
57
|
-
"_rels/.rels": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="${RELATIONSHIPS}"><Relationship Id="rId1" Type="${OFFICE_RELATIONSHIPS}/officeDocument" Target="word/document.xml"/></Relationships>`,
|
|
58
|
-
"
|
|
117
|
+
"[Content_Types].xml": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="${WORDPROCESSING}.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="${WORDPROCESSING}.styles+xml"/>` + (header ? `<Override PartName="/word/header1.xml" ContentType="${WORDPROCESSING}.header+xml"/>` : "") + `<Override PartName="/docProps/core.xml" ContentType="${CORE_PROPERTIES_TYPE}"/></Types>`,
|
|
118
|
+
"_rels/.rels": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="${RELATIONSHIPS}"><Relationship Id="rId1" Type="${OFFICE_RELATIONSHIPS}/officeDocument" Target="word/document.xml"/><Relationship Id="rId2" Type="${PACKAGE_RELATIONSHIPS}/metadata/core-properties" Target="docProps/core.xml"/></Relationships>`,
|
|
119
|
+
"docProps/core.xml": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><cp:coreProperties xmlns:cp="${PACKAGE_RELATIONSHIPS}/metadata/core-properties" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dcterms:created xsi:type="dcterms:W3CDTF">2000-01-01T00:00:00Z</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">2000-01-01T00:00:00Z</dcterms:modified></cp:coreProperties>`,
|
|
120
|
+
"word/_rels/document.xml.rels": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="${RELATIONSHIPS}"><Relationship Id="rId1" Type="${OFFICE_RELATIONSHIPS}/styles" Target="styles.xml"/>` + (header ? `<Relationship Id="${HEADER_RELATIONSHIP_ID}" Type="${OFFICE_RELATIONSHIPS}/header" Target="header1.xml"/>` : "") + linkRelationships + `</Relationships>`,
|
|
59
121
|
"word/styles.xml": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:styles xmlns:w="${NAMESPACE}"><w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/></w:style><w:style w:type="paragraph" w:styleId="Heading1"><w:name w:val="heading 1"/></w:style></w:styles>`,
|
|
60
|
-
"word/document.xml": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:document xmlns:w="${NAMESPACE}"
|
|
122
|
+
"word/document.xml": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:document xmlns:w="${NAMESPACE}" xmlns:r="${OFFICE_RELATIONSHIPS}" xmlns:mc="${MARKUP_COMPATIBILITY}" xmlns:w14="${WORDML_2010}" mc:Ignorable="w14"><w:body>` + bodyXml(items, {
|
|
123
|
+
links,
|
|
124
|
+
paraId
|
|
125
|
+
}) + `<w:sectPr>` + (header ? `<w:headerReference w:type="default" r:id="${HEADER_RELATIONSHIP_ID}"/>` : "") + "<w:pgSz w:w=\"12240\" w:h=\"15840\"/><w:pgMar w:top=\"1440\" w:right=\"1440\" w:bottom=\"1440\" w:left=\"1440\"/></w:sectPr></w:body></w:document>",
|
|
126
|
+
...header ? { "word/header1.xml": `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:hdr xmlns:w="${NAMESPACE}" xmlns:r="${OFFICE_RELATIONSHIPS}" xmlns:mc="${MARKUP_COMPATIBILITY}" xmlns:w14="${WORDML_2010}" mc:Ignorable="w14">${itemsXml(closedSequence(header), {
|
|
127
|
+
links,
|
|
128
|
+
paraId
|
|
129
|
+
})}</w:hdr>` } : {}
|
|
61
130
|
};
|
|
62
131
|
const zip = new JSZip();
|
|
63
132
|
for (const name of Object.keys(parts).toSorted()) zip.file(name, parts[name] ?? "", ZIP_ENTRY_OPTIONS);
|
|
@@ -3,7 +3,7 @@ import { WordDiffGranularity } from "../ai-edits/word-diff.js";
|
|
|
3
3
|
import { FolioRevisionStamp } from "../ai-edits/apply.js";
|
|
4
4
|
import { FolioDocumentStoryHandle, FolioDocxReviewer } from "../ai-edits/headless.js";
|
|
5
5
|
import { CompareVerification } from "./verification.js";
|
|
6
|
-
import { CompareChange, CompareDocxApplyError, CompareDocxError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxSerializeError, CompareResult, CompareUnsupportedPart, InvalidCompareDocxOptionsError } from "./types.js";
|
|
6
|
+
import { CompareChange, CompareDocxApplyError, CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxSerializeError, CompareResult, CompareUnsupportedPart, InvalidCompareDocxOptionsError } from "./types.js";
|
|
7
7
|
import { CompareStoryPlan } from "./plan.js";
|
|
8
8
|
import { Result } from "better-result";
|
|
9
9
|
//#region src/compare/compare.d.ts
|
|
@@ -89,7 +89,7 @@ declare const applyComparison: ({ reviewer, revisionStamp, granularity, numberin
|
|
|
89
89
|
* composition let the benchmark's own composition disagree with the shipped
|
|
90
90
|
* one within a single run.
|
|
91
91
|
*/
|
|
92
|
-
declare const serializeComparison: ({ baseBuffer, baseCarriedRevisions, reviewer, packageDate }: ParsedComparison, planned: readonly PlannedStoryComparison[]) => Promise<Result<ArrayBuffer, CompareDocxSerializeError>>;
|
|
92
|
+
declare const serializeComparison: ({ baseBuffer, baseCarriedRevisions, reviewer, packageDate }: ParsedComparison, planned: readonly PlannedStoryComparison[]) => Promise<Result<ArrayBuffer, CompareDocxSerializeError | CompareDocxFinalParagraphMarkError>>;
|
|
93
93
|
/**
|
|
94
94
|
* Compare `base` against `target` and return `base` carrying the tracked
|
|
95
95
|
* changes that turn it into `target`, alongside the change list describing
|
package/dist/compare/compare.js
CHANGED
|
@@ -3,8 +3,8 @@ import "../document-operations.js";
|
|
|
3
3
|
import { pairFolioDocumentStories } from "../document-stories.js";
|
|
4
4
|
import { planStoryCompare } from "./plan.js";
|
|
5
5
|
import { withFixedPackageDates } from "./reproducible-package.js";
|
|
6
|
-
import { CompareDocxApplyError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError } from "./types.js";
|
|
7
|
-
import { classifyProjectionMismatch, projectSupportedInlineFormatting } from "./verification.js";
|
|
6
|
+
import { CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError } from "./types.js";
|
|
7
|
+
import { classifyProjectionMismatch, deletedFinalParagraphMarks, projectSupportedInlineFormatting } from "./verification.js";
|
|
8
8
|
import { Result, panic } from "better-result";
|
|
9
9
|
//#region src/compare/compare.ts
|
|
10
10
|
/**
|
|
@@ -354,6 +354,12 @@ const applyComparison = ({ reviewer, revisionStamp, granularity, numberingChange
|
|
|
354
354
|
*/
|
|
355
355
|
const serializeComparison = async ({ baseBuffer, baseCarriedRevisions, reviewer, packageDate }, planned) => {
|
|
356
356
|
if (!baseCarriedRevisions && planned.every(({ plan }) => plan.operations.length === 0)) return Result.ok(baseBuffer);
|
|
357
|
+
const deletions = deletedFinalParagraphMarks(reviewer.toDocument());
|
|
358
|
+
const [firstDeletion] = deletions;
|
|
359
|
+
if (firstDeletion !== void 0) return Result.err(new CompareDocxFinalParagraphMarkError({
|
|
360
|
+
message: `A container's final paragraph mark carries a ${firstDeletion.kind}, which no consumer can resolve: ${firstDeletion.container} paragraph ${String(firstDeletion.paragraphIndex)}.`,
|
|
361
|
+
deletions
|
|
362
|
+
}));
|
|
357
363
|
return await Result.tryPromise({
|
|
358
364
|
try: async () => await withFixedPackageDates(await reviewer.toBuffer(), packageDate),
|
|
359
365
|
catch: (cause) => new CompareDocxSerializeError({
|
package/dist/compare/plan.js
CHANGED
|
@@ -701,6 +701,82 @@ const locationOf = (story, block) => block.table ? {
|
|
|
701
701
|
cell: block.table
|
|
702
702
|
} : { story };
|
|
703
703
|
/**
|
|
704
|
+
* The container a paragraph mark ends: the story's body, or one table cell. A
|
|
705
|
+
* mark joins the paragraph it ends with the next paragraph of the SAME
|
|
706
|
+
* container, so two blocks on either side of a boundary are not neighbours for
|
|
707
|
+
* this purpose however adjacent they read.
|
|
708
|
+
*/
|
|
709
|
+
const containerKeyOf = ({ table }) => table ? `t${String(table.tableIndex)}r${String(table.rowIndex)}c${String(table.cellIndex)}` : "body";
|
|
710
|
+
/** Each container's last block, in the order the story holds them. */
|
|
711
|
+
const lastBlockByContainer = (blocks) => {
|
|
712
|
+
const last = /* @__PURE__ */ new Map();
|
|
713
|
+
for (const block of blocks) last.set(containerKeyOf(block), block);
|
|
714
|
+
return last;
|
|
715
|
+
};
|
|
716
|
+
/**
|
|
717
|
+
* The operations that keep a container's final paragraph mark when the plan
|
|
718
|
+
* deletes the paragraphs that end it.
|
|
719
|
+
*
|
|
720
|
+
* A deleted paragraph mark means "merge this paragraph into the following
|
|
721
|
+
* one". A container's final paragraph has no following one, so the mark cannot
|
|
722
|
+
* say it: the applier leaves that mark alone, and the removal has to be
|
|
723
|
+
* expressed one paragraph earlier. The chain therefore runs from the last
|
|
724
|
+
* SURVIVING paragraph forward — its mark goes, each removed paragraph's mark
|
|
725
|
+
* goes with it, and the container's final paragraph stays as the carrier the
|
|
726
|
+
* merged text lands in.
|
|
727
|
+
*
|
|
728
|
+
* The carrier keeps its own mark, and a paragraph's properties live on its
|
|
729
|
+
* mark, so the merged paragraph ends up with the carrier's. Those properties
|
|
730
|
+
* therefore become the target's, written as `w:pPrChange` so rejecting
|
|
731
|
+
* restores what the carrier had. That is bookkeeping for the merge rather than
|
|
732
|
+
* an edit of its own, so it adds no entry to the change list: what the reader
|
|
733
|
+
* is told is that the paragraphs were removed.
|
|
734
|
+
*
|
|
735
|
+
* Nothing is rotated when the plan puts a block inside or after the run. The
|
|
736
|
+
* carrier is then no longer what ends the container, its mark is deleted like
|
|
737
|
+
* any other, and the count already works out.
|
|
738
|
+
*/
|
|
739
|
+
const trailingDeletionOperations = ({ baseSnapshot, targetSnapshot, operations, nextOperationId }) => {
|
|
740
|
+
const blocks = baseSnapshot.blocks;
|
|
741
|
+
const deletedBlockIds = new Set(operations.flatMap((operation) => operation.type === "deleteBlock" ? [operation.blockId] : []));
|
|
742
|
+
if (deletedBlockIds.size === 0) return [];
|
|
743
|
+
const placedAtBlockIds = new Set(operations.flatMap((operation) => operation.type === "insertBeforeBlock" || operation.type === "insertAfterBlock" || operation.type === "insertTable" ? [operation.blockId] : []));
|
|
744
|
+
const markedBlockIds = new Set(operations.flatMap((operation) => operation.type === "splitBlock" || operation.type === "mergeBlockWithNext" ? [operation.blockId] : []));
|
|
745
|
+
const targetLastByContainer = lastBlockByContainer(targetSnapshot.blocks);
|
|
746
|
+
const indexById = new Map(blocks.map((block, index) => [block.id, index]));
|
|
747
|
+
const added = [];
|
|
748
|
+
for (const [container, carrier] of lastBlockByContainer(blocks)) {
|
|
749
|
+
if (!deletedBlockIds.has(carrier.id)) continue;
|
|
750
|
+
let index = indexById.get(carrier.id) ?? panic("A container's last block is not in the snapshot it came from", { blockId: carrier.id });
|
|
751
|
+
let chainStart = null;
|
|
752
|
+
let placedInRun = false;
|
|
753
|
+
for (; index >= 0; index--) {
|
|
754
|
+
const block = blocks[index];
|
|
755
|
+
if (block === void 0 || containerKeyOf(block) !== container) break;
|
|
756
|
+
if (!deletedBlockIds.has(block.id)) {
|
|
757
|
+
chainStart = markedBlockIds.has(block.id) ? null : block;
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
placedInRun ||= placedAtBlockIds.has(block.id);
|
|
761
|
+
}
|
|
762
|
+
if (placedInRun) continue;
|
|
763
|
+
if (chainStart) added.push({
|
|
764
|
+
id: nextOperationId(),
|
|
765
|
+
type: "mergeBlockWithNext",
|
|
766
|
+
blockId: chainStart.id
|
|
767
|
+
});
|
|
768
|
+
const targetCarrier = targetLastByContainer.get(container);
|
|
769
|
+
const properties = targetCarrier && changedParagraphProperties(carrier, targetCarrier);
|
|
770
|
+
if (properties) added.push({
|
|
771
|
+
id: nextOperationId(),
|
|
772
|
+
type: "setBlockParagraphProperties",
|
|
773
|
+
blockId: carrier.id,
|
|
774
|
+
properties
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
return added;
|
|
778
|
+
};
|
|
779
|
+
/**
|
|
704
780
|
* Plan one story's comparison, or `null` when it needs more operations than
|
|
705
781
|
* `maxOperations`.
|
|
706
782
|
*/
|
|
@@ -1050,6 +1126,12 @@ const planStoryCompare = ({ story, baseSnapshot, targetSnapshot, maxOperations }
|
|
|
1050
1126
|
}
|
|
1051
1127
|
if (operations.length > maxOperations) return null;
|
|
1052
1128
|
}
|
|
1129
|
+
operations.push(...trailingDeletionOperations({
|
|
1130
|
+
baseSnapshot,
|
|
1131
|
+
targetSnapshot,
|
|
1132
|
+
operations,
|
|
1133
|
+
nextOperationId
|
|
1134
|
+
}));
|
|
1053
1135
|
return operations.length > maxOperations ? null : {
|
|
1054
1136
|
changes,
|
|
1055
1137
|
operations
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/compare/reproducible-package.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* The last
|
|
3
|
+
* The last two clocks in the compare path are outside the document body.
|
|
4
4
|
*
|
|
5
5
|
* Every part the serializer rewrites is stored with JSZip's default entry
|
|
6
6
|
* date, which is `new Date()`. The XML is identical between two runs, but the
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
* both runs land in the same two-second bucket — so the packages match most of
|
|
9
9
|
* the time and differ occasionally, which is worse than differing always.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* The save also stamps `dcterms:modified` in `docProps/core.xml` from the wall
|
|
12
|
+
* clock, which is the same failure one part deeper: two runs over identical
|
|
13
|
+
* inputs differ in that part alone.
|
|
14
|
+
*
|
|
15
|
+
* Restamping both from the comparison's own timestamp removes them. It also
|
|
16
|
+
* states the truth about the package: a generated redline is dated by the
|
|
13
17
|
* comparison that produced it, not by the second it happened to be written.
|
|
14
18
|
*/
|
|
15
19
|
declare const withFixedPackageDates: (buffer: ArrayBuffer, date: Date) => Promise<ArrayBuffer>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import JSZip from "jszip";
|
|
2
2
|
//#region src/compare/reproducible-package.ts
|
|
3
3
|
/**
|
|
4
|
-
* The last
|
|
4
|
+
* The last two clocks in the compare path are outside the document body.
|
|
5
5
|
*
|
|
6
6
|
* Every part the serializer rewrites is stored with JSZip's default entry
|
|
7
7
|
* date, which is `new Date()`. The XML is identical between two runs, but the
|
|
@@ -9,14 +9,31 @@ import JSZip from "jszip";
|
|
|
9
9
|
* both runs land in the same two-second bucket — so the packages match most of
|
|
10
10
|
* the time and differ occasionally, which is worse than differing always.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* The save also stamps `dcterms:modified` in `docProps/core.xml` from the wall
|
|
13
|
+
* clock, which is the same failure one part deeper: two runs over identical
|
|
14
|
+
* inputs differ in that part alone.
|
|
15
|
+
*
|
|
16
|
+
* Restamping both from the comparison's own timestamp removes them. It also
|
|
17
|
+
* states the truth about the package: a generated redline is dated by the
|
|
14
18
|
* comparison that produced it, not by the second it happened to be written.
|
|
15
19
|
*/
|
|
16
20
|
/** JSZip deflate level `repackDocx` writes DOCX parts at. */
|
|
17
21
|
const DOCX_COMPRESSION_LEVEL = 6;
|
|
22
|
+
const CORE_PROPERTIES_PATH = "docProps/core.xml";
|
|
23
|
+
const MODIFIED_ELEMENT = /<dcterms:modified[^<>]*>[^<]*<\/dcterms:modified>/u;
|
|
24
|
+
/**
|
|
25
|
+
* Rewrite `dcterms:modified` where the save already wrote one. An absent
|
|
26
|
+
* element stays absent: the comparison edits the document it was handed, and
|
|
27
|
+
* synthesizing metadata the input never carried is a different decision.
|
|
28
|
+
*/
|
|
29
|
+
const withFixedModifiedDate = (corePropsXml, date) => corePropsXml.replace(MODIFIED_ELEMENT, `<dcterms:modified xsi:type="dcterms:W3CDTF">${date.toISOString()}</dcterms:modified>`);
|
|
18
30
|
const withFixedPackageDates = async (buffer, date) => {
|
|
19
31
|
const zip = await JSZip.loadAsync(buffer);
|
|
32
|
+
const coreProps = zip.file(CORE_PROPERTIES_PATH);
|
|
33
|
+
if (coreProps) zip.file(CORE_PROPERTIES_PATH, withFixedModifiedDate(await coreProps.async("text"), date), {
|
|
34
|
+
compression: "DEFLATE",
|
|
35
|
+
compressionOptions: { level: DOCX_COMPRESSION_LEVEL }
|
|
36
|
+
});
|
|
20
37
|
zip.forEach((_path, file) => {
|
|
21
38
|
file.date = date;
|
|
22
39
|
});
|
package/dist/compare/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FolioAIBlockParagraphProperties, FolioAIBlockTableLocation, FolioAIEditSkippedOperation, FolioAIInlineFormatting } from "../ai-edits/types.js";
|
|
2
2
|
import { WordDiffGranularity } from "../ai-edits/word-diff.js";
|
|
3
3
|
import { FolioDocumentStoryHandle, FolioNumberingLevel } from "../ai-edits/headless.js";
|
|
4
|
-
import { CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant } from "./verification.js";
|
|
4
|
+
import { CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant, FinalParagraphMarkDeletion } from "./verification.js";
|
|
5
5
|
//#region src/compare/types.d.ts
|
|
6
6
|
/** Everything {@link compareDocx} needs; nothing it reads from the ambient clock. */
|
|
7
7
|
type CompareDocxOptions = {
|
|
@@ -277,6 +277,21 @@ declare class CompareDocxSerializeError extends CompareDocxSerializeError_base<{
|
|
|
277
277
|
message: string;
|
|
278
278
|
cause: unknown;
|
|
279
279
|
}> {}
|
|
280
|
-
|
|
280
|
+
declare const CompareDocxFinalParagraphMarkError_base: import("better-result").TaggedErrorClass<"CompareDocxFinalParagraphMarkError">;
|
|
281
|
+
/**
|
|
282
|
+
* A container's final paragraph mark carries a deletion, so the package would
|
|
283
|
+
* not open.
|
|
284
|
+
*
|
|
285
|
+
* A deleted paragraph mark means "merge this paragraph into the following
|
|
286
|
+
* one", and a container's last paragraph has no following one. Checked before
|
|
287
|
+
* the package is written, and fatal under either `onUnverified` setting: there
|
|
288
|
+
* is no redline to emit when a consumer refuses the file.
|
|
289
|
+
*/
|
|
290
|
+
declare class CompareDocxFinalParagraphMarkError extends CompareDocxFinalParagraphMarkError_base<{
|
|
291
|
+
message: string;
|
|
292
|
+
/** Every container that carries one, each named structurally. */
|
|
293
|
+
deletions: readonly FinalParagraphMarkDeletion[];
|
|
294
|
+
}> {}
|
|
295
|
+
type CompareDocxError = CompareDocxApplyError | CompareDocxFinalParagraphMarkError | CompareDocxOperationLimitError | CompareDocxParseError | CompareDocxRoundTripError | CompareDocxSerializeError | InvalidCompareDocxOptionsError;
|
|
281
296
|
//#endregion
|
|
282
|
-
export { COMPARE_UNSUPPORTED_REASONS, CompareChange, CompareChangeLocation, CompareDocxApplyError, CompareDocxError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, CompareFormatRange, CompareResult, CompareUnsupportedPart, CompareUnsupportedReason, InvalidCompareDocxOptionsError };
|
|
297
|
+
export { COMPARE_UNSUPPORTED_REASONS, CompareChange, CompareChangeLocation, CompareDocxApplyError, CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, CompareFormatRange, CompareResult, CompareUnsupportedPart, CompareUnsupportedReason, InvalidCompareDocxOptionsError };
|
package/dist/compare/types.js
CHANGED
|
@@ -28,5 +28,15 @@ var CompareDocxRoundTripError = class extends TaggedError("CompareDocxRoundTripE
|
|
|
28
28
|
/** The difference needs more operations than the engine will generate. */
|
|
29
29
|
var CompareDocxOperationLimitError = class extends TaggedError("CompareDocxOperationLimitError") {};
|
|
30
30
|
var CompareDocxSerializeError = class extends TaggedError("CompareDocxSerializeError") {};
|
|
31
|
+
/**
|
|
32
|
+
* A container's final paragraph mark carries a deletion, so the package would
|
|
33
|
+
* not open.
|
|
34
|
+
*
|
|
35
|
+
* A deleted paragraph mark means "merge this paragraph into the following
|
|
36
|
+
* one", and a container's last paragraph has no following one. Checked before
|
|
37
|
+
* the package is written, and fatal under either `onUnverified` setting: there
|
|
38
|
+
* is no redline to emit when a consumer refuses the file.
|
|
39
|
+
*/
|
|
40
|
+
var CompareDocxFinalParagraphMarkError = class extends TaggedError("CompareDocxFinalParagraphMarkError") {};
|
|
31
41
|
//#endregion
|
|
32
|
-
export { COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError };
|
|
42
|
+
export { COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError };
|
|
@@ -51,5 +51,33 @@ type ClassifyOptions = {
|
|
|
51
51
|
* a divergence always produces a failure rather than being dropped.
|
|
52
52
|
*/
|
|
53
53
|
declare const classifyProjectionMismatch: ({ invariant, story, actual, expected }: ClassifyOptions) => CompareVerificationFailure | null;
|
|
54
|
+
/**
|
|
55
|
+
* A container whose last paragraph carries a deletion on its mark.
|
|
56
|
+
*
|
|
57
|
+
* Structural facts only — a path through the package model and an index — so
|
|
58
|
+
* the finding is safe to log, report or quote.
|
|
59
|
+
*/
|
|
60
|
+
type FinalParagraphMarkDeletion = {
|
|
61
|
+
/** Where the container sits in the package model, e.g. `package.document.content`. */
|
|
62
|
+
container: string;
|
|
63
|
+
/** The paragraph's index among its container's children. */
|
|
64
|
+
paragraphIndex: number;
|
|
65
|
+
/** The mark kind found there: `del`, or `moveFrom` for a relocation's source. */
|
|
66
|
+
kind: "del" | "moveFrom";
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Every container in a package whose final paragraph mark carries a deletion.
|
|
70
|
+
*
|
|
71
|
+
* A deleted paragraph mark says "join this paragraph with the one after it".
|
|
72
|
+
* The last paragraph of a body, a table cell, a header or footer, a note or a
|
|
73
|
+
* text box has no paragraph after it, so the mark states an edit that cannot
|
|
74
|
+
* be carried out, and a consumer refuses the package rather than opening it.
|
|
75
|
+
*
|
|
76
|
+
* The walk is over the package model rather than over a list of the containers
|
|
77
|
+
* known today: a container is any sequence that ends in a paragraph, so a part
|
|
78
|
+
* the model grows later is covered the day it arrives instead of the day
|
|
79
|
+
* someone remembers this function.
|
|
80
|
+
*/
|
|
81
|
+
declare const deletedFinalParagraphMarks: (packageModel: unknown) => FinalParagraphMarkDeletion[];
|
|
54
82
|
//#endregion
|
|
55
|
-
export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant, classifyProjectionMismatch, projectSupportedInlineFormatting, sameProjection };
|
|
83
|
+
export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant, FinalParagraphMarkDeletion, classifyProjectionMismatch, deletedFinalParagraphMarks, projectSupportedInlineFormatting, sameProjection };
|
|
@@ -142,5 +142,48 @@ const classifyProjectionMismatch = ({ invariant, story, actual, expected }) => {
|
|
|
142
142
|
if (actual.length !== expected.length) return failure("block-count", `${counts}, first differing ${at}`);
|
|
143
143
|
return failure("text", `a ${containerKind(left.container)} block's text does not match ${at}, length ${String(left.text.length)} against ${String(right.text.length)} (${counts})`);
|
|
144
144
|
};
|
|
145
|
+
/** The mark kinds that resolve by joining the paragraph with the one after it. */
|
|
146
|
+
const JOINS_FORWARD_ON_ACCEPT = Object.freeze(["del", "moveFrom"]);
|
|
147
|
+
const joinsForwardOnAccept = (value) => JOINS_FORWARD_ON_ACCEPT.some((kind) => kind === value);
|
|
148
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
149
|
+
const isParagraph = (value) => isRecord(value) && value["type"] === "paragraph";
|
|
150
|
+
/**
|
|
151
|
+
* Every container in a package whose final paragraph mark carries a deletion.
|
|
152
|
+
*
|
|
153
|
+
* A deleted paragraph mark says "join this paragraph with the one after it".
|
|
154
|
+
* The last paragraph of a body, a table cell, a header or footer, a note or a
|
|
155
|
+
* text box has no paragraph after it, so the mark states an edit that cannot
|
|
156
|
+
* be carried out, and a consumer refuses the package rather than opening it.
|
|
157
|
+
*
|
|
158
|
+
* The walk is over the package model rather than over a list of the containers
|
|
159
|
+
* known today: a container is any sequence that ends in a paragraph, so a part
|
|
160
|
+
* the model grows later is covered the day it arrives instead of the day
|
|
161
|
+
* someone remembers this function.
|
|
162
|
+
*/
|
|
163
|
+
const deletedFinalParagraphMarks = (packageModel) => {
|
|
164
|
+
const found = [];
|
|
165
|
+
const visit = (value, path) => {
|
|
166
|
+
if (Array.isArray(value)) {
|
|
167
|
+
const last = value.at(-1);
|
|
168
|
+
const mark = isParagraph(last) ? last["pPrMark"] : void 0;
|
|
169
|
+
const kind = isRecord(mark) ? mark["kind"] : void 0;
|
|
170
|
+
if (joinsForwardOnAccept(kind)) found.push({
|
|
171
|
+
container: path,
|
|
172
|
+
paragraphIndex: value.length - 1,
|
|
173
|
+
kind
|
|
174
|
+
});
|
|
175
|
+
for (const [index, item] of value.entries()) visit(item, `${path}[${String(index)}]`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (value instanceof Map) {
|
|
179
|
+
for (const [key, item] of value) visit(item, `${path}.${String(key)}`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (!isRecord(value) || value instanceof Date || ArrayBuffer.isView(value)) return;
|
|
183
|
+
for (const [key, item] of Object.entries(value)) visit(item, `${path}.${key}`);
|
|
184
|
+
};
|
|
185
|
+
visit(packageModel, "package");
|
|
186
|
+
return found;
|
|
187
|
+
};
|
|
145
188
|
//#endregion
|
|
146
|
-
export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, classifyProjectionMismatch, projectSupportedInlineFormatting, sameProjection };
|
|
189
|
+
export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, classifyProjectionMismatch, deletedFinalParagraphMarks, projectSupportedInlineFormatting, sameProjection };
|
|
@@ -9,8 +9,8 @@ import { AIBarStatus, AIChatMode, AICitation, AICitationSource, AIGenerateInput,
|
|
|
9
9
|
import { ApplyResult, applySuggestions } from "../ai-suggestions/apply.js";
|
|
10
10
|
import { ResolvedAnchor, isSuggestionStale, resolveSuggestionAnchor } from "../ai-suggestions/conflict.js";
|
|
11
11
|
import { PositionalText, buildPositionalText } from "../ai-suggestions/text-positions.js";
|
|
12
|
-
import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant } from "../compare/verification.js";
|
|
13
|
-
import { COMPARE_UNSUPPORTED_REASONS, CompareChange, CompareChangeLocation, CompareDocxApplyError, CompareDocxError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, CompareFormatRange, CompareResult, CompareUnsupportedPart, CompareUnsupportedReason, InvalidCompareDocxOptionsError } from "../compare/types.js";
|
|
12
|
+
import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant, FinalParagraphMarkDeletion } from "../compare/verification.js";
|
|
13
|
+
import { COMPARE_UNSUPPORTED_REASONS, CompareChange, CompareChangeLocation, CompareDocxApplyError, CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, CompareFormatRange, CompareResult, CompareUnsupportedPart, CompareUnsupportedReason, InvalidCompareDocxOptionsError } from "../compare/types.js";
|
|
14
14
|
import { MAX_COMPARE_OPERATIONS, compareDocx } from "../compare/compare.js";
|
|
15
15
|
import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocumentPreset, DocumentStyleSet } from "../style-sets/types.js";
|
|
16
16
|
import { CreateEmptyDocumentOptions, createEmptyDocument } from "../utils/createDocument.js";
|
|
@@ -37,4 +37,4 @@ import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled
|
|
|
37
37
|
import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
|
|
38
38
|
type Document = document_d_exports.Document;
|
|
39
39
|
type DocxConformanceClass = document_d_exports.DocxConformanceClass;
|
|
40
|
-
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_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, CompareDocxApplyError, type CompareDocxError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFormatRange, type CompareResult, 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_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, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, 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 FolioAISignatureParty, type FolioBlockId, 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, 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, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, 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 };
|
|
40
|
+
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_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFormatRange, type CompareResult, 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_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, type FinalParagraphMarkDeletion, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, 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 FolioAISignatureParty, type FolioBlockId, 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, 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, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, 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
|
@@ -6,7 +6,7 @@ import { isSuggestionStale, resolveSuggestionAnchor } from "../ai-suggestions/co
|
|
|
6
6
|
import { buildPositionalText } from "../ai-suggestions/text-positions.js";
|
|
7
7
|
import { DEFAULT_AI_SUGGESTION_PRESETS } from "../ai-suggestions/types.js";
|
|
8
8
|
import { MAX_COMPARE_OPERATIONS, compareDocx } from "../compare/compare.js";
|
|
9
|
-
import { COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError } from "../compare/types.js";
|
|
9
|
+
import { COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError } from "../compare/types.js";
|
|
10
10
|
import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS } from "../compare/verification.js";
|
|
11
11
|
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, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
12
12
|
import { inspectDocxCompatibility } from "../docx/compatibility.js";
|
|
@@ -31,4 +31,4 @@ import { deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialF
|
|
|
31
31
|
import { createEmptyDocument } from "../utils/createDocument.js";
|
|
32
32
|
import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "../utils/fontResolver.js";
|
|
33
33
|
import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
|
|
34
|
-
export { COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, 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, InvalidCompareDocxOptionsError, 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, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, 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 };
|
|
34
|
+
export { 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_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, InvalidCompareDocxOptionsError, 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, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, 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 };
|