@stll/folio-core 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/ai-edits/apply.js +18 -4
- package/dist/ai-edits/headless.d.ts +73 -6
- package/dist/ai-edits/headless.js +299 -60
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/index.js +2 -1
- package/dist/ai-edits/snapshot.js +40 -3
- package/dist/ai-edits/types.d.ts +2 -1
- package/dist/compat/eigenpal.d.ts +6 -4
- package/dist/compat/eigenpal.js +5 -3
- package/dist/controller/latestRequestGate.d.ts +13 -0
- package/dist/controller/latestRequestGate.js +16 -0
- package/dist/controller/layoutPipeline.js +13 -1
- package/dist/document-operations.d.ts +20 -4
- package/dist/document-operations.js +36 -15
- package/dist/document-stories.d.ts +10 -0
- package/dist/document-stories.js +27 -0
- package/dist/docx/blockContentParser.js +2 -2
- package/dist/docx/commentParser.js +1 -1
- package/dist/docx/compatibility.d.ts +3 -7
- package/dist/docx/compatibility.js +0 -11
- package/dist/docx/corePropertiesParser.d.ts +8 -0
- package/dist/docx/corePropertiesParser.js +53 -0
- package/dist/docx/encryption/agileDecryption.js +1 -1
- package/dist/docx/encryption/encryptionInfo.js +1 -1
- package/dist/docx/encryption/openEncryptedDocx.js +1 -1
- package/dist/docx/fontTableParser.d.ts +6 -0
- package/dist/docx/fontTableParser.js +72 -0
- package/dist/docx/groupDrawingParser.js +7 -2
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/index.d.ts +2 -1
- package/dist/docx/index.js +2 -1
- package/dist/docx/metadataPrivacy.d.ts +40 -0
- package/dist/docx/metadataPrivacy.js +131 -0
- package/dist/docx/normalizeBaseDirection.js +1 -1
- package/dist/docx/numberingParser.js +1 -0
- package/dist/docx/paragraphParser.js +12 -1
- package/dist/docx/parser.d.ts +1 -1
- package/dist/docx/parser.js +16 -10
- package/dist/docx/rezip.d.ts +5 -4
- package/dist/docx/rezip.js +76 -13
- package/dist/docx/runConsolidator.js +4 -0
- package/dist/docx/runParser.js +19 -1
- package/dist/docx/selectiveSave.js +3 -3
- package/dist/docx/serializer/fontTableSerializer.d.ts +6 -0
- package/dist/docx/serializer/fontTableSerializer.js +26 -0
- package/dist/docx/serializer/headerFooterSerializer.js +1 -1
- package/dist/docx/serializer/paragraphSerializer.js +4 -0
- package/dist/docx/serializer/runSerializer.js +7 -0
- package/dist/docx/serializer/settingsSerializer.d.ts +6 -0
- package/dist/docx/serializer/settingsSerializer.js +16 -0
- package/dist/docx/serializer/stylesSerializer.d.ts +6 -0
- package/dist/docx/serializer/stylesSerializer.js +56 -0
- package/dist/docx/serializer/tableSerializer.js +25 -26
- package/dist/docx/serializer/themeSerializer.d.ts +6 -0
- package/dist/docx/serializer/themeSerializer.js +36 -0
- package/dist/docx/settingsParser.js +46 -0
- package/dist/docx/styleParser.js +26 -1
- package/dist/docx/tableParser.js +11 -1
- package/dist/docx/vmlImageParser.js +1 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +5916 -5916
- package/dist/i18n/messages/catalogs.gen.js +5910 -5910
- package/dist/index.d.ts +6 -4
- package/dist/index.js +5 -3
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -1
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +6 -1
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +14 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +52 -14
- package/dist/layout-bridge/engine/measuring/index.d.ts +2 -1
- package/dist/layout-bridge/engine/measuring/index.js +2 -1
- package/dist/layout-engine/index.js +36 -28
- package/dist/layout-engine/measure/cache.js +6 -3
- package/dist/layout-engine/measure/effectiveLineBreakPolicy.d.ts +29 -0
- package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +60 -0
- package/dist/layout-engine/measure/font-metrics.worker.js +1 -0
- package/dist/layout-engine/measure/index.d.ts +2 -1
- package/dist/layout-engine/measure/index.js +2 -1
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +33 -0
- package/dist/layout-engine/measure/lineBreakProvider.js +252 -0
- package/dist/layout-engine/measure/lineBreaks.d.ts +7 -2
- package/dist/layout-engine/measure/lineBreaks.js +11 -18
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +12 -6
- package/dist/layout-engine/measure/measureBlocks.d.ts +1 -2
- package/dist/layout-engine/measure/measureBlocks.js +6 -36
- package/dist/layout-engine/measure/measureContainer.js +32 -9
- package/dist/layout-engine/measure/measureHelpers.js +5 -2
- package/dist/layout-engine/measure/measureParagraph.js +332 -73
- package/dist/layout-engine/measure/measureTypes.d.ts +2 -1
- package/dist/layout-engine/measure/measureWorker.d.ts +2 -2
- package/dist/layout-engine/measure/measureWorker.js +8 -19
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +3 -14
- package/dist/layout-engine/measure/tableCellFloating.d.ts +10 -3
- package/dist/layout-engine/measure/tableCellFloating.js +51 -37
- package/dist/layout-engine/measure/tableCellFlow.d.ts +27 -0
- package/dist/layout-engine/measure/tableCellFlow.js +73 -0
- package/dist/layout-engine/measure/tableCellGrid.js +1 -1
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +18 -0
- package/dist/layout-engine/measure/textMeasurementPolicy.js +24 -0
- package/dist/layout-engine/renderedBreakReconciliation.d.ts +6 -1
- package/dist/layout-engine/renderedBreakReconciliation.js +34 -11
- package/dist/layout-engine/tableRowBreak.d.ts +5 -2
- package/dist/layout-engine/tableRowBreak.js +62 -29
- package/dist/layout-engine/types.d.ts +43 -8
- package/dist/layout-painter/anchoredImagePosition.d.ts +23 -0
- package/dist/layout-painter/anchoredImagePosition.js +95 -0
- package/dist/layout-painter/borderStroke.d.ts +23 -0
- package/dist/layout-painter/borderStroke.js +39 -0
- package/dist/layout-painter/renderImage.d.ts +5 -4
- package/dist/layout-painter/renderImage.js +18 -4
- package/dist/layout-painter/renderPage.d.ts +2 -27
- package/dist/layout-painter/renderPage.js +13 -99
- package/dist/layout-painter/renderParagraph.js +41 -23
- package/dist/layout-painter/renderTable.d.ts +2 -0
- package/dist/layout-painter/renderTable.js +223 -43
- package/dist/managers/DocumentLoaderManager.d.ts +1 -1
- package/dist/managers/DocumentLoaderManager.js +2 -2
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +22 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +1 -1
- package/dist/prosemirror/conversion/effectiveTableCellFormatting.d.ts +62 -0
- package/dist/prosemirror/conversion/effectiveTableCellFormatting.js +131 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +34 -18
- package/dist/prosemirror/conversion/toProseDoc.js +81 -77
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +7 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/HighlightExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/LanguageExtension.d.ts +7 -0
- package/dist/prosemirror/extensions/marks/LanguageExtension.js +30 -0
- package/dist/prosemirror/extensions/marks/RunShadingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +1 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +12 -0
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +3 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +4 -2
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +6 -1
- package/dist/prosemirror/schema/nodes.d.ts +15 -12
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/utils/tabCalculator.d.ts +3 -1
- package/dist/prosemirror/utils/tabCalculator.js +12 -10
- package/dist/prosemirror/validation.js +4 -1
- package/dist/redline.d.ts +26 -11
- package/dist/redline.js +107 -64
- package/dist/server.d.ts +9 -5
- package/dist/server.js +8 -4
- package/dist/style-sets/extract.d.ts +35 -0
- package/dist/style-sets/extract.js +123 -0
- package/dist/style-sets/stellaStyle.d.ts +13 -0
- package/dist/style-sets/stellaStyle.js +516 -0
- package/dist/style-sets/types.d.ts +31 -0
- package/dist/style-sets/types.js +5 -0
- package/dist/utils/createDocument.d.ts +12 -2
- package/dist/utils/createDocument.js +42 -31
- package/dist/utils/fontResolver.js +6 -6
- package/dist/utils/formatToStyle.js +1 -1
- package/dist/utils/paragraphFormattingMerge.d.ts +14 -3
- package/dist/utils/paragraphFormattingMerge.js +14 -4
- package/dist/version-comparison.d.ts +65 -11
- package/dist/version-comparison.js +187 -29
- package/package.json +5 -1
- package/dist/docx/capabilities.d.ts +0 -41
- package/dist/docx/capabilities.js +0 -322
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expectLanguageMarkAttrs } from "../../attrs/index.js";
|
|
2
|
+
import { createMarkExtension } from "../create.js";
|
|
3
|
+
//#region src/prosemirror/extensions/marks/LanguageExtension.ts
|
|
4
|
+
/** Preserve OOXML `w:lang` and expose its primary language to the editing DOM. */
|
|
5
|
+
const LanguageExtension = createMarkExtension({
|
|
6
|
+
name: "language",
|
|
7
|
+
schemaMarkName: "language",
|
|
8
|
+
markSpec: {
|
|
9
|
+
attrs: {
|
|
10
|
+
val: { default: null },
|
|
11
|
+
eastAsia: { default: null },
|
|
12
|
+
bidi: { default: null }
|
|
13
|
+
},
|
|
14
|
+
parseDOM: [{
|
|
15
|
+
tag: "span[lang]",
|
|
16
|
+
getAttrs: (dom) => typeof dom === "string" ? false : { val: dom.getAttribute("lang") ?? void 0 }
|
|
17
|
+
}],
|
|
18
|
+
toDOM(mark) {
|
|
19
|
+
const { val, eastAsia, bidi } = expectLanguageMarkAttrs(mark);
|
|
20
|
+
const language = val ?? eastAsia ?? bidi;
|
|
21
|
+
return language ? [
|
|
22
|
+
"span",
|
|
23
|
+
{ lang: language },
|
|
24
|
+
0
|
|
25
|
+
] : ["span", 0];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
//#endregion
|
|
30
|
+
export { LanguageExtension };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ensureHexPrefix } from "../../../utils/colorResolver.js";
|
|
2
1
|
import { expectRunShadingMarkAttrs } from "../../attrs/index.js";
|
|
3
2
|
import { createMarkExtension } from "../create.js";
|
|
3
|
+
import { ensureHexPrefix } from "../../../utils/colorResolver.js";
|
|
4
4
|
import { normalizeCssColorKey, parseDOMHighlightColor } from "./HighlightExtension.js";
|
|
5
5
|
//#region src/prosemirror/extensions/marks/RunShadingExtension.ts
|
|
6
6
|
const RunShadingExtension = createMarkExtension({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { textToStyle } from "../../../utils/formatToStyle.js";
|
|
2
1
|
import { expectTextColorMarkAttrs } from "../../attrs/index.js";
|
|
3
2
|
import { createMarkExtension } from "../create.js";
|
|
3
|
+
import { textToStyle } from "../../../utils/formatToStyle.js";
|
|
4
4
|
import { removeMark, setMark } from "./markUtils.js";
|
|
5
5
|
import { panic } from "better-result";
|
|
6
6
|
//#region src/prosemirror/extensions/marks/TextColorExtension.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AUTHOR_COLORS, getAuthorColorIdx } from "../../../utils/authorColors.js";
|
|
2
1
|
import { expectTrackedChangeMarkAttrs } from "../../attrs/index.js";
|
|
3
2
|
import { createMarkExtension } from "../create.js";
|
|
3
|
+
import { AUTHOR_COLORS, getAuthorColorIdx } from "../../../utils/authorColors.js";
|
|
4
4
|
//#region src/prosemirror/extensions/marks/TrackedChangeExtensions.ts
|
|
5
5
|
/**
|
|
6
6
|
* Tracked Change Mark Extensions — insertion and deletion marks
|
|
@@ -43,6 +43,17 @@ function marksToTextFormatting(marks) {
|
|
|
43
43
|
};
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
46
|
+
case "language": {
|
|
47
|
+
const val = mark.attrs["val"];
|
|
48
|
+
const eastAsia = mark.attrs["eastAsia"];
|
|
49
|
+
const bidi = mark.attrs["bidi"];
|
|
50
|
+
formatting.language = {
|
|
51
|
+
...typeof val === "string" ? { val } : {},
|
|
52
|
+
...typeof eastAsia === "string" ? { eastAsia } : {},
|
|
53
|
+
...typeof bidi === "string" ? { bidi } : {}
|
|
54
|
+
};
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
46
57
|
case "superscript":
|
|
47
58
|
formatting.vertAlign = "superscript";
|
|
48
59
|
break;
|
|
@@ -186,6 +197,7 @@ function textFormattingToMarks(formatting, schema) {
|
|
|
186
197
|
hAnsi: formatting.fontFamily.hAnsi,
|
|
187
198
|
asciiTheme: formatting.fontFamily.asciiTheme
|
|
188
199
|
}));
|
|
200
|
+
if (formatting.language && schema.marks["language"]) marks.push(schema.marks["language"].create(formatting.language));
|
|
189
201
|
if (formatting.vertAlign === "superscript" && schema.marks["superscript"]) marks.push(schema.marks["superscript"].create());
|
|
190
202
|
if (formatting.vertAlign === "subscript" && schema.marks["subscript"]) marks.push(schema.marks["subscript"].create());
|
|
191
203
|
if (formatting.rtl && schema.marks["rtl"]) marks.push(schema.marks["rtl"].create());
|
|
@@ -33,12 +33,14 @@ const ImageExtension = createNodeExtension({
|
|
|
33
33
|
cropBottom: { default: null },
|
|
34
34
|
cropLeft: { default: null },
|
|
35
35
|
position: { default: null },
|
|
36
|
+
layoutInCell: { default: null },
|
|
36
37
|
borderWidth: { default: null },
|
|
37
38
|
borderColor: { default: null },
|
|
38
39
|
borderStyle: { default: null },
|
|
39
40
|
wrapText: { default: null },
|
|
40
41
|
hlinkHref: { default: null },
|
|
41
|
-
_docxRawXml: { default: null }
|
|
42
|
+
_docxRawXml: { default: null },
|
|
43
|
+
_docxObjectPreview: { default: null }
|
|
42
44
|
},
|
|
43
45
|
parseDOM: [{
|
|
44
46
|
tag: "img[src]",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_WIDTH_TYPE_VALUES } from "../../../types/documentEnumValues.js";
|
|
2
|
-
import { resolveColor } from "../../../utils/colorResolver.js";
|
|
3
2
|
import { expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, mergeTableAttrs, mergeTableCellAttrs, mergeTableRowAttrs } from "../../attrs/index.js";
|
|
4
3
|
import { createExtension, createNodeExtension } from "../create.js";
|
|
4
|
+
import { resolveColor } from "../../../utils/colorResolver.js";
|
|
5
5
|
import { panic } from "better-result";
|
|
6
6
|
import { Plugin, PluginKey, Selection, TextSelection } from "prosemirror-state";
|
|
7
|
-
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
8
7
|
import { CellSelection, TableMap, columnResizing, mergeCells, removeRow, selectedRect, splitCell, tableEditing } from "prosemirror-tables";
|
|
8
|
+
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
9
9
|
//#region src/prosemirror/extensions/nodes/TableExtension.ts
|
|
10
10
|
/**
|
|
11
11
|
* Table Extension — 4 node specs + plugins + commands
|
|
@@ -310,6 +310,7 @@ const tableCellSpec = {
|
|
|
310
310
|
widthType: { default: null },
|
|
311
311
|
verticalAlign: { default: null },
|
|
312
312
|
backgroundColor: { default: null },
|
|
313
|
+
_resolvedBackgroundColor: { default: null },
|
|
313
314
|
borders: { default: null },
|
|
314
315
|
margins: { default: null },
|
|
315
316
|
textDirection: { default: null },
|
|
@@ -363,6 +364,7 @@ const tableHeaderSpec = {
|
|
|
363
364
|
widthType: { default: null },
|
|
364
365
|
verticalAlign: { default: null },
|
|
365
366
|
backgroundColor: { default: null },
|
|
367
|
+
_resolvedBackgroundColor: { default: null },
|
|
366
368
|
borders: { default: null },
|
|
367
369
|
margins: { default: null },
|
|
368
370
|
textDirection: { default: null },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ExtensionManager } from "../extensions/ExtensionManager.js";
|
|
2
2
|
import { BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, ParagraphAttrs, SdtAttrs, ShapeAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAttrs } from "./nodes.js";
|
|
3
|
-
import { CharacterSpacingAttrs, CharacterStyleAttrs, CommentAttrs, EmphasisMarkAttrs, FontFamilyAttrs, FontSizeAttrs, FootnoteRefAttrs, HighlightAttrs, HyperlinkAttrs, RunFormattingOverrideAttrs, RunShadingAttrs, StrikeAttrs, TextColorAttrs, TextEffectAttrs, TrackedChangeMarkAttrs, UnderlineAttrs } from "./marks.js";
|
|
3
|
+
import { CharacterSpacingAttrs, CharacterStyleAttrs, CommentAttrs, EmphasisMarkAttrs, FontFamilyAttrs, FontSizeAttrs, FootnoteRefAttrs, HighlightAttrs, HyperlinkAttrs, LanguageAttrs, RunFormattingOverrideAttrs, RunShadingAttrs, StrikeAttrs, TextColorAttrs, TextEffectAttrs, TrackedChangeMarkAttrs, UnderlineAttrs } from "./marks.js";
|
|
4
4
|
|
|
5
5
|
//#region src/prosemirror/schema/index.d.ts
|
|
6
6
|
declare const singletonManager: ExtensionManager;
|
|
@@ -12,4 +12,4 @@ type DocxSchema = typeof schema;
|
|
|
12
12
|
type DocxNode = ReturnType<typeof schema.node>;
|
|
13
13
|
type DocxMark = ReturnType<typeof schema.mark>;
|
|
14
14
|
//#endregion
|
|
15
|
-
export { type BlockSdtAttrs, type CharacterSpacingAttrs, type CharacterStyleAttrs, type CommentAttrs, DocxMark, DocxNode, DocxSchema, type EmphasisMarkAttrs, type FieldAttrs, type FontFamilyAttrs, type FontSizeAttrs, type FootnoteRefAttrs, type HardBreakAttrs, type HighlightAttrs, type HyperlinkAttrs, type ImageAttrs, type ImagePositionAttrs, type MathAttrs, type ParagraphAttrs, type RunFormattingOverrideAttrs, type RunShadingAttrs, type SdtAttrs, type ShapeAttrs, type StrikeAttrs, type TableAttrs, type TableCellAttrs, type TableRowAttrs, type TextBoxAttrs, type TextColorAttrs, type TextEffectAttrs, type TrackedChangeMarkAttrs, type UnderlineAttrs, schema, singletonManager };
|
|
15
|
+
export { type BlockSdtAttrs, type CharacterSpacingAttrs, type CharacterStyleAttrs, type CommentAttrs, DocxMark, DocxNode, DocxSchema, type EmphasisMarkAttrs, type FieldAttrs, type FontFamilyAttrs, type FontSizeAttrs, type FootnoteRefAttrs, type HardBreakAttrs, type HighlightAttrs, type HyperlinkAttrs, type ImageAttrs, type ImagePositionAttrs, type LanguageAttrs, type MathAttrs, type ParagraphAttrs, type RunFormattingOverrideAttrs, type RunShadingAttrs, type SdtAttrs, type ShapeAttrs, type StrikeAttrs, type TableAttrs, type TableCellAttrs, type TableRowAttrs, type TextBoxAttrs, type TextColorAttrs, type TextEffectAttrs, type TrackedChangeMarkAttrs, type UnderlineAttrs, schema, singletonManager };
|
|
@@ -40,6 +40,11 @@ type FontFamilyAttrs = {
|
|
|
40
40
|
eastAsiaTheme?: string;
|
|
41
41
|
csTheme?: string;
|
|
42
42
|
};
|
|
43
|
+
type LanguageAttrs = {
|
|
44
|
+
val?: string;
|
|
45
|
+
eastAsia?: string;
|
|
46
|
+
bidi?: string;
|
|
47
|
+
};
|
|
43
48
|
type HighlightAttrs = {
|
|
44
49
|
color: NonNullable<document_d_exports.TextFormatting["highlight"]>;
|
|
45
50
|
};
|
|
@@ -115,4 +120,4 @@ type HyperlinkAttrs = {
|
|
|
115
120
|
_docxHyperlinkIndex?: number;
|
|
116
121
|
};
|
|
117
122
|
//#endregion
|
|
118
|
-
export { CharacterSpacingAttrs, CharacterStyleAttrs, CommentAttrs, EmphasisMarkAttrs, FontFamilyAttrs, FontSizeAttrs, FootnoteRefAttrs, HighlightAttrs, HyperlinkAttrs, RunFormattingOverrideAttrs, RunShadingAttrs, StrikeAttrs, TextColorAttrs, TextEffectAttrs, TrackedChangeMarkAttrs, UnderlineAttrs };
|
|
123
|
+
export { CharacterSpacingAttrs, CharacterStyleAttrs, CommentAttrs, EmphasisMarkAttrs, FontFamilyAttrs, FontSizeAttrs, FootnoteRefAttrs, HighlightAttrs, HyperlinkAttrs, LanguageAttrs, RunFormattingOverrideAttrs, RunShadingAttrs, StrikeAttrs, TextColorAttrs, TextEffectAttrs, TrackedChangeMarkAttrs, UnderlineAttrs };
|
|
@@ -13,7 +13,10 @@ type HardBreakAttrs = {
|
|
|
13
13
|
type ParagraphAttrs = {
|
|
14
14
|
paraId?: string;
|
|
15
15
|
textId?: string;
|
|
16
|
-
alignment?: document_d_exports.ParagraphAlignment;
|
|
16
|
+
alignment?: document_d_exports.ParagraphAlignment; /** Effective East Asian line-edge policy (`w:kinsoku`). */
|
|
17
|
+
kinsoku?: boolean; /** Effective hanging-punctuation policy (`w:overflowPunct`). */
|
|
18
|
+
overflowPunctuation?: boolean; /** Effective paragraph opt-out from document automatic hyphenation. */
|
|
19
|
+
suppressAutoHyphens?: boolean;
|
|
17
20
|
spaceBefore?: number;
|
|
18
21
|
spaceAfter?: number;
|
|
19
22
|
lineSpacing?: number;
|
|
@@ -46,7 +49,8 @@ type ParagraphAttrs = {
|
|
|
46
49
|
listMarker?: string; /** Whether the list marker is hidden (w:vanish on numbering level rPr) */
|
|
47
50
|
listMarkerHidden?: boolean; /** Marker font family from numbering level rPr */
|
|
48
51
|
listMarkerFontFamily?: string; /** Marker font size from numbering level rPr, in points */
|
|
49
|
-
listMarkerFontSize?: number; /**
|
|
52
|
+
listMarkerFontSize?: number; /** Marker bold state from numbering level rPr */
|
|
53
|
+
listMarkerBold?: boolean; /** Horizontal alignment of the marker around the paragraph's list anchor. */
|
|
50
54
|
listMarkerAlignment?: "left" | "center" | "right";
|
|
51
55
|
/**
|
|
52
56
|
* `w:suff` (§17.9.25) — what follows the marker before body text.
|
|
@@ -83,7 +87,8 @@ type ParagraphAttrs = {
|
|
|
83
87
|
shading?: document_d_exports.ShadingProperties;
|
|
84
88
|
tabs?: document_d_exports.TabStop[];
|
|
85
89
|
pageBreakBefore?: boolean; /** Word's cached rendered-page-break marker; preserved for round-trip only. */
|
|
86
|
-
renderedPageBreakBefore?: boolean;
|
|
90
|
+
renderedPageBreakBefore?: boolean; /** Internal import marker for a paragraph whose only run content is a hard page break. */
|
|
91
|
+
_pageBreakCarrier?: boolean;
|
|
87
92
|
keepNext?: boolean;
|
|
88
93
|
keepLines?: boolean;
|
|
89
94
|
widowControl?: boolean; /** Contextual spacing — suppress space between same-style paragraphs */
|
|
@@ -192,13 +197,15 @@ type ImageAttrs = {
|
|
|
192
197
|
cropRight?: number;
|
|
193
198
|
cropBottom?: number;
|
|
194
199
|
cropLeft?: number; /** Position for floating images (horizontal and vertical alignment) */
|
|
195
|
-
position?: ImagePositionAttrs; /**
|
|
200
|
+
position?: ImagePositionAttrs; /** Use the containing table cell as the anchor's positioning scope (the OOXML default). */
|
|
201
|
+
layoutInCell?: boolean; /** Border width in pixels */
|
|
196
202
|
borderWidth?: number; /** Border color as CSS color string */
|
|
197
203
|
borderColor?: string; /** Border style (CSS border-style value) */
|
|
198
204
|
borderStyle?: string; /** Wrap text setting from DOCX (left, right, bothSides, largest) for round-trip */
|
|
199
205
|
wrapText?: NonNullable<document_d_exports.ImageWrap["wrapText"]>; /** Hyperlink URL for clickable image */
|
|
200
206
|
hlinkHref?: string; /** Original OOXML for opaque/unsupported DOCX drawings. */
|
|
201
|
-
_docxRawXml?: string;
|
|
207
|
+
_docxRawXml?: string; /** Embedded-object previews use their authored box as the exact line height. */
|
|
208
|
+
_docxObjectPreview?: boolean;
|
|
202
209
|
};
|
|
203
210
|
/**
|
|
204
211
|
* Field node attributes
|
|
@@ -375,15 +382,11 @@ type TableCellAttrs = {
|
|
|
375
382
|
width?: number; /** Cell width type */
|
|
376
383
|
widthType?: document_d_exports.TableWidthType; /** Vertical alignment */
|
|
377
384
|
verticalAlign?: "top" | "center" | "bottom"; /** Background color (RGB hex) */
|
|
378
|
-
backgroundColor?: string; /**
|
|
385
|
+
backgroundColor?: string; /** Resolved source color. PM-only; distinguishes theme rendering from a user override. */
|
|
386
|
+
_resolvedBackgroundColor?: string; /** OOXML text direction (e.g. 'tbRl', 'btLr') */
|
|
379
387
|
textDirection?: NonNullable<document_d_exports.TableCellFormatting["textDirection"]>; /** No text wrapping in cell */
|
|
380
388
|
noWrap?: boolean; /** Cell borders — full BorderSpec per side (style, color, size) */
|
|
381
|
-
borders?:
|
|
382
|
-
top?: document_d_exports.BorderSpec;
|
|
383
|
-
bottom?: document_d_exports.BorderSpec;
|
|
384
|
-
left?: document_d_exports.BorderSpec;
|
|
385
|
-
right?: document_d_exports.BorderSpec;
|
|
386
|
-
}; /** Cell margins/padding in twips per side */
|
|
389
|
+
borders?: document_d_exports.TableCellBorders; /** Cell margins/padding in twips per side */
|
|
387
390
|
margins?: {
|
|
388
391
|
top?: number;
|
|
389
392
|
bottom?: number;
|
|
@@ -86,6 +86,7 @@ function listAttrsFromResolvedStyle(resolved, numbering) {
|
|
|
86
86
|
listMarkerHidden: rendering?.markerHidden ?? null,
|
|
87
87
|
listMarkerFontFamily: rendering?.markerFontFamily ?? null,
|
|
88
88
|
listMarkerFontSize: rendering?.markerFontSize ?? null,
|
|
89
|
+
listMarkerBold: rendering?.markerBold ?? null,
|
|
89
90
|
listMarkerAlignment: rendering?.markerAlignment ?? null,
|
|
90
91
|
listMarkerSuffix: rendering?.markerSuffix ?? null,
|
|
91
92
|
listMarkerAllCaps: rendering?.markerAllCaps ?? null,
|
|
@@ -64,7 +64,9 @@ declare function pixelsToTwips(pixels: number): number;
|
|
|
64
64
|
* Compute the list of effective tab stops for a paragraph
|
|
65
65
|
*
|
|
66
66
|
* Merges explicit stops with default stops at regular intervals.
|
|
67
|
-
*
|
|
67
|
+
* Explicit stops before the left indent remain available to a hanging first
|
|
68
|
+
* line. Continuation lines naturally skip them because their cursor already
|
|
69
|
+
* starts at the left indent.
|
|
68
70
|
*
|
|
69
71
|
* @param context - Tab context with explicit stops and settings
|
|
70
72
|
* @returns Sorted array of tab stops in twips
|
|
@@ -27,25 +27,27 @@ function pixelsToTwips(pixels) {
|
|
|
27
27
|
* Compute the list of effective tab stops for a paragraph
|
|
28
28
|
*
|
|
29
29
|
* Merges explicit stops with default stops at regular intervals.
|
|
30
|
-
*
|
|
30
|
+
* Explicit stops before the left indent remain available to a hanging first
|
|
31
|
+
* line. Continuation lines naturally skip them because their cursor already
|
|
32
|
+
* starts at the left indent.
|
|
31
33
|
*
|
|
32
34
|
* @param context - Tab context with explicit stops and settings
|
|
33
35
|
* @returns Sorted array of tab stops in twips
|
|
34
36
|
*/
|
|
35
37
|
function computeTabStops(context) {
|
|
36
38
|
const { explicitStops = [], defaultTabInterval = 720, leftIndent = 0 } = context;
|
|
37
|
-
const validExplicitStops = explicitStops.filter((stop) => stop.val !== "clear")
|
|
39
|
+
const validExplicitStops = explicitStops.filter((stop) => stop.val !== "clear");
|
|
38
40
|
const clearPositions = explicitStops.filter((stop) => stop.val === "clear").map((stop) => stop.pos);
|
|
39
41
|
let maxExplicit = 0;
|
|
40
42
|
for (const stop of validExplicitStops) maxExplicit = Math.max(maxExplicit, stop.pos);
|
|
41
43
|
const stops = [...validExplicitStops];
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
44
|
+
const hasLeftIndentClear = clearPositions.some((p) => Math.abs(p - leftIndent) < 20);
|
|
45
|
+
const addsImplicitLeftIndent = leftIndent > 0 && !hasLeftIndentClear && !validExplicitStops.some((stop) => stop.pos <= leftIndent);
|
|
46
|
+
if (addsImplicitLeftIndent) stops.push({
|
|
47
|
+
val: "start",
|
|
48
|
+
pos: leftIndent,
|
|
49
|
+
leader: "none"
|
|
50
|
+
});
|
|
49
51
|
let pos = Math.floor(Math.max(maxExplicit, leftIndent) / defaultTabInterval) * defaultTabInterval;
|
|
50
52
|
const limitPos = leftIndent + 14400;
|
|
51
53
|
while (pos < limitPos) {
|
|
@@ -60,7 +62,7 @@ function computeTabStops(context) {
|
|
|
60
62
|
hasClearStop = true;
|
|
61
63
|
break;
|
|
62
64
|
}
|
|
63
|
-
const isAtLeftIndent =
|
|
65
|
+
const isAtLeftIndent = addsImplicitLeftIndent && Math.abs(pos - leftIndent) < 20;
|
|
64
66
|
if (!hasExplicitStop && !hasClearStop && !isAtLeftIndent) stops.push({
|
|
65
67
|
val: "start",
|
|
66
68
|
pos,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readMathAttrs, readParagraphAttrs, readRunFormattingOverrideMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
|
|
1
|
+
import { readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readLanguageMarkAttrs, readMathAttrs, readParagraphAttrs, readRunFormattingOverrideMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
|
|
2
2
|
//#region src/prosemirror/validation.ts
|
|
3
3
|
var ProseMirrorDocumentValidationError = class extends Error {
|
|
4
4
|
issues;
|
|
@@ -133,6 +133,9 @@ const validateMarks = (marks, path, issues) => {
|
|
|
133
133
|
case "fontFamily":
|
|
134
134
|
appendAttrIssues(markPath, readFontFamilyMarkAttrs(mark), issues);
|
|
135
135
|
continue;
|
|
136
|
+
case "language":
|
|
137
|
+
appendAttrIssues(markPath, readLanguageMarkAttrs(mark), issues);
|
|
138
|
+
continue;
|
|
136
139
|
case "characterSpacing":
|
|
137
140
|
appendAttrIssues(markPath, readCharacterSpacingMarkAttrs(mark), issues);
|
|
138
141
|
continue;
|
package/dist/redline.d.ts
CHANGED
|
@@ -1,20 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FolioAIEditAppliedOperation, FolioAIEditSkippedOperation } from "./ai-edits/types.js";
|
|
2
|
+
import { FolioDocumentStoryHandle, FolioResolvedReviewedView } from "./ai-edits/headless.js";
|
|
3
|
+
import { FolioDocumentPrivacyOptions, FolioDocumentPrivacyReport } from "./docx/metadataPrivacy.js";
|
|
2
4
|
|
|
3
5
|
//#region src/redline.d.ts
|
|
4
6
|
/** Options for {@link generateRedlineDocx}. */
|
|
5
7
|
type GenerateRedlineDocxOptions = {
|
|
6
|
-
/** Author recorded on the generated tracked changes. (default: `"folio compare"`) */author?: string;
|
|
8
|
+
/** Author recorded on the generated tracked changes. (default: `"folio compare"`) */author?: string; /** Resolved base input state. (default: `"final"`) */
|
|
9
|
+
baseView?: FolioResolvedReviewedView; /** Resolved revised input state. (default: `"final"`) */
|
|
10
|
+
revisedView?: FolioResolvedReviewedView; /** Optional output-only package-metadata privacy transforms. */
|
|
11
|
+
privacy?: FolioDocumentPrivacyOptions;
|
|
12
|
+
};
|
|
13
|
+
declare const InvalidGenerateRedlineDocxOptionsError_base: import("better-result").TaggedErrorClass<"InvalidGenerateRedlineDocxOptionsError", {
|
|
14
|
+
message: string;
|
|
15
|
+
option: "baseView" | "revisedView";
|
|
16
|
+
receivedValue: unknown;
|
|
17
|
+
}>;
|
|
18
|
+
declare class InvalidGenerateRedlineDocxOptionsError extends InvalidGenerateRedlineDocxOptionsError_base {}
|
|
19
|
+
type GenerateRedlineUnprocessedStory = {
|
|
20
|
+
baseStory: FolioDocumentStoryHandle | null;
|
|
21
|
+
revisedStory: FolioDocumentStoryHandle | null;
|
|
22
|
+
reason: "missing-base-story" | "missing-revised-story";
|
|
7
23
|
};
|
|
8
24
|
/** Result of {@link generateRedlineDocx}. */
|
|
9
|
-
type GenerateRedlineDocxResult =
|
|
10
|
-
/** The
|
|
25
|
+
type GenerateRedlineDocxResult = {
|
|
26
|
+
/** The base package with generated tracked changes. */buffer: ArrayBuffer; /** Operations applied across every matched story. */
|
|
27
|
+
applied: FolioAIEditAppliedOperation[]; /** Block operations that could not be applied. */
|
|
28
|
+
skipped: FolioAIEditSkippedOperation[]; /** Package parts that could not be represented as story-scoped text edits. */
|
|
29
|
+
unprocessedStories: GenerateRedlineUnprocessedStory[]; /** Privacy transforms applied to the generated package. */
|
|
30
|
+
privacyReport: FolioDocumentPrivacyReport;
|
|
11
31
|
};
|
|
12
|
-
/**
|
|
13
|
-
* Compare `base` and `revised` and return the base document with every
|
|
14
|
-
* difference recorded as a tracked change. See the module doc comment for
|
|
15
|
-
* semantics and limitations; `skipped` reports any block the generator could
|
|
16
|
-
* not redline (e.g. additions with no anchor in an empty base document).
|
|
17
|
-
*/
|
|
32
|
+
/** Compare two buffers and return tracked changes for every matched editable story. */
|
|
18
33
|
declare const generateRedlineDocx: (base: ArrayBuffer, revised: ArrayBuffer, options?: GenerateRedlineDocxOptions) => Promise<GenerateRedlineDocxResult>;
|
|
19
34
|
//#endregion
|
|
20
|
-
export { GenerateRedlineDocxOptions, GenerateRedlineDocxResult, generateRedlineDocx };
|
|
35
|
+
export { GenerateRedlineDocxOptions, GenerateRedlineDocxResult, GenerateRedlineUnprocessedStory, InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx };
|
package/dist/redline.js
CHANGED
|
@@ -1,75 +1,35 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./document-operations.js";
|
|
2
|
+
import { pairFolioDocumentStories } from "./document-stories.js";
|
|
3
|
+
import { FolioDocxReviewer, isFolioResolvedReviewedView } from "./ai-edits/headless.js";
|
|
4
|
+
import { resolveFolioDocumentPrivacyTransforms, rewriteDocxMetadataPrivacy } from "./docx/metadataPrivacy.js";
|
|
2
5
|
import { alignFolioBlocks } from "./version-comparison.js";
|
|
6
|
+
import { TaggedError, panic } from "better-result";
|
|
3
7
|
//#region src/redline.ts
|
|
4
8
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `w:del`), ready for review in Word or the folio editor — the
|
|
8
|
-
* document-producing counterpart to {@link compareDocxVersions}'s structured
|
|
9
|
-
* diff.
|
|
9
|
+
* Compare two `.docx` buffers and produce a third buffer whose text
|
|
10
|
+
* differences are represented as tracked changes.
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* tracked-changes {@link FolioAIEditOperation}, and the reviewer's shared
|
|
16
|
-
* apply path records them as redlines. Word-level minimality comes free:
|
|
17
|
-
* the apply engine word-diffs a `replaceBlock` and only marks the divergent
|
|
18
|
-
* tokens.
|
|
19
|
-
*
|
|
20
|
-
* ## Semantics and limitations
|
|
21
|
-
*
|
|
22
|
-
* - **As-accepted inputs.** Pending tracked changes in either input count as
|
|
23
|
-
* applied before comparison (mirroring {@link compareDocxVersions}): the
|
|
24
|
-
* base's own pending redlines are accepted in the output, so the tracked
|
|
25
|
-
* changes it carries are exactly base → revised. This is intentionally
|
|
26
|
-
* lossy about the inputs' own revision history and authorship.
|
|
27
|
-
* - **Text redlines only.** Format-only changes and relocated blocks are
|
|
28
|
-
* redlined as plain edits (a move becomes a delete + insert, like Word
|
|
29
|
-
* compare with move detection off); block-level formatting is carried via
|
|
30
|
-
* the revised block's `styleId` on inserted blocks.
|
|
31
|
-
* - **Anchoring.** Insertions anchor `before` the next surviving base block
|
|
32
|
-
* so consecutive additions keep their order; additions past the last base
|
|
33
|
-
* block anchor `after` it. A base document with no content blocks offers
|
|
34
|
-
* no anchor at all — such additions surface in `skipped` rather than
|
|
35
|
-
* silently vanishing.
|
|
36
|
-
*/
|
|
37
|
-
/**
|
|
38
|
-
* For each event index, the base block id the next `revisedOnly` event
|
|
39
|
-
* should anchor before: the base side of the nearest later `pair` or
|
|
40
|
-
* `baseOnly` event, or `null` when only additions remain until the end of
|
|
41
|
-
* the document. One backward pass, so a long run of trailing additions
|
|
42
|
-
* (huge revised document vs. a small base) stays linear instead of
|
|
43
|
-
* re-scanning the tail per added block.
|
|
12
|
+
* Each matched editable story is processed independently through the shared
|
|
13
|
+
* block alignment and document-operation paths. Package parts that exist on
|
|
14
|
+
* only one side are reported because creating or removing those parts is a
|
|
15
|
+
* distinct package-level operation.
|
|
44
16
|
*/
|
|
17
|
+
var InvalidGenerateRedlineDocxOptionsError = class extends TaggedError("InvalidGenerateRedlineDocxOptionsError")() {};
|
|
45
18
|
const nextBaseBlockIdByIndex = (events) => {
|
|
46
19
|
const nextIds = Array.from({ length: events.length });
|
|
47
20
|
let nextId = null;
|
|
48
|
-
for (let
|
|
49
|
-
nextIds[
|
|
50
|
-
const event = events[
|
|
21
|
+
for (let index = events.length - 1; index >= 0; index--) {
|
|
22
|
+
nextIds[index] = nextId;
|
|
23
|
+
const event = events[index];
|
|
51
24
|
if (event?.type === "pair") nextId = event.baseBlock.id;
|
|
52
25
|
else if (event?.type === "baseOnly") nextId = event.block.id;
|
|
53
26
|
}
|
|
54
27
|
return nextIds;
|
|
55
28
|
};
|
|
56
|
-
|
|
57
|
-
* Compare `base` and `revised` and return the base document with every
|
|
58
|
-
* difference recorded as a tracked change. See the module doc comment for
|
|
59
|
-
* semantics and limitations; `skipped` reports any block the generator could
|
|
60
|
-
* not redline (e.g. additions with no anchor in an empty base document).
|
|
61
|
-
*/
|
|
62
|
-
const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
63
|
-
const [baseReviewer, revisedReviewer] = await Promise.all([FolioDocxReviewer.fromBuffer(base, { author: options.author ?? "folio compare" }), FolioDocxReviewer.fromBuffer(revised)]);
|
|
64
|
-
baseReviewer.acceptAll();
|
|
65
|
-
const baseSnapshot = baseReviewer.snapshot();
|
|
66
|
-
const revisedBlocks = revisedReviewer.snapshot().blocks;
|
|
29
|
+
const buildRedlineOperations = ({ baseSnapshot, revisedBlocks, nextOperationId }) => {
|
|
67
30
|
const events = alignFolioBlocks(baseSnapshot.blocks, revisedBlocks);
|
|
68
31
|
const anchorIds = nextBaseBlockIdByIndex(events);
|
|
69
32
|
const operations = [];
|
|
70
|
-
let operationSeq = 0;
|
|
71
|
-
const nextOperationId = () => `redline-${++operationSeq}`;
|
|
72
|
-
/** Additions past the last base block, inserted after it in reverse so the final order matches the revised document. */
|
|
73
33
|
const trailingAdditions = [];
|
|
74
34
|
const lastBaseBlockId = baseSnapshot.blocks.at(-1)?.id ?? null;
|
|
75
35
|
events.forEach((event, eventIndex) => {
|
|
@@ -106,22 +66,105 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
|
106
66
|
...event.block.styleId !== void 0 && { styleId: event.block.styleId }
|
|
107
67
|
});
|
|
108
68
|
});
|
|
109
|
-
|
|
69
|
+
if (lastBaseBlockId === null && baseSnapshot.emptyDocumentAnchorId !== void 0) {
|
|
70
|
+
const firstAddition = trailingAdditions.shift();
|
|
71
|
+
if (firstAddition !== void 0) operations.push({
|
|
72
|
+
id: nextOperationId(),
|
|
73
|
+
type: "replaceBlock",
|
|
74
|
+
blockId: baseSnapshot.emptyDocumentAnchorId,
|
|
75
|
+
text: firstAddition.text,
|
|
76
|
+
...firstAddition.styleId !== void 0 && { styleId: firstAddition.styleId }
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
for (const addition of trailingAdditions) operations.push({
|
|
110
80
|
id: nextOperationId(),
|
|
111
81
|
type: "insertAfterBlock",
|
|
112
|
-
blockId: lastBaseBlockId ?? "redline-unanchored",
|
|
82
|
+
blockId: lastBaseBlockId ?? baseSnapshot.emptyDocumentAnchorId ?? "redline-unanchored",
|
|
113
83
|
text: addition.text,
|
|
114
84
|
...addition.styleId !== void 0 && { styleId: addition.styleId }
|
|
115
85
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
86
|
+
return operations;
|
|
87
|
+
};
|
|
88
|
+
const resolveInputView = (value, option) => {
|
|
89
|
+
if (value === void 0) return "final";
|
|
90
|
+
if (!isFolioResolvedReviewedView(value)) throw new InvalidGenerateRedlineDocxOptionsError({
|
|
91
|
+
message: `${option} must be original or final.`,
|
|
92
|
+
option,
|
|
93
|
+
receivedValue: value
|
|
119
94
|
});
|
|
95
|
+
return value;
|
|
96
|
+
};
|
|
97
|
+
/** Compare two buffers and return tracked changes for every matched editable story. */
|
|
98
|
+
const generateRedlineDocx = async (base, revised, options = {}) => {
|
|
99
|
+
const baseView = resolveInputView(options.baseView, "baseView");
|
|
100
|
+
const revisedView = resolveInputView(options.revisedView, "revisedView");
|
|
101
|
+
const privacyTransforms = resolveFolioDocumentPrivacyTransforms(options.privacy?.transforms ?? []);
|
|
102
|
+
const [baseReviewer, revisedReviewer] = await Promise.all([FolioDocxReviewer.fromBuffer(base, { author: options.author ?? "folio compare" }), FolioDocxReviewer.fromBuffer(revised)]);
|
|
103
|
+
const baseStories = baseReviewer.listStories().map(({ handle }) => handle);
|
|
104
|
+
const revisedStories = revisedReviewer.listStories().map(({ handle }) => handle);
|
|
105
|
+
for (const story of baseStories) if (!baseReviewer.resolveReviewedStory({
|
|
106
|
+
story,
|
|
107
|
+
view: baseView
|
|
108
|
+
})) panic("A listed base story could not be resolved");
|
|
109
|
+
const applied = [];
|
|
110
|
+
const skipped = [];
|
|
111
|
+
const unprocessedStories = [];
|
|
112
|
+
let operationSequence = 0;
|
|
113
|
+
const nextOperationId = () => `redline-${++operationSequence}`;
|
|
114
|
+
for (const pair of pairFolioDocumentStories(baseStories, revisedStories)) {
|
|
115
|
+
if (!pair.baseStory) {
|
|
116
|
+
unprocessedStories.push({
|
|
117
|
+
...pair,
|
|
118
|
+
reason: "missing-base-story"
|
|
119
|
+
});
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (!pair.revisedStory) {
|
|
123
|
+
unprocessedStories.push({
|
|
124
|
+
...pair,
|
|
125
|
+
reason: "missing-revised-story"
|
|
126
|
+
});
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const baseSnapshot = baseReviewer.snapshotStory(pair.baseStory);
|
|
130
|
+
const revisedSnapshot = revisedReviewer.readReviewedStory({
|
|
131
|
+
story: pair.revisedStory,
|
|
132
|
+
view: revisedView
|
|
133
|
+
})?.snapshot;
|
|
134
|
+
if (!baseSnapshot || !revisedSnapshot) panic("A matched document story could not be read");
|
|
135
|
+
const operations = buildRedlineOperations({
|
|
136
|
+
baseSnapshot,
|
|
137
|
+
revisedBlocks: revisedSnapshot.blocks,
|
|
138
|
+
nextOperationId
|
|
139
|
+
});
|
|
140
|
+
if (operations.length === 0) continue;
|
|
141
|
+
const result = baseReviewer.applyDocumentOperationsToStory({
|
|
142
|
+
story: pair.baseStory,
|
|
143
|
+
snapshot: baseSnapshot,
|
|
144
|
+
batch: {
|
|
145
|
+
version: 1,
|
|
146
|
+
mode: "tracked-changes",
|
|
147
|
+
operations
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
applied.push(...result.applied);
|
|
151
|
+
skipped.push(...result.skipped);
|
|
152
|
+
}
|
|
153
|
+
const redlineBuffer = await baseReviewer.toBuffer();
|
|
154
|
+
const privacyResult = privacyTransforms.length === 0 ? {
|
|
155
|
+
buffer: redlineBuffer,
|
|
156
|
+
privacyReport: {
|
|
157
|
+
appliedTransforms: [],
|
|
158
|
+
removedMetadataProperties: []
|
|
159
|
+
}
|
|
160
|
+
} : await rewriteDocxMetadataPrivacy(redlineBuffer, { transforms: privacyTransforms });
|
|
120
161
|
return {
|
|
121
|
-
buffer:
|
|
162
|
+
buffer: privacyResult.buffer,
|
|
122
163
|
applied,
|
|
123
|
-
skipped
|
|
164
|
+
skipped,
|
|
165
|
+
unprocessedStories,
|
|
166
|
+
privacyReport: privacyResult.privacyReport
|
|
124
167
|
};
|
|
125
168
|
};
|
|
126
169
|
//#endregion
|
|
127
|
-
export { generateRedlineDocx };
|
|
170
|
+
export { InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIComment, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditSnapshot, FolioAIInlineFormatting, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult } from "./ai-edits/types.js";
|
|
2
|
-
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, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationStatus, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "./document-operations.js";
|
|
2
|
+
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, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "./document-operations.js";
|
|
3
3
|
import { FolioReviewChange, FolioReviewChangeKind } from "./ai-edits/read.js";
|
|
4
|
-
import { ApplyFolioAIEditsToBufferOptions, ApplyFolioAIEditsToBufferResult, FolioApplyDocumentOperationsOptions, FolioApplyOperationsOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocxReviewer, FolioDocxReviewerOptions, FolioReviewChangeFilter, FolioReviewComment, FolioReviewCommentFilter, FolioReviewCommentReply, FolioReviewReplyInput, applyFolioAIEditsToBuffer } from "./ai-edits/headless.js";
|
|
4
|
+
import { ApplyFolioAIEditsToBufferOptions, ApplyFolioAIEditsToBufferResult, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioApplyDocumentOperationsOptions, FolioApplyDocumentOperationsToStoryOptions, FolioApplyOperationsOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioDocxReviewer, FolioDocxReviewerOptions, FolioEditableDocumentStoryHandle, FolioReadReviewedStoryOptions, FolioResolveReviewedStoryOptions, FolioResolvedReviewedView, FolioReviewChangeFilter, FolioReviewComment, FolioReviewCommentFilter, FolioReviewCommentReply, FolioReviewReplyInput, FolioReviewedStory, FolioReviewedView, UnsupportedFolioReviewedViewError, applyFolioAIEditsToBuffer, isFolioResolvedReviewedView, isFolioReviewedView } from "./ai-edits/headless.js";
|
|
5
5
|
import { createFolioAITextRangeHandle } from "./ai-edits/snapshot.js";
|
|
6
6
|
import { getFolioDocumentOutline, readFolioDocumentSection } from "./ai-edits/scoped-reading.js";
|
|
7
7
|
import { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
|
|
8
|
+
import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocumentPreset, DocumentStyleSet } from "./style-sets/types.js";
|
|
8
9
|
import { CreateEmptyDocumentOptions, createEmptyDocument } from "./utils/createDocument.js";
|
|
10
|
+
import { DocumentStyleCatalog, DocumentStyleCatalogEntry, ExtractDocumentStyleSetOptions, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, inspectDocumentStyles, inspectDocumentStylesFromDocx } from "./style-sets/extract.js";
|
|
11
|
+
import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet } from "./style-sets/stellaStyle.js";
|
|
9
12
|
import { createDocx } from "./docx/rezip.js";
|
|
10
13
|
import { EnsureParaIdsError, EnsureParaIdsOptions, EnsureParaIdsResult, ensureParaIds } from "./docx/ensureParaIds.js";
|
|
14
|
+
import { FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, FolioDocumentMetadataProperty, FolioDocumentPrivacyArchiveError, FolioDocumentPrivacyOptions, FolioDocumentPrivacyReport, FolioDocumentPrivacyTransform, InvalidFolioDocumentPrivacyOptionsError, RewriteDocxMetadataPrivacyResult, isFolioDocumentPrivacyTransform, rewriteDocxMetadataPrivacy } from "./docx/metadataPrivacy.js";
|
|
11
15
|
import { CreateCommentReplyInput, replyToComment } from "./docx/replyToComment.js";
|
|
12
16
|
import { DocxArchiveError } from "./docx/server/boundedArchive.js";
|
|
13
17
|
import { DocxParagraphSource, ExtractedDocxParagraph, ExtractedDocxText, extractDocxText } from "./docx/server/extractDocxText.js";
|
|
14
|
-
import { GenerateRedlineDocxOptions, GenerateRedlineDocxResult, generateRedlineDocx } from "./redline.js";
|
|
15
|
-
import { FolioBlockDiff, FolioFormatProperty, FolioVersionDiff, FolioVersionDiffSegment, compareDocxVersions } from "./version-comparison.js";
|
|
16
|
-
export { type ApplyFolioAIEditsToBufferOptions, type ApplyFolioAIEditsToBufferResult, type CreateCommentReplyInput, type CreateEmptyDocumentOptions, type DeriveBlockIdInput, DocxArchiveError, type DocxParagraphSource, EnsureParaIdsError, type EnsureParaIdsOptions, type EnsureParaIdsResult, type ExtractedDocxParagraph, type ExtractedDocxText, 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 FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditSnapshot, type FolioAIInlineFormatting, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsOptions, type FolioApplyOperationsOptions, type FolioBlockDiff, type FolioBlockId, type FolioDocumentNavigationTarget, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocumentOutline, type FolioDocumentOutlineEntry, type FolioDocumentSection, type FolioDocumentSectionHandle, type FolioDocumentSectionReadResult, type FolioDocumentStory, type FolioDocumentStoryHandle, FolioDocxReviewer, type FolioDocxReviewerOptions, type FolioFormatProperty, type FolioReviewChange, type FolioReviewChangeFilter, type FolioReviewChangeKind, type FolioReviewComment, type FolioReviewCommentFilter, type FolioReviewCommentReply, type FolioReviewReplyInput, type FolioVersionDiff, type FolioVersionDiffSegment, type GenerateRedlineDocxOptions, type GenerateRedlineDocxResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioAIEditsToBuffer, assertSupportedFolioDocumentOperationVersion, compareDocxVersions, createDocx, createEmptyDocument, createFolioAITextRangeHandle, deriveBlockId, ensureParaIds, extractDocxText, generateRedlineDocx, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch, readFolioDocumentSection, replyToComment };
|
|
18
|
+
import { GenerateRedlineDocxOptions, GenerateRedlineDocxResult, GenerateRedlineUnprocessedStory, InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx } from "./redline.js";
|
|
19
|
+
import { FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, FolioBlockDiff, FolioCompareDocxVersionsOptions, FolioDocumentMetadataValue, FolioFormatProperty, FolioMetadataDiff, FolioStoryDiff, FolioVersionBlockHandle, FolioVersionComparisonPrivacyTransform, FolioVersionComparisonScope, FolioVersionDiff, FolioVersionDiffPrivacyOptions, FolioVersionDiffPrivacyReport, FolioVersionDiffSegment, FolioVersionDiffSummaryCounts, InvalidFolioVersionComparisonOptionsError, applyFolioVersionDiffPrivacy, compareDocxVersions, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope } from "./version-comparison.js";
|
|
20
|
+
export { type ApplyFolioAIEditsToBufferOptions, type ApplyFolioAIEditsToBufferResult, type CreateCommentReplyInput, type CreateEmptyDocumentOptions, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, type DeriveBlockIdInput, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, DocxArchiveError, type DocxParagraphSource, EnsureParaIdsError, type EnsureParaIdsOptions, type EnsureParaIdsResult, type ExtractDocumentStyleSetOptions, type ExtractedDocxParagraph, type ExtractedDocxText, FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditSnapshot, type FolioAIInlineFormatting, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsOptions, type FolioApplyDocumentOperationsToStoryOptions, type FolioApplyOperationsOptions, type FolioBlockDiff, type FolioBlockId, type FolioCompareDocxVersionsOptions, type FolioDocumentMetadataProperty, type FolioDocumentMetadataValue, type FolioDocumentNavigationTarget, 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 FolioDocumentOutline, type FolioDocumentOutlineEntry, FolioDocumentPrivacyArchiveError, type FolioDocumentPrivacyOptions, type FolioDocumentPrivacyReport, type FolioDocumentPrivacyTransform, type FolioDocumentSection, type FolioDocumentSectionHandle, type FolioDocumentSectionReadResult, type FolioDocumentStory, type FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioDocxReviewer, type FolioDocxReviewerOptions, type FolioEditableDocumentStoryHandle, type FolioFormatProperty, type FolioMetadataDiff, type FolioReadReviewedStoryOptions, type FolioResolveReviewedStoryOptions, type FolioResolvedReviewedView, type FolioReviewChange, type FolioReviewChangeFilter, type FolioReviewChangeKind, type FolioReviewComment, type FolioReviewCommentFilter, type FolioReviewCommentReply, type FolioReviewReplyInput, type FolioReviewedStory, type FolioReviewedView, type FolioStoryDiff, type FolioVersionBlockHandle, type FolioVersionComparisonPrivacyTransform, type FolioVersionComparisonScope, type FolioVersionDiff, type FolioVersionDiffPrivacyOptions, type FolioVersionDiffPrivacyReport, type FolioVersionDiffSegment, type FolioVersionDiffSummaryCounts, type GenerateRedlineDocxOptions, type GenerateRedlineDocxResult, type GenerateRedlineUnprocessedStory, InvalidFolioDocumentOperationBatchError, InvalidFolioDocumentPrivacyOptionsError, InvalidFolioVersionComparisonOptionsError, InvalidGenerateRedlineDocxOptionsError, type RewriteDocxMetadataPrivacyResult, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioReviewedViewError, applyFolioAIEditsToBuffer, applyFolioVersionDiffPrivacy, assertSupportedFolioDocumentOperationVersion, compareDocxVersions, createDocx, createEmptyDocument, createFolioAITextRangeHandle, createStellaStyleDocumentPreset, createStellaStyleSet, deriveBlockId, ensureParaIds, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractDocxText, generateRedlineDocx, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, inspectDocumentStyles, inspectDocumentStylesFromDocx, isFolioBlockId, isFolioDocumentOperationModeSupported, isFolioDocumentPrivacyTransform, isFolioResolvedReviewedView, isFolioReviewedView, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope, isSequentialFolioBlockId, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch, readFolioDocumentSection, replyToComment, rewriteDocxMetadataPrivacy };
|