@stll/folio-core 0.45.0 → 0.46.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.js +59 -19
- package/dist/ai-edits/headless.js +1 -1
- package/dist/compare/compare.js +2 -5
- package/dist/compare/scenario.js +2 -5
- package/dist/compare/types.d.ts +9 -1
- package/dist/compare/types.js +12 -1
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/content-controls/checkboxDisplay.d.ts +11 -0
- package/dist/content-controls/checkboxDisplay.js +40 -0
- package/dist/content-controls/findContentControls.js +3 -1
- package/dist/content-controls/mutateContentControls.js +17 -2
- package/dist/controller/contentControlWidgetController.d.ts +1 -0
- package/dist/controller/contentControlWidgetController.js +3 -0
- package/dist/controller/hiddenEditorApi.js +3 -1
- package/dist/controller/hiddenEditorManager.d.ts +1 -1
- package/dist/controller/hiddenEditorManager.js +6 -3
- package/dist/display-list/build/buildDisplayList.js +20 -1
- package/dist/display-list/build/imagePrimitives.d.ts +1 -1
- package/dist/display-list/build/imagePrimitives.js +3 -1
- package/dist/display-list/build/paragraphPrimitives.js +21 -2
- package/dist/display-list/dom/renderDisplayListToDom.js +10 -2
- package/dist/display-list/types.d.ts +17 -0
- package/dist/docx/attributeRemainder.d.ts +43 -0
- package/dist/docx/attributeRemainder.js +65 -0
- package/dist/docx/blockContentParser.d.ts +1 -1
- package/dist/docx/blockContentParser.js +87 -63
- package/dist/docx/blockPlainText.d.ts +3 -4
- package/dist/docx/blockPlainText.js +1 -0
- package/dist/docx/bookmarkPlacement.js +2 -0
- package/dist/docx/commentAnchorIndex.d.ts +30 -0
- package/dist/docx/commentAnchorIndex.js +50 -0
- package/dist/docx/commentParser.d.ts +1 -1
- package/dist/docx/commentParser.js +54 -37
- package/dist/docx/commentRangeIntegrity.d.ts +16 -1
- package/dist/docx/commentRangeIntegrity.js +42 -1
- package/dist/docx/commentRangeJoin.d.ts +9 -0
- package/dist/docx/commentRangeJoin.js +33 -0
- package/dist/docx/commentReferenceCompletion.d.ts +9 -0
- package/dist/docx/commentReferenceCompletion.js +47 -0
- package/dist/docx/commentReferenceNormalization.js +1 -0
- package/dist/docx/commentReplyMarkers.js +11 -19
- package/dist/docx/compatibility.js +1 -0
- package/dist/docx/containerChildren.d.ts +111 -0
- package/dist/docx/containerChildren.gen.d.ts +28 -0
- package/dist/docx/containerChildren.gen.js +246 -0
- package/dist/docx/containerChildren.js +103 -0
- package/dist/docx/documentParser.d.ts +1 -1
- package/dist/docx/documentParser.js +3 -3
- package/dist/docx/ensureParaIds.js +17 -7
- package/dist/docx/fieldParser.d.ts +1 -1
- package/dist/docx/fieldParser.js +4 -4
- package/dist/docx/fieldState.d.ts +26 -0
- package/dist/docx/fieldState.js +53 -0
- package/dist/docx/footnoteParser.d.ts +1 -1
- package/dist/docx/graphicFrameLocks.d.ts +16 -4
- package/dist/docx/graphicFrameLocks.js +19 -6
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/headerFooterReferenceNormalization.js +1 -0
- package/dist/docx/hyperlinkParser.d.ts +27 -8
- package/dist/docx/hyperlinkParser.js +76 -18
- package/dist/docx/imageParser.js +33 -8
- package/dist/docx/inlineWrapperContent.d.ts +85 -0
- package/dist/docx/inlineWrapperContent.js +84 -0
- package/dist/docx/normalizeBaseDirection.js +10 -1
- package/dist/docx/paraIdAttribute.d.ts +21 -0
- package/dist/docx/paraIdAttribute.js +64 -0
- package/dist/docx/paragraphParser.d.ts +1 -1
- package/dist/docx/paragraphParser.js +277 -168
- package/dist/docx/paragraphPropertySource.js +5 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +1 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +6 -52
- package/dist/docx/paragraphTraversal.js +7 -4
- package/dist/docx/parseWarningMessage.js +2 -1
- package/dist/docx/preservedRunContent.d.ts +32 -0
- package/dist/docx/preservedRunContent.js +86 -0
- package/dist/docx/renderedPageBreakNormalization.js +2 -4
- package/dist/docx/rezip.js +74 -18
- package/dist/docx/runParser.d.ts +1 -1
- package/dist/docx/runParser.js +16 -12
- package/dist/docx/sectionParser.js +8 -1
- package/dist/docx/selectiveXmlPatch.d.ts +46 -2
- package/dist/docx/selectiveXmlPatch.js +86 -39
- package/dist/docx/serializer/borderSerializer.js +2 -2
- package/dist/docx/serializer/commentSerializer.js +5 -7
- package/dist/docx/serializer/documentSerializer.js +8 -11
- package/dist/docx/serializer/headerFooterSerializer.js +7 -9
- package/dist/docx/serializer/noteSerializer.js +8 -8
- package/dist/docx/serializer/paragraphSerializer.js +76 -56
- package/dist/docx/serializer/runSerializer.js +25 -16
- package/dist/docx/serializer/sectionPropertiesSerializer.js +8 -4
- package/dist/docx/serializer/tableSerializer.js +18 -8
- package/dist/docx/server/createBilingualDocument.js +3 -1
- package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
- package/dist/docx/server/materializeYjsDocx.js +9 -1
- package/dist/docx/server/migrateYjsAttrSchema.d.ts +55 -0
- package/dist/docx/server/migrateYjsAttrSchema.js +95 -0
- package/dist/docx/shapeParser.js +5 -5
- package/dist/docx/tableParser.d.ts +1 -1
- package/dist/docx/tableParser.js +206 -85
- package/dist/docx/textBoxParser.d.ts +25 -2
- package/dist/docx/textBoxParser.js +52 -2
- package/dist/docx/unzip.js +5 -4
- package/dist/docx/vmlImageParser.d.ts +17 -1
- package/dist/docx/vmlImageParser.js +17 -1
- package/dist/docx/xmlEncoding.d.ts +5 -0
- package/dist/docx/xmlEncoding.js +12 -0
- package/dist/docx/xmlParser.d.ts +10 -1
- package/dist/docx/xmlParser.js +14 -1
- package/dist/headless-layout.js +10 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +5 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +102 -12
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +2 -0
- package/dist/layout-engine/types.d.ts +23 -1
- package/dist/layout-painter/renderImage.d.ts +5 -1
- package/dist/layout-painter/renderImage.js +10 -3
- package/dist/layout-painter/renderPage.d.ts +2 -0
- package/dist/layout-painter/renderPage.js +4 -0
- package/dist/layout-painter/renderParagraph.d.ts +13 -1
- package/dist/layout-painter/renderParagraph.js +22 -3
- package/dist/managers/autoSaveCodec.d.ts +9 -1
- package/dist/managers/autoSaveCodec.js +12 -4
- package/dist/markdown/renderBlock.js +1 -0
- package/dist/markdown/renderRuns.d.ts +1 -1
- package/dist/markdown/renderRuns.js +28 -5
- package/dist/markdown/renderTable.js +22 -5
- package/dist/markdown/trailers.js +4 -1
- package/dist/pdf/images.js +142 -6
- package/dist/prosemirror/attrs/index.d.ts +14 -3
- package/dist/prosemirror/attrs/index.js +155 -2
- package/dist/prosemirror/authoredTransformAttrs.d.ts +28 -0
- package/dist/prosemirror/authoredTransformAttrs.js +64 -0
- package/dist/prosemirror/commands/contentControls.js +10 -2
- package/dist/prosemirror/commands/image.d.ts +9 -2
- package/dist/prosemirror/commands/image.js +42 -28
- package/dist/prosemirror/commands/pageBreak.js +1 -1
- package/dist/prosemirror/commentReferenceAttrs.d.ts +8 -0
- package/dist/prosemirror/commentReferenceAttrs.js +33 -0
- package/dist/prosemirror/commentReferenceIntegrity.d.ts +47 -0
- package/dist/prosemirror/commentReferenceIntegrity.js +43 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
- package/dist/prosemirror/conversion/fromProseDoc.js +269 -70
- package/dist/prosemirror/conversion/index.d.ts +2 -2
- package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -9
- package/dist/prosemirror/conversion/toProseDoc.js +468 -308
- package/dist/prosemirror/extensions/StarterKit.js +8 -58
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -1
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +45 -27
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -1
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +5 -3
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -0
- package/dist/prosemirror/extensions/markRegistry.d.ts +41 -0
- package/dist/prosemirror/extensions/markRegistry.js +75 -0
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.d.ts +18 -0
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +63 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +47 -4
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.d.ts +11 -0
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +87 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +9 -7
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +16 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.d.ts +32 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +67 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.d.ts +16 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +60 -0
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +3 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +3 -2
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +5 -1
- package/dist/prosemirror/inlineWrapperStack.d.ts +39 -0
- package/dist/prosemirror/inlineWrapperStack.js +75 -0
- package/dist/prosemirror/pageBreakRunProjection.d.ts +17 -7
- package/dist/prosemirror/pageBreakRunProjection.js +19 -9
- package/dist/prosemirror/replacedAnnotations.d.ts +59 -0
- package/dist/prosemirror/replacedAnnotations.js +165 -0
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +3 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +5 -1
- package/dist/prosemirror/schema/index.d.ts +3 -3
- package/dist/prosemirror/schema/marks.d.ts +25 -1
- package/dist/prosemirror/schema/nodes.d.ts +90 -3
- package/dist/prosemirror/schema/nodes.js +16 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
- package/dist/prosemirror/validation.js +16 -2
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +73 -0
- package/dist/prosemirror/yjsDocumentMetadata.js +171 -0
- package/dist/prosemirror/zeroWidthAnchors.js +2 -0
- package/dist/render-dom/commentAnchorAttributes.d.ts +37 -0
- package/dist/render-dom/commentAnchorAttributes.js +54 -0
- package/dist/server.d.ts +3 -1
- package/dist/server.js +3 -1
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/clipboard.d.ts +9 -1
- package/dist/utils/clipboard.js +27 -1
- package/dist/utils/findReplace.js +1 -1
- package/dist/utils/imageLuminance.d.ts +15 -0
- package/dist/utils/imageLuminance.js +32 -0
- package/dist/utils/mergeDocumentContent.js +7 -17
- package/dist/utils/replaceText.js +1 -0
- package/package.json +2 -2
- package/dist/docx/blockRangeMarkers.d.ts +0 -36
- package/dist/docx/blockRangeMarkers.js +0 -59
- package/dist/prosemirror/yjsParagraphSourceContract.d.ts +0 -9
- package/dist/prosemirror/yjsParagraphSourceContract.js +0 -26
|
@@ -6,7 +6,7 @@ import { countCompressibleSpaces, toPaintedText } from "../../layout-engine/meas
|
|
|
6
6
|
import { isFloatingImageRun } from "../../layout-engine/types.js";
|
|
7
7
|
import { resolveParagraphBorderHorizontalOutsets } from "../../layout-painter/borderStroke.js";
|
|
8
8
|
import { getAutomaticTextColorForBackground } from "../../layout-painter/documentColors.js";
|
|
9
|
-
import { getLeaderChar, getRenderableTextColor, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
|
|
9
|
+
import { UNICODE_BIDI_BY_WRAPPER_CONTROL, getLeaderChar, getRenderableTextColor, sliceRunsForLine, splitCollapsibleLineEdgeSpaces, splitTextRunsByEastAsia, startsAfterSoftWrap } from "../../layout-painter/renderParagraph.js";
|
|
10
10
|
import { getHorizontalScaleFactor } from "../../utils/horizontalScale.js";
|
|
11
11
|
import { resolvePhysicalParagraphInlineLayout } from "../../utils/paragraphInlineLayout.js";
|
|
12
12
|
import { inlineImageBoundingBox } from "../../utils/rotationBoundingBox.js";
|
|
@@ -278,6 +278,23 @@ const modelRangeOf = (run, context) => run.pmStart === void 0 || run.pmEnd === v
|
|
|
278
278
|
story: context.story
|
|
279
279
|
};
|
|
280
280
|
/**
|
|
281
|
+
* The base direction one run's glyphs are laid out in.
|
|
282
|
+
*
|
|
283
|
+
* A bidirectional wrapper the author wrote around the run states it, and is
|
|
284
|
+
* nearer than the paragraph's own base direction: an override (`w:bdo`) lays
|
|
285
|
+
* every character out that way, and an embedding (`w:dir`) opens a level in
|
|
286
|
+
* that direction. A wrapper with no `w:val` states nothing, and the paragraph
|
|
287
|
+
* decides as before.
|
|
288
|
+
*/
|
|
289
|
+
const runGlyphDirection = (run, paragraphIsRtl) => run.bidiWrapper?.direction ?? (paragraphIsRtl ? "rtl" : "ltr");
|
|
290
|
+
/**
|
|
291
|
+
* The wrapper's control, for the backend that resolves the order itself.
|
|
292
|
+
*
|
|
293
|
+
* The direction alone does not separate the two: an override forces the
|
|
294
|
+
* order, an embedding leaves the algorithm to resolve within it.
|
|
295
|
+
*/
|
|
296
|
+
const runUnicodeBidi = (run) => run.bidiWrapper === void 0 ? void 0 : UNICODE_BIDI_BY_WRAPPER_CONTROL[run.bidiWrapper.control];
|
|
297
|
+
/**
|
|
281
298
|
* One `glyphRun` plus everything painted around it: the run's background rect
|
|
282
299
|
* first, then the glyphs, then the decorations whose geometry CSS would have
|
|
283
300
|
* derived from the font.
|
|
@@ -342,6 +359,7 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
|
|
|
342
359
|
thicknessPx: 1,
|
|
343
360
|
pattern: "solid"
|
|
344
361
|
} : void 0;
|
|
362
|
+
const unicodeBidi = runUnicodeBidi(run);
|
|
345
363
|
sink.glyphs.push({
|
|
346
364
|
kind: "glyphRun",
|
|
347
365
|
font,
|
|
@@ -350,7 +368,8 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
|
|
|
350
368
|
xPx: paintXPx,
|
|
351
369
|
baselineYPx: runBaselineYPx,
|
|
352
370
|
...glyphRunText(glyphs),
|
|
353
|
-
direction: isRtl
|
|
371
|
+
direction: runGlyphDirection(run, isRtl),
|
|
372
|
+
...unicodeBidi === void 0 ? {} : { unicodeBidi },
|
|
354
373
|
...stroke === void 0 ? {} : { stroke },
|
|
355
374
|
...pmRange === void 0 ? {} : { pmRange },
|
|
356
375
|
...collapsedEdge === void 0 ? {} : { collapsedEdge }
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { writeCommentAnchorIds } from "../../render-dom/commentAnchorAttributes.js";
|
|
1
2
|
import { bytesToDataUrl } from "../../utils/base64.js";
|
|
3
|
+
import { imageLuminanceFilter } from "../../utils/imageLuminance.js";
|
|
2
4
|
import { anchorTargetAttrs } from "../../utils/urlSecurity.js";
|
|
3
5
|
import { STROKE_DASH_FACTORS, walkRegions } from "../primitives.js";
|
|
4
6
|
import { panic } from "better-result";
|
|
@@ -310,6 +312,7 @@ const paintGlyphRun = (run, context) => {
|
|
|
310
312
|
span.style.fontStyle = face.italic ? "italic" : "normal";
|
|
311
313
|
span.style.color = cssColor(run.color);
|
|
312
314
|
span.style.direction = run.direction;
|
|
315
|
+
if (run.unicodeBidi !== void 0) span.style.unicodeBidi = run.unicodeBidi;
|
|
313
316
|
if (run.stroke !== void 0) span.style.webkitTextStroke = `${px(run.stroke.thicknessPx)} ${cssColor(run.stroke.color)}`;
|
|
314
317
|
span.style.fontKerning = run.kerning ? "normal" : "none";
|
|
315
318
|
if (run.smallCaps) span.style.fontVariant = "small-caps";
|
|
@@ -387,13 +390,18 @@ const paintRect = ({ rect, fill, stroke }, context) => {
|
|
|
387
390
|
default: panic(`renderDisplayListToDom: unhandled rect stroke painter ${JSON.stringify(painter)}`);
|
|
388
391
|
}
|
|
389
392
|
};
|
|
390
|
-
const paintImage = ({ image, rect, crop, opacity }, context) => {
|
|
393
|
+
const paintImage = ({ image, rect, crop, opacity, brightness, contrast }, context) => {
|
|
391
394
|
const source = resolveImage(image, context.images);
|
|
392
395
|
const clip = createAbsoluteDiv(context, rect);
|
|
393
396
|
clip.style.overflow = "hidden";
|
|
394
397
|
const element = context.doc.createElement("img");
|
|
395
398
|
element.style.position = "absolute";
|
|
396
399
|
element.style.opacity = String(opacity);
|
|
400
|
+
const filter = imageLuminanceFilter({
|
|
401
|
+
...brightness === void 0 ? {} : { brightness },
|
|
402
|
+
...contrast === void 0 ? {} : { contrast }
|
|
403
|
+
});
|
|
404
|
+
if (filter !== void 0) element.style.filter = filter;
|
|
397
405
|
element.style.left = "0px";
|
|
398
406
|
element.style.top = "0px";
|
|
399
407
|
element.style.width = px(rect.widthPx);
|
|
@@ -549,7 +557,7 @@ const applyRegionModel = (element, region) => {
|
|
|
549
557
|
element.dataset["pmEnd"] = String(model.pmRange.end);
|
|
550
558
|
}
|
|
551
559
|
if (model.blockId !== void 0) element.dataset["blockId"] = model.blockId;
|
|
552
|
-
if (model.commentIds !== void 0
|
|
560
|
+
if (model.commentIds !== void 0) writeCommentAnchorIds(element, model.commentIds);
|
|
553
561
|
if (model.rowIndex !== void 0) element.dataset["rowIndex"] = String(model.rowIndex);
|
|
554
562
|
if (model.columnIndex !== void 0) element.dataset["columnIndex"] = String(model.columnIndex);
|
|
555
563
|
const story = model.story ?? model.pmRange?.story;
|
|
@@ -215,6 +215,19 @@ type DisplayGlyphRun = {
|
|
|
215
215
|
readonly text: string;
|
|
216
216
|
readonly advancesPx: readonly number[];
|
|
217
217
|
readonly direction: "ltr" | "rtl";
|
|
218
|
+
/**
|
|
219
|
+
* How a backend that resolves bidirectional text itself must treat the run.
|
|
220
|
+
*
|
|
221
|
+
* `direction` alone is the base direction, and a backend that hands the text
|
|
222
|
+
* to such a resolver gets the ordinary algorithm: a Latin word inside an
|
|
223
|
+
* `rtl` run reads forwards. That is an embedding, and it is wrong for the
|
|
224
|
+
* run the author wrapped in an override (`w:bdo`), where every character is
|
|
225
|
+
* laid out in `direction` whatever its own script. Absent is the ordinary
|
|
226
|
+
* run, whose base direction the paragraph or the run itself decided; a
|
|
227
|
+
* backend that positions every glyph from `advancesPx` reorders nothing and
|
|
228
|
+
* ignores this.
|
|
229
|
+
*/
|
|
230
|
+
readonly unicodeBidi?: "embed" | "bidi-override";
|
|
218
231
|
/**
|
|
219
232
|
* Whether the glyphs kern.
|
|
220
233
|
*
|
|
@@ -299,6 +312,10 @@ type DisplayImagePrimitive = {
|
|
|
299
312
|
readonly b: number;
|
|
300
313
|
};
|
|
301
314
|
readonly opacity: number;
|
|
315
|
+
/** DrawingML picture brightness as a signed percentage. */
|
|
316
|
+
readonly brightness?: number;
|
|
317
|
+
/** DrawingML picture contrast as a signed percentage. */
|
|
318
|
+
readonly contrast?: number;
|
|
302
319
|
};
|
|
303
320
|
/** Clips its children to `rect`. Used for cropped images and cell overflow. */
|
|
304
321
|
type DisplayClipGroup = {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { XmlElement } from "./xmlParser.js";
|
|
2
|
+
import { PreservedAttribute } from "@stll/docx-core/model";
|
|
3
|
+
//#region src/docx/attributeRemainder.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The modelled set of an element whose serializer writes no attribute at all.
|
|
6
|
+
*
|
|
7
|
+
* `w:r`, `w:tr` and `w:sectPr` are rebuilt as bare start tags, so everything
|
|
8
|
+
* their source wrote is the remainder. Named rather than spelled `new Set()`
|
|
9
|
+
* at each call site, so the claim is visible and one place has to change when
|
|
10
|
+
* one of them gains a modelled attribute.
|
|
11
|
+
*/
|
|
12
|
+
declare const NO_MODELLED_ATTRIBUTES: ReadonlySet<string>;
|
|
13
|
+
type AttributeRemainderOptions = {
|
|
14
|
+
/** The element, as the source wrote it. */
|
|
15
|
+
element: XmlElement;
|
|
16
|
+
/**
|
|
17
|
+
* Local names this element's own parser reads.
|
|
18
|
+
*
|
|
19
|
+
* Local names rather than qualified ones, because folio's attribute readers
|
|
20
|
+
* fall back to a local-name match across prefixes: an attribute the parser
|
|
21
|
+
* would read under any binding has to be out of the remainder, or the save
|
|
22
|
+
* writes the value twice under two spellings.
|
|
23
|
+
*/
|
|
24
|
+
modelled: ReadonlySet<string>;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Every attribute on the element the model has no field for.
|
|
28
|
+
*
|
|
29
|
+
* @returns the remainder, or `undefined` when the parser read them all — an
|
|
30
|
+
* empty list is never written, so a fully modelled element stays identical
|
|
31
|
+
* in the model.
|
|
32
|
+
*/
|
|
33
|
+
declare const attributeRemainder: ({ element, modelled }: AttributeRemainderOptions) => PreservedAttribute[] | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* The element's attributes, modelled first and the remainder after them.
|
|
36
|
+
*
|
|
37
|
+
* @param modelled the fragments the serializer is about to emit, already
|
|
38
|
+
* spelled — they win a collision, because the model is the editable copy
|
|
39
|
+
* @returns the fragments to write, so an element with neither writes nothing
|
|
40
|
+
*/
|
|
41
|
+
declare const serializePreservedAttributes: (modelled: readonly string[], preserved: readonly PreservedAttribute[] | undefined) => string[];
|
|
42
|
+
//#endregion
|
|
43
|
+
export { NO_MODELLED_ATTRIBUTES, attributeRemainder, serializePreservedAttributes };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { OOXML_NAMESPACES } from "./serializer/partNamespaces.js";
|
|
2
|
+
import { getLocalName, resolveAttributeNamespaceUri } from "./xmlParser.js";
|
|
3
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
4
|
+
//#region src/docx/attributeRemainder.ts
|
|
5
|
+
/** Namespace URI to the prefix a rebuilt part binds for it. */
|
|
6
|
+
const CANONICAL_PREFIX = new Map(Object.entries(OOXML_NAMESPACES).map(([prefix, { uri }]) => [uri, prefix]));
|
|
7
|
+
/**
|
|
8
|
+
* The modelled set of an element whose serializer writes no attribute at all.
|
|
9
|
+
*
|
|
10
|
+
* `w:r`, `w:tr` and `w:sectPr` are rebuilt as bare start tags, so everything
|
|
11
|
+
* their source wrote is the remainder. Named rather than spelled `new Set()`
|
|
12
|
+
* at each call site, so the claim is visible and one place has to change when
|
|
13
|
+
* one of them gains a modelled attribute.
|
|
14
|
+
*/
|
|
15
|
+
const NO_MODELLED_ATTRIBUTES = /* @__PURE__ */ new Set();
|
|
16
|
+
/**
|
|
17
|
+
* Every attribute on the element the model has no field for.
|
|
18
|
+
*
|
|
19
|
+
* @returns the remainder, or `undefined` when the parser read them all — an
|
|
20
|
+
* empty list is never written, so a fully modelled element stays identical
|
|
21
|
+
* in the model.
|
|
22
|
+
*/
|
|
23
|
+
const attributeRemainder = ({ element, modelled }) => {
|
|
24
|
+
const attributes = element.attributes;
|
|
25
|
+
if (!attributes) return;
|
|
26
|
+
const remainder = [];
|
|
27
|
+
for (const [spelling, value] of Object.entries(attributes)) {
|
|
28
|
+
if (value === void 0 || spelling === "xmlns" || spelling.startsWith("xmlns:")) continue;
|
|
29
|
+
const name = getLocalName(spelling);
|
|
30
|
+
if (modelled.has(name)) continue;
|
|
31
|
+
const namespace = resolveAttributeNamespaceUri(element, spelling);
|
|
32
|
+
if (namespace !== void 0 && !CANONICAL_PREFIX.has(namespace)) continue;
|
|
33
|
+
remainder.push({
|
|
34
|
+
...namespace === void 0 ? {} : { namespace },
|
|
35
|
+
name,
|
|
36
|
+
value: String(value)
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return remainder.length === 0 ? void 0 : remainder;
|
|
40
|
+
};
|
|
41
|
+
/** The name a fragment such as `w14:paraId="1F2E"` writes. */
|
|
42
|
+
const spelledName = (fragment) => fragment.slice(0, fragment.indexOf("="));
|
|
43
|
+
/**
|
|
44
|
+
* The element's attributes, modelled first and the remainder after them.
|
|
45
|
+
*
|
|
46
|
+
* @param modelled the fragments the serializer is about to emit, already
|
|
47
|
+
* spelled — they win a collision, because the model is the editable copy
|
|
48
|
+
* @returns the fragments to write, so an element with neither writes nothing
|
|
49
|
+
*/
|
|
50
|
+
const serializePreservedAttributes = (modelled, preserved) => {
|
|
51
|
+
if (preserved === void 0 || preserved.length === 0) return [...modelled];
|
|
52
|
+
const written = new Set(modelled.map(spelledName));
|
|
53
|
+
const fragments = [...modelled];
|
|
54
|
+
for (const { namespace, name, value } of preserved) {
|
|
55
|
+
const prefix = namespace === void 0 ? void 0 : CANONICAL_PREFIX.get(namespace);
|
|
56
|
+
if (namespace !== void 0 && prefix === void 0) continue;
|
|
57
|
+
const spelling = prefix === void 0 ? name : `${prefix}:${name}`;
|
|
58
|
+
if (written.has(spelling)) continue;
|
|
59
|
+
written.add(spelling);
|
|
60
|
+
fragments.push(`${spelling}="${escapeXmlAttribute(value)}"`);
|
|
61
|
+
}
|
|
62
|
+
return fragments;
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
export { NO_MODELLED_ATTRIBUTES, attributeRemainder, serializePreservedAttributes };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { NumberingMap } from "./numberingParser.js";
|
|
3
|
-
import { StyleMap } from "./styleParser.js";
|
|
4
3
|
import { XmlElement } from "./xmlParser.js";
|
|
4
|
+
import { StyleMap } from "./styleParser.js";
|
|
5
5
|
//#region src/docx/blockContentParser.d.ts
|
|
6
6
|
type ParseBlockContentOptions = {
|
|
7
7
|
inHeaderFooter?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { attachPendingRangeMarkers, attachTrailingRangeMarkers, isBlockRangeMarker } from "./blockRangeMarkers.js";
|
|
2
1
|
import { parseBookmarkEnd, parseBookmarkStart } from "./bookmarkParser.js";
|
|
3
2
|
import { appendBookmarkMarkerToLastParagraphInBlocks, prependBookmarkMarkersToFirstParagraphInBlocks } from "./bookmarkPlacement.js";
|
|
4
3
|
import { convertBulletToUnicode } from "./bulletMarkers.js";
|
|
4
|
+
import { CAPTURE, OWNED_ELSEWHERE, dispatchChildren, withPreservedChildren } from "./containerChildren.js";
|
|
5
5
|
import { isNumberingReference } from "./numberingReference.js";
|
|
6
6
|
import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
|
|
7
7
|
import { parseParagraph } from "./paragraphParser.js";
|
|
@@ -9,7 +9,7 @@ import { enrichParagraphTextBoxes } from "./paragraphTextBoxEnrichment.js";
|
|
|
9
9
|
import { parseSdtProperties } from "./sdtProperties.js";
|
|
10
10
|
import { parseTable } from "./tableParser.js";
|
|
11
11
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
12
|
-
import { findChild,
|
|
12
|
+
import { findChild, getLocalName, mergeXmlnsDeclarations, selectAlternateContentBranch } from "./xmlParser.js";
|
|
13
13
|
//#region src/docx/blockContentParser.ts
|
|
14
14
|
const computeListMarker = (paragraph, { numbering, listCounters, abstractCounters, restartedNumIds, previousList }) => {
|
|
15
15
|
const listRendering = paragraph.listRendering;
|
|
@@ -104,72 +104,100 @@ const parseBlockContent = (parent, styles, theme, numbering, rels, media, option
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
const parseBlockContentWithState = (parent, styles, theme, numbering, rels, media, state) => {
|
|
107
|
-
const
|
|
108
|
-
const children = getChildElements(parent);
|
|
107
|
+
const modelled = [];
|
|
109
108
|
const pendingBookmarkMarkers = [];
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
prependPendingBookmarkMarkers(paragraph, pendingBookmarkMarkers);
|
|
116
|
-
enrichParagraphTextBoxes(paragraph, child, styles, theme, numbering, rels, media, parseTable);
|
|
117
|
-
computeListMarker(paragraph, {
|
|
118
|
-
numbering,
|
|
119
|
-
listCounters: state.listCounters,
|
|
120
|
-
abstractCounters: state.abstractCounters,
|
|
121
|
-
restartedNumIds: state.restartedNumIds,
|
|
122
|
-
previousList: state.previousList
|
|
123
|
-
});
|
|
124
|
-
attachPendingRangeMarkers(paragraph, pendingRangeMarkers);
|
|
125
|
-
content.push(paragraph);
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (localName === "tbl") {
|
|
129
|
-
const table = parseTable(child, styles, theme, numbering, rels, media, state.options);
|
|
130
|
-
if (!table) continue;
|
|
131
|
-
if (prependBookmarkMarkersToFirstParagraphInBlocks([table], pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
|
|
132
|
-
attachPendingRangeMarkers(table, pendingRangeMarkers);
|
|
133
|
-
content.push(table);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
if (localName === "sdt") {
|
|
137
|
-
const sdtPr = findChild(child, "w", "sdtPr");
|
|
138
|
-
const sdtEndPr = findChild(child, "w", "sdtEndPr");
|
|
139
|
-
const sdtContent = findChild(child, "w", "sdtContent");
|
|
140
|
-
const properties = parseSdtProperties(sdtPr, sdtEndPr);
|
|
141
|
-
const captured = captureSdtSiblingMarkers(child);
|
|
142
|
-
if (captured.before.length > 0) properties.rawSdtChildrenBeforeContent = captured.before;
|
|
143
|
-
if (captured.after.length > 0) properties.rawSdtChildrenAfterContent = captured.after;
|
|
144
|
-
const blockSdt = {
|
|
145
|
-
type: "blockSdt",
|
|
146
|
-
properties,
|
|
147
|
-
content: sdtContent ? parseBlockContentWithState(sdtContent, styles, theme, numbering, rels, media, withContainerXmlns(withContainerXmlns(state, child), sdtContent)) : []
|
|
148
|
-
};
|
|
149
|
-
if (prependBookmarkMarkersToFirstParagraphInBlocks(blockSdt.content, pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
|
|
150
|
-
attachPendingRangeMarkers(blockSdt, pendingRangeMarkers);
|
|
151
|
-
content.push(blockSdt);
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
if (localName === "AlternateContent") {
|
|
109
|
+
const content = withPreservedChildren(modelled, dispatchChildren({
|
|
110
|
+
element: parent,
|
|
111
|
+
container: "block-content",
|
|
112
|
+
modelledCount: () => modelled.length,
|
|
113
|
+
undeclared: { AlternateContent: (child) => {
|
|
155
114
|
const selectedBranch = selectAlternateContentBranch(child);
|
|
156
|
-
if (selectedBranch)
|
|
157
|
-
|
|
115
|
+
if (!selectedBranch) return;
|
|
116
|
+
modelled.push(...parseBlockContentWithState(selectedBranch, styles, theme, numbering, rels, media, withContainerXmlns(withContainerXmlns(state, child), selectedBranch)));
|
|
117
|
+
} },
|
|
118
|
+
handlers: {
|
|
119
|
+
p: (child) => {
|
|
120
|
+
const paragraph = parseParagraph(child, styles, theme, numbering, rels, media, state.options);
|
|
121
|
+
prependPendingBookmarkMarkers(paragraph, pendingBookmarkMarkers);
|
|
122
|
+
enrichParagraphTextBoxes(paragraph, child, styles, theme, numbering, rels, media, parseTable);
|
|
123
|
+
computeListMarker(paragraph, {
|
|
124
|
+
numbering,
|
|
125
|
+
listCounters: state.listCounters,
|
|
126
|
+
abstractCounters: state.abstractCounters,
|
|
127
|
+
restartedNumIds: state.restartedNumIds,
|
|
128
|
+
previousList: state.previousList
|
|
129
|
+
});
|
|
130
|
+
modelled.push(paragraph);
|
|
131
|
+
},
|
|
132
|
+
tbl: (child) => {
|
|
133
|
+
const table = parseTable(child, styles, theme, numbering, rels, media, state.options);
|
|
134
|
+
if (!table) return;
|
|
135
|
+
if (prependBookmarkMarkersToFirstParagraphInBlocks([table], pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
|
|
136
|
+
modelled.push(table);
|
|
137
|
+
},
|
|
138
|
+
sdt: (child) => {
|
|
139
|
+
const blockSdt = parseBlockSdt(child, styles, theme, numbering, rels, media, state);
|
|
140
|
+
if (prependBookmarkMarkersToFirstParagraphInBlocks(blockSdt.content, pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
|
|
141
|
+
modelled.push(blockSdt);
|
|
142
|
+
},
|
|
143
|
+
bookmarkStart: (child) => {
|
|
144
|
+
collectBookmarkMarker(child, "bookmarkStart", modelled, pendingBookmarkMarkers);
|
|
145
|
+
},
|
|
146
|
+
bookmarkEnd: (child) => {
|
|
147
|
+
collectBookmarkMarker(child, "bookmarkEnd", modelled, pendingBookmarkMarkers);
|
|
148
|
+
},
|
|
149
|
+
sectPr: OWNED_ELSEWHERE,
|
|
150
|
+
tcPr: OWNED_ELSEWHERE,
|
|
151
|
+
altChunk: CAPTURE,
|
|
152
|
+
commentRangeEnd: CAPTURE,
|
|
153
|
+
commentRangeStart: CAPTURE,
|
|
154
|
+
customXml: CAPTURE,
|
|
155
|
+
customXmlDelRangeEnd: CAPTURE,
|
|
156
|
+
customXmlDelRangeStart: CAPTURE,
|
|
157
|
+
customXmlInsRangeEnd: CAPTURE,
|
|
158
|
+
customXmlInsRangeStart: CAPTURE,
|
|
159
|
+
customXmlMoveFromRangeEnd: CAPTURE,
|
|
160
|
+
customXmlMoveFromRangeStart: CAPTURE,
|
|
161
|
+
customXmlMoveToRangeEnd: CAPTURE,
|
|
162
|
+
customXmlMoveToRangeStart: CAPTURE,
|
|
163
|
+
del: CAPTURE,
|
|
164
|
+
ins: CAPTURE,
|
|
165
|
+
moveFrom: CAPTURE,
|
|
166
|
+
moveFromRangeEnd: CAPTURE,
|
|
167
|
+
moveFromRangeStart: CAPTURE,
|
|
168
|
+
moveTo: CAPTURE,
|
|
169
|
+
moveToRangeEnd: CAPTURE,
|
|
170
|
+
moveToRangeStart: CAPTURE,
|
|
171
|
+
permEnd: CAPTURE,
|
|
172
|
+
permStart: CAPTURE,
|
|
173
|
+
proofErr: CAPTURE
|
|
158
174
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
if (isBlockRangeMarker(localName)) pendingRangeMarkers.push(captureVerbatimXml(child));
|
|
165
|
-
}
|
|
175
|
+
}), (xml) => ({
|
|
176
|
+
type: "preservedBlock",
|
|
177
|
+
xml
|
|
178
|
+
}));
|
|
166
179
|
if (pendingBookmarkMarkers.length > 0) content.push({
|
|
167
180
|
type: "paragraph",
|
|
168
181
|
content: [...pendingBookmarkMarkers]
|
|
169
182
|
});
|
|
170
|
-
attachTrailingRangeMarkers(content, pendingRangeMarkers);
|
|
171
183
|
return content;
|
|
172
184
|
};
|
|
185
|
+
const parseBlockSdt = (child, styles, theme, numbering, rels, media, state) => {
|
|
186
|
+
const sdtContent = findChild(child, "w", "sdtContent");
|
|
187
|
+
const properties = parseSdtProperties(findChild(child, "w", "sdtPr"), findChild(child, "w", "sdtEndPr"));
|
|
188
|
+
const captured = captureSdtSiblingMarkers(child);
|
|
189
|
+
if (captured.before.length > 0) properties.rawSdtChildrenBeforeContent = captured.before;
|
|
190
|
+
if (captured.after.length > 0) properties.rawSdtChildrenAfterContent = captured.after;
|
|
191
|
+
return {
|
|
192
|
+
type: "blockSdt",
|
|
193
|
+
properties,
|
|
194
|
+
content: sdtContent ? parseBlockContentWithState(sdtContent, styles, theme, numbering, rels, media, withContainerXmlns(withContainerXmlns(state, child), sdtContent)) : []
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
const collectBookmarkMarker = (child, localName, content, pending) => {
|
|
198
|
+
const marker = localName === "bookmarkStart" ? parseBookmarkStart(child) : parseBookmarkEnd(child);
|
|
199
|
+
if (!appendBookmarkMarkerToLastParagraphInBlocks(content, marker)) pending.push(marker);
|
|
200
|
+
};
|
|
173
201
|
/**
|
|
174
202
|
* Walk a `<w:sdt>` element's direct children and return the verbatim XML
|
|
175
203
|
* for every child that is NOT `<w:sdtPr>`, `<w:sdtEndPr>`, or
|
|
@@ -202,10 +230,6 @@ const captureSdtSiblingMarkers = (sdt) => {
|
|
|
202
230
|
after: afterParts.join("")
|
|
203
231
|
};
|
|
204
232
|
};
|
|
205
|
-
const parseBookmarkMarker = (child, localName) => {
|
|
206
|
-
if (localName === "bookmarkStart") return parseBookmarkStart(child);
|
|
207
|
-
return parseBookmarkEnd(child);
|
|
208
|
-
};
|
|
209
233
|
const prependPendingBookmarkMarkers = (paragraph, pendingBookmarkMarkers) => {
|
|
210
234
|
if (pendingBookmarkMarkers.length === 0) return;
|
|
211
235
|
paragraph.content.unshift(...pendingBookmarkMarkers);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
//#region src/docx/blockPlainText.d.ts
|
|
3
|
-
type PlainTextBlock = document_d_exports.Paragraph | document_d_exports.Table | document_d_exports.BlockSdt;
|
|
4
3
|
/** One entry per block, so callers can join or count lines as they need. */
|
|
5
|
-
declare const collectBlockTexts: (blocks: readonly
|
|
6
|
-
declare const blockPlainText: (blocks: readonly
|
|
4
|
+
declare const collectBlockTexts: (blocks: readonly document_d_exports.BlockContent[]) => string[];
|
|
5
|
+
declare const blockPlainText: (blocks: readonly document_d_exports.BlockContent[]) => string;
|
|
7
6
|
//#endregion
|
|
8
|
-
export {
|
|
7
|
+
export { blockPlainText, collectBlockTexts };
|
|
@@ -31,6 +31,7 @@ const collectBlockTexts = (blocks) => {
|
|
|
31
31
|
case "blockSdt":
|
|
32
32
|
texts.push(...collectBlockTexts(block.content));
|
|
33
33
|
break;
|
|
34
|
+
case "preservedBlock": break;
|
|
34
35
|
default: panic(`Unsupported block in plain-text extraction: ${JSON.stringify(block)}`);
|
|
35
36
|
}
|
|
36
37
|
return texts;
|
|
@@ -25,6 +25,7 @@ const appendBookmarkMarkerToLastParagraph = (block, marker) => {
|
|
|
25
25
|
return true;
|
|
26
26
|
}
|
|
27
27
|
if (block.type === "table") return appendBookmarkMarkerToLastParagraphInTable(block, marker);
|
|
28
|
+
if (block.type === "preservedBlock") return false;
|
|
28
29
|
return appendBookmarkMarkerToLastParagraphInBlocks(block.content, marker);
|
|
29
30
|
};
|
|
30
31
|
const appendBookmarkMarkerToLastParagraphInTable = (table, marker) => {
|
|
@@ -40,6 +41,7 @@ const prependBookmarkMarkersToFirstParagraph = (block, markers) => {
|
|
|
40
41
|
return true;
|
|
41
42
|
}
|
|
42
43
|
if (block.type === "table") return prependBookmarkMarkersToFirstParagraphInTable(block, markers);
|
|
44
|
+
if (block.type === "preservedBlock") return false;
|
|
43
45
|
return prependBookmarkMarkersToFirstParagraphInBlocks(block.content, markers);
|
|
44
46
|
};
|
|
45
47
|
const prependBookmarkMarkersToFirstParagraphInTable = (table, markers) => {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/commentAnchorIndex.d.ts
|
|
3
|
+
type CommentMarkerSlot = {
|
|
4
|
+
/** The inline-content array the marker sits in, so a caller can splice it. */
|
|
5
|
+
content: document_d_exports.ParagraphContent[];
|
|
6
|
+
index: number;
|
|
7
|
+
item: Extract<document_d_exports.ParagraphContent, {
|
|
8
|
+
type: "commentRangeStart";
|
|
9
|
+
} | {
|
|
10
|
+
type: "commentRangeEnd";
|
|
11
|
+
} | {
|
|
12
|
+
type: "commentReference";
|
|
13
|
+
}>;
|
|
14
|
+
};
|
|
15
|
+
declare const visitCommentMarkers: (blocks: readonly document_d_exports.BlockContent[], visit: (slot: CommentMarkerSlot) => void) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Comments that open a range anywhere in these blocks.
|
|
18
|
+
*
|
|
19
|
+
* A `commentReference` whose id is absent has no highlight of its own — the
|
|
20
|
+
* point-comment shape the model's `CommentReference` documents — and only that
|
|
21
|
+
* one needs its mark anchored onto neighbouring text. Anchoring one whose range
|
|
22
|
+
* exists stretches that range to wherever the reference sits, which is how a
|
|
23
|
+
* comment on one word came back covering the rest of the sentence. The range
|
|
24
|
+
* and the reference need not share a paragraph, so the question is asked of the
|
|
25
|
+
* whole story: a reference that trails the end of a range three paragraphs back
|
|
26
|
+
* is still not a point comment.
|
|
27
|
+
*/
|
|
28
|
+
declare const rangedCommentIds: (blocks: readonly document_d_exports.BlockContent[]) => ReadonlySet<number>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { CommentMarkerSlot, rangedCommentIds, visitCommentMarkers };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { visitInlineContentSlots } from "./paragraphTraversal.js";
|
|
2
|
+
//#region src/docx/commentAnchorIndex.ts
|
|
3
|
+
const visitCommentMarkers = (blocks, visit) => {
|
|
4
|
+
const visitParagraph = (paragraph) => {
|
|
5
|
+
visitInlineContentSlots(paragraph, ({ content, index, item }) => {
|
|
6
|
+
if (item.type === "commentRangeStart" || item.type === "commentRangeEnd" || item.type === "commentReference") visit({
|
|
7
|
+
content,
|
|
8
|
+
index,
|
|
9
|
+
item
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
const visitBlock = (block) => {
|
|
14
|
+
if (block.type === "paragraph") {
|
|
15
|
+
visitParagraph(block);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (block.type === "table") {
|
|
19
|
+
for (const row of block.rows) for (const cell of row.cells) visitBlocks(cell.content);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (block.type === "preservedBlock") return;
|
|
23
|
+
visitBlocks(block.content);
|
|
24
|
+
};
|
|
25
|
+
const visitBlocks = (nested) => {
|
|
26
|
+
for (const block of nested) visitBlock(block);
|
|
27
|
+
};
|
|
28
|
+
visitBlocks(blocks);
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Comments that open a range anywhere in these blocks.
|
|
32
|
+
*
|
|
33
|
+
* A `commentReference` whose id is absent has no highlight of its own — the
|
|
34
|
+
* point-comment shape the model's `CommentReference` documents — and only that
|
|
35
|
+
* one needs its mark anchored onto neighbouring text. Anchoring one whose range
|
|
36
|
+
* exists stretches that range to wherever the reference sits, which is how a
|
|
37
|
+
* comment on one word came back covering the rest of the sentence. The range
|
|
38
|
+
* and the reference need not share a paragraph, so the question is asked of the
|
|
39
|
+
* whole story: a reference that trails the end of a range three paragraphs back
|
|
40
|
+
* is still not a point comment.
|
|
41
|
+
*/
|
|
42
|
+
const rangedCommentIds = (blocks) => {
|
|
43
|
+
const ids = /* @__PURE__ */ new Set();
|
|
44
|
+
visitCommentMarkers(blocks, ({ item }) => {
|
|
45
|
+
if (item.type === "commentRangeStart") ids.add(item.id);
|
|
46
|
+
});
|
|
47
|
+
return ids;
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { rangedCommentIds, visitCommentMarkers };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
-
import { StyleMap } from "./styleParser.js";
|
|
3
2
|
import { ParseContext } from "./parseContext.js";
|
|
3
|
+
import { StyleMap } from "./styleParser.js";
|
|
4
4
|
//#region src/docx/commentParser.d.ts
|
|
5
5
|
type CommentExtendedInfo = {
|
|
6
6
|
parentParaId?: string;
|