@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
package/dist/page/pageLayout.js
CHANGED
|
@@ -77,25 +77,18 @@ function pageLayout({
|
|
|
77
77
|
const pushes = [];
|
|
78
78
|
const cuts = [];
|
|
79
79
|
const splits = [];
|
|
80
|
-
const firstPage = {
|
|
81
|
-
page: 1,
|
|
82
|
-
bodyStart: 0,
|
|
83
|
-
exactPage: true,
|
|
84
|
-
crossed: false
|
|
85
|
-
};
|
|
80
|
+
const firstPage = { page: 1, bodyStart: 0, crossed: false };
|
|
86
81
|
const pages = [firstPage];
|
|
87
82
|
if (!(pageBodyHeight > 0)) {
|
|
88
83
|
return { pushes, cuts, splits, pages, bodyHeight: 0 };
|
|
89
84
|
}
|
|
90
85
|
let pageStart = 0;
|
|
91
86
|
let cursor = 0;
|
|
92
|
-
let exactPage = true;
|
|
93
87
|
const split = (y, crossed, forced) => {
|
|
94
|
-
if (!forced) exactPage = false;
|
|
95
88
|
const page = splits.length + 2;
|
|
96
|
-
splits.push({ y: round(y), page, forced,
|
|
89
|
+
splits.push({ y: round(y), page, forced, crossed });
|
|
97
90
|
pageStart = crossed ? y : y + pageStep;
|
|
98
|
-
pages.push({ page, bodyStart: round(pageStart),
|
|
91
|
+
pages.push({ page, bodyStart: round(pageStart), crossed });
|
|
99
92
|
};
|
|
100
93
|
const crossTo = (y) => {
|
|
101
94
|
while (y > pageStart + pageBodyHeight + TOLERANCE_PX) {
|
|
@@ -19,12 +19,6 @@ export interface PageMark {
|
|
|
19
19
|
height: number;
|
|
20
20
|
crossed: boolean;
|
|
21
21
|
}
|
|
22
|
-
/** The number laid on the corner of a page */
|
|
23
|
-
export interface PageBadge {
|
|
24
|
-
page: number;
|
|
25
|
-
top: number;
|
|
26
|
-
exactPage: boolean;
|
|
27
|
-
}
|
|
28
22
|
/** The paper area of one visual page, used to place its header and footer stories. */
|
|
29
23
|
export interface PageFace {
|
|
30
24
|
page: number;
|
|
@@ -41,7 +35,6 @@ export interface PageOverlay {
|
|
|
41
35
|
/** The sheet height with the last page filled out in full */
|
|
42
36
|
sheetHeight: number;
|
|
43
37
|
marks: PageMark[];
|
|
44
|
-
badges: PageBadge[];
|
|
45
38
|
pages: PageFace[];
|
|
46
39
|
}
|
|
47
40
|
interface PageLayoutOptions {
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
pageLayout,
|
|
16
16
|
pagePixels
|
|
17
17
|
} from "./pageLayout.js";
|
|
18
|
-
var BADGE_INSET_PX = 8;
|
|
19
18
|
function useFrameThrottle(run, hold) {
|
|
20
19
|
const latest = useRef({ run, hold });
|
|
21
20
|
const frame = useRef(0);
|
|
@@ -46,7 +45,7 @@ function useFrameThrottle(run, hold) {
|
|
|
46
45
|
}, []);
|
|
47
46
|
}
|
|
48
47
|
function sameOverlay(a, b) {
|
|
49
|
-
return a !== null && a.left === b.left && a.top === b.top && a.width === b.width && a.sheetHeight === b.sheetHeight && JSON.stringify(a.marks) === JSON.stringify(b.marks) && JSON.stringify(a.
|
|
48
|
+
return a !== null && a.left === b.left && a.top === b.top && a.width === b.width && a.sheetHeight === b.sheetHeight && JSON.stringify(a.marks) === JSON.stringify(b.marks) && JSON.stringify(a.pages) === JSON.stringify(b.pages);
|
|
50
49
|
}
|
|
51
50
|
function usePageLayout({
|
|
52
51
|
view,
|
|
@@ -84,13 +83,7 @@ function usePageLayout({
|
|
|
84
83
|
height: split.crossed ? 0 : PAGE_SPLIT_PX,
|
|
85
84
|
crossed: split.crossed
|
|
86
85
|
})),
|
|
87
|
-
//
|
|
88
|
-
// so the place it was split at is its corner
|
|
89
|
-
badges: layout.pages.map((start) => ({
|
|
90
|
-
page: start.page,
|
|
91
|
-
top: measured.contentTop + start.bodyStart - (start.crossed ? 0 : page.marginTop) + BADGE_INSET_PX,
|
|
92
|
-
exactPage: start.exactPage
|
|
93
|
-
})),
|
|
86
|
+
// A page crossed into has no margin, so the place it was split at is its top corner
|
|
94
87
|
pages: layout.pages.map((start) => {
|
|
95
88
|
const paperTop = measured.contentTop + start.bodyStart - (start.crossed ? 0 : page.marginTop);
|
|
96
89
|
return {
|
package/dist/schema/attrRoles.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// src/schema/attrRoles.ts
|
|
2
2
|
import { NodeType } from "prosemirror-model";
|
|
3
3
|
var NODE_ATTR_ROLES = {
|
|
4
|
+
doc: {
|
|
5
|
+
// The definitions of the lists started while editing. The export writes numbering.xml from
|
|
6
|
+
// them and nothing derives them again, so they are a source value the document node holds
|
|
7
|
+
newLists: { role: "source", class: "model" }
|
|
8
|
+
},
|
|
4
9
|
paragraph: {
|
|
5
10
|
srcId: { role: "session", class: "identity" },
|
|
6
11
|
pAttrs: { role: "source", class: "preserved" },
|
|
@@ -18,7 +23,9 @@ var NODE_ATTR_ROLES = {
|
|
|
18
23
|
gridChange: { role: "source", class: "preserved" },
|
|
19
24
|
format: { role: "display", class: "derived" },
|
|
20
25
|
styleInside: { role: "display", class: "derived" },
|
|
21
|
-
styleCellMargins: { role: "display", class: "derived" }
|
|
26
|
+
styleCellMargins: { role: "display", class: "derived" },
|
|
27
|
+
styleConditions: { role: "display", class: "derived" },
|
|
28
|
+
styleBands: { role: "display", class: "derived" }
|
|
22
29
|
},
|
|
23
30
|
tableRow: {
|
|
24
31
|
trAttrs: { role: "source", class: "preserved" },
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Schema } from "prosemirror-model";
|
|
3
3
|
import {
|
|
4
4
|
spanCount,
|
|
5
|
+
toBandSizes,
|
|
5
6
|
toCellFormat,
|
|
6
7
|
toCellMargins,
|
|
7
8
|
toColWidth,
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
toRowFormat,
|
|
12
13
|
toRunFormat,
|
|
13
14
|
toTableFormat,
|
|
15
|
+
toTableStyleConditions,
|
|
14
16
|
toTableWidth
|
|
15
17
|
} from "../model/format.js";
|
|
16
18
|
import {
|
|
@@ -112,7 +114,16 @@ var DOCX_RAW_SELECTOR = [
|
|
|
112
114
|
].map((className) => `div[data-src].${className}`).join(", ");
|
|
113
115
|
var docxSchema = new Schema({
|
|
114
116
|
nodes: {
|
|
115
|
-
doc: {
|
|
117
|
+
doc: {
|
|
118
|
+
content: "block+",
|
|
119
|
+
attrs: {
|
|
120
|
+
/**
|
|
121
|
+
* The definitions of the lists started while editing, which the export writes into
|
|
122
|
+
* numbering.xml. Read back through `numbering/listRegistry`.
|
|
123
|
+
*/
|
|
124
|
+
newLists: { default: null }
|
|
125
|
+
}
|
|
126
|
+
},
|
|
116
127
|
paragraph: {
|
|
117
128
|
group: "block modelled",
|
|
118
129
|
content: "inline*",
|
|
@@ -202,7 +213,15 @@ var docxSchema = new Schema({
|
|
|
202
213
|
/** The lines between cells the table style laid down, so an edit can derive them again */
|
|
203
214
|
styleInside: { default: null },
|
|
204
215
|
/** The cell margins the table style laid down, carried along for the same reason */
|
|
205
|
-
styleCellMargins: { default: null }
|
|
216
|
+
styleCellMargins: { default: null },
|
|
217
|
+
/**
|
|
218
|
+
* What the table style dresses each part of a table with (`w:tblStylePr`), by the part it
|
|
219
|
+
* covers. Which of them a cell takes is worked out from where it sits and the table's own
|
|
220
|
+
* `w:tblLook`, so an edit that moves the grid derives them again
|
|
221
|
+
*/
|
|
222
|
+
styleConditions: { default: null },
|
|
223
|
+
/** How many rows and columns one band of the table style is made of */
|
|
224
|
+
styleBands: { default: null }
|
|
206
225
|
},
|
|
207
226
|
toDOM(node) {
|
|
208
227
|
const format = toTableFormat(node.attrs.format);
|
|
@@ -223,7 +242,11 @@ var docxSchema = new Schema({
|
|
|
223
242
|
),
|
|
224
243
|
"data-style-margins": formatJson(
|
|
225
244
|
toCellMargins(node.attrs.styleCellMargins)
|
|
226
|
-
)
|
|
245
|
+
),
|
|
246
|
+
"data-style-conditions": formatJson(
|
|
247
|
+
toTableStyleConditions(node.attrs.styleConditions)
|
|
248
|
+
),
|
|
249
|
+
"data-style-bands": formatJson(toBandSizes(node.attrs.styleBands))
|
|
227
250
|
};
|
|
228
251
|
const body = ["tbody", 0];
|
|
229
252
|
if (gridCols.length === 0) return ["table", attrs, body];
|
|
@@ -262,6 +285,12 @@ var docxSchema = new Schema({
|
|
|
262
285
|
),
|
|
263
286
|
styleCellMargins: toCellMargins(
|
|
264
287
|
parseJson(dom.getAttribute("data-style-margins"))
|
|
288
|
+
),
|
|
289
|
+
styleConditions: toTableStyleConditions(
|
|
290
|
+
parseJson(dom.getAttribute("data-style-conditions"))
|
|
291
|
+
),
|
|
292
|
+
styleBands: toBandSizes(
|
|
293
|
+
parseJson(dom.getAttribute("data-style-bands"))
|
|
265
294
|
)
|
|
266
295
|
};
|
|
267
296
|
}
|
|
@@ -61,8 +61,6 @@ export declare const editorClassNames: {
|
|
|
61
61
|
readonly pageSplit: "docx-editor-page-split";
|
|
62
62
|
/** The line drawn where a block that cannot be pushed down crosses a page */
|
|
63
63
|
readonly pageCrossed: "docx-editor-page-crossed";
|
|
64
|
-
/** The page number laid on the top corner of a page */
|
|
65
|
-
readonly pageBadge: "docx-editor-page-badge";
|
|
66
64
|
/** A first-section header story projected into a visual page margin */
|
|
67
65
|
readonly pageHeader: "docx-editor-page-header";
|
|
68
66
|
/** A first-section footer story projected into a visual page margin */
|
|
@@ -165,6 +163,19 @@ export declare const editorCssVariables: {
|
|
|
165
163
|
readonly lineHeight: "--docx-editor-line-height";
|
|
166
164
|
/** The hanging indent width the list marker sits in */
|
|
167
165
|
readonly markerWidth: "--docx-editor-marker-width";
|
|
166
|
+
/** The room kept after the list marker, which a level asking for no tab closes up (`w:suff`) */
|
|
167
|
+
readonly markerGap: "--docx-editor-marker-gap";
|
|
168
|
+
/** Where the marker sits inside the width kept for it (`w:lvlJc`) */
|
|
169
|
+
readonly markerAlign: "--docx-editor-marker-align";
|
|
170
|
+
/**
|
|
171
|
+
* The formatting the numbering level puts on its marker (`lvl/rPr`). It dresses the marker
|
|
172
|
+
* alone, so it reaches the pseudo-element that draws it and nothing the paragraph holds
|
|
173
|
+
*/
|
|
174
|
+
readonly markerFontWeight: "--docx-editor-marker-font-weight";
|
|
175
|
+
readonly markerFontStyle: "--docx-editor-marker-font-style";
|
|
176
|
+
readonly markerColor: "--docx-editor-marker-color";
|
|
177
|
+
readonly markerFontSize: "--docx-editor-marker-font-size";
|
|
178
|
+
readonly markerFontFamily: "--docx-editor-marker-font-family";
|
|
168
179
|
/** The width calculated for a tab using custom paragraph stops. */
|
|
169
180
|
readonly tabWidth: "--docx-editor-tab-width";
|
|
170
181
|
/** The paper height, grown to match the page count */
|
|
@@ -56,8 +56,6 @@ var editorClassNames = {
|
|
|
56
56
|
pageSplit: `${PREFIX}-page-split`,
|
|
57
57
|
/** The line drawn where a block that cannot be pushed down crosses a page */
|
|
58
58
|
pageCrossed: `${PREFIX}-page-crossed`,
|
|
59
|
-
/** The page number laid on the top corner of a page */
|
|
60
|
-
pageBadge: `${PREFIX}-page-badge`,
|
|
61
59
|
/** A first-section header story projected into a visual page margin */
|
|
62
60
|
pageHeader: `${PREFIX}-page-header`,
|
|
63
61
|
/** A first-section footer story projected into a visual page margin */
|
|
@@ -161,6 +159,19 @@ var editorCssVariables = {
|
|
|
161
159
|
lineHeight: `--${PREFIX}-line-height`,
|
|
162
160
|
/** The hanging indent width the list marker sits in */
|
|
163
161
|
markerWidth: `--${PREFIX}-marker-width`,
|
|
162
|
+
/** The room kept after the list marker, which a level asking for no tab closes up (`w:suff`) */
|
|
163
|
+
markerGap: `--${PREFIX}-marker-gap`,
|
|
164
|
+
/** Where the marker sits inside the width kept for it (`w:lvlJc`) */
|
|
165
|
+
markerAlign: `--${PREFIX}-marker-align`,
|
|
166
|
+
/**
|
|
167
|
+
* The formatting the numbering level puts on its marker (`lvl/rPr`). It dresses the marker
|
|
168
|
+
* alone, so it reaches the pseudo-element that draws it and nothing the paragraph holds
|
|
169
|
+
*/
|
|
170
|
+
markerFontWeight: `--${PREFIX}-marker-font-weight`,
|
|
171
|
+
markerFontStyle: `--${PREFIX}-marker-font-style`,
|
|
172
|
+
markerColor: `--${PREFIX}-marker-color`,
|
|
173
|
+
markerFontSize: `--${PREFIX}-marker-font-size`,
|
|
174
|
+
markerFontFamily: `--${PREFIX}-marker-font-family`,
|
|
164
175
|
/** The width calculated for a tab using custom paragraph stops. */
|
|
165
176
|
tabWidth: `--${PREFIX}-tab-width`,
|
|
166
177
|
/** The paper height, grown to match the page count */
|
package/dist/styles.css
CHANGED
|
@@ -677,22 +677,6 @@ button.docx-editor-comment-body {
|
|
|
677
677
|
border-top: 1px dotted rgb(26 79 208 / 40%);
|
|
678
678
|
}
|
|
679
679
|
|
|
680
|
-
/* The page number. Laid on the top right corner of every page */
|
|
681
|
-
.docx-editor-page-badge {
|
|
682
|
-
position: absolute;
|
|
683
|
-
right: 10px;
|
|
684
|
-
min-width: 18px;
|
|
685
|
-
padding: 0 6px;
|
|
686
|
-
border-radius: 9px;
|
|
687
|
-
background: rgb(0 0 0 / 6%);
|
|
688
|
-
color: #808080;
|
|
689
|
-
font-family: system-ui, sans-serif;
|
|
690
|
-
font-size: 10px;
|
|
691
|
-
line-height: 18px;
|
|
692
|
-
text-align: center;
|
|
693
|
-
letter-spacing: 0.02em;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
680
|
/* Display-only projections of the first section's header and footer stories. */
|
|
697
681
|
.docx-editor-page-header,
|
|
698
682
|
.docx-editor-page-footer {
|
|
@@ -720,14 +704,28 @@ button.docx-editor-comment-body {
|
|
|
720
704
|
* the space.
|
|
721
705
|
* Because box-sizing is border-box, as long as the number fits inside the space it
|
|
722
706
|
* does not push where the body starts.
|
|
707
|
+
*
|
|
708
|
+
* A level that asks for a space or for nothing after its number (w:suff) keeps no
|
|
709
|
+
* space at all, so both variables are set to zero and the body starts right after
|
|
710
|
+
* the number. Where the number sits inside the space is the level's w:lvlJc.
|
|
711
|
+
*
|
|
712
|
+
* The level dresses its number and nothing else (lvl/rPr), so its character
|
|
713
|
+
* formatting arrives as variables read here rather than as anything the paragraph
|
|
714
|
+
* wears. Where the level writes none, the number is drawn like the text it stands
|
|
715
|
+
* in front of.
|
|
723
716
|
*/
|
|
724
717
|
.docx-editor-p[data-marker]::before {
|
|
725
718
|
content: attr(data-marker);
|
|
726
719
|
display: inline-block;
|
|
727
720
|
box-sizing: border-box;
|
|
728
721
|
min-width: var(--docx-editor-marker-width, 18pt);
|
|
729
|
-
padding-right: 4pt;
|
|
730
|
-
text-align: left;
|
|
722
|
+
padding-right: var(--docx-editor-marker-gap, 4pt);
|
|
723
|
+
text-align: var(--docx-editor-marker-align, left);
|
|
724
|
+
font-weight: var(--docx-editor-marker-font-weight, inherit);
|
|
725
|
+
font-style: var(--docx-editor-marker-font-style, inherit);
|
|
726
|
+
font-size: var(--docx-editor-marker-font-size, inherit);
|
|
727
|
+
font-family: var(--docx-editor-marker-font-family, inherit);
|
|
728
|
+
color: var(--docx-editor-marker-color, inherit);
|
|
731
729
|
/* Keeps the paragraph's hanging indent (text-indent) from being inherited and shifting the number again inside its own box */
|
|
732
730
|
text-indent: 0;
|
|
733
731
|
user-select: none;
|
|
@@ -38,8 +38,7 @@ function planChanges(rect, edit) {
|
|
|
38
38
|
const next = editCellProps(
|
|
39
39
|
text(cell.attrs.tcPr),
|
|
40
40
|
edit(rect, pos),
|
|
41
|
-
cellDefaultsAt(rect.map, pos, sources)
|
|
42
|
-
sources.margins
|
|
41
|
+
cellDefaultsAt(rect.map, pos, sources)
|
|
43
42
|
);
|
|
44
43
|
if (!next) continue;
|
|
45
44
|
changes.push({
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The lines a cell draws because of where it sits in the grid.
|
|
2
|
+
* The lines and the fill a cell draws because of where it sits in the grid.
|
|
3
3
|
*
|
|
4
4
|
* Every line of a table is drawn by its cells (see `docx/tableFormatting`), so which line a side
|
|
5
|
-
* falls back on depends on where in the grid the cell sits
|
|
6
|
-
* formatting, which is what a background has to
|
|
7
|
-
*
|
|
8
|
-
* leave the table with no line along its bottom.
|
|
5
|
+
* falls back on depends on where in the grid the cell sits, and so does which parts of the table
|
|
6
|
+
* style dress it. A new cell inherits its neighbour's formatting, which is what a background has to
|
|
7
|
+
* do but not a line: the row appended under the last one would draw the table's outer line against
|
|
8
|
+
* the row above it, and deleting the last row would leave the table with no line along its bottom.
|
|
9
|
+
* A row added under the header row is likewise no header row.
|
|
9
10
|
*
|
|
10
11
|
* So the cells of a table whose grid moved derive their display values again, along the same path
|
|
11
12
|
* the import takes. What a cell wrote down itself lives in its `w:tcPr` and is read straight back
|
|
@@ -14,21 +15,16 @@
|
|
|
14
15
|
* deriver that runs them after an edit is `editor/plugins/tableDisplay`.
|
|
15
16
|
*/
|
|
16
17
|
import type { Node as PMNode } from "prosemirror-model";
|
|
17
|
-
import { type
|
|
18
|
-
import { type CellMargins, type InsideBorders, type TableFormat } from "../model/format";
|
|
18
|
+
import { type CellDefaults, type TableCellSources } from "../docx/tableFormatting";
|
|
19
19
|
import type { NodeAttrs, TableGridMap } from "./format";
|
|
20
20
|
/**
|
|
21
|
-
* What
|
|
21
|
+
* What this table lays down for its cells to draw.
|
|
22
22
|
* The values a table style laid down are not in the `tblPr`, so the table carries them separately.
|
|
23
|
+
* A node never changes once it is built, so what is read out of one is read once.
|
|
23
24
|
*/
|
|
24
|
-
export interface TableCellSources {
|
|
25
|
-
outer: TableFormat | null;
|
|
26
|
-
inside: InsideBorders;
|
|
27
|
-
margins: CellMargins;
|
|
28
|
-
}
|
|
29
25
|
export declare function tableCellSources(table: PMNode): TableCellSources;
|
|
30
|
-
/**
|
|
31
|
-
export declare function cellDefaultsAt(map: TableGridMap, pos: number, sources: TableCellSources):
|
|
26
|
+
/** What the cell at this position falls back on for everything it did not write down itself */
|
|
27
|
+
export declare function cellDefaultsAt(map: TableGridMap, pos: number, sources: TableCellSources): CellDefaults;
|
|
32
28
|
export interface CellFix {
|
|
33
29
|
/** The position of the cell within the table's content */
|
|
34
30
|
pos: number;
|
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
// src/table/gridBorders.ts
|
|
2
2
|
import { TableMap } from "prosemirror-tables";
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
cellDefaultsFor,
|
|
5
5
|
cellMarginsOf,
|
|
6
|
-
gridEdgesOf,
|
|
7
6
|
insideBordersOf,
|
|
8
7
|
layerCellMargins,
|
|
9
8
|
layerInsideBorders,
|
|
10
|
-
|
|
9
|
+
NO_BAND_SIZES,
|
|
10
|
+
NO_CELL_DEFAULTS,
|
|
11
11
|
NO_CELL_MARGINS,
|
|
12
12
|
NO_INSIDE_BORDERS,
|
|
13
|
-
|
|
13
|
+
NO_TABLE_STYLE_CONDITIONS,
|
|
14
|
+
readCellProps,
|
|
15
|
+
readTableLook,
|
|
16
|
+
tblStyleIdOf
|
|
14
17
|
} from "../docx/tableFormatting.js";
|
|
15
18
|
import {
|
|
16
19
|
spanCount,
|
|
20
|
+
toBandSizes,
|
|
17
21
|
toCellFormat,
|
|
18
22
|
toCellMargins,
|
|
19
23
|
toInsideBorders,
|
|
20
|
-
toTableFormat
|
|
24
|
+
toTableFormat,
|
|
25
|
+
toTableStyleConditions
|
|
21
26
|
} from "../model/format.js";
|
|
27
|
+
import { parsePropsXml } from "../ooxml/props.js";
|
|
22
28
|
function text(value) {
|
|
23
29
|
return typeof value === "string" ? value : null;
|
|
24
30
|
}
|
|
25
31
|
function tableCellSources(table) {
|
|
32
|
+
const known = sourcesByTable.get(table);
|
|
33
|
+
if (known) return known;
|
|
26
34
|
const tblPr = text(table.attrs.tblPr);
|
|
27
|
-
|
|
35
|
+
const props = tblPr === null ? null : parsePropsXml(tblPr);
|
|
36
|
+
const sources = {
|
|
28
37
|
outer: toTableFormat(table.attrs.format),
|
|
29
38
|
inside: layerInsideBorders(
|
|
30
39
|
toInsideBorders(table.attrs.styleInside) ?? NO_INSIDE_BORDERS,
|
|
@@ -33,14 +42,23 @@ function tableCellSources(table) {
|
|
|
33
42
|
margins: layerCellMargins(
|
|
34
43
|
toCellMargins(table.attrs.styleCellMargins) ?? NO_CELL_MARGINS,
|
|
35
44
|
cellMarginsOf(tblPr)
|
|
36
|
-
)
|
|
45
|
+
),
|
|
46
|
+
look: readTableLook(props),
|
|
47
|
+
bands: toBandSizes(table.attrs.styleBands) ?? NO_BAND_SIZES,
|
|
48
|
+
conditions: toTableStyleConditions(table.attrs.styleConditions) ?? NO_TABLE_STYLE_CONDITIONS,
|
|
49
|
+
// The style the paragraphs inside resolve against; what it lays down for the cells is already
|
|
50
|
+
// in `styleConditions`
|
|
51
|
+
styleId: tblStyleIdOf(props)
|
|
37
52
|
};
|
|
53
|
+
sourcesByTable.set(table, sources);
|
|
54
|
+
return sources;
|
|
38
55
|
}
|
|
56
|
+
var sourcesByTable = /* @__PURE__ */ new WeakMap();
|
|
39
57
|
function cellDefaultsAt(map, pos, sources) {
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
sources
|
|
58
|
+
return cellDefaultsFor(
|
|
59
|
+
map.findCell(pos),
|
|
60
|
+
{ rows: map.height, cols: map.width },
|
|
61
|
+
sources
|
|
44
62
|
);
|
|
45
63
|
}
|
|
46
64
|
var CELL_FORMAT_KEYS = [
|
|
@@ -106,16 +124,12 @@ function cellFixes(table) {
|
|
|
106
124
|
const cell = table.nodeAt(pos);
|
|
107
125
|
if (!cell) continue;
|
|
108
126
|
const tcPr = text(cell.attrs.tcPr);
|
|
109
|
-
const format = readCellProps(
|
|
110
|
-
tcPr,
|
|
111
|
-
cellDefaultsAt(map, pos, sources),
|
|
112
|
-
sources.margins
|
|
113
|
-
);
|
|
127
|
+
const format = readCellProps(tcPr, cellDefaultsAt(map, pos, sources));
|
|
114
128
|
cells.set(pos, {
|
|
115
129
|
pos,
|
|
116
130
|
attrs: cell.attrs,
|
|
117
131
|
format: { ...format },
|
|
118
|
-
direct: readCellProps(tcPr,
|
|
132
|
+
direct: readCellProps(tcPr, NO_CELL_DEFAULTS)
|
|
119
133
|
});
|
|
120
134
|
}
|
|
121
135
|
reconcileSharedBorders(map, cells);
|
|
@@ -144,7 +158,7 @@ function sameCellFormattingInputs(a, b) {
|
|
|
144
158
|
);
|
|
145
159
|
}
|
|
146
160
|
function sameFormattingInputs(a, b) {
|
|
147
|
-
return sameGrid(a, b) && a.attrs.tblPr === b.attrs.tblPr && a.attrs.format === b.attrs.format && a.attrs.styleInside === b.attrs.styleInside && a.attrs.styleCellMargins === b.attrs.styleCellMargins && sameCellFormattingInputs(a, b);
|
|
161
|
+
return sameGrid(a, b) && a.attrs.tblPr === b.attrs.tblPr && a.attrs.format === b.attrs.format && a.attrs.styleInside === b.attrs.styleInside && a.attrs.styleCellMargins === b.attrs.styleCellMargins && a.attrs.styleConditions === b.attrs.styleConditions && a.attrs.styleBands === b.attrs.styleBands && sameCellFormattingInputs(a, b);
|
|
148
162
|
}
|
|
149
163
|
export {
|
|
150
164
|
cellDefaultsAt,
|