@stll/folio-core 0.66.0 → 0.66.2
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 +13 -1
- package/dist/ai-edits/apply.js +533 -136
- package/dist/ai-edits/batch-claims.d.ts +26 -0
- package/dist/ai-edits/batch-claims.js +30 -5
- package/dist/ai-edits/headless.d.ts +6 -0
- package/dist/ai-edits/headless.js +25 -3
- package/dist/ai-edits/newListNumbering.d.ts +4 -1
- package/dist/ai-edits/newListNumbering.js +4 -2
- package/dist/ai-edits/types.d.ts +1 -1
- package/dist/document-operations.d.ts +13 -1
- package/dist/document-operations.js +11 -4
- package/dist/docx/listNumberingInstances.d.ts +6 -4
- package/dist/docx/listNumberingInstances.js +12 -11
- package/dist/docx/numberingIds.d.ts +10 -0
- package/dist/docx/numberingIds.js +5 -1
- package/dist/docx/paragraphParser.js +16 -3
- package/dist/docx/paragraphProperties.js +2 -1
- package/dist/docx/serializer/paragraphSerializer.js +86 -66
- package/dist/fonts/bundledFonts.d.ts +54 -0
- package/dist/fonts/bundledFonts.js +45 -0
- package/dist/fonts/fontsourceFaces.d.ts +9 -14
- package/dist/fonts/fontsourceFaces.js +10 -22
- package/dist/i18n/messages/ar.gen.js +1 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
- package/dist/i18n/messages/catalogs.gen.js +17 -0
- package/dist/i18n/messages/cs.gen.js +1 -0
- package/dist/i18n/messages/de.gen.js +1 -0
- package/dist/i18n/messages/en.gen.js +1 -0
- package/dist/i18n/messages/es.gen.js +1 -0
- package/dist/i18n/messages/et.gen.js +1 -0
- package/dist/i18n/messages/fr.gen.js +1 -0
- package/dist/i18n/messages/he.gen.js +1 -0
- package/dist/i18n/messages/hi.gen.js +1 -0
- package/dist/i18n/messages/hu.gen.js +1 -0
- package/dist/i18n/messages/lt.gen.js +1 -0
- package/dist/i18n/messages/lv.gen.js +1 -0
- package/dist/i18n/messages/messages.gen.d.ts +1 -0
- package/dist/i18n/messages/pl.gen.js +1 -0
- package/dist/i18n/messages/pt-BR.gen.js +1 -0
- package/dist/i18n/messages/sk.gen.js +1 -0
- package/dist/i18n/messages/tr.gen.js +1 -0
- package/dist/i18n/messages/zh-CN.gen.js +1 -0
- package/dist/internal/wholeStoryRevisionResolution.d.ts +1 -1
- package/dist/internal/wholeStoryRevisionResolution.js +24 -9
- package/dist/layout-bridge/convert/runMarkFormatting.js +1 -0
- package/dist/markdown/renderRuns.js +68 -12
- package/dist/prosemirror/commands/comments.js +2 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.js +15 -2
- package/dist/prosemirror/conversion/fromProseDoc.js +55 -18
- package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +23 -1
- package/dist/prosemirror/conversion/hyphenTextCarriers.js +46 -1
- package/dist/prosemirror/conversion/toProseDoc.js +15 -9
- package/dist/prosemirror/extensions/StarterKit.js +1 -1
- package/dist/prosemirror/extensions/features/pasteCleanup.js +6 -0
- package/dist/prosemirror/extensions/features/pastedHtmlLists.js +2 -1
- package/dist/prosemirror/extensions/markRegistry.d.ts +3 -1
- package/dist/prosemirror/extensions/markRegistry.js +3 -0
- package/dist/prosemirror/extensions/marks/HyphenElementExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/marks/HyphenElementExtension.js +54 -0
- package/dist/prosemirror/fieldRepresentation.js +2 -1
- package/dist/prosemirror/hyphenElementAttrs.d.ts +10 -0
- package/dist/prosemirror/hyphenElementAttrs.js +32 -0
- package/dist/prosemirror/keptRangeBoundaries.d.ts +2 -0
- package/dist/prosemirror/keptRangeBoundaries.js +1 -1
- package/dist/prosemirror/listNumbering.js +3 -2
- package/dist/prosemirror/paragraphIndentation.js +2 -1
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +1 -14
- package/dist/prosemirror/paragraphPropertyCarry.js +4 -28
- package/dist/prosemirror/plugins/suggestionMode.js +19 -6
- package/dist/prosemirror/replacedAnnotations.d.ts +1 -0
- package/dist/prosemirror/replacedAnnotations.js +1 -0
- package/dist/prosemirror/sectionCarrier.d.ts +8 -0
- package/dist/prosemirror/sectionCarrier.js +29 -1
- package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +10 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +12 -2
- package/dist/prosemirror/tableRunIn.d.ts +24 -9
- package/dist/prosemirror/tableRunIn.js +107 -21
- package/dist/prosemirror/textInput.js +3 -1
- package/dist/prosemirror/validation.js +6 -0
- package/dist/utils/createDocument.js +11 -8
- package/dist/utils/fontLoader.d.ts +1 -1
- package/dist/utils/fontLoader.js +3 -11
- package/dist/utils/formatToStyle.js +2 -2
- package/dist/utils/units.d.ts +5 -0
- package/dist/utils/units.js +6 -1
- package/package.json +6 -4
|
@@ -18,8 +18,6 @@ import { panic } from "better-result";
|
|
|
18
18
|
* revision, so accepting reads as the direct edit and rejecting restores the
|
|
19
19
|
* second's own.
|
|
20
20
|
*/
|
|
21
|
-
/** The exact formatting transfer, shared with pre-mutation capacity checks. */
|
|
22
|
-
const carriedParagraphProperties = ({ source, target, keep }) => Object.fromEntries([...Object.entries(paragraphPropertiesSnapshot(source)).filter(([key]) => !keep?.has(key)), ...Object.entries(paragraphPropertiesSnapshot(target)).filter(([key]) => keep?.has(key))]);
|
|
23
21
|
/**
|
|
24
22
|
* Give a paragraph another one's properties: the pPr a property change
|
|
25
23
|
* covers. Its identity, mark, mark run properties and section stay its own,
|
|
@@ -27,7 +25,7 @@ const carriedParagraphProperties = ({ source, target, keep }) => Object.fromEntr
|
|
|
27
25
|
* change now records what it had: a paragraph holds one, and a pending one
|
|
28
26
|
* already records it.
|
|
29
27
|
*/
|
|
30
|
-
const carryParagraphProperties = ({ tr, position, source, styleResolver, numbering, revision
|
|
28
|
+
const carryParagraphProperties = ({ tr, position, source, styleResolver, numbering, revision }) => {
|
|
31
29
|
const target = tr.doc.nodeAt(position);
|
|
32
30
|
if (!target || target.type !== source.type) return {
|
|
33
31
|
tr,
|
|
@@ -35,11 +33,7 @@ const carryParagraphProperties = ({ tr, position, source, styleResolver, numberi
|
|
|
35
33
|
tracked: false
|
|
36
34
|
};
|
|
37
35
|
const previousFormatting = paragraphPropertiesSnapshot(target);
|
|
38
|
-
const formatting =
|
|
39
|
-
source,
|
|
40
|
-
target,
|
|
41
|
-
...keep === void 0 ? {} : { keep }
|
|
42
|
-
});
|
|
36
|
+
const formatting = paragraphPropertiesSnapshot(source);
|
|
43
37
|
if (JSON.stringify(previousFormatting) === JSON.stringify(formatting)) return {
|
|
44
38
|
tr,
|
|
45
39
|
changed: false,
|
|
@@ -74,7 +68,7 @@ const carryParagraphProperties = ({ tr, position, source, styleResolver, numberi
|
|
|
74
68
|
}] : []];
|
|
75
69
|
tr.setNodeMarkup(position, void 0, {
|
|
76
70
|
...carried,
|
|
77
|
-
|
|
71
|
+
numPrFromStyle: expectParagraphAttrs(source).numPrFromStyle,
|
|
78
72
|
_sectionProperties: target.attrs["_sectionProperties"],
|
|
79
73
|
_propertyChanges: changes.length > 0 ? changes : null
|
|
80
74
|
});
|
|
@@ -91,12 +85,6 @@ const carryParagraphProperties = ({ tr, position, source, styleResolver, numberi
|
|
|
91
85
|
};
|
|
92
86
|
};
|
|
93
87
|
/**
|
|
94
|
-
* Whether the carried numbering is the paragraph's own or its style's: the
|
|
95
|
-
* record holds only stated numbering, and a style's numbering
|
|
96
|
-
* stays the style's rather than becoming the paragraph's own `w:numPr`.
|
|
97
|
-
*/
|
|
98
|
-
const carriedNumberingProvenance = (source, target, keep) => ({ numPrFromStyle: expectParagraphAttrs(keep?.has("numPr") ? target : source).numPrFromStyle });
|
|
99
|
-
/**
|
|
100
88
|
* The paragraph left once the break of the paragraph at `paragraphPos` goes:
|
|
101
89
|
* the next one, or, when its own break is pending deletion too, the first
|
|
102
90
|
* paragraph after it whose break stays. Null when no paragraph follows.
|
|
@@ -143,16 +131,4 @@ const recordReplacedParagraphProperties = ({ tr, position, replaced, revision })
|
|
|
143
131
|
}]);
|
|
144
132
|
return true;
|
|
145
133
|
};
|
|
146
|
-
|
|
147
|
-
* The properties a batch's own property change set on a paragraph: the ones
|
|
148
|
-
* whose value differs from what that change records as before.
|
|
149
|
-
*/
|
|
150
|
-
const propertiesSetInBatch = (node, batchRevisionIds) => {
|
|
151
|
-
const changes = expectParagraphAttrs(node)._propertyChanges;
|
|
152
|
-
const change = Array.isArray(changes) ? changes.find(({ info }) => batchRevisionIds.has(info.id)) : void 0;
|
|
153
|
-
if (change === void 0) return /* @__PURE__ */ new Set();
|
|
154
|
-
const before = change.previousFormatting ?? {};
|
|
155
|
-
const now = paragraphPropertiesSnapshot(node);
|
|
156
|
-
return new Set([.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(now)])].filter((key) => JSON.stringify(before[key]) !== JSON.stringify(now[key])));
|
|
157
|
-
};
|
|
158
|
-
export { carriedParagraphProperties, carryParagraphProperties, paragraphLeftAfter, propertiesSetInBatch, recordReplacedParagraphProperties };
|
|
134
|
+
export { carryParagraphProperties, paragraphLeftAfter, recordReplacedParagraphProperties };
|
|
@@ -531,6 +531,17 @@ function applySuggestionInsert(view, from, to, text, pluginState) {
|
|
|
531
531
|
if (selectsAll) {
|
|
532
532
|
from = Math.max(from, Selection.atStart(view.state.doc).from);
|
|
533
533
|
to = Math.min(to, Selection.atEnd(view.state.doc).to);
|
|
534
|
+
} else if (typesOverSelection && selection instanceof CellSelection) {
|
|
535
|
+
const cellDeletion = view.state.schema.marks["deletion"];
|
|
536
|
+
if (cellDeletion) {
|
|
537
|
+
const ranges = selection.ranges.toSorted((a, b) => b.$from.pos - a.$from.pos);
|
|
538
|
+
for (const range of ranges) markRangeAsDeleted(tr, view.state.doc, range.$from.pos, range.$to.pos, cellDeletion, pluginState, view.state);
|
|
539
|
+
}
|
|
540
|
+
const last = Selection.findFrom(view.state.doc.resolve(to), -1, true);
|
|
541
|
+
if (last && last.to >= from) {
|
|
542
|
+
from = last.to;
|
|
543
|
+
to = last.to;
|
|
544
|
+
}
|
|
534
545
|
}
|
|
535
546
|
const replacedFormatting = selectsAll ? (view.state.doc.resolve(from).nodeAfter?.marks ?? []).filter(({ type }) => RUN_FORMATTING_MARK_NAMES.has(type.name)) : null;
|
|
536
547
|
const insertAttrs = findAdjacentRevision(view.state.doc, from, "insertion", pluginState.author) || makeMarkAttrs(pluginState);
|
|
@@ -545,16 +556,18 @@ function applySuggestionInsert(view, from, to, text, pluginState) {
|
|
|
545
556
|
to
|
|
546
557
|
});
|
|
547
558
|
if (formattingMarks !== void 0) tr.setStoredMarks(formattingMarks);
|
|
559
|
+
const typedFrom = tr.doc.resolve(insertAt).parent.inlineContent ? insertAt : insertAt + 1;
|
|
560
|
+
const typedTo = typedFrom + text.length;
|
|
548
561
|
tr.insertText(text, insertAt, insertAt);
|
|
549
562
|
const deletionType = view.state.schema.marks["deletion"];
|
|
550
|
-
if (deletionType) tr.removeMark(
|
|
551
|
-
tr.addMark(
|
|
563
|
+
if (deletionType) tr.removeMark(typedFrom, typedTo, deletionType);
|
|
564
|
+
tr.addMark(typedFrom, typedTo, insertionType.create(insertAttrs));
|
|
552
565
|
if (replacedFormatting) {
|
|
553
|
-
for (const mark of tr.doc.resolve(
|
|
554
|
-
for (const mark of replacedFormatting) tr.addMark(
|
|
566
|
+
for (const mark of tr.doc.resolve(typedFrom).nodeAfter?.marks ?? []) if (RUN_FORMATTING_MARK_NAMES.has(mark.type.name)) tr.removeMark(typedFrom, typedTo, mark.type);
|
|
567
|
+
for (const mark of replacedFormatting) tr.addMark(typedFrom, typedTo, mark);
|
|
555
568
|
}
|
|
556
|
-
separateSplitStretch(tr,
|
|
557
|
-
if (typesOverSelection) tr.setSelection(TextSelection.create(tr.doc,
|
|
569
|
+
separateSplitStretch(tr, typedFrom, typedTo, insertAttrs.revisionId);
|
|
570
|
+
if (typesOverSelection) tr.setSelection(TextSelection.create(tr.doc, typedTo));
|
|
558
571
|
view.dispatch(tr.scrollIntoView());
|
|
559
572
|
return true;
|
|
560
573
|
}
|
|
@@ -12,6 +12,7 @@ export declare const NON_INCLUSIVE_MARK_DISPOSITION: {
|
|
|
12
12
|
readonly hyperlink: "carry";
|
|
13
13
|
readonly footnoteRef: "followsTheText";
|
|
14
14
|
readonly runIdentity: "followsTheText";
|
|
15
|
+
readonly hyphenElement: "followsTheText";
|
|
15
16
|
readonly insertion: "followsTheText";
|
|
16
17
|
readonly deletion: "followsTheText";
|
|
17
18
|
readonly runPropertyChange: "followsTheText";
|
|
@@ -84,6 +84,7 @@ const NON_INCLUSIVE_MARK_DISPOSITION = {
|
|
|
84
84
|
hyperlink: "carry",
|
|
85
85
|
footnoteRef: "followsTheText",
|
|
86
86
|
runIdentity: "followsTheText",
|
|
87
|
+
hyphenElement: "followsTheText",
|
|
87
88
|
insertion: "followsTheText",
|
|
88
89
|
deletion: "followsTheText",
|
|
89
90
|
runPropertyChange: "followsTheText",
|
|
@@ -14,6 +14,14 @@ export type SectionBreakType = (typeof SECTION_BREAK_TYPES)[number];
|
|
|
14
14
|
export declare const parseSectionBreakType: (value: unknown) => SectionBreakType | null;
|
|
15
15
|
/** The section record a paragraph holds, or `null` when it ends no section. */
|
|
16
16
|
export declare const sectionPropertiesOf: (paragraph: Node) => document_d_exports.SectionProperties | null;
|
|
17
|
+
/**
|
|
18
|
+
* The positions of paragraphs that hold only a copy of a section record: every
|
|
19
|
+
* carrier of a record but its last. The from-leg writes the record on the last
|
|
20
|
+
* carrier alone (`keepTheSectionBreakOnTheLastParagraphThatCarriesIt`), so a
|
|
21
|
+
* resolution that lets the last carrier's mark go must not leave a copy to
|
|
22
|
+
* inherit the section a saved package no longer has.
|
|
23
|
+
*/
|
|
24
|
+
export declare const sectionRecordCopyPositions: (doc: Node) => number[];
|
|
17
25
|
/**
|
|
18
26
|
* The break type a section record states, or `null` when it states none.
|
|
19
27
|
*
|
|
@@ -19,6 +19,34 @@ const parseSectionBreakType = (value) => isSectionBreakType(value) ? value : nul
|
|
|
19
19
|
/** The section record a paragraph holds, or `null` when it ends no section. */
|
|
20
20
|
const sectionPropertiesOf = (paragraph) => paragraph.attrs["_sectionProperties"] ?? null;
|
|
21
21
|
/**
|
|
22
|
+
* The positions of paragraphs that hold only a copy of a section record: every
|
|
23
|
+
* carrier of a record but its last. The from-leg writes the record on the last
|
|
24
|
+
* carrier alone (`keepTheSectionBreakOnTheLastParagraphThatCarriesIt`), so a
|
|
25
|
+
* resolution that lets the last carrier's mark go must not leave a copy to
|
|
26
|
+
* inherit the section a saved package no longer has.
|
|
27
|
+
*/
|
|
28
|
+
const sectionRecordCopyPositions = (doc) => {
|
|
29
|
+
const lastCarrier = /* @__PURE__ */ new Map();
|
|
30
|
+
const copies = [];
|
|
31
|
+
const visit = (parent, parentStart) => {
|
|
32
|
+
parent.forEach((node, offset) => {
|
|
33
|
+
const position = parentStart + offset;
|
|
34
|
+
if (!node.isTextblock) {
|
|
35
|
+
if (!node.isLeaf) visit(node, position + 1);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (node.type.name !== "paragraph") return;
|
|
39
|
+
const record = sectionPropertiesOf(node);
|
|
40
|
+
if (record === null) return;
|
|
41
|
+
const earlier = lastCarrier.get(record);
|
|
42
|
+
if (earlier !== void 0) copies.push(earlier);
|
|
43
|
+
lastCarrier.set(record, position);
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
visit(doc, 0);
|
|
47
|
+
return copies;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
22
50
|
* The break type a section record states, or `null` when it states none.
|
|
23
51
|
*
|
|
24
52
|
* The single derivation every reader goes through. Every producer of a record
|
|
@@ -36,4 +64,4 @@ const sectionBreakTypeOf = (properties) => properties?.sectionStart ?? null;
|
|
|
36
64
|
* package does with a `w:sectPr` that omits them.
|
|
37
65
|
*/
|
|
38
66
|
const mintSectionProperties = (breakType) => ({ sectionStart: breakType });
|
|
39
|
-
export { SECTION_BREAK_TYPES, mintSectionProperties, parseSectionBreakType, sectionBreakTypeOf, sectionPropertiesOf };
|
|
67
|
+
export { SECTION_BREAK_TYPES, mintSectionProperties, parseSectionBreakType, sectionBreakTypeOf, sectionPropertiesOf, sectionRecordCopyPositions };
|
|
@@ -13,6 +13,16 @@ export type ParagraphCascadeResolver = Pick<StyleEngine, "getStyle" | "getDocDef
|
|
|
13
13
|
*/
|
|
14
14
|
type ParagraphDefaultFormattingResolver = Pick<StyleEngine, "getStyle" | "getDocDefaults" | "getDefaultParagraphStyle" | "getDefaultCharacterStyle" | "getRunStyleOwnProperties">;
|
|
15
15
|
export declare function resolveRunFormattingWithoutDefaults(formatting: document_d_exports.TextFormatting | undefined, styleResolver: ParagraphDefaultFormattingResolver | null): document_d_exports.TextFormatting | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* What a paragraph's mark lends its body runs: nothing when the paragraph has a
|
|
18
|
+
* style, and never the font or the mark-only decorations. One rule for a
|
|
19
|
+
* document read and for a paragraph whose properties a review restores.
|
|
20
|
+
*/
|
|
21
|
+
export declare const inheritableParagraphMarkFormatting: ({ runProperties, styleId, styleResolver }: {
|
|
22
|
+
runProperties: document_d_exports.TextFormatting | undefined;
|
|
23
|
+
styleId: string | undefined;
|
|
24
|
+
styleResolver: Parameters<typeof resolveRunFormattingWithoutDefaults>[1];
|
|
25
|
+
}) => document_d_exports.TextFormatting | undefined;
|
|
16
26
|
/** @internal Recompute a paragraph's inherited run defaults from authored package state. */
|
|
17
27
|
export declare function resolveParagraphDefaultTextFormatting(styleId: string | undefined, formatting: document_d_exports.Paragraph["formatting"] | undefined, styleResolver: ParagraphDefaultFormattingResolver, options?: {
|
|
18
28
|
includeParagraphMarkRunProperties?: boolean;
|
|
@@ -5,7 +5,7 @@ import { paragraphNumberingAttr } from "../numberingAttr.js";
|
|
|
5
5
|
import { directionFromBidi } from "../paragraphDirection.js";
|
|
6
6
|
import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenance.js";
|
|
7
7
|
import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
|
|
8
|
-
import { stripParagraphMarkOnlyFormatting } from "../runStyleFormatting.js";
|
|
8
|
+
import { stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting } from "../runStyleFormatting.js";
|
|
9
9
|
import { cascadeStyleTextFormatting } from "./styleToggleCascade.js";
|
|
10
10
|
// src/prosemirror/styles/paragraphStyleCascade.ts
|
|
11
11
|
/**
|
|
@@ -30,6 +30,16 @@ function resolveRunFormattingWithoutDefaults(formatting, styleResolver) {
|
|
|
30
30
|
type: "direct"
|
|
31
31
|
}]).formatting;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* What a paragraph's mark lends its body runs: nothing when the paragraph has a
|
|
35
|
+
* style, and never the font or the mark-only decorations. One rule for a
|
|
36
|
+
* document read and for a paragraph whose properties a review restores.
|
|
37
|
+
*/
|
|
38
|
+
const inheritableParagraphMarkFormatting = ({ runProperties, styleId, styleResolver }) => {
|
|
39
|
+
if (styleId !== void 0) return void 0;
|
|
40
|
+
const formatting = resolveRunFormattingWithoutDefaults(runProperties, styleResolver);
|
|
41
|
+
return formatting ? stripParagraphMarkFormattingForBodyRuns(formatting) : void 0;
|
|
42
|
+
};
|
|
33
43
|
/** @internal Recompute a paragraph's inherited run defaults from authored package state. */
|
|
34
44
|
function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, options = {}) {
|
|
35
45
|
const style = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
@@ -155,4 +165,4 @@ function tableCellParagraphOverlay(styleResolver, tableStyleId, regions) {
|
|
|
155
165
|
}
|
|
156
166
|
return overlay;
|
|
157
167
|
}
|
|
158
|
-
export { extractTableParagraphOverlay, paragraphStyleCascadeAttrs, resolveParagraphDefaultTextFormatting, resolveRunFormattingWithoutDefaults, tableCellParagraphOverlay };
|
|
168
|
+
export { extractTableParagraphOverlay, inheritableParagraphMarkFormatting, paragraphStyleCascadeAttrs, resolveParagraphDefaultTextFormatting, resolveRunFormattingWithoutDefaults, tableCellParagraphOverlay };
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { RunStyleResolver } from "./runStyleFormatting.js";
|
|
2
2
|
import { ParagraphPropertySourceTransfer } from "../docx/paragraphPropertySource.js";
|
|
3
|
-
import {
|
|
3
|
+
import { Node } from "prosemirror-model";
|
|
4
4
|
import { StepMap, Transform } from "prosemirror-transform";
|
|
5
|
+
type ResolutionMode = "accept" | "reject";
|
|
5
6
|
/**
|
|
6
7
|
* Whether the cell a paragraph's words would run into is itself pending: its
|
|
7
8
|
* row or the cell (through nested tables' first cells) is inserted, deleted
|
|
8
|
-
* or merged, so resolving may not keep it.
|
|
9
|
-
*
|
|
9
|
+
* or merged, so resolving may not keep it. A deletion is not pending for a
|
|
10
|
+
* rejection of every change. Pending rows or cells elsewhere in the table leave
|
|
11
|
+
* that cell where it is.
|
|
10
12
|
*/
|
|
11
|
-
export declare const runInCellPending: (table: Node) => boolean;
|
|
13
|
+
export declare const runInCellPending: (table: Node, everyChange?: ResolutionMode) => boolean;
|
|
12
14
|
type RunParagraphIntoTableOptions = {
|
|
13
15
|
tr: Transform;
|
|
14
16
|
paragraphPos: number;
|
|
15
17
|
styleResolver: RunStyleResolver | null;
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Set when every change of the story resolves this way, not only some: what
|
|
20
|
+
* it removes does not count as words left, and a rejection takes a deleted
|
|
21
|
+
* row as staying.
|
|
22
|
+
*/
|
|
23
|
+
everyChange?: ResolutionMode | undefined;
|
|
18
24
|
};
|
|
19
25
|
/**
|
|
20
26
|
* Run the paragraph at `paragraphPos` on into the table right after it.
|
|
@@ -22,7 +28,7 @@ type RunParagraphIntoTableOptions = {
|
|
|
22
28
|
* paragraph-property source it hands over, or null when it did not run in and
|
|
23
29
|
* the caller keeps its own handling.
|
|
24
30
|
*/
|
|
25
|
-
export declare const runParagraphIntoTable: ({ tr, paragraphPos, styleResolver,
|
|
31
|
+
export declare const runParagraphIntoTable: ({ tr, paragraphPos, styleResolver, everyChange }: RunParagraphIntoTableOptions) => {
|
|
26
32
|
position: number;
|
|
27
33
|
map: StepMap;
|
|
28
34
|
transfer: ParagraphPropertySourceTransfer;
|
|
@@ -34,8 +40,17 @@ export declare const runParagraphIntoTable: ({ tr, paragraphPos, styleResolver,
|
|
|
34
40
|
type RunsIntoFollowingTableOptions = {
|
|
35
41
|
parent: Node;
|
|
36
42
|
index: number;
|
|
37
|
-
mode:
|
|
43
|
+
mode: ResolutionMode;
|
|
38
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* Whether what stands right after a paragraph whose mark goes is itself removed
|
|
47
|
+
* by this resolution, so the paragraph runs on into what stands after that, as
|
|
48
|
+
* it would had the removed block never been there: a table it removes, or, when
|
|
49
|
+
* rejecting, an inserted paragraph it empties with a table after it. (Accepted,
|
|
50
|
+
* a deleted paragraph did stand there, and the join ended at it. Paragraphs join
|
|
51
|
+
* among themselves without help.)
|
|
52
|
+
*/
|
|
53
|
+
export declare const paragraphBeforeRemovedBlock: ({ parent, index, mode }: RunsIntoFollowingTableOptions) => boolean;
|
|
39
54
|
export declare const runsIntoFollowingTable: ({ parent, index, mode }: RunsIntoFollowingTableOptions) => boolean;
|
|
40
55
|
/**
|
|
41
56
|
* Before every change in a story is resolved: run each paragraph whose mark
|
|
@@ -43,7 +58,7 @@ export declare const runsIntoFollowingTable: ({ parent, index, mode }: RunsIntoF
|
|
|
43
58
|
* paragraph that took words (its position after the step count given) and
|
|
44
59
|
* the paragraph-property sources handed over.
|
|
45
60
|
*/
|
|
46
|
-
export declare const runParagraphsIntoTables: (tr: Transform, mode:
|
|
61
|
+
export declare const runParagraphsIntoTables: (tr: Transform, mode: ResolutionMode, styleResolver: RunStyleResolver | null) => {
|
|
47
62
|
targets: {
|
|
48
63
|
position: number;
|
|
49
64
|
step: number;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { getProseParagraphPropertySourceToken, recreateProseNodeWithParagraphPropertySource } from "../docx/paragraphPropertySource.js";
|
|
2
2
|
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
3
|
-
import { paragraphRemainsOf } from "./keptRangeBoundaries.js";
|
|
3
|
+
import { REVISION_MARK_NAMES, paragraphRemainsOf, revisionLayerRemovesContent } from "./keptRangeBoundaries.js";
|
|
4
4
|
import { rebaseParagraphRuns } from "./rebaseParagraphRunFormatting.js";
|
|
5
5
|
import { paragraphRunStyleContext } from "./runStyleFormatting.js";
|
|
6
|
+
import { trackedRevisionPathOf } from "./trackedRevisionPath.js";
|
|
6
7
|
import { paragraphContentOf } from "./zeroWidthAnchors.js";
|
|
7
8
|
import { Fragment, Slice } from "prosemirror-model";
|
|
8
|
-
import { ReplaceAroundStep, StepMap } from "prosemirror-transform";
|
|
9
|
+
import { ReplaceAroundStep, ReplaceStep, StepMap } from "prosemirror-transform";
|
|
9
10
|
import { paragraphMarkOutcome } from "@stll/docx-core/ops";
|
|
10
11
|
// src/prosemirror/tableRunIn.ts
|
|
11
12
|
/**
|
|
@@ -19,35 +20,53 @@ import { paragraphMarkOutcome } from "@stll/docx-core/ops";
|
|
|
19
20
|
*
|
|
20
21
|
* A paragraph with nothing left to carry is simply removed by the resolvers;
|
|
21
22
|
* one that ends a section keeps its place, as does one before a table whose
|
|
22
|
-
*
|
|
23
|
+
* first row or cell may not stay. Rejecting every change gives the document
|
|
24
|
+
* before back, so a deleted row stays for it. A table that resolving every
|
|
25
|
+
* change removes never stood in the way: the paragraph runs on into what follows
|
|
26
|
+
* that table.
|
|
23
27
|
*/
|
|
24
28
|
/**
|
|
25
29
|
* Whether the cell a paragraph's words would run into is itself pending: its
|
|
26
30
|
* row or the cell (through nested tables' first cells) is inserted, deleted
|
|
27
|
-
* or merged, so resolving may not keep it.
|
|
28
|
-
*
|
|
31
|
+
* or merged, so resolving may not keep it. A deletion is not pending for a
|
|
32
|
+
* rejection of every change. Pending rows or cells elsewhere in the table leave
|
|
33
|
+
* that cell where it is.
|
|
29
34
|
*/
|
|
30
|
-
const runInCellPending = (table) => {
|
|
35
|
+
const runInCellPending = (table, everyChange) => {
|
|
36
|
+
const deletionStays = everyChange === "reject";
|
|
31
37
|
let node = table;
|
|
32
38
|
while (node?.type.spec["tableRole"] === "table") {
|
|
33
39
|
const row = node.firstChild;
|
|
34
40
|
if (!row) return false;
|
|
35
|
-
if (row.attrs["trIns"] != null
|
|
41
|
+
if (row.attrs["trIns"] != null) return true;
|
|
42
|
+
if (row.attrs["trDel"] != null && !deletionStays) return true;
|
|
36
43
|
const cell = row.firstChild;
|
|
37
44
|
if (!cell) return false;
|
|
38
|
-
|
|
45
|
+
const marker = cell.attrs["cellMarker"];
|
|
46
|
+
if (marker != null && !(deletionStays && marker.kind === "del")) return true;
|
|
39
47
|
node = cell.firstChild;
|
|
40
48
|
}
|
|
41
49
|
return false;
|
|
42
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* Whether resolving every change takes this row out with what it records. The
|
|
53
|
+
* table it stands in goes when all its rows do.
|
|
54
|
+
*/
|
|
55
|
+
const rowGoes = (row, mode) => row.attrs[mode === "accept" ? "trDel" : "trIns"] != null;
|
|
56
|
+
/** Whether resolving every change in `mode` removes the whole table. */
|
|
57
|
+
const tableGoes = (table, mode) => {
|
|
58
|
+
if (table.type.spec["tableRole"] !== "table" || table.childCount === 0) return false;
|
|
59
|
+
for (let index = 0; index < table.childCount; index++) if (!rowGoes(table.child(index), mode)) return false;
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
43
62
|
/** The first paragraph of a table's first cell, descending into nested tables. */
|
|
44
|
-
const runInTarget = (doc, tablePos) => {
|
|
63
|
+
const runInTarget = (doc, tablePos, everyChange) => {
|
|
45
64
|
let node = doc.nodeAt(tablePos);
|
|
46
65
|
let pos = tablePos;
|
|
47
66
|
const table = node;
|
|
48
67
|
const firstRow = table?.firstChild;
|
|
49
68
|
if (!table || table.type.spec["tableRole"] !== "table" || !firstRow) return null;
|
|
50
|
-
if (runInCellPending(table)) return null;
|
|
69
|
+
if (runInCellPending(table, everyChange)) return null;
|
|
51
70
|
while (node && node.type.name !== "paragraph") {
|
|
52
71
|
const child = node.firstChild;
|
|
53
72
|
if (!child || child.isInline) return null;
|
|
@@ -59,22 +78,22 @@ const runInTarget = (doc, tablePos) => {
|
|
|
59
78
|
node
|
|
60
79
|
} : null;
|
|
61
80
|
};
|
|
62
|
-
const paragraphAfterContentRemoval = (paragraph,
|
|
81
|
+
const paragraphAfterContentRemoval = (paragraph, everyChange) => everyChange ? paragraph.copy(Fragment.fromArray(paragraph.children.filter((child) => !child.marks.some((mark) => REVISION_MARK_NAMES.has(mark.type.name) && trackedRevisionPathOf(mark).some((layer) => revisionLayerRemovesContent(layer, everyChange)))))) : paragraph;
|
|
63
82
|
/**
|
|
64
83
|
* Run the paragraph at `paragraphPos` on into the table right after it.
|
|
65
84
|
* Returns where the paragraph that took its words now starts and the
|
|
66
85
|
* paragraph-property source it hands over, or null when it did not run in and
|
|
67
86
|
* the caller keeps its own handling.
|
|
68
87
|
*/
|
|
69
|
-
const runParagraphIntoTable = ({ tr, paragraphPos, styleResolver,
|
|
88
|
+
const runParagraphIntoTable = ({ tr, paragraphPos, styleResolver, everyChange }) => {
|
|
70
89
|
const paragraph = tr.doc.nodeAt(paragraphPos);
|
|
71
90
|
if (paragraph?.type.name !== "paragraph") return null;
|
|
72
91
|
if (expectParagraphAttrs(paragraph)._sectionProperties !== void 0) return null;
|
|
73
|
-
const left = paragraphAfterContentRemoval(paragraph,
|
|
92
|
+
const left = paragraphAfterContentRemoval(paragraph, everyChange);
|
|
74
93
|
const remains = paragraphRemainsOf(left);
|
|
75
94
|
if (!paragraphContentOf(left) && (remains.blocks.length > 0 || remains.comments.length === 0)) return null;
|
|
76
95
|
const tablePos = paragraphPos + paragraph.nodeSize;
|
|
77
|
-
const target = runInTarget(tr.doc, tablePos);
|
|
96
|
+
const target = runInTarget(tr.doc, tablePos, everyChange);
|
|
78
97
|
if (!target) return null;
|
|
79
98
|
const $target = tr.doc.resolve(target.pos + 1);
|
|
80
99
|
const containerDepth = tr.doc.resolve(paragraphPos).depth;
|
|
@@ -118,6 +137,36 @@ const markGoes = (paragraph, mode) => {
|
|
|
118
137
|
if (!mark) return false;
|
|
119
138
|
return (mark.kind === "ins" || mark.kind === "moveTo") !== (mode === "accept");
|
|
120
139
|
};
|
|
140
|
+
/** Whether resolving every change in `mode` leaves nothing of this paragraph. */
|
|
141
|
+
const paragraphGoes = (paragraph, mode) => {
|
|
142
|
+
if (paragraph.type.name !== "paragraph" || !markGoes(paragraph, mode) || expectParagraphAttrs(paragraph)._sectionProperties != null) return false;
|
|
143
|
+
const left = paragraphAfterContentRemoval(paragraph, mode);
|
|
144
|
+
if (paragraphContentOf(left)) return false;
|
|
145
|
+
const remains = paragraphRemainsOf(left);
|
|
146
|
+
return remains.blocks.length === 0 && remains.comments.length === 0 && remains.inline.length === 0;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Whether what stands right after a paragraph whose mark goes is itself removed
|
|
150
|
+
* by this resolution, so the paragraph runs on into what stands after that, as
|
|
151
|
+
* it would had the removed block never been there: a table it removes, or, when
|
|
152
|
+
* rejecting, an inserted paragraph it empties with a table after it. (Accepted,
|
|
153
|
+
* a deleted paragraph did stand there, and the join ended at it. Paragraphs join
|
|
154
|
+
* among themselves without help.)
|
|
155
|
+
*/
|
|
156
|
+
const paragraphBeforeRemovedBlock = ({ parent, index, mode }) => {
|
|
157
|
+
const paragraph = parent.child(index);
|
|
158
|
+
const next = parent.maybeChild(index + 1);
|
|
159
|
+
if (paragraph.type.name !== "paragraph" || !next || !markGoes(paragraph, mode)) return false;
|
|
160
|
+
if (tableGoes(next, mode)) return true;
|
|
161
|
+
if (mode !== "reject" || paragraphGoes(paragraph, mode)) return false;
|
|
162
|
+
let following = index + 1;
|
|
163
|
+
while (following < parent.childCount) {
|
|
164
|
+
const block = parent.child(following);
|
|
165
|
+
if (!paragraphGoes(block, mode)) break;
|
|
166
|
+
following += 1;
|
|
167
|
+
}
|
|
168
|
+
return following > index + 1 && parent.maybeChild(following)?.type.spec["tableRole"] === "table";
|
|
169
|
+
};
|
|
121
170
|
const runsIntoFollowingTable = ({ parent, index, mode }) => {
|
|
122
171
|
const paragraph = parent.child(index);
|
|
123
172
|
const next = parent.maybeChild(index + 1);
|
|
@@ -125,7 +174,6 @@ const runsIntoFollowingTable = ({ parent, index, mode }) => {
|
|
|
125
174
|
const remains = paragraphRemainsOf(paragraph);
|
|
126
175
|
const holdsContent = paragraphContentOf(paragraph);
|
|
127
176
|
const needsCommentHost = !holdsContent && remains.blocks.length === 0 && remains.comments.length > 0;
|
|
128
|
-
const removedMark = paragraph.type.schema.marks[mode === "accept" ? "deletion" : "insertion"];
|
|
129
177
|
let hasPrecedingCommentHost = false;
|
|
130
178
|
for (let previousIndex = needsCommentHost ? index - 1 : -1; previousIndex >= 0; previousIndex -= 1) {
|
|
131
179
|
const previous = parent.child(previousIndex);
|
|
@@ -134,7 +182,7 @@ const runsIntoFollowingTable = ({ parent, index, mode }) => {
|
|
|
134
182
|
hasPrecedingCommentHost = true;
|
|
135
183
|
break;
|
|
136
184
|
}
|
|
137
|
-
const retained = paragraphAfterContentRemoval(previous,
|
|
185
|
+
const retained = paragraphAfterContentRemoval(previous, mode);
|
|
138
186
|
if (paragraphContentOf(retained)) break;
|
|
139
187
|
if (paragraphRemainsOf(retained).blocks.length > 0) {
|
|
140
188
|
hasPrecedingCommentHost = true;
|
|
@@ -146,22 +194,60 @@ const runsIntoFollowingTable = ({ parent, index, mode }) => {
|
|
|
146
194
|
holdsContent,
|
|
147
195
|
markWasAdded: expectParagraphAttrs(paragraph).pPrMark?.kind === "ins" || expectParagraphAttrs(paragraph).pPrMark?.kind === "moveTo",
|
|
148
196
|
containerStillEndsWithParagraph: false,
|
|
149
|
-
followingTableCanReceiveRunIn: expectParagraphAttrs(paragraph)._sectionProperties === void 0 && !runInCellPending(next),
|
|
197
|
+
followingTableCanReceiveRunIn: expectParagraphAttrs(paragraph)._sectionProperties === void 0 && !runInCellPending(next, mode),
|
|
150
198
|
needsFollowingCommentHost: needsCommentHost && !hasPrecedingCommentHost
|
|
151
199
|
}).kind === "run-in";
|
|
152
200
|
};
|
|
153
201
|
/**
|
|
202
|
+
* Stand each block this resolution removes before the paragraph whose mark goes
|
|
203
|
+
* right before it, so that paragraph meets what it will run on into. The block
|
|
204
|
+
* is going, so where it goes from does not show; the paragraph's words keep
|
|
205
|
+
* mapping to themselves.
|
|
206
|
+
*/
|
|
207
|
+
const moveRemovedBlocksBeforeParagraphs = (tr, mode) => {
|
|
208
|
+
const maps = [];
|
|
209
|
+
for (;;) {
|
|
210
|
+
let move = null;
|
|
211
|
+
tr.doc.descendants((node, position, parent, index) => {
|
|
212
|
+
if (move !== null) return false;
|
|
213
|
+
if (node.type.name !== "paragraph") return !node.isTextblock;
|
|
214
|
+
const block = parent?.maybeChild(index + 1);
|
|
215
|
+
if (parent && block && paragraphBeforeRemovedBlock({
|
|
216
|
+
parent,
|
|
217
|
+
index,
|
|
218
|
+
mode
|
|
219
|
+
})) move = {
|
|
220
|
+
position,
|
|
221
|
+
paragraph: node,
|
|
222
|
+
block
|
|
223
|
+
};
|
|
224
|
+
return false;
|
|
225
|
+
});
|
|
226
|
+
if (move === null) return maps;
|
|
227
|
+
const { position, paragraph, block } = move;
|
|
228
|
+
const blockPosition = position + paragraph.nodeSize;
|
|
229
|
+
tr.step(new ReplaceStep(position, blockPosition + block.nodeSize, new Slice(Fragment.fromArray([block, paragraph]), 0, 0)));
|
|
230
|
+
maps.push(new StepMap([
|
|
231
|
+
position,
|
|
232
|
+
0,
|
|
233
|
+
block.nodeSize,
|
|
234
|
+
blockPosition,
|
|
235
|
+
block.nodeSize,
|
|
236
|
+
0
|
|
237
|
+
]));
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
154
241
|
* Before every change in a story is resolved: run each paragraph whose mark
|
|
155
242
|
* goes and that sits right before a table on into that table. Returns each
|
|
156
243
|
* paragraph that took words (its position after the step count given) and
|
|
157
244
|
* the paragraph-property sources handed over.
|
|
158
245
|
*/
|
|
159
246
|
const runParagraphsIntoTables = (tr, mode, styleResolver) => {
|
|
160
|
-
const removedMark = tr.doc.type.schema.marks[mode === "accept" ? "deletion" : "insertion"];
|
|
161
247
|
const tried = /* @__PURE__ */ new Set();
|
|
162
248
|
const targets = [];
|
|
163
249
|
const transfers = [];
|
|
164
|
-
const maps =
|
|
250
|
+
const maps = moveRemovedBlocksBeforeParagraphs(tr, mode);
|
|
165
251
|
for (;;) {
|
|
166
252
|
let candidate = null;
|
|
167
253
|
tr.doc.descendants((node, pos, parent, index) => {
|
|
@@ -183,7 +269,7 @@ const runParagraphsIntoTables = (tr, mode, styleResolver) => {
|
|
|
183
269
|
tr,
|
|
184
270
|
paragraphPos: candidate,
|
|
185
271
|
styleResolver,
|
|
186
|
-
|
|
272
|
+
everyChange: mode
|
|
187
273
|
});
|
|
188
274
|
if (ranIn !== null) {
|
|
189
275
|
targets.push({
|
|
@@ -196,4 +282,4 @@ const runParagraphsIntoTables = (tr, mode, styleResolver) => {
|
|
|
196
282
|
}
|
|
197
283
|
}
|
|
198
284
|
};
|
|
199
|
-
export { runInCellPending, runParagraphIntoTable, runParagraphsIntoTables, runsIntoFollowingTable };
|
|
285
|
+
export { paragraphBeforeRemovedBlock, runInCellPending, runParagraphIntoTable, runParagraphsIntoTables, runsIntoFollowingTable };
|
|
@@ -30,8 +30,10 @@ const dispatchEditorTextInput = (view, input) => {
|
|
|
30
30
|
});
|
|
31
31
|
const tr = view.state.tr;
|
|
32
32
|
if (formattingMarks !== void 0) tr.setStoredMarks(formattingMarks);
|
|
33
|
+
const typesOverSelection = !selection.empty && selection.from === from && selection.to === to;
|
|
34
|
+
if (typesOverSelection && !selection.$from.parent.inlineContent) return tr.insertText(text);
|
|
33
35
|
tr.insertText(text, from, to);
|
|
34
|
-
return
|
|
36
|
+
return typesOverSelection ? tr.setSelection(TextSelection.create(tr.doc, from + text.length)) : tr;
|
|
35
37
|
}
|
|
36
38
|
const start = Selection.atStart(view.state.doc);
|
|
37
39
|
const end = Selection.atEnd(view.state.doc);
|
|
@@ -3,7 +3,9 @@ import { readBlockCustomXmlAttrs, readBlockSdtAttrs, readCharacterSpacingMarkAtt
|
|
|
3
3
|
import { readBookmarkBoundaryAttrs } from "./bookmarkBoundaryAttrs.js";
|
|
4
4
|
import { readCommentRangeBoundaryAttrs } from "./commentRangeBoundaryAttrs.js";
|
|
5
5
|
import { readCommentReferenceAttrs } from "./commentReferenceAttrs.js";
|
|
6
|
+
import { HYPHEN_ELEMENT_MARK_NAME } from "./conversion/hyphenTextCarriers.js";
|
|
6
7
|
import { fieldRequiresStructuredContent } from "./fieldRepresentation.js";
|
|
8
|
+
import { readHyphenElementMarkAttrs } from "./hyphenElementAttrs.js";
|
|
7
9
|
import { readMoveRangeBoundaryAttrs } from "./moveRangeBoundaryAttrs.js";
|
|
8
10
|
import { readRangeAnchorAttrs } from "./rangeAnchorAttrs.js";
|
|
9
11
|
import { isRunContentInlineNodeName } from "./runContentProjection.js";
|
|
@@ -15,6 +17,7 @@ import { readTextBoxAnchorAttrs } from "./textBoxAnchorAttrs.js";
|
|
|
15
17
|
const COMPLEX_FIELD_RESULT_MARK_NAMES = /* @__PURE__ */ new Set([
|
|
16
18
|
...RUN_FORMATTING_MARK_NAMES,
|
|
17
19
|
RUN_IDENTITY_MARK_NAME,
|
|
20
|
+
HYPHEN_ELEMENT_MARK_NAME,
|
|
18
21
|
"runPropertyChange",
|
|
19
22
|
"footnoteRef"
|
|
20
23
|
]);
|
|
@@ -352,6 +355,9 @@ const validateMark = (mark, markPath, issues) => {
|
|
|
352
355
|
case "textShadow":
|
|
353
356
|
case "textOutline":
|
|
354
357
|
case "rtl": return;
|
|
358
|
+
case "hyphenElement":
|
|
359
|
+
appendAttrIssues(markPath, readHyphenElementMarkAttrs(mark), issues);
|
|
360
|
+
return;
|
|
355
361
|
case "textEffect":
|
|
356
362
|
appendAttrIssues(markPath, readTextEffectMarkAttrs(mark), issues);
|
|
357
363
|
return;
|
|
@@ -5,6 +5,7 @@ import { formatParseWarnings } from "../docx/parseWarningMessage.js";
|
|
|
5
5
|
import { DEFAULT_TAB_STOP_TWIPS as DEFAULT_TAB_STOP_TWIPS$1 } from "../docx/settingsParser.js";
|
|
6
6
|
import { STYLE_SET_PART, normalizeDocumentStyleSet } from "../style-sets/styleSetNormalization.js";
|
|
7
7
|
import "../style-sets/types.js";
|
|
8
|
+
import { generateHexId } from "./hexId.js";
|
|
8
9
|
import { panic } from "better-result";
|
|
9
10
|
import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
|
|
10
11
|
// src/utils/createDocument.ts
|
|
@@ -368,17 +369,19 @@ function createEmptyDocument(options = {}) {
|
|
|
368
369
|
if (options.marginLeft !== void 0) sectionProps.marginLeft = Math.round(options.marginLeft);
|
|
369
370
|
if (options.marginRight !== void 0) sectionProps.marginRight = Math.round(options.marginRight);
|
|
370
371
|
const initialText = options.initialText ?? "";
|
|
372
|
+
const run = {
|
|
373
|
+
type: "run",
|
|
374
|
+
content: initialText ? [{
|
|
375
|
+
type: "text",
|
|
376
|
+
text: initialText
|
|
377
|
+
}] : [],
|
|
378
|
+
formatting: {}
|
|
379
|
+
};
|
|
371
380
|
const documentBody = {
|
|
372
381
|
content: [{
|
|
373
382
|
type: "paragraph",
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
content: initialText ? [{
|
|
377
|
-
type: "text",
|
|
378
|
-
text: initialText
|
|
379
|
-
}] : [],
|
|
380
|
-
formatting: {}
|
|
381
|
-
}],
|
|
383
|
+
paraId: generateHexId(),
|
|
384
|
+
content: [run],
|
|
382
385
|
formatting: { styleId: styleSet?.initialParagraphStyleId ?? "Normal" }
|
|
383
386
|
}],
|
|
384
387
|
finalSectionProperties: sectionProps
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Font Loader
|
|
3
3
|
*
|
|
4
4
|
* Manages font availability for the DOCX editor. Fonts are bundled via
|
|
5
|
-
*
|
|
5
|
+
* `@stll/folio-fonts` (WOFF2, no external requests). This module
|
|
6
6
|
* tracks which fonts are loaded and provides callbacks for re-rendering
|
|
7
7
|
* when fonts become available.
|
|
8
8
|
*/
|