@stll/folio-core 0.22.3 → 0.23.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 +1 -1
- package/dist/document-operations.d.ts +4 -4
- package/dist/document-operations.js +17 -1
- package/dist/docx/rezip.d.ts +1 -1
- package/dist/docx/rezip.js +12 -31
- package/dist/layout-bridge/convert/toFlowBlocks.js +35 -61
- package/dist/layout-painter/imageLayout.d.ts +1 -1
- package/dist/managers/AutoSaveManager.js +8 -40
- package/dist/managers/TableSelectionManager.d.ts +1 -1
- package/dist/managers/autoSaveCodec.d.ts +17 -0
- package/dist/managers/autoSaveCodec.js +109 -0
- package/dist/prosemirror/attrs/index.js +273 -25
- package/dist/prosemirror/commands/comments.js +3 -3
- package/dist/prosemirror/commands/formatting.js +19 -19
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/paragraph.js +32 -32
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +4 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +8 -8
- package/dist/prosemirror/commands/table.d.ts +10 -52
- package/dist/prosemirror/commands/table.js +34 -34
- package/dist/prosemirror/conversion/fromProseDoc.js +20 -17
- package/dist/prosemirror/conversion/sdtAttrs.d.ts +2 -1
- package/dist/prosemirror/conversion/sdtAttrs.js +9 -4
- package/dist/prosemirror/extensions/ExtensionManager.d.ts +6 -3
- package/dist/prosemirror/extensions/ExtensionManager.js +5 -3
- package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +4 -4
- package/dist/prosemirror/extensions/nodes/ShapeExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/types.d.ts +134 -1
- package/dist/prosemirror/index.d.ts +2 -2
- package/dist/prosemirror/plugins/selectionTracker.js +25 -99
- package/dist/prosemirror/revisionCarriers.js +3 -1
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/index.js +87 -0
- package/dist/prosemirror/schema/nodes.d.ts +13 -2
- package/dist/prosemirror/selectionState.d.ts +11 -5
- package/dist/prosemirror/selectionState.js +94 -57
- package/dist/utils/tableOperations.d.ts +7 -6
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { expectCommentMarkAttrs, expectTrackedChangeMarkAttrs } from "../attrs/index.js";
|
|
2
|
+
import { extractSelectionSnapshot } from "../selectionState.js";
|
|
2
3
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
3
4
|
//#region src/prosemirror/plugins/selectionTracker.ts
|
|
4
5
|
/**
|
|
@@ -18,56 +19,41 @@ const selectionTrackerKey = new PluginKey("selectionTracker");
|
|
|
18
19
|
* Extract selection context from editor state
|
|
19
20
|
*/
|
|
20
21
|
function extractSelectionContext(state) {
|
|
21
|
-
const { selection
|
|
22
|
-
const {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (offset <= to) endParagraphIndex = index;
|
|
30
|
-
});
|
|
31
|
-
const textFormatting = extractTextFormatting(state);
|
|
32
|
-
const paragraph = $from.parent;
|
|
33
|
-
const paragraphFormatting = {};
|
|
34
|
-
if (paragraph.type.name === "paragraph") {
|
|
35
|
-
if (paragraph.attrs["alignment"]) paragraphFormatting.alignment = paragraph.attrs["alignment"];
|
|
36
|
-
if (typeof paragraph.attrs["lineSpacing"] === "number") {
|
|
37
|
-
paragraphFormatting.lineSpacing = paragraph.attrs["lineSpacing"];
|
|
38
|
-
paragraphFormatting.lineSpacingRule = paragraph.attrs["lineSpacingRule"];
|
|
39
|
-
}
|
|
40
|
-
if (typeof paragraph.attrs["snapToGrid"] === "boolean") paragraphFormatting.snapToGrid = paragraph.attrs["snapToGrid"];
|
|
41
|
-
if (paragraph.attrs["indentLeft"]) paragraphFormatting.indentLeft = paragraph.attrs["indentLeft"];
|
|
42
|
-
if (paragraph.attrs["indentRight"]) paragraphFormatting.indentRight = paragraph.attrs["indentRight"];
|
|
43
|
-
if (paragraph.attrs["indentFirstLine"]) paragraphFormatting.indentFirstLine = paragraph.attrs["indentFirstLine"];
|
|
44
|
-
if (paragraph.attrs["hangingIndent"]) paragraphFormatting.hangingIndent = paragraph.attrs["hangingIndent"];
|
|
45
|
-
if (paragraph.attrs["tabs"]) paragraphFormatting.tabs = paragraph.attrs["tabs"];
|
|
46
|
-
if (paragraph.attrs["numPr"]) paragraphFormatting.numPr = paragraph.attrs["numPr"];
|
|
47
|
-
if (paragraph.attrs["styleId"]) paragraphFormatting.styleId = paragraph.attrs["styleId"];
|
|
48
|
-
}
|
|
49
|
-
const numPr = paragraph.attrs["numPr"];
|
|
22
|
+
const { selection } = state;
|
|
23
|
+
const { empty } = selection;
|
|
24
|
+
const snapshot = extractSelectionSnapshot(state);
|
|
25
|
+
const paragraphFormatting = snapshot.styleId === null ? snapshot.paragraphFormatting : {
|
|
26
|
+
...snapshot.paragraphFormatting,
|
|
27
|
+
styleId: snapshot.styleId
|
|
28
|
+
};
|
|
29
|
+
const numPr = snapshot.paragraphFormatting.numPr;
|
|
50
30
|
const inList = !!numPr?.numId;
|
|
51
31
|
let listType;
|
|
52
32
|
if (numPr?.numId === 1) listType = "bullet";
|
|
53
33
|
else if (numPr?.numId) listType = "numbered";
|
|
54
34
|
const listLevel = numPr?.ilvl;
|
|
55
|
-
const allMarks = state.storedMarks || (empty ?
|
|
35
|
+
const allMarks = state.storedMarks || (empty ? selection.$from.marks() : []);
|
|
56
36
|
const activeCommentIds = [];
|
|
57
37
|
let inInsertion = false;
|
|
58
38
|
let inDeletion = false;
|
|
59
39
|
for (const mark of allMarks) {
|
|
60
|
-
if (mark.type.name === "comment"
|
|
61
|
-
if (mark.type.name === "insertion")
|
|
62
|
-
|
|
40
|
+
if (mark.type.name === "comment") activeCommentIds.push(expectCommentMarkAttrs(mark).commentId);
|
|
41
|
+
if (mark.type.name === "insertion") {
|
|
42
|
+
expectTrackedChangeMarkAttrs(mark);
|
|
43
|
+
inInsertion = true;
|
|
44
|
+
}
|
|
45
|
+
if (mark.type.name === "deletion") {
|
|
46
|
+
expectTrackedChangeMarkAttrs(mark);
|
|
47
|
+
inDeletion = true;
|
|
48
|
+
}
|
|
63
49
|
}
|
|
64
50
|
return {
|
|
65
|
-
hasSelection:
|
|
66
|
-
isMultiParagraph:
|
|
67
|
-
textFormatting,
|
|
51
|
+
hasSelection: snapshot.hasSelection,
|
|
52
|
+
isMultiParagraph: snapshot.isMultiParagraph,
|
|
53
|
+
textFormatting: snapshot.textFormatting,
|
|
68
54
|
paragraphFormatting,
|
|
69
|
-
startParagraphIndex,
|
|
70
|
-
endParagraphIndex,
|
|
55
|
+
startParagraphIndex: snapshot.startParagraphIndex,
|
|
56
|
+
endParagraphIndex: snapshot.endParagraphIndex,
|
|
71
57
|
inList,
|
|
72
58
|
...listType !== void 0 ? { listType } : {},
|
|
73
59
|
...listLevel !== void 0 ? { listLevel } : {},
|
|
@@ -77,66 +63,6 @@ function extractSelectionContext(state) {
|
|
|
77
63
|
};
|
|
78
64
|
}
|
|
79
65
|
/**
|
|
80
|
-
* Extract text formatting from current selection/cursor marks
|
|
81
|
-
*/
|
|
82
|
-
function extractTextFormatting(state) {
|
|
83
|
-
const { selection, doc } = state;
|
|
84
|
-
const { from, to, empty, $from } = selection;
|
|
85
|
-
const marks = empty ? state.storedMarks || $from.marks() : collectMarksInRange({
|
|
86
|
-
doc,
|
|
87
|
-
from,
|
|
88
|
-
to
|
|
89
|
-
});
|
|
90
|
-
const formatting = {};
|
|
91
|
-
for (const mark of marks) switch (mark.type.name) {
|
|
92
|
-
case "bold":
|
|
93
|
-
formatting.bold = true;
|
|
94
|
-
break;
|
|
95
|
-
case "italic":
|
|
96
|
-
formatting.italic = true;
|
|
97
|
-
break;
|
|
98
|
-
case "underline":
|
|
99
|
-
if (mark.attrs["style"] !== "none") formatting.underline = {
|
|
100
|
-
style: mark.attrs["style"] || "single",
|
|
101
|
-
color: mark.attrs["color"]
|
|
102
|
-
};
|
|
103
|
-
break;
|
|
104
|
-
case "strike":
|
|
105
|
-
if (mark.attrs["double"]) formatting.doubleStrike = true;
|
|
106
|
-
else formatting.strike = true;
|
|
107
|
-
break;
|
|
108
|
-
case "textColor":
|
|
109
|
-
formatting.color = {
|
|
110
|
-
rgb: mark.attrs["rgb"],
|
|
111
|
-
themeColor: mark.attrs["themeColor"],
|
|
112
|
-
themeTint: mark.attrs["themeTint"],
|
|
113
|
-
themeShade: mark.attrs["themeShade"]
|
|
114
|
-
};
|
|
115
|
-
break;
|
|
116
|
-
case "highlight":
|
|
117
|
-
formatting.highlight = mark.attrs["color"];
|
|
118
|
-
break;
|
|
119
|
-
case "fontSize":
|
|
120
|
-
formatting.fontSize = mark.attrs["size"];
|
|
121
|
-
break;
|
|
122
|
-
case "fontFamily":
|
|
123
|
-
formatting.fontFamily = {
|
|
124
|
-
ascii: mark.attrs["ascii"],
|
|
125
|
-
hAnsi: mark.attrs["hAnsi"],
|
|
126
|
-
asciiTheme: mark.attrs["asciiTheme"]
|
|
127
|
-
};
|
|
128
|
-
break;
|
|
129
|
-
case "superscript":
|
|
130
|
-
formatting.vertAlign = "superscript";
|
|
131
|
-
break;
|
|
132
|
-
case "subscript":
|
|
133
|
-
formatting.vertAlign = "subscript";
|
|
134
|
-
break;
|
|
135
|
-
default: break;
|
|
136
|
-
}
|
|
137
|
-
return formatting;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
66
|
* Create selection tracker plugin
|
|
141
67
|
*/
|
|
142
68
|
function createSelectionTrackerPlugin(onSelectionChange) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { expectParagraphAttrs } from "./attrs/index.js";
|
|
1
2
|
//#region src/prosemirror/revisionCarriers.ts
|
|
2
3
|
const isObjectRecord = (value) => typeof value === "object" && value !== null;
|
|
3
4
|
const revisionMetadata = (value) => {
|
|
@@ -34,6 +35,7 @@ const getFolioNodeRevisionCarriers = (node, nodePos) => {
|
|
|
34
35
|
if (node.type.name === "paragraph") {
|
|
35
36
|
const from = nodePos + node.nodeSize - 1;
|
|
36
37
|
const to = nodePos + node.nodeSize;
|
|
38
|
+
const paragraphAttrs = expectParagraphAttrs(node);
|
|
37
39
|
const paragraphMark = node.attrs["pPrMark"];
|
|
38
40
|
if (isObjectRecord(paragraphMark) && (paragraphMark["kind"] === "ins" || paragraphMark["kind"] === "del")) {
|
|
39
41
|
const metadata = revisionMetadata(paragraphMark["info"]);
|
|
@@ -47,7 +49,7 @@ const getFolioNodeRevisionCarriers = (node, nodePos) => {
|
|
|
47
49
|
}
|
|
48
50
|
appendPropertyCarriers({
|
|
49
51
|
carriers,
|
|
50
|
-
changes:
|
|
52
|
+
changes: paragraphAttrs._propertyChanges,
|
|
51
53
|
type: "paragraphPropertiesChanged",
|
|
52
54
|
node,
|
|
53
55
|
from,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CharacterSpacingAttrs, CharacterStyleAttrs, CommentAttrs, EmphasisMarkAttrs, FontFamilyAttrs, FontSizeAttrs, FootnoteRefAttrs, HighlightAttrs, HyperlinkAttrs, LanguageAttrs, RunFormattingOverrideAttrs, RunPropertyChangeMarkAttrs, RunShadingAttrs, StrikeAttrs, TextColorAttrs, TextEffectAttrs, TrackedChangeMarkAttrs, UnderlineAttrs } from "./marks.js";
|
|
2
|
+
import { BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, ParagraphAttrs, ParagraphPropertyChangeAttrs, SdtAttrs, ShapeAttrs, SymbolAttrs, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAttrs } from "./nodes.js";
|
|
2
3
|
import { ExtensionManager } from "../extensions/ExtensionManager.js";
|
|
3
|
-
import { BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, ParagraphAttrs, SdtAttrs, ShapeAttrs, SymbolAttrs, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAttrs } from "./nodes.js";
|
|
4
4
|
//#region src/prosemirror/schema/index.d.ts
|
|
5
5
|
declare const singletonManager: ExtensionManager;
|
|
6
6
|
declare const schema: import("prosemirror-model").Schema<any, any>;
|
|
@@ -11,4 +11,4 @@ type DocxSchema = typeof schema;
|
|
|
11
11
|
type DocxNode = ReturnType<typeof schema.node>;
|
|
12
12
|
type DocxMark = ReturnType<typeof schema.mark>;
|
|
13
13
|
//#endregion
|
|
14
|
-
export { type BlockSdtAttrs, type CharacterSpacingAttrs, type CharacterStyleAttrs, type CommentAttrs, DocxMark, DocxNode, DocxSchema, type EmphasisMarkAttrs, type FieldAttrs, type FontFamilyAttrs, type FontSizeAttrs, type FootnoteRefAttrs, type HardBreakAttrs, type HighlightAttrs, type HyperlinkAttrs, type ImageAttrs, type ImagePositionAttrs, type LanguageAttrs, type MathAttrs, type ParagraphAttrs, type RunFormattingOverrideAttrs, type RunPropertyChangeMarkAttrs, type RunShadingAttrs, type SdtAttrs, type ShapeAttrs, type StrikeAttrs, type SymbolAttrs, type TabAttrs, type TableAttrs, type TableCellAttrs, type TableRowAttrs, type TextBoxAttrs, type TextColorAttrs, type TextEffectAttrs, type TrackedChangeMarkAttrs, type UnderlineAttrs, schema, singletonManager };
|
|
14
|
+
export { type BlockSdtAttrs, type CharacterSpacingAttrs, type CharacterStyleAttrs, type CommentAttrs, DocxMark, DocxNode, DocxSchema, type EmphasisMarkAttrs, type FieldAttrs, type FontFamilyAttrs, type FontSizeAttrs, type FootnoteRefAttrs, type HardBreakAttrs, type HighlightAttrs, type HyperlinkAttrs, type ImageAttrs, type ImagePositionAttrs, type LanguageAttrs, type MathAttrs, type ParagraphAttrs, type ParagraphPropertyChangeAttrs, type RunFormattingOverrideAttrs, type RunPropertyChangeMarkAttrs, type RunShadingAttrs, type SdtAttrs, type ShapeAttrs, type StrikeAttrs, type SymbolAttrs, type TabAttrs, type TableAttrs, type TableCellAttrs, type TableRowAttrs, type TextBoxAttrs, type TextColorAttrs, type TextEffectAttrs, type TrackedChangeMarkAttrs, type UnderlineAttrs, schema, singletonManager };
|
|
@@ -14,6 +14,93 @@ import { createStarterKit } from "../extensions/StarterKit.js";
|
|
|
14
14
|
const mgr = new ExtensionManager(createStarterKit());
|
|
15
15
|
mgr.buildSchema();
|
|
16
16
|
mgr.initializeRuntime();
|
|
17
|
+
const completeCommandNames = (names) => names;
|
|
18
|
+
const requiredCommands = completeCommandNames([
|
|
19
|
+
"toggleBold",
|
|
20
|
+
"toggleItalic",
|
|
21
|
+
"toggleUnderline",
|
|
22
|
+
"toggleStrike",
|
|
23
|
+
"toggleSuperscript",
|
|
24
|
+
"toggleSubscript",
|
|
25
|
+
"setTextColor",
|
|
26
|
+
"clearTextColor",
|
|
27
|
+
"setHighlight",
|
|
28
|
+
"clearHighlight",
|
|
29
|
+
"setFontSize",
|
|
30
|
+
"clearFontSize",
|
|
31
|
+
"setFontFamily",
|
|
32
|
+
"clearFontFamily",
|
|
33
|
+
"setUnderlineStyle",
|
|
34
|
+
"setHyperlink",
|
|
35
|
+
"removeHyperlink",
|
|
36
|
+
"insertHyperlink",
|
|
37
|
+
"setAlignment",
|
|
38
|
+
"alignLeft",
|
|
39
|
+
"alignCenter",
|
|
40
|
+
"alignRight",
|
|
41
|
+
"alignJustify",
|
|
42
|
+
"setLineSpacing",
|
|
43
|
+
"singleSpacing",
|
|
44
|
+
"oneAndHalfSpacing",
|
|
45
|
+
"doubleSpacing",
|
|
46
|
+
"increaseIndent",
|
|
47
|
+
"decreaseIndent",
|
|
48
|
+
"setIndentLeft",
|
|
49
|
+
"setIndentRight",
|
|
50
|
+
"setIndentFirstLine",
|
|
51
|
+
"toggleBulletList",
|
|
52
|
+
"toggleNumberedList",
|
|
53
|
+
"increaseListLevel",
|
|
54
|
+
"decreaseListLevel",
|
|
55
|
+
"removeList",
|
|
56
|
+
"setSpaceBefore",
|
|
57
|
+
"setSpaceAfter",
|
|
58
|
+
"applyStyle",
|
|
59
|
+
"clearStyle",
|
|
60
|
+
"insertSectionBreak",
|
|
61
|
+
"removeSectionBreak",
|
|
62
|
+
"addTabStop",
|
|
63
|
+
"removeTabStop",
|
|
64
|
+
"toggleBidi",
|
|
65
|
+
"setRtl",
|
|
66
|
+
"setLtr",
|
|
67
|
+
"setTabs",
|
|
68
|
+
"generateTOC",
|
|
69
|
+
"insertTable",
|
|
70
|
+
"addRowAbove",
|
|
71
|
+
"addRowBelow",
|
|
72
|
+
"deleteRow",
|
|
73
|
+
"addColumnLeft",
|
|
74
|
+
"addColumnRight",
|
|
75
|
+
"deleteColumn",
|
|
76
|
+
"deleteTable",
|
|
77
|
+
"selectTable",
|
|
78
|
+
"selectRow",
|
|
79
|
+
"selectColumn",
|
|
80
|
+
"mergeCells",
|
|
81
|
+
"splitCell",
|
|
82
|
+
"setCellBorder",
|
|
83
|
+
"setTableBorderPreset",
|
|
84
|
+
"setTableBorders",
|
|
85
|
+
"removeTableBorders",
|
|
86
|
+
"setAllTableBorders",
|
|
87
|
+
"setOutsideTableBorders",
|
|
88
|
+
"setInsideTableBorders",
|
|
89
|
+
"setCellVerticalAlign",
|
|
90
|
+
"setCellMargins",
|
|
91
|
+
"setCellTextDirection",
|
|
92
|
+
"toggleNoWrap",
|
|
93
|
+
"setRowHeight",
|
|
94
|
+
"toggleHeaderRow",
|
|
95
|
+
"distributeColumns",
|
|
96
|
+
"autoFitContents",
|
|
97
|
+
"setTableProperties",
|
|
98
|
+
"applyTableStyle",
|
|
99
|
+
"setCellFillColor",
|
|
100
|
+
"setTableBorderColor",
|
|
101
|
+
"setTableBorderWidth"
|
|
102
|
+
]);
|
|
103
|
+
for (const commandName of requiredCommands) mgr.requireCommand(commandName);
|
|
17
104
|
const singletonManager = mgr;
|
|
18
105
|
const schema = mgr.getSchema();
|
|
19
106
|
//#endregion
|
|
@@ -177,7 +177,7 @@ type ParagraphAttrs = {
|
|
|
177
177
|
* them in UI today, but stripping them on every edit would corrupt the
|
|
178
178
|
* `w:pPrChange` history Word relies on for "show previous formatting"
|
|
179
179
|
* and for reverting an accepted property change. */
|
|
180
|
-
_propertyChanges?:
|
|
180
|
+
_propertyChanges?: ParagraphPropertyChangeAttrs[];
|
|
181
181
|
/** Paragraph-mark insertion / deletion (`<w:pPr><w:rPr><w:ins/>` /
|
|
182
182
|
* `<w:del/>`). Word emits this when the paragraph break itself was
|
|
183
183
|
* authored in track-changes mode — pressing Enter mid-paragraph
|
|
@@ -192,6 +192,17 @@ type ParagraphAttrs = {
|
|
|
192
192
|
*/
|
|
193
193
|
_suggestedInsert?: SuggestedStructuralMarker | null;
|
|
194
194
|
};
|
|
195
|
+
/**
|
|
196
|
+
* ProseMirror property-change attrs may also carry the editor's list-marker
|
|
197
|
+
* snapshot fields alongside the canonical paragraph formatting fields.
|
|
198
|
+
* Keeping that shape typed here lets layout consume validated attrs directly.
|
|
199
|
+
*/
|
|
200
|
+
type ParagraphPropertyChangeAttrs = Omit<document_d_exports.ParagraphPropertyChange, "previousFormatting" | "currentFormatting"> & {
|
|
201
|
+
previousFormatting?: Omit<document_d_exports.ParagraphFormatting, "numPr"> & {
|
|
202
|
+
numPr?: document_d_exports.ParagraphFormatting["numPr"] | null;
|
|
203
|
+
} & Partial<Pick<ParagraphAttrs, "listIsBullet" | "listIsLegal" | "listNumFmt" | "listMarker" | "listMarkerHidden" | "listMarkerFontFamily" | "listMarkerFontSize" | "listMarkerBold" | "listMarkerAlignment" | "listMarkerSuffix" | "listLevelNumFmts" | "listLevelStarts" | "listAbstractNumId" | "listStartOverride" | "lineSpacingExplicit" | "direction" | "_autospacingBase">>;
|
|
204
|
+
currentFormatting?: document_d_exports.ParagraphFormatting;
|
|
205
|
+
};
|
|
195
206
|
/**
|
|
196
207
|
* Image position for floating images (horizontal and vertical positioning)
|
|
197
208
|
*/
|
|
@@ -689,4 +700,4 @@ type TableCellAttrs = {
|
|
|
689
700
|
_docxVMergeContinuationCells?: document_d_exports.TableCell[];
|
|
690
701
|
};
|
|
691
702
|
//#endregion
|
|
692
|
-
export { BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, ParagraphAttrs, SdtAttrs, ShapeAttrs, SuggestedStructuralMarker, SymbolAttrs, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAnchorAttrs, TextBoxAttrs };
|
|
703
|
+
export { BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, ImagePositionAttrs, MathAttrs, ParagraphAttrs, ParagraphPropertyChangeAttrs, SdtAttrs, ShapeAttrs, SuggestedStructuralMarker, SymbolAttrs, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAnchorAttrs, TextBoxAttrs };
|
|
@@ -2,9 +2,11 @@ import { document_d_exports } from "../types/document.js";
|
|
|
2
2
|
import { EditorState } from "prosemirror-state";
|
|
3
3
|
//#region src/prosemirror/selectionState.d.ts
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Canonical selection projection shared by toolbar and selection-change APIs.
|
|
6
|
+
* Adapter-specific context belongs on top of this snapshot rather than in a
|
|
7
|
+
* second formatting extractor.
|
|
6
8
|
*/
|
|
7
|
-
type
|
|
9
|
+
type SelectionSnapshot = {
|
|
8
10
|
/** Whether there's an active selection (not just cursor) */
|
|
9
11
|
hasSelection: boolean;
|
|
10
12
|
/** Whether selection spans multiple paragraphs */
|
|
@@ -20,10 +22,14 @@ type SelectionState = {
|
|
|
20
22
|
/** End paragraph index */
|
|
21
23
|
endParagraphIndex: number;
|
|
22
24
|
};
|
|
25
|
+
/** Compatibility name for the public toolbar selection contract. */
|
|
26
|
+
type SelectionState = SelectionSnapshot;
|
|
23
27
|
/**
|
|
24
|
-
* Extract selection
|
|
25
|
-
* Used by
|
|
28
|
+
* Extract the canonical selection snapshot from editor state.
|
|
29
|
+
* Used by both the toolbar callback and the selection tracker plugin.
|
|
26
30
|
*/
|
|
31
|
+
declare function extractSelectionSnapshot(state: EditorState): SelectionSnapshot;
|
|
32
|
+
/** Compatibility entry point used by existing React and Vue integrations. */
|
|
27
33
|
declare function extractSelectionState(state: EditorState): SelectionState | null;
|
|
28
34
|
//#endregion
|
|
29
|
-
export { SelectionState, extractSelectionState };
|
|
35
|
+
export { SelectionSnapshot, SelectionState, extractSelectionSnapshot, extractSelectionState };
|
|
@@ -1,100 +1,137 @@
|
|
|
1
|
+
import { FONT_THEME_VALUES } from "../types/documentEnumValues.js";
|
|
2
|
+
import { expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectHighlightMarkAttrs, expectParagraphAttrs, expectStrikeMarkAttrs, expectTextColorMarkAttrs, expectUnderlineMarkAttrs } from "./attrs/index.js";
|
|
1
3
|
import { directionIsRtl } from "./paragraphDirection.js";
|
|
2
4
|
import { collectMarksInRange } from "./selectionMarks.js";
|
|
3
5
|
//#region src/prosemirror/selectionState.ts
|
|
6
|
+
const isFontTheme = (value) => value !== void 0 && FONT_THEME_VALUES.some((theme) => theme === value);
|
|
4
7
|
/**
|
|
5
|
-
* Extract selection
|
|
6
|
-
* Used by
|
|
8
|
+
* Extract the canonical selection snapshot from editor state.
|
|
9
|
+
* Used by both the toolbar callback and the selection tracker plugin.
|
|
7
10
|
*/
|
|
8
|
-
function
|
|
11
|
+
function extractSelectionSnapshot(state) {
|
|
9
12
|
const { selection, doc } = state;
|
|
10
13
|
const { from, to, empty } = selection;
|
|
11
14
|
const $from = doc.resolve(from);
|
|
15
|
+
const { startParagraphIndex, endParagraphIndex } = paragraphIndexes(doc, from, to);
|
|
16
|
+
const paragraph = $from.parent;
|
|
17
|
+
const paragraphAttrs = paragraph.type.name === "paragraph" ? expectParagraphAttrs(paragraph) : null;
|
|
18
|
+
const marks = selectionMarks(state);
|
|
19
|
+
let textFormatting = extractTextFormatting(marks);
|
|
20
|
+
if (paragraph.type.name === "paragraph" && paragraph.textContent.length === 0 && marks.length === 0 && paragraphAttrs?.defaultTextFormatting) textFormatting = { ...paragraphAttrs.defaultTextFormatting };
|
|
21
|
+
const paragraphFormatting = {};
|
|
22
|
+
let styleId = null;
|
|
23
|
+
if (paragraphAttrs) {
|
|
24
|
+
if (paragraphAttrs.alignment !== void 0) paragraphFormatting.alignment = paragraphAttrs.alignment;
|
|
25
|
+
if (paragraphAttrs.lineSpacing !== void 0) {
|
|
26
|
+
paragraphFormatting.lineSpacing = paragraphAttrs.lineSpacing;
|
|
27
|
+
if (paragraphAttrs.lineSpacingRule !== void 0) paragraphFormatting.lineSpacingRule = paragraphAttrs.lineSpacingRule;
|
|
28
|
+
}
|
|
29
|
+
if (paragraphAttrs.snapToGrid !== void 0) paragraphFormatting.snapToGrid = paragraphAttrs.snapToGrid;
|
|
30
|
+
if (paragraphAttrs.numPr !== void 0) paragraphFormatting.numPr = paragraphAttrs.numPr;
|
|
31
|
+
if (paragraphAttrs.indentLeft !== void 0) paragraphFormatting.indentLeft = paragraphAttrs.indentLeft;
|
|
32
|
+
if (paragraphAttrs.indentRight !== void 0) paragraphFormatting.indentRight = paragraphAttrs.indentRight;
|
|
33
|
+
if (paragraphAttrs.indentFirstLine !== void 0) paragraphFormatting.indentFirstLine = paragraphAttrs.indentFirstLine;
|
|
34
|
+
if (paragraphAttrs.hangingIndent !== void 0) paragraphFormatting.hangingIndent = paragraphAttrs.hangingIndent;
|
|
35
|
+
if (paragraphAttrs.tabs !== void 0) paragraphFormatting.tabs = paragraphAttrs.tabs;
|
|
36
|
+
if (directionIsRtl(paragraphAttrs.direction)) paragraphFormatting.bidi = true;
|
|
37
|
+
if (paragraphAttrs.styleId !== void 0) styleId = paragraphAttrs.styleId;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
hasSelection: !empty,
|
|
41
|
+
isMultiParagraph: startParagraphIndex !== endParagraphIndex,
|
|
42
|
+
textFormatting,
|
|
43
|
+
paragraphFormatting,
|
|
44
|
+
styleId,
|
|
45
|
+
startParagraphIndex,
|
|
46
|
+
endParagraphIndex
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Compatibility entry point used by existing React and Vue integrations. */
|
|
50
|
+
function extractSelectionState(state) {
|
|
51
|
+
return extractSelectionSnapshot(state);
|
|
52
|
+
}
|
|
53
|
+
function paragraphIndexes(doc, from, to) {
|
|
12
54
|
let startParagraphIndex = 0;
|
|
13
55
|
let endParagraphIndex = 0;
|
|
14
56
|
doc.forEach((_node, offset, index) => {
|
|
15
57
|
if (offset <= from) startParagraphIndex = index;
|
|
16
58
|
if (offset <= to) endParagraphIndex = index;
|
|
17
59
|
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
60
|
+
return {
|
|
61
|
+
startParagraphIndex,
|
|
62
|
+
endParagraphIndex
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function selectionMarks(state) {
|
|
66
|
+
const { selection, doc } = state;
|
|
67
|
+
const { from, to, empty } = selection;
|
|
68
|
+
return empty ? state.storedMarks || selection.$from.marks() : collectMarksInRange({
|
|
23
69
|
doc,
|
|
24
70
|
from,
|
|
25
71
|
to
|
|
26
72
|
});
|
|
27
|
-
|
|
73
|
+
}
|
|
74
|
+
function extractTextFormatting(marks) {
|
|
75
|
+
const formatting = {};
|
|
28
76
|
for (const mark of marks) switch (mark.type.name) {
|
|
29
77
|
case "bold":
|
|
30
|
-
|
|
78
|
+
formatting.bold = true;
|
|
31
79
|
break;
|
|
32
80
|
case "italic":
|
|
33
|
-
|
|
81
|
+
formatting.italic = true;
|
|
34
82
|
break;
|
|
35
|
-
case "underline":
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
83
|
+
case "underline": {
|
|
84
|
+
const attrs = expectUnderlineMarkAttrs(mark);
|
|
85
|
+
if (attrs.style !== "none") formatting.underline = {
|
|
86
|
+
style: attrs.style ?? "single",
|
|
87
|
+
...attrs.color !== void 0 ? { color: attrs.color } : {}
|
|
39
88
|
};
|
|
40
89
|
break;
|
|
90
|
+
}
|
|
41
91
|
case "strike":
|
|
42
|
-
if (mark.
|
|
43
|
-
else
|
|
92
|
+
if (expectStrikeMarkAttrs(mark).double) formatting.doubleStrike = true;
|
|
93
|
+
else formatting.strike = true;
|
|
44
94
|
break;
|
|
45
|
-
case "textColor":
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
95
|
+
case "textColor": {
|
|
96
|
+
const attrs = expectTextColorMarkAttrs(mark);
|
|
97
|
+
formatting.color = {
|
|
98
|
+
...attrs.rgb !== void 0 ? { rgb: attrs.rgb } : {},
|
|
99
|
+
...attrs.themeColor !== void 0 ? { themeColor: attrs.themeColor } : {},
|
|
100
|
+
...attrs.themeTint !== void 0 ? { themeTint: attrs.themeTint } : {},
|
|
101
|
+
...attrs.themeShade !== void 0 ? { themeShade: attrs.themeShade } : {}
|
|
49
102
|
};
|
|
50
103
|
break;
|
|
104
|
+
}
|
|
51
105
|
case "highlight":
|
|
52
|
-
|
|
106
|
+
formatting.highlight = expectHighlightMarkAttrs(mark).color;
|
|
53
107
|
break;
|
|
54
108
|
case "fontSize":
|
|
55
|
-
|
|
109
|
+
formatting.fontSize = expectFontSizeMarkAttrs(mark).size;
|
|
56
110
|
break;
|
|
57
|
-
case "fontFamily":
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
111
|
+
case "fontFamily": {
|
|
112
|
+
const attrs = expectFontFamilyMarkAttrs(mark);
|
|
113
|
+
formatting.fontFamily = {
|
|
114
|
+
...attrs.ascii !== void 0 ? { ascii: attrs.ascii } : {},
|
|
115
|
+
...attrs.hAnsi !== void 0 ? { hAnsi: attrs.hAnsi } : {},
|
|
116
|
+
...attrs.eastAsia !== void 0 ? { eastAsia: attrs.eastAsia } : {},
|
|
117
|
+
...attrs.cs !== void 0 ? { cs: attrs.cs } : {},
|
|
118
|
+
...attrs.hint !== void 0 ? { hint: attrs.hint } : {},
|
|
119
|
+
...isFontTheme(attrs.asciiTheme) ? { asciiTheme: attrs.asciiTheme } : {},
|
|
120
|
+
...attrs.hAnsiTheme !== void 0 ? { hAnsiTheme: attrs.hAnsiTheme } : {},
|
|
121
|
+
...attrs.eastAsiaTheme !== void 0 ? { eastAsiaTheme: attrs.eastAsiaTheme } : {},
|
|
122
|
+
...attrs.csTheme !== void 0 ? { csTheme: attrs.csTheme } : {}
|
|
61
123
|
};
|
|
62
124
|
break;
|
|
125
|
+
}
|
|
63
126
|
case "superscript":
|
|
64
|
-
|
|
127
|
+
formatting.vertAlign = "superscript";
|
|
65
128
|
break;
|
|
66
129
|
case "subscript":
|
|
67
|
-
|
|
130
|
+
formatting.vertAlign = "subscript";
|
|
68
131
|
break;
|
|
69
132
|
default: break;
|
|
70
133
|
}
|
|
71
|
-
|
|
72
|
-
let styleId = null;
|
|
73
|
-
if (paragraph.type.name === "paragraph") {
|
|
74
|
-
if (paragraph.attrs["alignment"]) paragraphFormatting.alignment = paragraph.attrs["alignment"];
|
|
75
|
-
if (typeof paragraph.attrs["lineSpacing"] === "number") {
|
|
76
|
-
paragraphFormatting.lineSpacing = paragraph.attrs["lineSpacing"];
|
|
77
|
-
paragraphFormatting.lineSpacingRule = paragraph.attrs["lineSpacingRule"];
|
|
78
|
-
}
|
|
79
|
-
if (typeof paragraph.attrs["snapToGrid"] === "boolean") paragraphFormatting.snapToGrid = paragraph.attrs["snapToGrid"];
|
|
80
|
-
if (paragraph.attrs["numPr"]) paragraphFormatting.numPr = paragraph.attrs["numPr"];
|
|
81
|
-
if (paragraph.attrs["indentLeft"]) paragraphFormatting.indentLeft = paragraph.attrs["indentLeft"];
|
|
82
|
-
if (paragraph.attrs["indentRight"]) paragraphFormatting.indentRight = paragraph.attrs["indentRight"];
|
|
83
|
-
if (paragraph.attrs["indentFirstLine"]) paragraphFormatting.indentFirstLine = paragraph.attrs["indentFirstLine"];
|
|
84
|
-
if (paragraph.attrs["hangingIndent"]) paragraphFormatting.hangingIndent = paragraph.attrs["hangingIndent"];
|
|
85
|
-
if (paragraph.attrs["tabs"]) paragraphFormatting.tabs = paragraph.attrs["tabs"];
|
|
86
|
-
if (directionIsRtl(paragraph.attrs["direction"])) paragraphFormatting.bidi = true;
|
|
87
|
-
if (paragraph.attrs["styleId"]) styleId = paragraph.attrs["styleId"];
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
hasSelection: !empty,
|
|
91
|
-
isMultiParagraph: startParagraphIndex !== endParagraphIndex,
|
|
92
|
-
textFormatting,
|
|
93
|
-
paragraphFormatting,
|
|
94
|
-
styleId,
|
|
95
|
-
startParagraphIndex,
|
|
96
|
-
endParagraphIndex
|
|
97
|
-
};
|
|
134
|
+
return formatting;
|
|
98
135
|
}
|
|
99
136
|
//#endregion
|
|
100
|
-
export { extractSelectionState };
|
|
137
|
+
export { extractSelectionSnapshot, extractSelectionState };
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
//#region src/utils/tableOperations.d.ts
|
|
3
|
+
type TablePropertiesCommand = {
|
|
4
|
+
width?: number | null;
|
|
5
|
+
widthType?: document_d_exports.TableWidthType | null;
|
|
6
|
+
justification?: "left" | "center" | "right" | null;
|
|
7
|
+
};
|
|
3
8
|
type TableAction = "addRowAbove" | "addRowBelow" | "addColumnLeft" | "addColumnRight" | "deleteRow" | "deleteColumn" | "mergeCells" | "splitCell" | "deleteTable" | "selectTable" | "selectRow" | "selectColumn" | "borderAll" | "borderOutside" | "borderInside" | "borderNone" | "borderTop" | "borderBottom" | "borderLeft" | "borderRight" | {
|
|
4
9
|
type: "cellFillColor";
|
|
5
10
|
color: string | null;
|
|
@@ -43,11 +48,7 @@ type TableAction = "addRowAbove" | "addRowBelow" | "addColumnLeft" | "addColumnR
|
|
|
43
48
|
type: "autoFitContents";
|
|
44
49
|
} | {
|
|
45
50
|
type: "tableProperties";
|
|
46
|
-
props:
|
|
47
|
-
width?: number | null;
|
|
48
|
-
widthType?: string | null;
|
|
49
|
-
justification?: "left" | "center" | "right" | null;
|
|
50
|
-
};
|
|
51
|
+
props: TablePropertiesCommand;
|
|
51
52
|
} | {
|
|
52
53
|
type: "openTableProperties";
|
|
53
54
|
} | {
|
|
@@ -83,4 +84,4 @@ declare const deleteColumn: (table: document_d_exports.Table, columnIndex: numbe
|
|
|
83
84
|
declare const mergeCells: (table: document_d_exports.Table, selection: TableSelection) => document_d_exports.Table;
|
|
84
85
|
declare const splitCell: (table: document_d_exports.Table, rowIndex: number, columnIndex: number) => document_d_exports.Table;
|
|
85
86
|
//#endregion
|
|
86
|
-
export { TableAction, TableContext, TableSelection, addColumn, addRow, createTableContext, deleteColumn, deleteRow, getCellAt, getColumnCount, mergeCells, splitCell };
|
|
87
|
+
export { TableAction, TableContext, TablePropertiesCommand, TableSelection, addColumn, addRow, createTableContext, deleteColumn, deleteRow, getCellAt, getColumnCount, mergeCells, splitCell };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/folio-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"document-model",
|
|
@@ -113,13 +113,13 @@
|
|
|
113
113
|
"perf": "bun scripts/profile-editor.ts"
|
|
114
114
|
},
|
|
115
115
|
"dependencies": {
|
|
116
|
-
"@stll/docx-core": "^0.15.
|
|
116
|
+
"@stll/docx-core": "^0.15.2",
|
|
117
117
|
"@stll/docx-utils": "^0.1.0",
|
|
118
118
|
"@stll/template-conditions": "^0.1.0",
|
|
119
119
|
"better-result": "3.0.1",
|
|
120
120
|
"csstype": "^3.1.3",
|
|
121
121
|
"dompurify": "^3.4.13",
|
|
122
|
-
"fast-xml-parser": "^5.
|
|
122
|
+
"fast-xml-parser": "^5.10.1",
|
|
123
123
|
"hyphen": "1.14.1",
|
|
124
124
|
"jszip": "3.10.1",
|
|
125
125
|
"marked": "^18.0.5",
|