@stll/folio-core 0.4.0 → 0.5.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/apply.d.ts +3 -9
- package/dist/ai-edits/apply.js +94 -14
- package/dist/ai-edits/blockRange.d.ts +33 -0
- package/dist/ai-edits/blockRange.js +58 -0
- package/dist/ai-edits/headless.d.ts +33 -4
- package/dist/ai-edits/headless.js +83 -15
- package/dist/ai-edits/index.d.ts +5 -3
- package/dist/ai-edits/index.js +3 -2
- package/dist/ai-edits/snapshot.d.ts +14 -2
- package/dist/ai-edits/snapshot.js +12 -1
- package/dist/ai-edits/types.d.ts +42 -3
- package/dist/compat/eigenpal.d.ts +3 -2
- package/dist/compat/eigenpal.js +6 -5
- package/dist/controller/layoutPipeline.d.ts +1 -0
- package/dist/controller/layoutPipeline.js +35 -137
- package/dist/controller/layoutScheduler.d.ts +2 -1
- package/dist/controller/layoutScheduler.js +6 -0
- package/dist/document-operations.d.ts +122 -0
- package/dist/document-operations.js +575 -0
- package/dist/docx/blockContentParser.js +17 -7
- package/dist/docx/encryption/agileDecryption.js +2 -1
- package/dist/docx/encryption/compoundFile.js +4 -2
- package/dist/docx/footnoteParser.d.ts +1 -17
- package/dist/docx/footnoteParser.js +1 -27
- package/dist/docx/groupDrawingParser.d.ts +8 -0
- package/dist/docx/groupDrawingParser.js +131 -0
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +8 -2
- package/dist/docx/paragraphParser.js +9 -3
- package/dist/docx/runParser.js +8 -1
- package/dist/docx/selectiveXmlPatch.js +4 -10
- package/dist/docx/serializer/numberingSerializer.js +3 -1
- package/dist/docx/settingsParser.d.ts +6 -3
- package/dist/docx/settingsParser.js +2 -0
- package/dist/docx/xmlParser.js +11 -4
- package/dist/index.d.ts +3 -2
- package/dist/index.js +6 -5
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +37 -1
- package/dist/layout-bridge/convert/footnoteLayout.js +138 -14
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +5 -7
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -7
- package/dist/layout-bridge/convert/toFlowBlocks.js +56 -19
- package/dist/layout-engine/index.d.ts +6 -5
- package/dist/layout-engine/index.js +89 -26
- package/dist/layout-engine/keep-together.d.ts +13 -8
- package/dist/layout-engine/keep-together.js +40 -25
- package/dist/layout-engine/layoutInstrumentation.d.ts +11 -1
- package/dist/layout-engine/layoutInstrumentation.js +10 -1
- package/dist/layout-engine/measure/measureBlocks.js +28 -18
- package/dist/layout-engine/measure/measureParagraph.js +61 -15
- package/dist/layout-engine/paginator.d.ts +2 -1
- package/dist/layout-engine/paginator.js +9 -3
- package/dist/layout-engine/textBoxGroup.d.ts +7 -0
- package/dist/layout-engine/textBoxGroup.js +8 -0
- package/dist/layout-engine/types.d.ts +30 -9
- package/dist/layout-engine/types.js +20 -2
- package/dist/layout-painter/renderPage.d.ts +15 -1
- package/dist/layout-painter/renderPage.js +27 -11
- package/dist/layout-painter/renderParagraph.js +18 -8
- package/dist/layout-painter/renderTable.js +10 -7
- package/dist/managers/DocumentLoaderManager.js +12 -5
- package/dist/managers/TableSelectionManager.js +1 -1
- package/dist/model.js +1 -1
- package/dist/paged-layout/pageText.d.ts +14 -0
- package/dist/paged-layout/pageText.js +21 -0
- package/dist/prosemirror/attrs/index.js +2 -0
- package/dist/prosemirror/commands/comments.js +75 -5
- package/dist/prosemirror/commands/hyperlink.js +4 -2
- package/dist/prosemirror/commands/image.js +2 -1
- package/dist/prosemirror/commands/index.js +1 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +68 -0
- package/dist/prosemirror/commands/propertyChangeScope.js +242 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +14 -3
- package/dist/prosemirror/conversion/toProseDoc.js +29 -8
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +6 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +10 -11
- package/dist/prosemirror/findReplaceSelection.js +2 -1
- package/dist/prosemirror/index.js +1 -1
- package/dist/prosemirror/insertOperations.js +1 -1
- package/dist/prosemirror/schema/nodes.d.ts +10 -5
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/utils/tabCalculator.js +4 -2
- package/dist/redline.d.ts +20 -0
- package/dist/redline.js +127 -0
- package/dist/server.d.ts +7 -3
- package/dist/server.js +6 -2
- package/dist/symbols.d.ts +35 -0
- package/dist/symbols.js +512 -0
- package/dist/utils/clipboard.js +3 -3
- package/dist/utils/fontLoader.js +3 -0
- package/dist/utils/fontResolver.js +48 -1
- package/dist/utils/zoom.d.ts +21 -0
- package/dist/utils/zoom.js +21 -0
- package/dist/version-comparison.d.ts +92 -0
- package/dist/version-comparison.js +436 -0
- package/package.json +3 -3
- package/dist/paged-layout/headerFooterMargins.d.ts +0 -75
- package/dist/paged-layout/headerFooterMargins.js +0 -122
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { tableColumnsArePinned } from "../layout-engine/types.js";
|
|
1
2
|
import { measureParagraph } from "../layout-engine/measure/measureParagraph.js";
|
|
2
3
|
import { getAutomaticTextColorForBackground } from "./documentColors.js";
|
|
3
4
|
import { renderParagraphFragment } from "./renderParagraph.js";
|
|
@@ -137,6 +138,7 @@ function renderNestedTable(block, measure, context, doc) {
|
|
|
137
138
|
}
|
|
138
139
|
rowYPositions.push(yPos);
|
|
139
140
|
const spanningCells = /* @__PURE__ */ new Map();
|
|
141
|
+
const columnsPinned = tableColumnsArePinned(block);
|
|
140
142
|
let y = 0;
|
|
141
143
|
for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex++) {
|
|
142
144
|
const row = block.rows[rowIndex];
|
|
@@ -146,7 +148,7 @@ function renderNestedTable(block, measure, context, doc) {
|
|
|
146
148
|
y += rowMeasure.height;
|
|
147
149
|
continue;
|
|
148
150
|
}
|
|
149
|
-
const rowEl = renderTableRow(row, rowMeasure, rowIndex, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, void 0, block.bidi);
|
|
151
|
+
const rowEl = renderTableRow(row, rowMeasure, rowIndex, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, void 0, block.bidi, columnsPinned);
|
|
150
152
|
tableEl.append(rowEl);
|
|
151
153
|
y += rowMeasure.height;
|
|
152
154
|
}
|
|
@@ -169,7 +171,7 @@ function applyBorder(el, side, border) {
|
|
|
169
171
|
/**
|
|
170
172
|
* Render a single table cell
|
|
171
173
|
*/
|
|
172
|
-
function renderTableCell(cell, cellMeasure, x, rowHeight, borderFlags, context, doc) {
|
|
174
|
+
function renderTableCell(cell, cellMeasure, x, rowHeight, borderFlags, columnsPinned, context, doc) {
|
|
173
175
|
const cellEl = doc.createElement("div");
|
|
174
176
|
cellEl.className = TABLE_CLASS_NAMES.cell;
|
|
175
177
|
cellEl.style.position = "absolute";
|
|
@@ -195,7 +197,7 @@ function renderTableCell(cell, cellMeasure, x, rowHeight, borderFlags, context,
|
|
|
195
197
|
const automaticTextColor = getAutomaticTextColorForBackground(cell.background);
|
|
196
198
|
if (automaticTextColor) cellEl.style.color = automaticTextColor;
|
|
197
199
|
}
|
|
198
|
-
if (cell.noWrap) cellEl.style.whiteSpace = "nowrap";
|
|
200
|
+
if (cell.noWrap && !columnsPinned) cellEl.style.whiteSpace = "nowrap";
|
|
199
201
|
if (cell.verticalAlign) {
|
|
200
202
|
cellEl.style.display = "flex";
|
|
201
203
|
cellEl.style.flexDirection = "column";
|
|
@@ -226,7 +228,7 @@ function renderTableCell(cell, cellMeasure, x, rowHeight, borderFlags, context,
|
|
|
226
228
|
/**
|
|
227
229
|
* Render a table row with rowSpan support
|
|
228
230
|
*/
|
|
229
|
-
function renderTableRow(row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, spanningCells, rowYPositions, isFirstRowInFragment, bidi = false) {
|
|
231
|
+
function renderTableRow(row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, spanningCells, rowYPositions, isFirstRowInFragment, bidi = false, columnsPinned = false) {
|
|
230
232
|
const rowEl = doc.createElement("div");
|
|
231
233
|
rowEl.className = TABLE_CLASS_NAMES.row;
|
|
232
234
|
const tableWidth = bidi ? columnWidths.reduce((sum, columnWidth) => sum + columnWidth, 0) : 0;
|
|
@@ -270,7 +272,7 @@ function renderTableRow(row, rowMeasure, rowIndex, y, columnWidths, totalRows, c
|
|
|
270
272
|
isLastRow,
|
|
271
273
|
isFirstCol: bidi ? atLogicalEnd : atLogicalStart,
|
|
272
274
|
isLastCol: bidi ? atLogicalStart : atLogicalEnd
|
|
273
|
-
}, context, doc);
|
|
275
|
+
}, columnsPinned, context, doc);
|
|
274
276
|
cellEl.dataset["cellIndex"] = String(cellIndex);
|
|
275
277
|
cellEl.dataset["columnIndex"] = String(columnIndex);
|
|
276
278
|
if (rowSpan > 1) cellEl.dataset["rowSpan"] = String(rowSpan);
|
|
@@ -348,6 +350,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
|
|
|
348
350
|
}
|
|
349
351
|
rowYPositions.push(yPos);
|
|
350
352
|
const spanningCells = /* @__PURE__ */ new Map();
|
|
353
|
+
const columnsPinned = tableColumnsArePinned(block);
|
|
351
354
|
const headerRowCount = fragment.headerRowCount ?? 0;
|
|
352
355
|
let y = 0;
|
|
353
356
|
if (headerRowCount > 0 && fragment.continuesFromPrev) for (let hdrIdx = 0; hdrIdx < headerRowCount; hdrIdx++) {
|
|
@@ -358,7 +361,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
|
|
|
358
361
|
y += hdrRowMeasure.height;
|
|
359
362
|
continue;
|
|
360
363
|
}
|
|
361
|
-
const rowEl = renderTableRow(hdrRow, hdrRowMeasure, hdrIdx, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, hdrIdx === 0, block.bidi);
|
|
364
|
+
const rowEl = renderTableRow(hdrRow, hdrRowMeasure, hdrIdx, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, hdrIdx === 0, block.bidi, columnsPinned);
|
|
362
365
|
rowEl.dataset["repeatedHeader"] = "true";
|
|
363
366
|
tableEl.append(rowEl);
|
|
364
367
|
y += hdrRowMeasure.height;
|
|
@@ -386,7 +389,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
|
|
|
386
389
|
continue;
|
|
387
390
|
}
|
|
388
391
|
const isFirstRowInFragment = headerRowCount > 0 && fragment.continuesFromPrev ? false : fragment.continuesFromPrev && rowIndex === fragment.fromRow;
|
|
389
|
-
const rowEl = renderTableRow(row, rowMeasure, rowIndex, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, isFirstRowInFragment, block.bidi);
|
|
392
|
+
const rowEl = renderTableRow(row, rowMeasure, rowIndex, y, measure.columnWidths, block.rows.length, context, doc, spanningCells, rowYPositions, isFirstRowInFragment, block.bidi, columnsPinned);
|
|
390
393
|
contentParent.append(rowEl);
|
|
391
394
|
y += rowMeasure.height;
|
|
392
395
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resetAuthorColors } from "../utils/authorColors.js";
|
|
2
2
|
import { loadFontsWithMapping } from "../utils/fontLoader.js";
|
|
3
3
|
import { parseDocx } from "../docx/parser.js";
|
|
4
|
+
import { recordDocumentLoadPhase } from "../layout-engine/layoutInstrumentation.js";
|
|
4
5
|
import { inspectDocxCompatibility } from "../docx/compatibility.js";
|
|
5
6
|
//#region src/managers/DocumentLoaderManager.ts
|
|
6
7
|
/**
|
|
@@ -48,11 +49,17 @@ var DocumentLoaderManager = class {
|
|
|
48
49
|
const generation = ++this.loadGeneration;
|
|
49
50
|
if (!(history.state !== null)) setDocumentLoadState({ status: "loading" });
|
|
50
51
|
try {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const parseStartedAt = performance.now();
|
|
53
|
+
let doc;
|
|
54
|
+
try {
|
|
55
|
+
doc = await parseDocx(buffer, {
|
|
56
|
+
detectVariables: false,
|
|
57
|
+
preloadFonts: false,
|
|
58
|
+
password: options.password
|
|
59
|
+
});
|
|
60
|
+
} finally {
|
|
61
|
+
recordDocumentLoadPhase("docx-parse", performance.now() - parseStartedAt);
|
|
62
|
+
}
|
|
56
63
|
if (this.loadGeneration !== generation) return;
|
|
57
64
|
this.loadParsedDocument(doc);
|
|
58
65
|
} catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Subscribable } from "./Subscribable.js";
|
|
2
1
|
import { addColumn, addRow, createTableContext, deleteColumn, deleteRow, getColumnCount, mergeCells, splitCell } from "../utils/tableOperations.js";
|
|
2
|
+
import { Subscribable } from "./Subscribable.js";
|
|
3
3
|
//#region src/managers/TableSelectionManager.ts
|
|
4
4
|
/** Data attributes for table elements in the rendered DOM */
|
|
5
5
|
const TABLE_DATA_ATTRIBUTES = {
|
package/dist/model.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "./types/documentEnumValues.js";
|
|
2
1
|
import { deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
|
|
2
|
+
import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "./types/documentEnumValues.js";
|
|
3
3
|
import { types_exports } from "./layout-engine/types.js";
|
|
4
4
|
export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_exports as Layout, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Layout } from "../layout-engine/types.js";
|
|
2
|
+
import { Node } from "prosemirror-model";
|
|
3
|
+
|
|
4
|
+
//#region src/paged-layout/pageText.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* The plain text of a single rendered page (1-based), read by joining each of
|
|
7
|
+
* the page's layout fragments' `[pmStart, pmEnd)` document text with a
|
|
8
|
+
* newline. Fragments with no `pmStart`/`pmEnd` (e.g. a page-shell placeholder)
|
|
9
|
+
* are skipped. Returns `null` when the layout hasn't been computed yet or the
|
|
10
|
+
* page number is out of range.
|
|
11
|
+
*/
|
|
12
|
+
declare const getPageTextFromLayout: (layout: Layout | null, doc: Node, page: number) => string | null;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { getPageTextFromLayout };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/paged-layout/pageText.ts
|
|
2
|
+
/**
|
|
3
|
+
* The plain text of a single rendered page (1-based), read by joining each of
|
|
4
|
+
* the page's layout fragments' `[pmStart, pmEnd)` document text with a
|
|
5
|
+
* newline. Fragments with no `pmStart`/`pmEnd` (e.g. a page-shell placeholder)
|
|
6
|
+
* are skipped. Returns `null` when the layout hasn't been computed yet or the
|
|
7
|
+
* page number is out of range.
|
|
8
|
+
*/
|
|
9
|
+
const getPageTextFromLayout = (layout, doc, page) => {
|
|
10
|
+
if (!layout || !Number.isInteger(page) || page < 1) return null;
|
|
11
|
+
const layoutPage = layout.pages[page - 1];
|
|
12
|
+
if (!layoutPage) return null;
|
|
13
|
+
const fragmentTexts = [];
|
|
14
|
+
for (const fragment of layoutPage.fragments) {
|
|
15
|
+
if (typeof fragment.pmStart !== "number" || typeof fragment.pmEnd !== "number") continue;
|
|
16
|
+
fragmentTexts.push(doc.textBetween(fragment.pmStart, fragment.pmEnd, "\n"));
|
|
17
|
+
}
|
|
18
|
+
return fragmentTexts.join("\n");
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
export { getPageTextFromLayout };
|
|
@@ -174,6 +174,7 @@ const readParagraphAttrs = (node) => {
|
|
|
174
174
|
});
|
|
175
175
|
optionalOneOf(attrs, "sectionBreakType", "paragraph.attrs.sectionBreakType", issues, SECTION_BREAK_TYPES);
|
|
176
176
|
optionalStringArray(attrs, "listLevelNumFmts", "paragraph.attrs.listLevelNumFmts", issues);
|
|
177
|
+
optionalNumberArray(attrs, "listLevelStarts", "paragraph.attrs.listLevelStarts", issues);
|
|
177
178
|
optionalNumber(attrs, "listAbstractNumId", "paragraph.attrs.listAbstractNumId", issues);
|
|
178
179
|
optionalBorderMap(attrs, "borders", "paragraph.attrs.borders", issues, [
|
|
179
180
|
"top",
|
|
@@ -186,6 +187,7 @@ const readParagraphAttrs = (node) => {
|
|
|
186
187
|
optionalShading(attrs, "shading", "paragraph.attrs.shading", issues);
|
|
187
188
|
optionalTabStops(attrs, "tabs", "paragraph.attrs.tabs", issues);
|
|
188
189
|
optionalRecord(attrs, "spacingExplicit", "paragraph.attrs.spacingExplicit", issues);
|
|
190
|
+
optionalRecord(attrs, "spacingFromDocDefaults", "paragraph.attrs.spacingFromDocDefaults", issues);
|
|
189
191
|
optionalTextFormatting(attrs, "defaultTextFormatting", "paragraph.attrs.defaultTextFormatting", issues);
|
|
190
192
|
optionalRecord(attrs, "numPr", "paragraph.attrs.numPr", issues);
|
|
191
193
|
validateNumPr(attrs["numPr"], issues);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, sectionRejectProperties, tableCellRejectAttrPatch, tableRejectAttrPatch, tableRowRejectAttrPatch } from "./propertyChangeScope.js";
|
|
1
2
|
//#region src/prosemirror/commands/comments.ts
|
|
2
3
|
/**
|
|
3
4
|
* Add a comment mark to the current selection.
|
|
@@ -59,21 +60,47 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
59
60
|
if (node.type.name === "paragraph") {
|
|
60
61
|
const op = collectPPrMarkOp(node, pos, from, to, mode, revisionSet);
|
|
61
62
|
if (op) pPrMarkOps.push(op);
|
|
63
|
+
const boundaryCovered = rangeCoversParagraphBoundary(from, to, pos, node);
|
|
64
|
+
let nextAttrs = null;
|
|
62
65
|
const propertyChanges = node.attrs["_propertyChanges"];
|
|
63
|
-
if (Array.isArray(propertyChanges) && propertyChanges.length > 0 &&
|
|
66
|
+
if (Array.isArray(propertyChanges) && propertyChanges.length > 0 && boundaryCovered) {
|
|
64
67
|
const matches = propertyChanges.filter((c) => revisionSet === null || c.info && revisionSet.has(c.info.id));
|
|
65
68
|
if (matches.length > 0) {
|
|
66
69
|
const remaining = propertyChanges.filter((c) => revisionSet !== null && (!c.info || !revisionSet.has(c.info.id)));
|
|
67
|
-
|
|
70
|
+
nextAttrs = {
|
|
68
71
|
...node.attrs,
|
|
69
72
|
_propertyChanges: remaining.length > 0 ? remaining : null
|
|
70
73
|
};
|
|
71
|
-
if (mode === "reject") {
|
|
72
|
-
|
|
74
|
+
if (mode === "reject") for (const change of matches.toReversed()) {
|
|
75
|
+
Object.assign(nextAttrs, paragraphRejectAttrPatch(change.previousFormatting));
|
|
76
|
+
nextAttrs["_originalFormatting"] = paragraphRejectOriginalFormatting(change.previousFormatting, node.attrs["_originalFormatting"]);
|
|
73
77
|
}
|
|
74
|
-
tr.setNodeMarkup(pos, void 0, nextAttrs);
|
|
75
78
|
}
|
|
76
79
|
}
|
|
80
|
+
const sectionProperties = node.attrs["_sectionProperties"];
|
|
81
|
+
const sectionChanges = sectionProperties?.propertyChanges;
|
|
82
|
+
if (sectionProperties && Array.isArray(sectionChanges) && sectionChanges.length > 0 && boundaryCovered) {
|
|
83
|
+
const matches = sectionChanges.filter((c) => revisionSet === null || c.info && revisionSet.has(c.info.id));
|
|
84
|
+
if (matches.length > 0) {
|
|
85
|
+
const remaining = sectionChanges.filter((c) => revisionSet !== null && (!c.info || !revisionSet.has(c.info.id)));
|
|
86
|
+
let restored = { ...sectionProperties };
|
|
87
|
+
if (mode === "reject") for (const change of matches.toReversed()) restored = sectionRejectProperties(restored, change.previousProperties);
|
|
88
|
+
delete restored.propertyChanges;
|
|
89
|
+
if (remaining.length > 0) restored.propertyChanges = remaining;
|
|
90
|
+
nextAttrs = nextAttrs ?? { ...node.attrs };
|
|
91
|
+
nextAttrs["_sectionProperties"] = restored;
|
|
92
|
+
nextAttrs["sectionBreakType"] = sectionBreakTypeFromSectionStart(restored.sectionStart);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (nextAttrs) tr.setNodeMarkup(pos, void 0, nextAttrs);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
const tableChangeAttrName = TABLE_PROPERTY_CHANGE_ATTR_BY_NODE[node.type.name];
|
|
99
|
+
if (tableChangeAttrName !== void 0) {
|
|
100
|
+
if (rangeCoversNode(from, to, pos, node)) {
|
|
101
|
+
const nextAttrs = resolveTablePropertyChangeAttrs(node, tableChangeAttrName, mode, revisionSet);
|
|
102
|
+
if (nextAttrs) tr.setNodeMarkup(pos, void 0, nextAttrs);
|
|
103
|
+
}
|
|
77
104
|
return true;
|
|
78
105
|
}
|
|
79
106
|
if (!node.isInline) return true;
|
|
@@ -124,6 +151,49 @@ function rangeCoversParagraphBoundary(from, to, pos, node) {
|
|
|
124
151
|
const boundaryTo = pos + node.nodeSize;
|
|
125
152
|
return from <= boundaryFrom && to >= boundaryTo;
|
|
126
153
|
}
|
|
154
|
+
/** Whether [from, to] fully covers the node — the range property-change cards
|
|
155
|
+
* and accept-all / reject-all sweeps supply for table-level records. */
|
|
156
|
+
function rangeCoversNode(from, to, pos, node) {
|
|
157
|
+
return from <= pos && to >= pos + node.nodeSize;
|
|
158
|
+
}
|
|
159
|
+
const SECTION_BREAK_TYPE_VALUES = [
|
|
160
|
+
"nextPage",
|
|
161
|
+
"continuous",
|
|
162
|
+
"oddPage",
|
|
163
|
+
"evenPage"
|
|
164
|
+
];
|
|
165
|
+
function sectionBreakTypeFromSectionStart(sectionStart) {
|
|
166
|
+
return SECTION_BREAK_TYPE_VALUES.find((value) => value === sectionStart) ?? null;
|
|
167
|
+
}
|
|
168
|
+
/** PM node type name → the attr its tracked property-change records live on. */
|
|
169
|
+
const TABLE_PROPERTY_CHANGE_ATTR_BY_NODE = {
|
|
170
|
+
table: "tblPrChange",
|
|
171
|
+
tableRow: "trPrChange",
|
|
172
|
+
tableCell: "tcPrChange",
|
|
173
|
+
tableHeader: "tcPrChange"
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Resolve the tracked property-change records on one table / row / cell node.
|
|
177
|
+
* Accept keeps the live formatting and clears the matched records; reject
|
|
178
|
+
* additionally restores the stored previous formatting wholesale (the change
|
|
179
|
+
* element stores the complete old property set — see propertyChangeScope.ts).
|
|
180
|
+
* Returns the next attrs, or `null` when no record matches.
|
|
181
|
+
*/
|
|
182
|
+
function resolveTablePropertyChangeAttrs(node, attrName, mode, revisionSet) {
|
|
183
|
+
const changes = node.attrs[attrName];
|
|
184
|
+
if (!Array.isArray(changes) || changes.length === 0) return null;
|
|
185
|
+
const matches = changes.filter((c) => revisionSet === null || c.info && revisionSet.has(c.info.id));
|
|
186
|
+
if (matches.length === 0) return null;
|
|
187
|
+
const remaining = changes.filter((c) => revisionSet !== null && (!c.info || !revisionSet.has(c.info.id)));
|
|
188
|
+
const nextAttrs = {
|
|
189
|
+
...node.attrs,
|
|
190
|
+
[attrName]: remaining.length > 0 ? remaining : null
|
|
191
|
+
};
|
|
192
|
+
if (mode === "reject") for (const change of matches.toReversed()) if (attrName === "tblPrChange") Object.assign(nextAttrs, tableRejectAttrPatch(change.previousFormatting));
|
|
193
|
+
else if (attrName === "trPrChange") Object.assign(nextAttrs, tableRowRejectAttrPatch(change.previousFormatting));
|
|
194
|
+
else Object.assign(nextAttrs, tableCellRejectAttrPatch(change.previousFormatting, node.attrs["_originalFormatting"]));
|
|
195
|
+
return nextAttrs;
|
|
196
|
+
}
|
|
127
197
|
function isPPrMarkAttr(value) {
|
|
128
198
|
if (typeof value !== "object" || value === null) return false;
|
|
129
199
|
const kind = value.kind;
|
|
@@ -39,7 +39,8 @@ const editHyperlinkAtCursor = (view, { displayText, href }) => {
|
|
|
39
39
|
const { $from } = view.state.selection;
|
|
40
40
|
const linkMark = $from.marks().find((m) => m.type === hlType);
|
|
41
41
|
if (!linkMark) return true;
|
|
42
|
-
const
|
|
42
|
+
const ranges = collectHyperlinkRanges($from.parent, $from.start(), hlType, hyperlinkHref(linkMark));
|
|
43
|
+
const targetRange = rangeAtCursor(ranges, $from.pos);
|
|
43
44
|
if (!targetRange) return false;
|
|
44
45
|
const { tooltip } = expectHyperlinkMarkAttrs(linkMark);
|
|
45
46
|
const newMark = hlType.create({
|
|
@@ -69,7 +70,8 @@ const removeHyperlinkAtCursor = (view, { popupHref }) => {
|
|
|
69
70
|
}
|
|
70
71
|
});
|
|
71
72
|
if (!linkMark) return false;
|
|
72
|
-
const
|
|
73
|
+
const ranges = collectHyperlinkRanges($from.parent, $from.start(), hlType, hyperlinkHref(linkMark));
|
|
74
|
+
const targetRange = rangeAtCursor(ranges, $from.pos);
|
|
73
75
|
if (!targetRange) return false;
|
|
74
76
|
const tr = view.state.tr.removeMark(targetRange.start, targetRange.end, hlType);
|
|
75
77
|
view.dispatch(tr.scrollIntoView());
|
|
@@ -124,7 +124,8 @@ const applyImageWrapType = (view, pos, wrapType) => {
|
|
|
124
124
|
const applyImageTransform = (view, pos, action) => {
|
|
125
125
|
const node = imageNodeAt(view, pos);
|
|
126
126
|
if (!node) return false;
|
|
127
|
-
const
|
|
127
|
+
const currentTransform = expectImageAttrs(node).transform ?? "";
|
|
128
|
+
const transform = computeImageTransform(currentTransform, action);
|
|
128
129
|
const tr = view.state.tr.setNodeMarkup(pos, void 0, mergeImageAttrs(node, { transform }));
|
|
129
130
|
view.dispatch(tr.scrollIntoView());
|
|
130
131
|
return true;
|
|
@@ -5,9 +5,9 @@ import { getTableContext, isInTable as isInTableCell } from "../extensions/nodes
|
|
|
5
5
|
import { getListInfo, isInList } from "../extensions/features/ListExtension.js";
|
|
6
6
|
import { CLIPBOARD_READ_ERROR_EVENT, buildPlainTextSlice, pasteWithoutFormatting } from "./pastePlainText.js";
|
|
7
7
|
import { getHyperlinkAttrs, getSelectedText, isHyperlinkActive } from "../extensions/marks/HyperlinkExtension.js";
|
|
8
|
-
import { addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyTableStyle, autoFitContents, deleteColumn, deleteRow, deleteTable, distributeColumns, insertTable, mergeCells, removeTableBorders, selectColumn, selectRow, selectTable, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setInsideTableBorders, setOutsideTableBorders, setRowHeight, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, splitCell, toggleHeaderRow, toggleNoWrap } from "./table.js";
|
|
9
8
|
import { clearFontFamily, clearFontSize, clearHighlight, clearTextColor, insertHyperlink, removeHyperlink, setFontFamily, setFontSize, setHighlight, setHyperlink, setTextColor, setUnderlineStyle, toggleBold, toggleItalic, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline } from "./formatting.js";
|
|
10
9
|
import { addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyStyle, clearStyle, decreaseIndent, decreaseListLevel, doubleSpacing, generateTOC, increaseIndent, increaseListLevel, oneAndHalfSpacing, removeList, removeTabStop, setAlignment, setIndentFirstLine, setIndentLeft, setIndentRight, setLineSpacing, setLtr, setRtl, setSpaceAfter, setSpaceBefore, singleSpacing, toggleBidi, toggleBulletList, toggleNumberedList } from "./paragraph.js";
|
|
10
|
+
import { addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyTableStyle, autoFitContents, deleteColumn, deleteRow, deleteTable, distributeColumns, insertTable, mergeCells, removeTableBorders, selectColumn, selectRow, selectTable, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setInsideTableBorders, setOutsideTableBorders, setRowHeight, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, splitCell, toggleHeaderRow, toggleNoWrap } from "./table.js";
|
|
11
11
|
import { PAINTABLE_MARK_NAMES, applyFormatMarks, captureFormatMarks } from "./formatPainter.js";
|
|
12
12
|
import { insertPageBreak } from "./pageBreak.js";
|
|
13
13
|
export { CLIPBOARD_READ_ERROR_EVENT, PAINTABLE_MARK_NAMES, acceptAIEditRevision, acceptAllChanges, acceptChange, addColumnLeft, addColumnRight, addCommentMark, addRowAbove, addRowBelow, addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, buildPlainTextSlice, captureFormatMarks, clearFontFamily, clearFontSize, clearFormatting, clearHighlight, clearStyle, clearTextColor, createRemoveMarkCommand, createSetMarkCommand, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, doubleSpacing, findAIEditRevisionRange, findNextChange, findPreviousChange, generateTOC, getHyperlinkAttrs, getListInfo, getMarkAttr, getParagraphAlignment, getParagraphBidi, getSelectedText, getStyleId, getTableContext, increaseIndent, increaseListLevel, insertHyperlink, insertPageBreak, insertTable, isHyperlinkActive, isInList, isInTableCell as isInTable, isMarkActive, mergeCells, oneAndHalfSpacing, pasteWithoutFormatting, rejectAIEditRevision, rejectAllChanges, rejectChange, removeCommentMark, removeHyperlink, removeList, removeTabStop, removeTableBorders, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setHyperlink, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setSpaceAfter, setSpaceBefore, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, setTextColor, setUnderlineStyle, singleSpacing, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
|
|
3
|
+
//#region src/prosemirror/commands/propertyChangeScope.d.ts
|
|
4
|
+
type AttrPatch = Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* Paragraph attrs governed by a `w:pPrChange` — the attrs
|
|
7
|
+
* `paragraphFormattingToAttrs` (conversion/toProseDoc.ts) can produce from a
|
|
8
|
+
* parsed `CT_PPrBase` (ECMA-376 §17.13.5.29). Rejecting a pPrChange restores
|
|
9
|
+
* the stored old pPr wholesale for exactly these keys: a key absent from the
|
|
10
|
+
* stored record resets to the schema default (`null`).
|
|
11
|
+
*
|
|
12
|
+
* Deliberately OUT of scope (preserved across a reject):
|
|
13
|
+
* - identity/structure: `paraId`, `textId`, `sectionBreakType`,
|
|
14
|
+
* `_sectionProperties`, `_propertyChanges`, `pPrMark`, `bookmarks`,
|
|
15
|
+
* `_emptyHyperlinks`, `renderedPageBreakBefore`
|
|
16
|
+
* - paragraph-mark run properties — `pPr/rPr` is CT_PPr-only, not part of the
|
|
17
|
+
* CT_PPrBase payload a pPrChange stores: `defaultTextFormatting`,
|
|
18
|
+
* `runInWithNext` (`w:specVanish` lives in that rPr)
|
|
19
|
+
* - load-time style/numbering bookkeeping the command layer cannot recompute
|
|
20
|
+
* without a style resolver: `numPrFromStyle`, the `list*` rendering attrs,
|
|
21
|
+
* `spacingFromDocDefaults`
|
|
22
|
+
*/
|
|
23
|
+
declare const PPR_CHANGE_SCOPED_ATTR_KEYS: readonly ["styleId", "numPr", "alignment", "spaceBefore", "spaceAfter", "lineSpacing", "lineSpacingRule", "spacingExplicit", "indentLeft", "indentRight", "indentFirstLine", "hangingIndent", "borders", "shading", "tabs", "pageBreakBefore", "keepNext", "keepLines", "widowControl", "contextualSpacing", "outlineLevel", "direction", "_autospacingBase"];
|
|
24
|
+
/**
|
|
25
|
+
* Build the attr patch that rejecting one pPrChange applies to a paragraph:
|
|
26
|
+
* every in-scope key set to the stored previous value, or reset to `null`
|
|
27
|
+
* when the stored old pPr does not carry it. Keys the record captured beyond
|
|
28
|
+
* the scoped set (editor-created list suggestions snapshot list-rendering
|
|
29
|
+
* bookkeeping attrs) merge through 1:1 so their pre-change values restore too.
|
|
30
|
+
*/
|
|
31
|
+
declare function paragraphRejectAttrPatch(previousFormatting: Record<string, unknown> | null | undefined): AttrPatch;
|
|
32
|
+
/**
|
|
33
|
+
* Rebuild the paragraph's `_originalFormatting` (the serializer's pPr source)
|
|
34
|
+
* after a reject: the stored old pPr wholesale within CT_PPrBase scope, with
|
|
35
|
+
* the paragraph-mark rPr fields (`runProperties`, `runInWithNext`) preserved
|
|
36
|
+
* from the live original — a pPrChange cannot store them, so a reject must
|
|
37
|
+
* not drop them.
|
|
38
|
+
*/
|
|
39
|
+
declare function paragraphRejectOriginalFormatting(previousFormatting: Record<string, unknown> | null | undefined, liveOriginal: unknown): document_d_exports.ParagraphFormatting | null;
|
|
40
|
+
/**
|
|
41
|
+
* Rejected section properties: the stored old sectPr wholesale, preserving
|
|
42
|
+
* the live header/footer references — `EG_HdrFtrReferences` is not part of
|
|
43
|
+
* the `CT_SectPrBase` payload a `w:sectPrChange` stores (ECMA-376
|
|
44
|
+
* §17.13.5.32), so those children survive a reject. The caller re-attaches
|
|
45
|
+
* whatever `propertyChanges` remain unresolved.
|
|
46
|
+
*/
|
|
47
|
+
declare function sectionRejectProperties(live: document_d_exports.SectionProperties, previousProperties: document_d_exports.SectionProperties | undefined): document_d_exports.SectionProperties;
|
|
48
|
+
/**
|
|
49
|
+
* Attr patch for rejecting a `w:tblPrChange`: the stored old tblPr wholesale
|
|
50
|
+
* (`w:tblPrChange` stores the complete previous tblPr, so every tblPr-derived
|
|
51
|
+
* attr resets when absent). `columnWidths` comes from `w:tblGrid`, not tblPr,
|
|
52
|
+
* and is untouched.
|
|
53
|
+
*/
|
|
54
|
+
declare function tableRejectAttrPatch(previousFormatting: document_d_exports.TableFormatting | undefined): AttrPatch;
|
|
55
|
+
/** Attr patch for rejecting a `w:trPrChange`: the stored old trPr wholesale. */
|
|
56
|
+
declare function tableRowRejectAttrPatch(previousFormatting: document_d_exports.TableRowFormatting | undefined): AttrPatch;
|
|
57
|
+
/**
|
|
58
|
+
* Attr patch for rejecting a `w:tcPrChange`: the stored old tcPr wholesale
|
|
59
|
+
* for the non-structural attrs. `gridSpan` / `vMerge` are structural in
|
|
60
|
+
* ProseMirror (`colspan` / `rowspan` shape the table grid); restoring them
|
|
61
|
+
* from the record would desync the grid without a full table restructure, so
|
|
62
|
+
* the live structure is kept and the rebuilt `_originalFormatting` inherits
|
|
63
|
+
* the live original's `gridSpan` / `vMerge` to stay consistent with it.
|
|
64
|
+
* (Word would also restore tracked merges; folio deliberately does not.)
|
|
65
|
+
*/
|
|
66
|
+
declare function tableCellRejectAttrPatch(previousFormatting: document_d_exports.TableCellFormatting | undefined, liveOriginalFormatting: document_d_exports.TableCellFormatting | null | undefined): AttrPatch;
|
|
67
|
+
//#endregion
|
|
68
|
+
export { PPR_CHANGE_SCOPED_ATTR_KEYS, paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, sectionRejectProperties, tableCellRejectAttrPatch, tableRejectAttrPatch, tableRowRejectAttrPatch };
|