@portone/docx-editor 0.3.0 → 0.4.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/CHANGELOG.md +46 -0
- package/dist/DocxEditor.js +1 -0
- package/dist/core.d.ts +1 -1
- package/dist/docx/comments/writing.js +14 -8
- package/dist/docx/exportDocx.js +20 -4
- package/dist/docx/formatting/attrs.d.ts +20 -2
- package/dist/docx/formatting/attrs.js +57 -2
- package/dist/docx/formatting/context.d.ts +10 -2
- package/dist/docx/formatting/context.js +23 -5
- package/dist/docx/formatting/resolve.d.ts +10 -4
- package/dist/docx/formatting/resolve.js +31 -11
- package/dist/docx/formatting/styles.d.ts +25 -2
- package/dist/docx/formatting/styles.js +84 -3
- package/dist/docx/hyperlink.d.ts +14 -4
- package/dist/docx/hyperlink.js +4 -1
- package/dist/docx/importDocx.js +46 -37
- package/dist/docx/importTable.d.ts +2 -2
- package/dist/docx/importTable.js +52 -55
- package/dist/docx/invariants.js +26 -13
- package/dist/docx/newLists.d.ts +30 -0
- package/dist/docx/newLists.js +24 -1
- package/dist/docx/numberingPlanner.d.ts +6 -3
- package/dist/docx/numberingPlanner.js +38 -7
- package/dist/docx/session.d.ts +1 -1
- package/dist/docx/session.js +11 -1
- package/dist/docx/tableFormatting/conditions.d.ts +76 -0
- package/dist/docx/tableFormatting/conditions.js +196 -0
- package/dist/docx/tableFormatting/editing.d.ts +7 -3
- package/dist/docx/tableFormatting/editing.js +4 -5
- package/dist/docx/tableFormatting/reading.d.ts +49 -19
- package/dist/docx/tableFormatting/reading.js +109 -35
- package/dist/docx/tableFormatting.d.ts +1 -0
- package/dist/docx/tableFormatting.js +1 -0
- package/dist/docx/tableTemplate.js +12 -12
- package/dist/editor/commands/formatting/propertyCommands.js +6 -1
- package/dist/editor/commands/listCommands.d.ts +6 -3
- package/dist/editor/commands/listCommands.js +73 -28
- package/dist/editor/commands/paragraphCommands.js +6 -1
- package/dist/editor/createEditor.js +1 -1
- package/dist/editor/editorDocument.d.ts +7 -6
- package/dist/editor/editorDocument.js +18 -6
- package/dist/editor/externalClipboard.d.ts +13 -2
- package/dist/editor/externalClipboard.js +64 -34
- package/dist/editor/paragraphEdits.d.ts +16 -1
- package/dist/editor/paragraphEdits.js +13 -5
- package/dist/editor/paragraphPlacement.d.ts +11 -0
- package/dist/editor/paragraphPlacement.js +18 -0
- package/dist/editor/plugins/imagePaste.js +7 -4
- package/dist/editor/plugins/numberingDecorations.d.ts +10 -4
- package/dist/editor/plugins/numberingDecorations.js +43 -2
- package/dist/editor/plugins/paragraphDisplay.js +9 -3
- package/dist/editor/plugins/tableDisplay.js +19 -5
- package/dist/model/format.d.ts +50 -0
- package/dist/model/format.js +65 -0
- package/dist/numbering/listRegistry.d.ts +37 -0
- package/dist/numbering/listRegistry.js +112 -0
- package/dist/numbering/listTemplate.d.ts +26 -17
- package/dist/numbering/listTemplate.js +66 -20
- package/dist/numbering/markers.d.ts +15 -6
- package/dist/numbering/markers.js +26 -59
- package/dist/numbering/parseNumbering.d.ts +70 -5
- package/dist/numbering/parseNumbering.js +100 -26
- package/dist/numbering/spellers.d.ts +15 -0
- package/dist/numbering/spellers.js +96 -0
- package/dist/numbering/writeNumbering.d.ts +5 -3
- package/dist/numbering/writeNumbering.js +15 -15
- package/dist/ooxml/conformance.d.ts +28 -0
- package/dist/ooxml/conformance.js +20 -0
- package/dist/ooxml/errors.d.ts +5 -5
- package/dist/ooxml/names.d.ts +9 -0
- package/dist/ooxml/names.js +8 -1
- package/dist/ooxml/partSplice.d.ts +1 -1
- package/dist/ooxml/partSplice.js +10 -3
- package/dist/ooxml/xml.d.ts +8 -9
- package/dist/ooxml/xml.js +6 -6
- package/dist/page/PageGuides.d.ts +1 -1
- package/dist/page/PageGuides.js +0 -13
- package/dist/page/pageLayout.d.ts +0 -10
- package/dist/page/pageLayout.js +3 -10
- package/dist/page/usePageLayout.d.ts +0 -7
- package/dist/page/usePageLayout.js +2 -9
- package/dist/schema/attrRoles.js +8 -1
- package/dist/schema/docxSchema.js +32 -3
- package/dist/styles/classNames.d.ts +13 -2
- package/dist/styles/classNames.js +13 -2
- package/dist/styles.css +16 -18
- package/dist/table/cellFormatting.js +1 -2
- package/dist/table/gridBorders.d.ts +11 -15
- package/dist/table/gridBorders.js +32 -18
- package/package.json +1 -1
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// src/docx/tableFormatting/reading.ts
|
|
2
|
+
import {
|
|
3
|
+
TABLE_STYLE_CONDITIONS
|
|
4
|
+
} from "../../model/format.js";
|
|
2
5
|
import { parsePropsXml } from "../../ooxml/props.js";
|
|
3
6
|
import {
|
|
7
|
+
ST_DecimalNumber,
|
|
4
8
|
ST_MeasurementOrPercent,
|
|
5
9
|
ST_SignedTwipsMeasure,
|
|
6
10
|
ST_TwipsMeasure
|
|
@@ -8,7 +12,6 @@ import {
|
|
|
8
12
|
import {
|
|
9
13
|
ALIGN_BY_JC,
|
|
10
14
|
borderLineCss,
|
|
11
|
-
borderLineOfCss,
|
|
12
15
|
borderSide,
|
|
13
16
|
childValue,
|
|
14
17
|
isOn,
|
|
@@ -109,30 +112,89 @@ var NO_BORDER_DEFAULTS = {
|
|
|
109
112
|
left: null,
|
|
110
113
|
right: null
|
|
111
114
|
};
|
|
112
|
-
|
|
115
|
+
var NO_CELL_DEFAULTS = {
|
|
116
|
+
borders: NO_BORDER_DEFAULTS,
|
|
117
|
+
margins: NO_CELL_MARGINS,
|
|
118
|
+
background: null,
|
|
119
|
+
verticalAlign: null,
|
|
120
|
+
placement: { tableStyleId: null, conditions: [] }
|
|
121
|
+
};
|
|
122
|
+
var NO_BAND_SIZES = { row: null, col: null };
|
|
123
|
+
function bandSize(tblPr, name) {
|
|
124
|
+
const count = ST_DecimalNumber.parse(childValue(tblPr, name));
|
|
125
|
+
return count !== null && count > 0 ? count : null;
|
|
126
|
+
}
|
|
127
|
+
function readBandSizes(tblPr) {
|
|
128
|
+
if (!tblPr) return NO_BAND_SIZES;
|
|
129
|
+
return {
|
|
130
|
+
row: bandSize(tblPr, "tblStyleRowBandSize"),
|
|
131
|
+
col: bandSize(tblPr, "tblStyleColBandSize")
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function layerBandSizes(style, over) {
|
|
135
|
+
return { row: over.row ?? style.row, col: over.col ?? style.col };
|
|
136
|
+
}
|
|
137
|
+
var NO_CELL_STYLE_BORDERS = {
|
|
138
|
+
top: null,
|
|
139
|
+
bottom: null,
|
|
140
|
+
left: null,
|
|
141
|
+
right: null
|
|
142
|
+
};
|
|
143
|
+
var NO_CELL_STYLE_FORMAT = {
|
|
144
|
+
background: null,
|
|
145
|
+
borders: NO_CELL_STYLE_BORDERS,
|
|
146
|
+
inside: NO_INSIDE_BORDERS,
|
|
147
|
+
margins: NO_CELL_MARGINS,
|
|
148
|
+
verticalAlign: null
|
|
149
|
+
};
|
|
150
|
+
var NO_TABLE_STYLE_CONDITIONS = {};
|
|
151
|
+
function conditionBorders(tcBorders, table) {
|
|
113
152
|
return {
|
|
114
|
-
top:
|
|
115
|
-
bottom:
|
|
116
|
-
left:
|
|
117
|
-
right:
|
|
153
|
+
top: borderSide(tcBorders, "top") ?? table.borderTop ?? null,
|
|
154
|
+
bottom: borderSide(tcBorders, "bottom") ?? table.borderBottom ?? null,
|
|
155
|
+
left: borderSide(tcBorders, "left") ?? borderSide(tcBorders, "start") ?? table.borderLeft ?? null,
|
|
156
|
+
right: borderSide(tcBorders, "right") ?? borderSide(tcBorders, "end") ?? table.borderRight ?? null
|
|
118
157
|
};
|
|
119
158
|
}
|
|
120
|
-
function
|
|
159
|
+
function readCellStyleFormat(tcPr, tblPr) {
|
|
160
|
+
const table = readTableFormat(tblPr) ?? {};
|
|
161
|
+
const tcBorders = tcPr ? childByLocalName(tcPr, "tcBorders") : null;
|
|
121
162
|
return {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
),
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
),
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
),
|
|
131
|
-
right: borderLineOfCss(
|
|
132
|
-
edges.right ? outer?.borderRight ?? null : inside.vertical
|
|
133
|
-
)
|
|
163
|
+
background: (tcPr ? shadingOf(tcPr) : null) ?? table.background ?? null,
|
|
164
|
+
borders: conditionBorders(tcBorders, table),
|
|
165
|
+
inside: layerInsideBorders(readInsideBorders(tblPr), {
|
|
166
|
+
horizontal: borderSide(tcBorders, "insideH"),
|
|
167
|
+
vertical: borderSide(tcBorders, "insideV")
|
|
168
|
+
}),
|
|
169
|
+
margins: readCellMarginsOf(tcPr, "tcMar"),
|
|
170
|
+
verticalAlign: tcPr ? cellVerticalAlignOf(tcPr) : null
|
|
134
171
|
};
|
|
135
172
|
}
|
|
173
|
+
function layerCellStyleBorders(base, over) {
|
|
174
|
+
return {
|
|
175
|
+
top: over.top ?? base.top,
|
|
176
|
+
bottom: over.bottom ?? base.bottom,
|
|
177
|
+
left: over.left ?? base.left,
|
|
178
|
+
right: over.right ?? base.right
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function layerCellStyleFormat(base, over) {
|
|
182
|
+
return {
|
|
183
|
+
background: over.background ?? base.background,
|
|
184
|
+
borders: layerCellStyleBorders(base.borders, over.borders),
|
|
185
|
+
inside: layerInsideBorders(base.inside, over.inside),
|
|
186
|
+
margins: layerCellMargins(base.margins, over.margins),
|
|
187
|
+
verticalAlign: over.verticalAlign ?? base.verticalAlign
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function cellConditionsOf(conditions) {
|
|
191
|
+
const cells = {};
|
|
192
|
+
for (const type of TABLE_STYLE_CONDITIONS) {
|
|
193
|
+
const format = conditions[type];
|
|
194
|
+
if (format) cells[type] = format.cell;
|
|
195
|
+
}
|
|
196
|
+
return cells;
|
|
197
|
+
}
|
|
136
198
|
function tblStyleIdOf(tblPr) {
|
|
137
199
|
return tblPr ? childValue(tblPr, "tblStyle") : null;
|
|
138
200
|
}
|
|
@@ -178,6 +240,9 @@ var CELL_VERTICAL_ALIGN_BY_VAL = {
|
|
|
178
240
|
center: "center",
|
|
179
241
|
bottom: "bottom"
|
|
180
242
|
};
|
|
243
|
+
function cellVerticalAlignOf(tcPr) {
|
|
244
|
+
return CELL_VERTICAL_ALIGN_BY_VAL[childValue(tcPr, "vAlign") ?? ""] ?? null;
|
|
245
|
+
}
|
|
181
246
|
function readCellPadding(tcPr, margins) {
|
|
182
247
|
const padding = layerCellMargins(margins, readCellMarginsOf(tcPr, "tcMar"));
|
|
183
248
|
const format = {};
|
|
@@ -187,24 +252,26 @@ function readCellPadding(tcPr, margins) {
|
|
|
187
252
|
if (padding.leftPt !== null) format.paddingLeftPt = padding.leftPt;
|
|
188
253
|
return format;
|
|
189
254
|
}
|
|
190
|
-
function readCellFormat(tcPr, defaults
|
|
255
|
+
function readCellFormat(tcPr, defaults = NO_CELL_DEFAULTS) {
|
|
191
256
|
const borders = tcPr ? childByLocalName(tcPr, "tcBorders") : null;
|
|
257
|
+
const lines = defaults.borders;
|
|
192
258
|
const format = {};
|
|
193
|
-
const top = borderSide(borders, "top") ?? borderLineCss(
|
|
259
|
+
const top = borderSide(borders, "top") ?? borderLineCss(lines.top);
|
|
194
260
|
if (top) format.borderTop = top;
|
|
195
|
-
const bottom = borderSide(borders, "bottom") ?? borderLineCss(
|
|
261
|
+
const bottom = borderSide(borders, "bottom") ?? borderLineCss(lines.bottom);
|
|
196
262
|
if (bottom) format.borderBottom = bottom;
|
|
197
|
-
const left = borderSide(borders, "left") ?? borderSide(borders, "start") ?? borderLineCss(
|
|
263
|
+
const left = borderSide(borders, "left") ?? borderSide(borders, "start") ?? borderLineCss(lines.left);
|
|
198
264
|
if (left) format.borderLeft = left;
|
|
199
|
-
const right = borderSide(borders, "right") ?? borderSide(borders, "end") ?? borderLineCss(
|
|
265
|
+
const right = borderSide(borders, "right") ?? borderSide(borders, "end") ?? borderLineCss(lines.right);
|
|
200
266
|
if (right) format.borderRight = right;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
267
|
+
const background = (tcPr ? shadingOf(tcPr) : null) ?? defaults.background;
|
|
268
|
+
if (background) format.background = background;
|
|
269
|
+
const verticalAlign = (tcPr ? cellVerticalAlignOf(tcPr) : null) ?? defaults.verticalAlign;
|
|
270
|
+
if (verticalAlign) format.verticalAlign = verticalAlign;
|
|
271
|
+
const padded = {
|
|
272
|
+
...format,
|
|
273
|
+
...readCellPadding(tcPr, defaults.margins)
|
|
274
|
+
};
|
|
208
275
|
return Object.keys(padded).length > 0 ? padded : null;
|
|
209
276
|
}
|
|
210
277
|
function insideBordersOf(tblPr) {
|
|
@@ -215,23 +282,30 @@ function cellMarginsOf(tblPr) {
|
|
|
215
282
|
const el = tblPr === null ? null : parsePropsXml(tblPr);
|
|
216
283
|
return readCellMarginsOf(el, "tblCellMar");
|
|
217
284
|
}
|
|
218
|
-
function readCellProps(tcPr, defaults
|
|
285
|
+
function readCellProps(tcPr, defaults = NO_CELL_DEFAULTS) {
|
|
219
286
|
const el = tcPr === null ? null : parsePropsXml(tcPr);
|
|
220
|
-
return readCellFormat(el, defaults
|
|
287
|
+
return readCellFormat(el, defaults);
|
|
221
288
|
}
|
|
222
289
|
export {
|
|
290
|
+
NO_BAND_SIZES,
|
|
223
291
|
NO_BORDER_DEFAULTS,
|
|
292
|
+
NO_CELL_DEFAULTS,
|
|
224
293
|
NO_CELL_MARGINS,
|
|
294
|
+
NO_CELL_STYLE_FORMAT,
|
|
225
295
|
NO_INSIDE_BORDERS,
|
|
226
|
-
|
|
296
|
+
NO_TABLE_STYLE_CONDITIONS,
|
|
297
|
+
cellConditionsOf,
|
|
227
298
|
cellMarginsOf,
|
|
228
|
-
gridEdgesOf,
|
|
229
299
|
insideBordersOf,
|
|
300
|
+
layerBandSizes,
|
|
230
301
|
layerCellMargins,
|
|
302
|
+
layerCellStyleFormat,
|
|
231
303
|
layerInsideBorders,
|
|
304
|
+
readBandSizes,
|
|
232
305
|
readCellFormat,
|
|
233
306
|
readCellMarginsOf,
|
|
234
307
|
readCellProps,
|
|
308
|
+
readCellStyleFormat,
|
|
235
309
|
readGridCols,
|
|
236
310
|
readInsideBorders,
|
|
237
311
|
readRowFormat,
|
|
@@ -5,9 +5,8 @@ import { orderedElement, parsePropsXml } from "../ooxml/props.js";
|
|
|
5
5
|
import { docxSchema } from "../schema/index.js";
|
|
6
6
|
import { A4_PORTRAIT, bodyWidth } from "./pageGeometry.js";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
NO_CELL_MARGINS,
|
|
8
|
+
cellDefaultsFor,
|
|
9
|
+
NO_CELL_SOURCES,
|
|
11
10
|
readCellFormat,
|
|
12
11
|
readInsideBorders,
|
|
13
12
|
readTableFormat,
|
|
@@ -81,7 +80,7 @@ function cellTemplate(width, defaults) {
|
|
|
81
80
|
tcPr,
|
|
82
81
|
tcW: readTableWidth(el, "tcW"),
|
|
83
82
|
// A new table writes no `tblCellMar`, so its cells take their padding from the stylesheet
|
|
84
|
-
format: readCellFormat(el, defaults
|
|
83
|
+
format: readCellFormat(el, defaults)
|
|
85
84
|
};
|
|
86
85
|
}
|
|
87
86
|
function cellNode(props) {
|
|
@@ -109,17 +108,18 @@ function createTableNode(rows, cols, geometry = A4_PORTRAIT) {
|
|
|
109
108
|
const gridCols = evenGridCols(cols, total);
|
|
110
109
|
const tblPr = tablePropsXml(total);
|
|
111
110
|
const tblPrEl = parsePropsXml(tblPr);
|
|
112
|
-
const inside = readInsideBorders(tblPrEl);
|
|
113
111
|
const outer = readTableFormat(tblPrEl);
|
|
112
|
+
const sources = {
|
|
113
|
+
...NO_CELL_SOURCES,
|
|
114
|
+
outer,
|
|
115
|
+
inside: readInsideBorders(tblPrEl)
|
|
116
|
+
};
|
|
114
117
|
const cellAt = (row, col) => cellTemplate(
|
|
115
118
|
gridCols[col],
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
),
|
|
121
|
-
outer,
|
|
122
|
-
inside
|
|
119
|
+
cellDefaultsFor(
|
|
120
|
+
{ top: row, bottom: row + 1, left: col, right: col + 1 },
|
|
121
|
+
{ rows, cols },
|
|
122
|
+
sources
|
|
123
123
|
)
|
|
124
124
|
);
|
|
125
125
|
return docxSchema.nodes.table.create(
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { docxSchema } from "../../../schema/index.js";
|
|
13
13
|
import { editShut, openStretches } from "../../../schema/guards.js";
|
|
14
14
|
import { documentFormatting } from "../../documentStyles.js";
|
|
15
|
+
import { paragraphPlacementAt } from "../../paragraphPlacement.js";
|
|
15
16
|
import {
|
|
16
17
|
activePieces,
|
|
17
18
|
caretPiece,
|
|
@@ -21,7 +22,11 @@ import {
|
|
|
21
22
|
function editedMark(state, target, edit) {
|
|
22
23
|
const context = documentFormatting(state);
|
|
23
24
|
const rPr = text(target.mark?.attrs.rPr);
|
|
24
|
-
const paragraph = resolveParagraph(
|
|
25
|
+
const paragraph = resolveParagraph(
|
|
26
|
+
target.pPr,
|
|
27
|
+
context,
|
|
28
|
+
paragraphPlacementAt(state.doc, target.from)
|
|
29
|
+
);
|
|
25
30
|
const next = editRunProps(
|
|
26
31
|
{ rPr, format: target.format },
|
|
27
32
|
inheritedRunFormat(rPr, paragraph, context),
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* All they do is change a paragraph's place in a list (its numbering id and level).
|
|
5
5
|
* Editing the formatting fragments belongs to `docx/paraProps`, and the list's appearance
|
|
6
6
|
* belongs to `numbering/`.
|
|
7
|
-
*
|
|
7
|
+
* Starting a list records its definition on the document node in the same transaction, and the
|
|
8
|
+
* export writes that definition into numbering.xml.
|
|
8
9
|
*/
|
|
9
10
|
import type { Node as PMNode } from "prosemirror-model";
|
|
10
11
|
import type { Command, EditorState } from "prosemirror-state";
|
|
@@ -24,6 +25,8 @@ export declare function listLevelChange(numbering: Numbering, node: PMNode, delt
|
|
|
24
25
|
export declare const increaseListLevel: Command;
|
|
25
26
|
/** Moves a list item one level back up, which is not the paragraph's own indent. What Shift+Tab does */
|
|
26
27
|
export declare const decreaseListLevel: Command;
|
|
28
|
+
/** Every numbering id a paragraph of this document wears */
|
|
29
|
+
export declare function numIdsIn(doc: PMNode): Set<number>;
|
|
27
30
|
/**
|
|
28
31
|
* Takes the selected paragraphs out of the list.
|
|
29
32
|
* Only the hanging indentation the marker sat in goes with it; an indentation the paragraph had
|
|
@@ -31,8 +34,8 @@ export declare const decreaseListLevel: Command;
|
|
|
31
34
|
*/
|
|
32
35
|
export declare const removeFromList: Command;
|
|
33
36
|
/**
|
|
34
|
-
* The kind of list the selected paragraphs belong to. Null when they are not a list
|
|
35
|
-
* are mixed.
|
|
37
|
+
* The kind of list the selected paragraphs belong to. Null when they are not a list, when nothing
|
|
38
|
+
* defines the list they are in, or when the kinds are mixed.
|
|
36
39
|
* It reads the paragraphs a lock leaves open, the same ones `editParagraphs` writes to: counting a
|
|
37
40
|
* locked paragraph that stays out of the list would keep the answer mixed, so the button would make
|
|
38
41
|
* a list a second time instead of taking it off.
|
|
@@ -5,12 +5,18 @@ import {
|
|
|
5
5
|
} from "../../docx/paraProps.js";
|
|
6
6
|
import { toParagraphFormat } from "../../model/format.js";
|
|
7
7
|
import {
|
|
8
|
+
listsWorn,
|
|
9
|
+
NEW_LISTS_ATTR,
|
|
10
|
+
newListsValue
|
|
11
|
+
} from "../../numbering/listRegistry.js";
|
|
12
|
+
import {
|
|
13
|
+
allocateList,
|
|
8
14
|
listFor,
|
|
9
|
-
listKindOf,
|
|
10
15
|
MAX_ILVL,
|
|
11
|
-
|
|
16
|
+
templateList
|
|
12
17
|
} from "../../numbering/listTemplate.js";
|
|
13
18
|
import { docxSchema } from "../../schema/index.js";
|
|
19
|
+
import { documentFormatting } from "../documentStyles.js";
|
|
14
20
|
import {
|
|
15
21
|
editableParagraphs,
|
|
16
22
|
editParagraphs,
|
|
@@ -24,18 +30,25 @@ import {
|
|
|
24
30
|
function listRefOf(node) {
|
|
25
31
|
return toParagraphFormat(node.attrs.format)?.numbering ?? null;
|
|
26
32
|
}
|
|
27
|
-
function changeParagraphs(state, dispatch, plan
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
function changeParagraphs(state, dispatch, plan, extras = {
|
|
34
|
+
alongside: pruneLists(documentNumbering(state).added)
|
|
35
|
+
}) {
|
|
36
|
+
return editParagraphs(
|
|
37
|
+
state,
|
|
38
|
+
dispatch,
|
|
39
|
+
(node) => {
|
|
40
|
+
const change = plan(node);
|
|
41
|
+
return change && withListNumbering(paragraphPPr(node), change);
|
|
42
|
+
},
|
|
43
|
+
extras
|
|
44
|
+
);
|
|
32
45
|
}
|
|
33
46
|
function indentForLevel(numbering, node, ref) {
|
|
34
47
|
const format = toParagraphFormat(node.attrs.format);
|
|
35
48
|
if (format?.indentStartPt === void 0 && format?.indentLeftPt === void 0) {
|
|
36
49
|
return { kind: "keep" };
|
|
37
50
|
}
|
|
38
|
-
const indent = listFor(numbering, ref.numId)
|
|
51
|
+
const indent = listFor(numbering, ref.numId)?.levels.get(ref.ilvl)?.indent;
|
|
39
52
|
return indent ? { kind: "level", indent } : { kind: "keep" };
|
|
40
53
|
}
|
|
41
54
|
function listLevelChange(numbering, node, delta) {
|
|
@@ -58,24 +71,50 @@ function levelShift(delta) {
|
|
|
58
71
|
}
|
|
59
72
|
var increaseListLevel = levelShift(1);
|
|
60
73
|
var decreaseListLevel = levelShift(-1);
|
|
61
|
-
function
|
|
62
|
-
const
|
|
63
|
-
|
|
74
|
+
function numIdsIn(doc) {
|
|
75
|
+
const worn = /* @__PURE__ */ new Set();
|
|
76
|
+
doc.descendants((node) => {
|
|
64
77
|
if (node.type !== docxSchema.nodes.paragraph) return true;
|
|
65
78
|
const ref = listRefOf(node);
|
|
66
|
-
if (ref)
|
|
79
|
+
if (ref) worn.add(ref.numId);
|
|
67
80
|
return false;
|
|
68
81
|
});
|
|
69
|
-
return
|
|
82
|
+
return worn;
|
|
83
|
+
}
|
|
84
|
+
function recordLists(tr, lists) {
|
|
85
|
+
tr.setDocAttribute(
|
|
86
|
+
NEW_LISTS_ATTR,
|
|
87
|
+
newListsValue(listsWorn(lists, numIdsIn(tr.doc)))
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
function pruneLists(lists) {
|
|
91
|
+
return (tr) => {
|
|
92
|
+
if (listsWorn(lists, numIdsIn(tr.doc)) !== lists) recordLists(tr, lists);
|
|
93
|
+
};
|
|
70
94
|
}
|
|
71
95
|
function startList(kind) {
|
|
72
96
|
return (state, dispatch) => {
|
|
73
97
|
if (!canStartNewList(state)) return false;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
98
|
+
const started = allocateList(
|
|
99
|
+
documentNumbering(state),
|
|
100
|
+
numIdsIn(state.doc),
|
|
101
|
+
templateList(kind)
|
|
102
|
+
);
|
|
103
|
+
return changeParagraphs(
|
|
104
|
+
state,
|
|
105
|
+
dispatch,
|
|
106
|
+
(node) => ({
|
|
107
|
+
numbering: { numId: started.numId, ilvl: listRefOf(node)?.ilvl ?? 0 },
|
|
108
|
+
indent: { kind: "keep" }
|
|
109
|
+
}),
|
|
110
|
+
{
|
|
111
|
+
formatting: {
|
|
112
|
+
...documentFormatting(state),
|
|
113
|
+
numbering: started.numbering
|
|
114
|
+
},
|
|
115
|
+
alongside: (tr) => recordLists(tr, started.numbering.added)
|
|
116
|
+
}
|
|
117
|
+
);
|
|
79
118
|
};
|
|
80
119
|
}
|
|
81
120
|
var removeFromList = (state, dispatch) => changeParagraphs(
|
|
@@ -84,8 +123,8 @@ var removeFromList = (state, dispatch) => changeParagraphs(
|
|
|
84
123
|
(node) => listRefOf(node) ? { numbering: null, indent: { kind: "clearHanging" } } : null
|
|
85
124
|
);
|
|
86
125
|
function kindOf(numbering, ref) {
|
|
87
|
-
const level = listFor(numbering, ref.numId)
|
|
88
|
-
if (!level) return
|
|
126
|
+
const level = listFor(numbering, ref.numId)?.levels.get(ref.ilvl);
|
|
127
|
+
if (!level) return null;
|
|
89
128
|
return level.format === "bullet" ? "bullet" : "numbered";
|
|
90
129
|
}
|
|
91
130
|
function activeListKind(state) {
|
|
@@ -107,14 +146,19 @@ function isInList(state) {
|
|
|
107
146
|
(spot) => listRefOf(spot.node) !== null
|
|
108
147
|
);
|
|
109
148
|
}
|
|
110
|
-
var leaveListAtLineStart = (state, dispatch) => editParagraphs(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
149
|
+
var leaveListAtLineStart = (state, dispatch) => editParagraphs(
|
|
150
|
+
state,
|
|
151
|
+
dispatch,
|
|
152
|
+
(node) => {
|
|
153
|
+
if (!listRefOf(node)) return null;
|
|
154
|
+
const unlisted = withListNumbering(paragraphPPr(node), {
|
|
155
|
+
numbering: null,
|
|
156
|
+
indent: { kind: "clearHanging" }
|
|
157
|
+
});
|
|
158
|
+
return unlisted && withLeftIndent(unlisted.pPr, 0);
|
|
159
|
+
},
|
|
160
|
+
{ alongside: pruneLists(documentNumbering(state).added) }
|
|
161
|
+
);
|
|
118
162
|
var leaveEmptyListItem = (state, dispatch) => {
|
|
119
163
|
const { empty, $from } = state.selection;
|
|
120
164
|
const paragraph = $from.parent;
|
|
@@ -132,6 +176,7 @@ export {
|
|
|
132
176
|
leaveEmptyListItem,
|
|
133
177
|
listLevelChange,
|
|
134
178
|
listRefOf,
|
|
179
|
+
numIdsIn,
|
|
135
180
|
removeFromList,
|
|
136
181
|
toggleBulletList,
|
|
137
182
|
toggleNumberedList
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
paragraphPPr,
|
|
20
20
|
selectedParagraphs
|
|
21
21
|
} from "../paragraphEdits.js";
|
|
22
|
+
import { paragraphPlacementAt } from "../paragraphPlacement.js";
|
|
22
23
|
function alignOf(node) {
|
|
23
24
|
return toParagraphFormat(node.attrs.format)?.align ?? "left";
|
|
24
25
|
}
|
|
@@ -78,7 +79,11 @@ function setParagraphStyle(styleId) {
|
|
|
78
79
|
if (styleIdOf(pPr) === styleId) return [];
|
|
79
80
|
const props = withParagraphStyle(pPr, styleId);
|
|
80
81
|
if (!props) return [];
|
|
81
|
-
const paragraph = resolveParagraph(
|
|
82
|
+
const paragraph = resolveParagraph(
|
|
83
|
+
props.pPr,
|
|
84
|
+
context,
|
|
85
|
+
paragraphPlacementAt(state.doc, spot.pos)
|
|
86
|
+
);
|
|
82
87
|
return [
|
|
83
88
|
{
|
|
84
89
|
spot,
|
|
@@ -112,7 +112,7 @@ function createEditorState(doc, options = {}) {
|
|
|
112
112
|
function editorStateForSession(opened, options = {}) {
|
|
113
113
|
return createEditorState(opened.doc, {
|
|
114
114
|
...options,
|
|
115
|
-
document: editorDocumentOf(opened.session)
|
|
115
|
+
document: editorDocumentOf(opened.session, opened.doc)
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
var sheetStyles = /* @__PURE__ */ new WeakMap();
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* behalf, and `editorDocumentOf` is the one place a session is read into editor values: a screen
|
|
8
8
|
* and a test that open the same document hold the same values.
|
|
9
9
|
*/
|
|
10
|
+
import type { Node as PMNode } from "prosemirror-model";
|
|
10
11
|
import { type EditorState, Plugin } from "prosemirror-state";
|
|
11
12
|
import { type FormattingContext, type ParagraphStyleOption } from "../docx/formatting";
|
|
12
13
|
import { type PageGeometry } from "../docx/pageGeometry";
|
|
@@ -22,8 +23,8 @@ export interface EditorDocument {
|
|
|
22
23
|
/** The styles the document defines for the style picker to offer */
|
|
23
24
|
readonly paragraphStyles: ParagraphStyleOption[];
|
|
24
25
|
/**
|
|
25
|
-
* Whether the
|
|
26
|
-
* A state built without opening a document assumes
|
|
26
|
+
* Whether the definition of a new list has somewhere to go, which is what the commands that
|
|
27
|
+
* start one ask. A state built without opening a document assumes it has and behaves as every
|
|
27
28
|
* state did before the question was asked.
|
|
28
29
|
*/
|
|
29
30
|
readonly canStartNewList: boolean;
|
|
@@ -39,15 +40,15 @@ export interface EditorDocument {
|
|
|
39
40
|
/** What a state built without an opened document answers: the same as nothing being written down */
|
|
40
41
|
export declare const NO_DOCUMENT: EditorDocument;
|
|
41
42
|
/** The one place an opened document is read into the values the editor holds */
|
|
42
|
-
export declare function editorDocumentOf(session: SessionStore): EditorDocument;
|
|
43
|
+
export declare function editorDocumentOf(session: SessionStore, doc: PMNode): EditorDocument;
|
|
43
44
|
/** The document the state was built for. `NO_DOCUMENT` for a state built without one */
|
|
44
45
|
export declare function documentOf(state: EditorState): EditorDocument;
|
|
45
46
|
/**
|
|
46
47
|
* Holds the snapshot for the lifetime of the state.
|
|
47
48
|
*
|
|
48
|
-
* It is derived again only where a document-level edit could have been recorded
|
|
49
|
-
*
|
|
50
|
-
* cached against that identity.
|
|
49
|
+
* It is derived again only where a document-level edit could have been recorded - the attrs of the
|
|
50
|
+
* document node, which is where such an edit is written - so an ordinary edit and a selection move
|
|
51
|
+
* both leave the same object behind, allowing the sheet's style to be cached against that identity.
|
|
51
52
|
*/
|
|
52
53
|
export declare function editorDocument(document: EditorDocument): Plugin<EditorDocument>;
|
|
53
54
|
/** The comment ids the opened document already spent, which a new comment may not take */
|
|
@@ -5,7 +5,9 @@ import {
|
|
|
5
5
|
NO_DOCUMENT_DEFAULTS,
|
|
6
6
|
NO_FORMATTING
|
|
7
7
|
} from "../docx/formatting.js";
|
|
8
|
+
import { canDefineNewList } from "../docx/newLists.js";
|
|
8
9
|
import { A4_PORTRAIT } from "../docx/pageGeometry.js";
|
|
10
|
+
import { NEW_LISTS_ATTR, newListsOf } from "../numbering/listRegistry.js";
|
|
9
11
|
var NO_IDS = /* @__PURE__ */ new Set();
|
|
10
12
|
var NO_PARAGRAPH_STYLES = [];
|
|
11
13
|
var NO_DOCUMENT = {
|
|
@@ -29,13 +31,20 @@ function reservedParaIds(session) {
|
|
|
29
31
|
}
|
|
30
32
|
return paraIds;
|
|
31
33
|
}
|
|
32
|
-
function
|
|
34
|
+
function formattingWithNewLists(formatting, doc) {
|
|
35
|
+
const added = newListsOf(doc.attrs[NEW_LISTS_ATTR]);
|
|
36
|
+
if (added.size === 0 && formatting.numbering.added.size === 0) {
|
|
37
|
+
return formatting;
|
|
38
|
+
}
|
|
39
|
+
return { ...formatting, numbering: { ...formatting.numbering, added } };
|
|
40
|
+
}
|
|
41
|
+
function editorDocumentOf(session, doc) {
|
|
33
42
|
return {
|
|
34
43
|
session,
|
|
35
|
-
formatting: session.formatting,
|
|
44
|
+
formatting: formattingWithNewLists(session.formatting, doc),
|
|
36
45
|
defaults: session.defaults,
|
|
37
46
|
paragraphStyles: session.paragraphStyles,
|
|
38
|
-
canStartNewList: session
|
|
47
|
+
canStartNewList: canDefineNewList(session),
|
|
39
48
|
geometry: session.geometry,
|
|
40
49
|
defaultTabStopPt: session.defaultTabStopPt,
|
|
41
50
|
reservedCommentIds: new Set(session.comments.byId.keys()),
|
|
@@ -46,15 +55,18 @@ var editorDocumentKey = new PluginKey("docxEditorDocument");
|
|
|
46
55
|
function documentOf(state) {
|
|
47
56
|
return editorDocumentKey.getState(state) ?? NO_DOCUMENT;
|
|
48
57
|
}
|
|
49
|
-
function
|
|
50
|
-
return
|
|
58
|
+
function derived(current, doc) {
|
|
59
|
+
return current.session === null ? {
|
|
60
|
+
...current,
|
|
61
|
+
formatting: formattingWithNewLists(current.formatting, doc)
|
|
62
|
+
} : editorDocumentOf(current.session, doc);
|
|
51
63
|
}
|
|
52
64
|
function editorDocument(document) {
|
|
53
65
|
return new Plugin({
|
|
54
66
|
key: editorDocumentKey,
|
|
55
67
|
state: {
|
|
56
68
|
init: () => document,
|
|
57
|
-
apply: (tr, current, old) =>
|
|
69
|
+
apply: (tr, current, old) => tr.doc.attrs === old.doc.attrs ? current : derived(current, tr.doc)
|
|
58
70
|
}
|
|
59
71
|
});
|
|
60
72
|
}
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { Slice } from "prosemirror-model";
|
|
2
|
-
import { type EditorState, Plugin } from "prosemirror-state";
|
|
2
|
+
import { type EditorState, Plugin, type Transaction } from "prosemirror-state";
|
|
3
3
|
import type { EditorView } from "prosemirror-view";
|
|
4
|
+
import { type NewLists } from "../numbering/listRegistry";
|
|
4
5
|
import type { ImageToInsert } from "./insertImage";
|
|
5
|
-
|
|
6
|
+
/** What a paste puts in: the content, and the definitions of the lists it started */
|
|
7
|
+
export interface PastedContent {
|
|
8
|
+
slice: Slice;
|
|
9
|
+
newLists: NewLists;
|
|
10
|
+
}
|
|
11
|
+
export declare function richHtmlSlice(state: EditorState, document: Document, source: string, images?: ReadonlyMap<string, ImageToInsert>): PastedContent | null;
|
|
12
|
+
/**
|
|
13
|
+
* The transaction a paste is put in with: the content, and the definitions of the lists it started
|
|
14
|
+
* recorded on the document node so that the export writes them out and undo takes them back.
|
|
15
|
+
*/
|
|
16
|
+
export declare function withPastedContent(tr: Transaction, content: PastedContent): Transaction;
|
|
6
17
|
export declare function insertRichHtml(view: EditorView, source: string): boolean;
|
|
7
18
|
export declare function insertClipboardData(view: EditorView, data: {
|
|
8
19
|
html?: string;
|