@stll/folio-core 0.32.2 → 0.33.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/dist/ai-edits/__fixtures__/paragraphs.d.ts +17 -0
- package/dist/ai-edits/__fixtures__/paragraphs.js +33 -0
- package/dist/ai-edits/apply.d.ts +49 -3
- package/dist/ai-edits/apply.js +649 -85
- package/dist/ai-edits/blockRange.d.ts +7 -3
- package/dist/ai-edits/blockRange.js +14 -6
- package/dist/ai-edits/headless.d.ts +39 -5
- package/dist/ai-edits/headless.js +76 -17
- package/dist/ai-edits/index.d.ts +6 -6
- package/dist/ai-edits/index.js +3 -3
- package/dist/ai-edits/read.d.ts +4 -0
- package/dist/ai-edits/read.js +30 -6
- package/dist/ai-edits/scoped-reading.js +4 -3
- package/dist/ai-edits/snapshot.d.ts +42 -2
- package/dist/ai-edits/snapshot.js +127 -62
- package/dist/ai-edits/table-row-column-mutations.d.ts +24 -1
- package/dist/ai-edits/table-row-column-mutations.js +98 -6
- package/dist/ai-edits/table-targets.d.ts +12 -3
- package/dist/ai-edits/table-targets.js +15 -5
- package/dist/ai-edits/types.d.ts +219 -15
- package/dist/ai-edits/word-diff.d.ts +54 -11
- package/dist/ai-edits/word-diff.js +221 -61
- package/dist/compare/__fixtures__/body-sequence.d.ts +33 -0
- package/dist/compare/__fixtures__/body-sequence.js +67 -0
- package/dist/compare/__fixtures__/nested-table.d.ts +16 -0
- package/dist/compare/__fixtures__/nested-table.js +50 -0
- package/dist/compare/__fixtures__/numbered-list.d.ts +34 -0
- package/dist/compare/__fixtures__/numbered-list.js +85 -0
- package/dist/compare/column-alignment.d.ts +27 -0
- package/dist/compare/column-alignment.js +162 -0
- package/dist/compare/compare.d.ts +107 -0
- package/dist/compare/compare.js +406 -0
- package/dist/compare/formatting.d.ts +29 -0
- package/dist/compare/formatting.js +84 -0
- package/dist/compare/plan.d.ts +22 -0
- package/dist/compare/plan.js +1059 -0
- package/dist/compare/reproducible-package.d.ts +17 -0
- package/dist/compare/reproducible-package.js +30 -0
- package/dist/compare/scenario.d.ts +77 -0
- package/dist/compare/scenario.js +263 -0
- package/dist/compare/types.d.ts +282 -0
- package/dist/compare/types.js +32 -0
- package/dist/compare/verification.d.ts +55 -0
- package/dist/compare/verification.js +146 -0
- package/dist/compat/eigenpal.d.ts +9 -6
- package/dist/compat/eigenpal.js +6 -3
- package/dist/controller/layoutPipeline.d.ts +13 -0
- package/dist/controller/layoutPipeline.js +15 -1
- package/dist/display-list/build/buildContext.d.ts +39 -0
- package/dist/display-list/build/buildContext.js +31 -0
- package/dist/display-list/build/buildDisplayList.d.ts +79 -0
- package/dist/display-list/build/buildDisplayList.js +283 -0
- package/dist/display-list/build/colors.d.ts +20 -0
- package/dist/display-list/build/colors.js +136 -0
- package/dist/display-list/build/floatingImages.d.ts +24 -0
- package/dist/display-list/build/floatingImages.js +41 -0
- package/dist/display-list/build/fontTable.d.ts +31 -0
- package/dist/display-list/build/fontTable.js +97 -0
- package/dist/display-list/build/furniture.d.ts +86 -0
- package/dist/display-list/build/furniture.js +98 -0
- package/dist/display-list/build/glyphs.d.ts +55 -0
- package/dist/display-list/build/glyphs.js +103 -0
- package/dist/display-list/build/headerFooterPrimitives.d.ts +17 -0
- package/dist/display-list/build/headerFooterPrimitives.js +40 -0
- package/dist/display-list/build/imagePrimitives.d.ts +35 -0
- package/dist/display-list/build/imagePrimitives.js +264 -0
- package/dist/display-list/build/pageBorderPrimitives.d.ts +23 -0
- package/dist/display-list/build/pageBorderPrimitives.js +111 -0
- package/dist/display-list/build/pageFurniture.d.ts +35 -0
- package/dist/display-list/build/pageFurniture.js +141 -0
- package/dist/display-list/build/paragraphPrimitives.d.ts +19 -0
- package/dist/display-list/build/paragraphPrimitives.js +819 -0
- package/dist/display-list/build/regions.d.ts +46 -0
- package/dist/display-list/build/regions.js +56 -0
- package/dist/display-list/build/storyPrimitives.d.ts +29 -0
- package/dist/display-list/build/storyPrimitives.js +279 -0
- package/dist/display-list/build/strokes.d.ts +19 -0
- package/dist/display-list/build/strokes.js +78 -0
- package/dist/display-list/build/tablePrimitives.d.ts +38 -0
- package/dist/display-list/build/tablePrimitives.js +409 -0
- package/dist/display-list/build/textBoxPrimitives.d.ts +14 -0
- package/dist/display-list/build/textBoxPrimitives.js +129 -0
- package/dist/display-list/build/textDecorations.d.ts +29 -0
- package/dist/display-list/build/textDecorations.js +29 -0
- package/dist/display-list/build/unsupported.d.ts +57 -0
- package/dist/display-list/build/unsupported.js +0 -0
- package/dist/display-list/build/watermarkPrimitives.d.ts +15 -0
- package/dist/display-list/build/watermarkPrimitives.js +128 -0
- package/dist/display-list/dom/renderDisplayListToDom.d.ts +26 -0
- package/dist/display-list/dom/renderDisplayListToDom.js +620 -0
- package/dist/display-list/editor/displayListPagePainter.d.ts +22 -0
- package/dist/display-list/editor/displayListPagePainter.js +63 -0
- package/dist/display-list/editor/pageRenderer.d.ts +24 -0
- package/dist/display-list/editor/pageRenderer.js +36 -0
- package/dist/display-list/primitives.d.ts +95 -0
- package/dist/display-list/primitives.js +127 -0
- package/dist/display-list/types.d.ts +472 -0
- package/dist/display-list/types.js +0 -0
- package/dist/document-operations.d.ts +39 -8
- package/dist/document-operations.js +169 -16
- package/dist/document-stories.d.ts +16 -0
- package/dist/document-stories.js +48 -4
- package/dist/docx/packageParts.d.ts +35 -0
- package/dist/docx/packageParts.js +120 -0
- package/dist/docx/paragraphParser.js +22 -22
- package/dist/docx/paragraphTraversal.js +1 -1
- package/dist/docx/renderedPageBreakNormalization.js +3 -1
- package/dist/docx/revisionIdNormalization.d.ts +13 -0
- package/dist/docx/revisionIdNormalization.js +103 -0
- package/dist/docx/rezip.js +26 -17
- package/dist/docx/selectiveSave.js +2 -2
- package/dist/docx/serializer/commentSerializer.js +6 -1
- package/dist/docx/serializer/paragraphSerializer.js +33 -4
- package/dist/docx/serializer/runSerializer.js +11 -10
- package/dist/docx/serializer/tableSerializer.js +2 -1
- package/dist/docx/server/applyDocxXmlPatchProposal.js +1 -1
- package/dist/docx/server/createBilingualDocx.js +3 -2
- package/dist/docx/streamingXmlParser.d.ts +13 -1
- package/dist/docx/streamingXmlParser.js +49 -11
- package/dist/docx/unzip.d.ts +1 -2
- package/dist/docx/unzip.js +25 -6
- package/dist/docx/xmlParser.d.ts +3 -1
- package/dist/docx/xmlParser.js +33 -27
- package/dist/export-pdf.d.ts +43 -0
- package/dist/export-pdf.js +98 -0
- package/dist/fonts/headlessMeasure.d.ts +76 -0
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/fonts/sfnt/parse.d.ts +51 -0
- package/dist/fonts/sfnt/parse.js +525 -0
- package/dist/fonts/sfnt/subset.d.ts +20 -0
- package/dist/fonts/sfnt/subset.js +350 -0
- package/dist/fonts/sfnt/tables.d.ts +88 -0
- package/dist/fonts/sfnt/tables.js +131 -0
- package/dist/fonts/sfnt/woff.d.ts +14 -0
- package/dist/fonts/sfnt/woff.js +163 -0
- package/dist/generated/text_shaper.js +324 -0
- package/dist/generated/text_shaper_bg.wasm +0 -0
- package/dist/headless-layout.d.ts +75 -0
- package/dist/headless-layout.js +350 -0
- package/dist/index.d.ts +9 -6
- package/dist/index.js +6 -3
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -0
- package/dist/layout-engine/measure/advanceComposition.d.ts +62 -0
- package/dist/layout-engine/measure/advanceComposition.js +148 -0
- package/dist/layout-engine/measure/cache.d.ts +2 -0
- package/dist/layout-engine/measure/measureContainer.js +13 -0
- package/dist/layout-engine/measure/measureParagraph.js +1 -2
- package/dist/layout-engine/measure/measureTypes.d.ts +12 -0
- package/dist/layout-engine/measure/tableInlinePlacement.d.ts +3 -2
- package/dist/layout-engine/measure/tableInlinePlacement.js +14 -1
- package/dist/layout-engine/tableIndentCompatibility.d.ts +5 -0
- package/dist/layout-engine/tableIndentCompatibility.js +15 -0
- package/dist/layout-engine/types.d.ts +8 -0
- package/dist/layout-painter/renderPage.d.ts +29 -1
- package/dist/layout-painter/renderPage.js +47 -19
- package/dist/layout-painter/renderParagraph.d.ts +21 -2
- package/dist/layout-painter/renderParagraph.js +1 -1
- package/dist/layout-painter/renderTable.js +37 -4
- package/dist/managers/editorShortcuts.d.ts +33 -1
- package/dist/managers/editorShortcuts.js +20 -1
- package/dist/markdown/renderRuns.js +7 -2
- package/dist/markdown/renderTable.js +5 -1
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/pdf/contentStream.d.ts +73 -0
- package/dist/pdf/contentStream.js +143 -0
- package/dist/pdf/fonts.d.ts +96 -0
- package/dist/pdf/fonts.js +593 -0
- package/dist/pdf/images.d.ts +28 -0
- package/dist/pdf/images.js +439 -0
- package/dist/pdf/objects.d.ts +93 -0
- package/dist/pdf/objects.js +237 -0
- package/dist/pdf/pageSpace.d.ts +43 -0
- package/dist/pdf/pageSpace.js +57 -0
- package/dist/pdf/paint.d.ts +32 -0
- package/dist/pdf/paint.js +442 -0
- package/dist/pdf/writePdf.d.ts +56 -0
- package/dist/pdf/writePdf.js +345 -0
- package/dist/prosemirror/commands/comments.js +91 -6
- package/dist/prosemirror/conversion/fromProseDoc.js +41 -7
- package/dist/prosemirror/conversion/toProseDoc.js +41 -4
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +15 -2
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +35 -6
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +2 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +4 -3
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +3 -1
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +5 -3
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -1
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +9 -3
- package/dist/prosemirror/extensions/nodes/TableExtension.js +56 -39
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +3 -1
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +5 -3
- package/dist/prosemirror/plugins/suggestionMode.js +1 -0
- package/dist/prosemirror/revisionCarriers.js +19 -2
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +2 -2
- package/dist/prosemirror/utils/extractTrackedChanges.js +59 -23
- package/dist/prosemirror/validation.js +55 -27
- package/dist/prosemirror/zeroWidthAnchors.d.ts +10 -0
- package/dist/prosemirror/zeroWidthAnchors.js +23 -0
- package/dist/redline.js +12 -79
- package/dist/server.d.ts +3 -3
- package/dist/server.js +2 -2
- package/dist/shaping/placeRun.d.ts +51 -0
- package/dist/shaping/placeRun.js +84 -0
- package/dist/shaping/shaper.d.ts +92 -0
- package/dist/shaping/shaper.js +102 -0
- package/dist/types/block-id.d.ts +18 -2
- package/dist/types/block-id.js +49 -5
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/clipboard.js +4 -3
- package/dist/utils/fontResolver.js +183 -0
- package/dist/utils/htmlComments.d.ts +17 -0
- package/dist/utils/htmlComments.js +22 -0
- package/dist/utils/scriptSegments.d.ts +12 -1
- package/dist/utils/scriptSegments.js +17 -1
- package/dist/version-comparison.d.ts +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { TaggedError } from "better-result";
|
|
2
|
+
//#region src/compare/types.ts
|
|
3
|
+
/**
|
|
4
|
+
* Public vocabulary of {@link ./compare.compareDocx}: the change list, the
|
|
5
|
+
* options that pin its output, and the failures it reports.
|
|
6
|
+
*/
|
|
7
|
+
/** Why a part of the package is absent from `changes`. */
|
|
8
|
+
const COMPARE_UNSUPPORTED_REASONS = Object.freeze([
|
|
9
|
+
"story-missing-in-base",
|
|
10
|
+
"story-missing-in-target",
|
|
11
|
+
"story-not-editable"
|
|
12
|
+
]);
|
|
13
|
+
var InvalidCompareDocxOptionsError = class extends TaggedError("InvalidCompareDocxOptionsError") {};
|
|
14
|
+
var CompareDocxParseError = class extends TaggedError("CompareDocxParseError") {};
|
|
15
|
+
/**
|
|
16
|
+
* The applier refused at least one derived operation, so accepting the result
|
|
17
|
+
* would not reproduce the target. Reported instead of returning a package that
|
|
18
|
+
* silently under-represents the difference.
|
|
19
|
+
*/
|
|
20
|
+
var CompareDocxApplyError = class extends TaggedError("CompareDocxApplyError") {};
|
|
21
|
+
/**
|
|
22
|
+
* The generated tracked changes do not accept back to the target. Raised by
|
|
23
|
+
* the self-check {@link compareDocx} runs before returning: a redline that
|
|
24
|
+
* quietly loses part of the difference is worse than no redline, so the
|
|
25
|
+
* mismatch is surfaced instead of the document.
|
|
26
|
+
*/
|
|
27
|
+
var CompareDocxRoundTripError = class extends TaggedError("CompareDocxRoundTripError") {};
|
|
28
|
+
/** The difference needs more operations than the engine will generate. */
|
|
29
|
+
var CompareDocxOperationLimitError = class extends TaggedError("CompareDocxOperationLimitError") {};
|
|
30
|
+
var CompareDocxSerializeError = class extends TaggedError("CompareDocxSerializeError") {};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { FolioAIBlock } from "../ai-edits/types.js";
|
|
2
|
+
import { FolioDocumentStoryHandle } from "../ai-edits/headless.js";
|
|
3
|
+
//#region src/compare/verification.d.ts
|
|
4
|
+
/** The two directions of the round trip, each an invariant of its own. */
|
|
5
|
+
declare const COMPARE_VERIFICATION_INVARIANTS: readonly ["accept-reproduces-target", "reject-reproduces-base"];
|
|
6
|
+
type CompareVerificationInvariant = (typeof COMPARE_VERIFICATION_INVARIANTS)[number];
|
|
7
|
+
/**
|
|
8
|
+
* What diverged. Ordered from the structural to the textual: the first cause
|
|
9
|
+
* that fits is the one reported, because a block in the wrong container is a
|
|
10
|
+
* different finding from a block whose words are wrong even when both are true.
|
|
11
|
+
*/
|
|
12
|
+
declare const COMPARE_VERIFICATION_CAUSES: readonly ["invisible-structure", "block-count", "container", "style", "list-level", "inline-formatting", "whitespace", "text"];
|
|
13
|
+
type CompareVerificationCause = (typeof COMPARE_VERIFICATION_CAUSES)[number];
|
|
14
|
+
/** One invariant that did not hold, in one story. */
|
|
15
|
+
type CompareVerificationFailure = {
|
|
16
|
+
invariant: CompareVerificationInvariant;
|
|
17
|
+
cause: CompareVerificationCause;
|
|
18
|
+
story: FolioDocumentStoryHandle;
|
|
19
|
+
/** Structural facts only: counts, offsets, container kinds. Safe to quote. */
|
|
20
|
+
detail: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Whether the redline was proven to round-trip.
|
|
24
|
+
*
|
|
25
|
+
* `unverified` is only ever returned when the caller asked for it with
|
|
26
|
+
* `onUnverified: "emit"`; the default refuses instead, because a redline that
|
|
27
|
+
* reads plausibly and is wrong is worse than no redline.
|
|
28
|
+
*/
|
|
29
|
+
type CompareVerification = {
|
|
30
|
+
status: "verified";
|
|
31
|
+
} | {
|
|
32
|
+
status: "unverified";
|
|
33
|
+
failures: readonly CompareVerificationFailure[];
|
|
34
|
+
};
|
|
35
|
+
/** Effective supported formatting with equivalent adjacent runs normalized. */
|
|
36
|
+
declare const projectSupportedInlineFormatting: ({ text, previewRuns }: FolioAIBlock) => string;
|
|
37
|
+
/** Element by element, never by joining: a block's text may hold the separator. */
|
|
38
|
+
declare const sameProjection: (left: readonly string[], right: readonly string[]) => boolean;
|
|
39
|
+
type ClassifyOptions = {
|
|
40
|
+
invariant: CompareVerificationInvariant;
|
|
41
|
+
story: FolioDocumentStoryHandle;
|
|
42
|
+
/** What the redline actually leaves. */
|
|
43
|
+
actual: readonly string[];
|
|
44
|
+
/** What the invariant says it should leave. */
|
|
45
|
+
expected: readonly string[];
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* The failure two projections describe, or `null` when they agree.
|
|
49
|
+
*
|
|
50
|
+
* Total over the causes by construction: the last branch is unconditional, so
|
|
51
|
+
* a divergence always produces a failure rather than being dropped.
|
|
52
|
+
*/
|
|
53
|
+
declare const classifyProjectionMismatch: ({ invariant, story, actual, expected }: ClassifyOptions) => CompareVerificationFailure | null;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant, classifyProjectionMismatch, projectSupportedInlineFormatting, sameProjection };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
//#region src/compare/verification.ts
|
|
2
|
+
/** The two directions of the round trip, each an invariant of its own. */
|
|
3
|
+
const COMPARE_VERIFICATION_INVARIANTS = Object.freeze(["accept-reproduces-target", "reject-reproduces-base"]);
|
|
4
|
+
/**
|
|
5
|
+
* What diverged. Ordered from the structural to the textual: the first cause
|
|
6
|
+
* that fits is the one reported, because a block in the wrong container is a
|
|
7
|
+
* different finding from a block whose words are wrong even when both are true.
|
|
8
|
+
*/
|
|
9
|
+
const COMPARE_VERIFICATION_CAUSES = Object.freeze([
|
|
10
|
+
"invisible-structure",
|
|
11
|
+
"block-count",
|
|
12
|
+
"container",
|
|
13
|
+
"style",
|
|
14
|
+
"list-level",
|
|
15
|
+
"inline-formatting",
|
|
16
|
+
"whitespace",
|
|
17
|
+
"text"
|
|
18
|
+
]);
|
|
19
|
+
const supportedInlineStyle = ({ bold, italic, underline, strike }) => `${bold === true ? "b" : ""}${italic === true ? "i" : ""}${underline === true ? "u" : ""}${strike === true ? "s" : ""}`;
|
|
20
|
+
/** Effective supported formatting with equivalent adjacent runs normalized. */
|
|
21
|
+
const projectSupportedInlineFormatting = ({ text, previewRuns }) => {
|
|
22
|
+
const projected = [];
|
|
23
|
+
for (const run of previewRuns ?? [{ text }]) {
|
|
24
|
+
if (run.text.length === 0) continue;
|
|
25
|
+
const style = supportedInlineStyle(run);
|
|
26
|
+
const previous = projected.at(-1);
|
|
27
|
+
if (previous?.style === style) {
|
|
28
|
+
previous.length += run.text.length;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
projected.push({
|
|
32
|
+
length: run.text.length,
|
|
33
|
+
style
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return projected.map(({ length, style }) => `${String(length)}:${style}`).join(",");
|
|
37
|
+
};
|
|
38
|
+
const parseProjection = (entry) => {
|
|
39
|
+
const first = entry.indexOf("|");
|
|
40
|
+
const second = entry.indexOf("|", first + 1);
|
|
41
|
+
const third = entry.indexOf("|", second + 1);
|
|
42
|
+
if (first === -1 || second === -1 || third === -1) return {
|
|
43
|
+
container: "",
|
|
44
|
+
styleId: "",
|
|
45
|
+
listLevel: "",
|
|
46
|
+
text: entry
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
container: entry.slice(0, first),
|
|
50
|
+
styleId: entry.slice(first + 1, second),
|
|
51
|
+
listLevel: entry.slice(second + 1, third),
|
|
52
|
+
text: entry.slice(third + 1)
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const CONTAINER_PATTERN = /^t(\d+)r(\d+)c(\d+)p(\d+)$/u;
|
|
56
|
+
const containerKind = (container) => CONTAINER_PATTERN.test(container) ? "cell" : "body";
|
|
57
|
+
const collapseWhitespace = (text) => text.replace(/\s+/gu, " ").trim();
|
|
58
|
+
/** Element by element, never by joining: a block's text may hold the separator. */
|
|
59
|
+
const sameProjection = (left, right) => left.length === right.length && left.every((entry, index) => entry === right[index]);
|
|
60
|
+
/**
|
|
61
|
+
* The same projection with every table coordinate renumbered by first
|
|
62
|
+
* appearance, so it counts the blocks the model holds rather than the
|
|
63
|
+
* paragraphs the package contains.
|
|
64
|
+
*
|
|
65
|
+
* The snapshot skips a hidden row's whole subtree, so a table that hides a row
|
|
66
|
+
* on one side only reports every later row one position along. No operation
|
|
67
|
+
* can put a block at those coordinates, because none can create or remove the
|
|
68
|
+
* hidden row that produces them. When two projections agree here and disagree
|
|
69
|
+
* on the raw coordinates, the redline holds every block the other side does,
|
|
70
|
+
* in order, and the difference is one the block model cannot see.
|
|
71
|
+
*/
|
|
72
|
+
const byVisibleOrdinal = (entries) => {
|
|
73
|
+
const ordinals = /* @__PURE__ */ new Map();
|
|
74
|
+
const counts = /* @__PURE__ */ new Map();
|
|
75
|
+
const ordinalWithin = (scope, index) => {
|
|
76
|
+
const key = `${scope}:${index}`;
|
|
77
|
+
const existing = ordinals.get(key);
|
|
78
|
+
if (existing !== void 0) return existing;
|
|
79
|
+
const next = counts.get(scope) ?? 0;
|
|
80
|
+
counts.set(scope, next + 1);
|
|
81
|
+
ordinals.set(key, next);
|
|
82
|
+
return next;
|
|
83
|
+
};
|
|
84
|
+
const paragraphCounts = /* @__PURE__ */ new Map();
|
|
85
|
+
return entries.map((entry) => {
|
|
86
|
+
const first = entry.indexOf("|");
|
|
87
|
+
const match = CONTAINER_PATTERN.exec(entry.slice(0, first));
|
|
88
|
+
if (!match) return entry;
|
|
89
|
+
const [, table = "", row = "", cell = ""] = match;
|
|
90
|
+
const tableOrdinal = ordinalWithin("t", table);
|
|
91
|
+
const rowScope = `r${String(tableOrdinal)}`;
|
|
92
|
+
const rowOrdinal = ordinalWithin(rowScope, row);
|
|
93
|
+
const cellScope = `c${String(tableOrdinal)}.${String(rowOrdinal)}`;
|
|
94
|
+
const cellOrdinal = ordinalWithin(cellScope, cell);
|
|
95
|
+
const cellKey = `${cellScope}:${cell}`;
|
|
96
|
+
const paragraphOrdinal = paragraphCounts.get(cellKey) ?? 0;
|
|
97
|
+
paragraphCounts.set(cellKey, paragraphOrdinal + 1);
|
|
98
|
+
return `t${String(tableOrdinal)}r${String(rowOrdinal)}c${String(cellOrdinal)}p${String(paragraphOrdinal)}` + entry.slice(first);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Where two projections first diverge, and what diverged there. A pair that
|
|
103
|
+
* matches everywhere but in length diverges at the shorter one's end.
|
|
104
|
+
*/
|
|
105
|
+
const firstDivergence = (actual, expected) => {
|
|
106
|
+
const shared = Math.min(actual.length, expected.length);
|
|
107
|
+
for (let index = 0; index < shared; index++) if (actual[index] !== expected[index]) return {
|
|
108
|
+
index,
|
|
109
|
+
actual: parseProjection(actual[index] ?? ""),
|
|
110
|
+
expected: parseProjection(expected[index] ?? "")
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
index: shared,
|
|
114
|
+
actual: shared < actual.length ? parseProjection(actual[shared] ?? "") : null,
|
|
115
|
+
expected: shared < expected.length ? parseProjection(expected[shared] ?? "") : null
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* The failure two projections describe, or `null` when they agree.
|
|
120
|
+
*
|
|
121
|
+
* Total over the causes by construction: the last branch is unconditional, so
|
|
122
|
+
* a divergence always produces a failure rather than being dropped.
|
|
123
|
+
*/
|
|
124
|
+
const classifyProjectionMismatch = ({ invariant, story, actual, expected }) => {
|
|
125
|
+
if (sameProjection(actual, expected)) return null;
|
|
126
|
+
const failure = (cause, detail) => ({
|
|
127
|
+
invariant,
|
|
128
|
+
cause,
|
|
129
|
+
story,
|
|
130
|
+
detail
|
|
131
|
+
});
|
|
132
|
+
if (sameProjection(byVisibleOrdinal(actual), byVisibleOrdinal(expected))) return failure("invisible-structure", `every block matches once table coordinates count visible blocks (${String(expected.length)} blocks)`);
|
|
133
|
+
const divergence = firstDivergence(actual, expected);
|
|
134
|
+
const at = `at block ${String(divergence.index)}/${String(expected.length)}`;
|
|
135
|
+
const counts = `${String(actual.length)} blocks against ${String(expected.length)}`;
|
|
136
|
+
if (divergence.actual === null || divergence.expected === null) return failure("block-count", `${actual.length > expected.length ? "more" : "fewer"} blocks than expected (${counts}), diverging ${at}`);
|
|
137
|
+
const { actual: left, expected: right } = divergence;
|
|
138
|
+
if (left.container !== right.container) return failure("container", `a block sits in a ${containerKind(left.container)} where it is expected in a ${containerKind(right.container)}, ${at} (${counts})`);
|
|
139
|
+
if (left.text === right.text && left.styleId !== right.styleId) return failure("style", `the paragraph style did not move ${at} (${counts})`);
|
|
140
|
+
if (left.text === right.text && left.listLevel !== right.listLevel) return failure("list-level", `the list level did not move ${at} (${counts})`);
|
|
141
|
+
if (collapseWhitespace(left.text) === collapseWhitespace(right.text)) return failure("whitespace", `a block's text differs only in whitespace ${at} (${counts})`);
|
|
142
|
+
if (actual.length !== expected.length) return failure("block-count", `${counts}, first differing ${at}`);
|
|
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
|
+
};
|
|
145
|
+
//#endregion
|
|
146
|
+
export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, classifyProjectionMismatch, projectSupportedInlineFormatting, sameProjection };
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAISignatureParty } from "../ai-edits/types.js";
|
|
2
|
-
import {
|
|
1
|
+
import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAISignatureParty } from "../ai-edits/types.js";
|
|
2
|
+
import { WORD_DIFF_GRANULARITIES, WordDiffGranularity, WordDiffNormalization, WordDiffOptions, WordDiffSegment, diffWordSegments } from "../ai-edits/word-diff.js";
|
|
3
|
+
import { FolioAIEditApplyOutcome, FolioRevisionStamp, FolioWordDiffOptions, applyFolioAIEditOperations } from "../ai-edits/apply.js";
|
|
3
4
|
import { document_d_exports } from "../types/document.js";
|
|
4
|
-
import { ApplyFolioDocumentOperationsOptions, 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, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
5
|
-
import { createFolioAIEditSnapshot, hashFolioAIBlockText, normalizeFolioAIBlockText } from "../ai-edits/snapshot.js";
|
|
5
|
+
import { ApplyFolioDocumentOperationsOptions, 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, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
6
|
+
import { createFolioAIEditSnapshot, hashFolioAIBlockText, isFolioAIContentBlock, normalizeFolioAIBlockText } from "../ai-edits/snapshot.js";
|
|
6
7
|
import { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "../types/block-id.js";
|
|
7
|
-
import { WordDiffSegment, diffWordSegments } from "../ai-edits/word-diff.js";
|
|
8
8
|
import { AIBarStatus, AIChatMode, AICitation, AICitationSource, AIGenerateInput, AISuggestion, AISuggestionApplyMode, AISuggestionPreset, AISuggestionSeverity, AISuggestionStatus, DEFAULT_AI_SUGGESTION_PRESETS } from "../ai-suggestions/types.js";
|
|
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";
|
|
14
|
+
import { MAX_COMPARE_OPERATIONS, compareDocx } from "../compare/compare.js";
|
|
12
15
|
import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocumentPreset, DocumentStyleSet } from "../style-sets/types.js";
|
|
13
16
|
import { CreateEmptyDocumentOptions, createEmptyDocument } from "../utils/createDocument.js";
|
|
14
17
|
import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
|
|
@@ -34,4 +37,4 @@ import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled
|
|
|
34
37
|
import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
|
|
35
38
|
type Document = document_d_exports.Document;
|
|
36
39
|
type DocxConformanceClass = document_d_exports.DocxConformanceClass;
|
|
37
|
-
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, 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 FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, 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 FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidFolioDocumentOperationBatchError, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, 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, 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, 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 };
|
package/dist/compat/eigenpal.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { applyFolioAIEditOperations } from "../ai-edits/apply.js";
|
|
2
|
-
import { createFolioAIEditSnapshot, hashFolioAIBlockText, normalizeFolioAIBlockText } from "../ai-edits/snapshot.js";
|
|
3
|
-
import { diffWordSegments } from "../ai-edits/word-diff.js";
|
|
2
|
+
import { createFolioAIEditSnapshot, hashFolioAIBlockText, isFolioAIContentBlock, normalizeFolioAIBlockText } from "../ai-edits/snapshot.js";
|
|
3
|
+
import { WORD_DIFF_GRANULARITIES, diffWordSegments } from "../ai-edits/word-diff.js";
|
|
4
4
|
import { applySuggestions } from "../ai-suggestions/apply.js";
|
|
5
5
|
import { isSuggestionStale, resolveSuggestionAnchor } from "../ai-suggestions/conflict.js";
|
|
6
6
|
import { buildPositionalText } from "../ai-suggestions/text-positions.js";
|
|
7
7
|
import { DEFAULT_AI_SUGGESTION_PRESETS } from "../ai-suggestions/types.js";
|
|
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";
|
|
10
|
+
import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS } from "../compare/verification.js";
|
|
8
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";
|
|
9
12
|
import { inspectDocxCompatibility } from "../docx/compatibility.js";
|
|
10
13
|
import { createDocx } from "../docx/rezip.js";
|
|
@@ -28,4 +31,4 @@ import { deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialF
|
|
|
28
31
|
import { createEmptyDocument } from "../utils/createDocument.js";
|
|
29
32
|
import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "../utils/fontResolver.js";
|
|
30
33
|
import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
|
|
31
|
-
export { 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, InvalidFolioDocumentOperationBatchError, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, 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, 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, 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 };
|
|
@@ -7,6 +7,7 @@ import { ConvertHeaderFooterOptions, HeaderFooterMetrics } from "../layout-bridg
|
|
|
7
7
|
import "../layout-engine/index.js";
|
|
8
8
|
import { FootnoteRenderItem } from "../layout-painter/renderPage.js";
|
|
9
9
|
import { BlockLookup, LayoutPainter } from "../layout-painter/index.js";
|
|
10
|
+
import { PageRendererName } from "../display-list/editor/pageRenderer.js";
|
|
10
11
|
import { LayoutSelectionGate } from "../paged-layout/LayoutSelectionGate.js";
|
|
11
12
|
import { LayoutSession } from "./layoutSession.js";
|
|
12
13
|
import { EditorState } from "prosemirror-state";
|
|
@@ -59,6 +60,18 @@ type LayoutPipelineDeps<THfPMs> = {
|
|
|
59
60
|
documentFontsAreLoaded: () => boolean;
|
|
60
61
|
buildFootnoteRenderItems: (pageFootnoteMap: Map<number, number[]>, footnoteContentMap: Map<number, FootnoteContent>, doc: document_d_exports.Document | null) => Map<number, FootnoteRenderItem[]>;
|
|
61
62
|
describeInvalidHighlightMarks: (doc: EditorState["doc"]) => string;
|
|
63
|
+
/**
|
|
64
|
+
* Which renderer paints the pages. `"legacy"` is the painter that has always
|
|
65
|
+
* painted them; `"display-list"` builds the painter-neutral paint IR from
|
|
66
|
+
* this layout and paints the pages from it, so the editor and an export draw
|
|
67
|
+
* from one structure.
|
|
68
|
+
*
|
|
69
|
+
* Only the *painting* is swapped. Page shells, virtualization, the
|
|
70
|
+
* fingerprint comparison that skips an unchanged page and the painted event
|
|
71
|
+
* are page-container concerns and stay shared, because a second copy of them
|
|
72
|
+
* is how incremental repaint would quietly stop working on long documents.
|
|
73
|
+
*/
|
|
74
|
+
pageRenderer?: PageRendererName;
|
|
62
75
|
emptyTemplatePreviewEntries: readonly TemplatePreviewEntry[];
|
|
63
76
|
};
|
|
64
77
|
declare function runLayoutPipeline<THfPMs>(deps: LayoutPipelineDeps<THfPMs>, state: EditorState, options?: LayoutRunOptions): LayoutOutcome;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createDisplayListPagePainter } from "../display-list/editor/displayListPagePainter.js";
|
|
2
|
+
import { PAGE_RENDERER, displayListFurnitureFrom } from "../display-list/editor/pageRenderer.js";
|
|
1
3
|
import { resolveDocumentGridLinePitch } from "../docx/documentGrid.js";
|
|
2
4
|
import { buildBookmarkPageMap } from "../fields/bookmarkPages.js";
|
|
3
5
|
import { buildBookmarkText } from "../fields/bookmarkText.js";
|
|
@@ -15,6 +17,7 @@ import { recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayou
|
|
|
15
17
|
import { measureBlocks, measureSingleBlockWithoutFloatingZones } from "../layout-engine/measure/measureBlocks.js";
|
|
16
18
|
import { installCanvasMeasureProvider } from "../layout-engine/measure/measureContainer.js";
|
|
17
19
|
import { resolveEffectiveParagraphSpacingTree } from "../layout-engine/paragraphSpacing.js";
|
|
20
|
+
import { resolveTableIndentCompatibility } from "../layout-engine/tableIndentCompatibility.js";
|
|
18
21
|
import "../layout-engine/types.js";
|
|
19
22
|
import { renderPages } from "../layout-painter/renderPage.js";
|
|
20
23
|
import { tryBuildIncrementalMeasures } from "../paged-layout/incrementalMeasure.js";
|
|
@@ -84,7 +87,7 @@ function attachAuthoredMarginsToLayoutPages(layout, options) {
|
|
|
84
87
|
} : layout;
|
|
85
88
|
}
|
|
86
89
|
function runLayoutPipeline(deps, state, options = {}) {
|
|
87
|
-
const { contentWidth, columns, pageSize, margins, pageGap, showMarginGuides, marginGuideColor, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, documentFontsAreLoaded, buildFootnoteRenderItems, describeInvalidHighlightMarks, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES } = deps;
|
|
90
|
+
const { contentWidth, columns, pageSize, margins, pageGap, showMarginGuides, marginGuideColor, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, documentFontsAreLoaded, buildFootnoteRenderItems, describeInvalidHighlightMarks, pageRenderer = PAGE_RENDERER.legacy, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES } = deps;
|
|
88
91
|
let outcome = {};
|
|
89
92
|
let pendingArtifacts;
|
|
90
93
|
let pendingTemplatePreview;
|
|
@@ -110,6 +113,8 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
110
113
|
const documentSettings = document?.package.settings;
|
|
111
114
|
const justificationCompatibility = resolveJustificationCompatibility(documentSettings?.compatibilityMode);
|
|
112
115
|
if (justificationCompatibility) flowOpts.justificationCompatibility = justificationCompatibility;
|
|
116
|
+
const tableIndentCompatibility = resolveTableIndentCompatibility(documentSettings?.compatibilityMode);
|
|
117
|
+
if (tableIndentCompatibility) flowOpts.tableIndentCompatibility = tableIndentCompatibility;
|
|
113
118
|
if (documentSettings?.autoHyphenation === true) flowOpts.automaticHyphenation = {
|
|
114
119
|
enabled: true,
|
|
115
120
|
...documentSettings.doNotHyphenateCaps !== void 0 ? { doNotHyphenateCaps: documentSettings.doNotHyphenateCaps } : {},
|
|
@@ -166,6 +171,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
166
171
|
...defaultTabStop !== void 0 ? { defaultTabStopTwips: defaultTabStop } : {},
|
|
167
172
|
...flowOpts.lineBreakRules ? { lineBreakRules: flowOpts.lineBreakRules } : {},
|
|
168
173
|
...flowOpts.justificationCompatibility ? { justificationCompatibility: flowOpts.justificationCompatibility } : {},
|
|
174
|
+
...flowOpts.tableIndentCompatibility ? { tableIndentCompatibility: flowOpts.tableIndentCompatibility } : {},
|
|
169
175
|
...flowOpts.automaticHyphenation ? { automaticHyphenation: flowOpts.automaticHyphenation } : {}
|
|
170
176
|
};
|
|
171
177
|
};
|
|
@@ -312,6 +318,7 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
312
318
|
if (defaultTabStop !== void 0) footnoteOptions.defaultTabStopTwips = defaultTabStop;
|
|
313
319
|
if (flowOpts.lineBreakRules) footnoteOptions.lineBreakRules = flowOpts.lineBreakRules;
|
|
314
320
|
if (flowOpts.justificationCompatibility) footnoteOptions.justificationCompatibility = flowOpts.justificationCompatibility;
|
|
321
|
+
if (flowOpts.tableIndentCompatibility) footnoteOptions.tableIndentCompatibility = flowOpts.tableIndentCompatibility;
|
|
315
322
|
if (flowOpts.automaticHyphenation) footnoteOptions.automaticHyphenation = flowOpts.automaticHyphenation;
|
|
316
323
|
return footnoteOptions;
|
|
317
324
|
})());
|
|
@@ -479,6 +486,13 @@ function runLayoutPipeline(deps, state, options = {}) {
|
|
|
479
486
|
if (watermarkByHeaderRId.size > 0) renderOpts.watermarkByHeaderRId = watermarkByHeaderRId;
|
|
480
487
|
}
|
|
481
488
|
}
|
|
489
|
+
if (pageRenderer === PAGE_RENDERER.displayList) renderOpts.paintPage = createDisplayListPagePainter({
|
|
490
|
+
layout: newLayout,
|
|
491
|
+
blockLookup,
|
|
492
|
+
doc: pagesContainer.ownerDocument,
|
|
493
|
+
...displayListFurnitureFrom(renderOpts),
|
|
494
|
+
...footnoteContentMap.size === 0 ? {} : { footnoteContentById: footnoteContentMap }
|
|
495
|
+
}).paintPage;
|
|
482
496
|
renderPages(newLayout.pages, pagesContainer, renderOpts);
|
|
483
497
|
recordPhaseDuration("render-pages", phaseStartedAt);
|
|
484
498
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DisplayColor, DisplayLink, DisplayLinkTarget, DisplayStoryRef } from "../types.js";
|
|
2
|
+
import { FontTable } from "./fontTable.js";
|
|
3
|
+
import { ImageTable } from "./imagePrimitives.js";
|
|
4
|
+
import { UnsupportedCollector } from "./unsupported.js";
|
|
5
|
+
//#region src/display-list/build/buildContext.d.ts
|
|
6
|
+
/** Word's per-author redline palette, assigned in first-seen order per build. */
|
|
7
|
+
declare class AuthorColorTable {
|
|
8
|
+
private readonly indexByAuthor;
|
|
9
|
+
colorFor(author: string | undefined): DisplayColor;
|
|
10
|
+
}
|
|
11
|
+
/** Colour a tracked change paints in: the author's hue, or the proposal hue. */
|
|
12
|
+
declare const trackedChangeColor: (authorColors: AuthorColorTable, changeAuthor: string | undefined, isSuggestion: boolean | undefined) => DisplayColor;
|
|
13
|
+
/**
|
|
14
|
+
* Which OOXML story the primitives being built belong to, named precisely
|
|
15
|
+
* enough to address it: a document has many headers and many notes, and a
|
|
16
|
+
* position only means something against one of them.
|
|
17
|
+
*/
|
|
18
|
+
type DisplayStory = DisplayStoryRef;
|
|
19
|
+
type BuildContext = {
|
|
20
|
+
readonly fonts: FontTable;
|
|
21
|
+
readonly images: ImageTable;
|
|
22
|
+
readonly unsupported: UnsupportedCollector;
|
|
23
|
+
readonly authorColors: AuthorColorTable;
|
|
24
|
+
/** Link sink for the page being built. */
|
|
25
|
+
readonly links: DisplayLink[];
|
|
26
|
+
/**
|
|
27
|
+
* Bookmark name → where it lands, collected in a first pass over the layout.
|
|
28
|
+
* A `#name` hyperlink can only become a `page` target once every page is
|
|
29
|
+
* known, which is why this is resolved before any page is painted.
|
|
30
|
+
*/
|
|
31
|
+
readonly bookmarkTargets: ReadonlyMap<string, DisplayLinkTarget>;
|
|
32
|
+
readonly story: DisplayStory;
|
|
33
|
+
readonly pageIndex: number;
|
|
34
|
+
/** Authored page number, for `PAGE` fields. */
|
|
35
|
+
readonly pageNumber: number;
|
|
36
|
+
readonly totalPages: number;
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { AuthorColorTable, BuildContext, DisplayStory, trackedChangeColor };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AUTHOR_COLORS } from "../../utils/authorColors.js";
|
|
2
|
+
import { SUGGESTION_COLOR, parseDisplayColor } from "./colors.js";
|
|
3
|
+
//#region src/display-list/build/buildContext.ts
|
|
4
|
+
/**
|
|
5
|
+
* State threaded through one `buildDisplayList` call.
|
|
6
|
+
*
|
|
7
|
+
* Everything mutable the builder needs lives here so the builder itself stays a
|
|
8
|
+
* pure function of its arguments: the font table, the image table, the
|
|
9
|
+
* unsupported log and the author-colour assignment are all born and die inside
|
|
10
|
+
* a single call. `utils/authorColors.ts`'s `getAuthorColorIdx` deliberately is
|
|
11
|
+
* not used: it keeps a module-level map, so the colour an author gets depends
|
|
12
|
+
* on which documents the process opened earlier, and two builds of the same
|
|
13
|
+
* layout would not compare equal.
|
|
14
|
+
*/
|
|
15
|
+
/** Word's per-author redline palette, assigned in first-seen order per build. */
|
|
16
|
+
var AuthorColorTable = class {
|
|
17
|
+
indexByAuthor = /* @__PURE__ */ new Map();
|
|
18
|
+
colorFor(author) {
|
|
19
|
+
const key = author ?? "";
|
|
20
|
+
let index = this.indexByAuthor.get(key);
|
|
21
|
+
if (index === void 0) {
|
|
22
|
+
index = this.indexByAuthor.size % AUTHOR_COLORS.length;
|
|
23
|
+
this.indexByAuthor.set(key, index);
|
|
24
|
+
}
|
|
25
|
+
return parseDisplayColor(AUTHOR_COLORS[index]) ?? SUGGESTION_COLOR;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/** Colour a tracked change paints in: the author's hue, or the proposal hue. */
|
|
29
|
+
const trackedChangeColor = (authorColors, changeAuthor, isSuggestion) => isSuggestion ? SUGGESTION_COLOR : authorColors.colorFor(changeAuthor);
|
|
30
|
+
//#endregion
|
|
31
|
+
export { AuthorColorTable, trackedChangeColor };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { EmbeddedFont } from "../../fonts/embeddedFonts.js";
|
|
2
|
+
import { Layout } from "../../layout-engine/types.js";
|
|
3
|
+
import { BlockLookup } from "../../layout-painter/index.js";
|
|
4
|
+
import { DisplayColor, DisplayList, DisplayMetadata, DisplayPage } from "../types.js";
|
|
5
|
+
import { PageFurnitureInputs } from "./furniture.js";
|
|
6
|
+
//#region src/display-list/build/buildDisplayList.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Every feature a source document can have that a `Layout` does not record and
|
|
9
|
+
* that nothing on a page betrays, with the reason it paints nothing when the
|
|
10
|
+
* caller supplies neither the construct nor a flag denying it. The list is the
|
|
11
|
+
* single source of truth: {@link DocumentFeatures} is derived from it, so a
|
|
12
|
+
* feature added here cannot be left without a flag or without a reason.
|
|
13
|
+
*
|
|
14
|
+
* Footnote bodies and header/footer stories are deliberately absent: a page
|
|
15
|
+
* that carries them says so itself (`footnoteIds`, `headerFooterRefs`), so
|
|
16
|
+
* their gaps are reported per page from the layout rather than from a
|
|
17
|
+
* document-wide flag the caller would have to remember to set.
|
|
18
|
+
*/
|
|
19
|
+
declare const DOCUMENT_FEATURE_GAPS: readonly [readonly ["pageBorders", "w:pgBorders reach the painter through render options, not through Layout, and none were supplied to the builder"], readonly ["watermark", "watermarks reach the painter through render options, not through Layout, and none was supplied to the builder"]];
|
|
20
|
+
/**
|
|
21
|
+
* Which of those features the source document actually has. The builder cannot
|
|
22
|
+
* detect them, so the caller that parsed the document states it.
|
|
23
|
+
*/
|
|
24
|
+
type DocumentFeatures = { readonly [Feature in (typeof DOCUMENT_FEATURE_GAPS)[number][0]]: boolean; };
|
|
25
|
+
type BuildDisplayListOptions = PageFurnitureInputs & {
|
|
26
|
+
readonly layout: Layout;
|
|
27
|
+
readonly blockLookup: BlockLookup;
|
|
28
|
+
readonly metadata?: DisplayMetadata;
|
|
29
|
+
/** Page background. Defaults to opaque white: the PDF has no theme. */
|
|
30
|
+
readonly pageBackground?: DisplayColor;
|
|
31
|
+
/**
|
|
32
|
+
* States, for each construct in {@link DOCUMENT_FEATURE_GAPS}, whether the
|
|
33
|
+
* document has one at all. Omitted means unknown, and an unknown document is
|
|
34
|
+
* reported as having both: a silent gap is worse than one the reader can
|
|
35
|
+
* dismiss. A construct supplied through {@link PageFurnitureInputs} is
|
|
36
|
+
* painted and never reported, whatever this says.
|
|
37
|
+
*/
|
|
38
|
+
readonly documentFeatures?: DocumentFeatures;
|
|
39
|
+
/**
|
|
40
|
+
* The package's own font faces (`fonts/embeddedFonts.ts`). Absent: a face the
|
|
41
|
+
* measurer resolved to an embedded family travels as a name, and a backend
|
|
42
|
+
* that cannot find that name on the host paints the document in a substitute.
|
|
43
|
+
*/
|
|
44
|
+
readonly embeddedFonts?: readonly EmbeddedFont[];
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* A document's display list, one page at a time.
|
|
48
|
+
*
|
|
49
|
+
* The tables a page refers to (faces, images), the bookmark targets a link can
|
|
50
|
+
* resolve against, and the outline are properties of the whole document, so
|
|
51
|
+
* they are computed once; a page's primitives are not, and an editor paints a
|
|
52
|
+
* window of pages rather than all of them. Building every page to paint three
|
|
53
|
+
* of them is the difference between work proportional to the screen and work
|
|
54
|
+
* proportional to the document, which on a long one is the difference a reader
|
|
55
|
+
* feels on every keystroke.
|
|
56
|
+
*
|
|
57
|
+
* A page is built at most once. `snapshot` returns what has been built so far,
|
|
58
|
+
* so a caller that wants the whole list asks for every page first — which is
|
|
59
|
+
* what {@link buildDisplayList} does.
|
|
60
|
+
*/
|
|
61
|
+
type DisplayListBuilder = {
|
|
62
|
+
readonly pageCount: number;
|
|
63
|
+
/** The page at that index, built on first request and kept. */
|
|
64
|
+
readonly pageAt: (pageIndex: number) => DisplayPage | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* The list as far as it has been built. The tables grow as pages are built,
|
|
67
|
+
* so a backend reads them after the page it is about to paint, never before.
|
|
68
|
+
*/
|
|
69
|
+
readonly snapshot: () => DisplayList;
|
|
70
|
+
};
|
|
71
|
+
declare const createDisplayListBuilder: ({ layout, blockLookup, metadata, pageBackground, documentFeatures, embeddedFonts, ...furniture }: BuildDisplayListOptions) => DisplayListBuilder;
|
|
72
|
+
/**
|
|
73
|
+
* The whole document's display list. Every page is built, so the tables, the
|
|
74
|
+
* outline and the gap report are complete; an editor that paints a window of
|
|
75
|
+
* pages uses {@link createDisplayListBuilder} instead.
|
|
76
|
+
*/
|
|
77
|
+
declare const buildDisplayList: (options: BuildDisplayListOptions) => DisplayList;
|
|
78
|
+
//#endregion
|
|
79
|
+
export { BuildDisplayListOptions, DisplayListBuilder, DocumentFeatures, buildDisplayList, createDisplayListBuilder };
|