@portone/docx-editor 0.1.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 +7 -0
- package/CONTRIBUTING.md +63 -0
- package/LICENSE +203 -0
- package/README.md +48 -0
- package/assets/editor.png +0 -0
- package/dist/DocxEditor.d.ts +123 -0
- package/dist/DocxEditor.js +348 -0
- package/dist/core.d.ts +36 -0
- package/dist/core.js +38 -0
- package/dist/docx/comments/constants.d.ts +8 -0
- package/dist/docx/comments/constants.js +20 -0
- package/dist/docx/comments/model.d.ts +37 -0
- package/dist/docx/comments/model.js +104 -0
- package/dist/docx/comments/reading.d.ts +36 -0
- package/dist/docx/comments/reading.js +149 -0
- package/dist/docx/comments/writing.d.ts +11 -0
- package/dist/docx/comments/writing.js +327 -0
- package/dist/docx/comments.d.ts +3 -0
- package/dist/docx/comments.js +4 -0
- package/dist/docx/container.d.ts +12 -0
- package/dist/docx/container.js +130 -0
- package/dist/docx/documentSettings.d.ts +4 -0
- package/dist/docx/documentSettings.js +14 -0
- package/dist/docx/exportDocx.d.ts +15 -0
- package/dist/docx/exportDocx.js +163 -0
- package/dist/docx/exportRefs.d.ts +16 -0
- package/dist/docx/exportRefs.js +10 -0
- package/dist/docx/formatting/direct.d.ts +30 -0
- package/dist/docx/formatting/direct.js +201 -0
- package/dist/docx/formatting/effectiveParagraph.d.ts +15 -0
- package/dist/docx/formatting/effectiveParagraph.js +81 -0
- package/dist/docx/formatting/styles.d.ts +67 -0
- package/dist/docx/formatting/styles.js +165 -0
- package/dist/docx/formatting/tabStops.d.ts +8 -0
- package/dist/docx/formatting/tabStops.js +65 -0
- package/dist/docx/formatting.d.ts +4 -0
- package/dist/docx/formatting.js +4 -0
- package/dist/docx/headersFooters.d.ts +36 -0
- package/dist/docx/headersFooters.js +218 -0
- package/dist/docx/hyperlink.d.ts +75 -0
- package/dist/docx/hyperlink.js +71 -0
- package/dist/docx/importDocx.d.ts +21 -0
- package/dist/docx/importDocx.js +263 -0
- package/dist/docx/importParagraph.d.ts +32 -0
- package/dist/docx/importParagraph.js +308 -0
- package/dist/docx/importTable.d.ts +9 -0
- package/dist/docx/importTable.js +275 -0
- package/dist/docx/media.d.ts +60 -0
- package/dist/docx/media.js +213 -0
- package/dist/docx/notes.d.ts +22 -0
- package/dist/docx/notes.js +71 -0
- package/dist/docx/pageGeometry.d.ts +75 -0
- package/dist/docx/pageGeometry.js +88 -0
- package/dist/docx/paraProps.d.ts +74 -0
- package/dist/docx/paraProps.js +167 -0
- package/dist/docx/propsXml.d.ts +49 -0
- package/dist/docx/propsXml.js +302 -0
- package/dist/docx/relationships.d.ts +42 -0
- package/dist/docx/relationships.js +94 -0
- package/dist/docx/runProps.d.ts +51 -0
- package/dist/docx/runProps.js +207 -0
- package/dist/docx/scan.d.ts +20 -0
- package/dist/docx/scan.js +110 -0
- package/dist/docx/sdt.d.ts +56 -0
- package/dist/docx/sdt.js +104 -0
- package/dist/docx/sdtProps.d.ts +18 -0
- package/dist/docx/sdtProps.js +11 -0
- package/dist/docx/serializeBlock.d.ts +4 -0
- package/dist/docx/serializeBlock.js +30 -0
- package/dist/docx/serializeParagraph.d.ts +15 -0
- package/dist/docx/serializeParagraph.js +208 -0
- package/dist/docx/serializeTable.d.ts +12 -0
- package/dist/docx/serializeTable.js +134 -0
- package/dist/docx/session.d.ts +81 -0
- package/dist/docx/session.js +79 -0
- package/dist/docx/tableFormatting/editing.d.ts +64 -0
- package/dist/docx/tableFormatting/editing.js +318 -0
- package/dist/docx/tableFormatting/reading.d.ts +96 -0
- package/dist/docx/tableFormatting/reading.js +221 -0
- package/dist/docx/tableFormatting.d.ts +2 -0
- package/dist/docx/tableFormatting.js +3 -0
- package/dist/docx/tableTemplate.d.ts +22 -0
- package/dist/docx/tableTemplate.js +111 -0
- package/dist/docx/theme.d.ts +40 -0
- package/dist/docx/theme.js +61 -0
- package/dist/docx/uniqueControls.d.ts +14 -0
- package/dist/docx/uniqueControls.js +62 -0
- package/dist/download.d.ts +57 -0
- package/dist/download.js +44 -0
- package/dist/editor/clipboard/images.d.ts +14 -0
- package/dist/editor/clipboard/images.js +158 -0
- package/dist/editor/clipboard/inlineFormatting.d.ts +21 -0
- package/dist/editor/clipboard/inlineFormatting.js +232 -0
- package/dist/editor/commands/breakCommands.d.ts +8 -0
- package/dist/editor/commands/breakCommands.js +19 -0
- package/dist/editor/commands/canRunCommand.d.ts +6 -0
- package/dist/editor/commands/canRunCommand.js +10 -0
- package/dist/editor/commands/commentCommands.d.ts +3 -0
- package/dist/editor/commands/commentCommands.js +4 -0
- package/dist/editor/commands/comments/editing.d.ts +21 -0
- package/dist/editor/commands/comments/editing.js +305 -0
- package/dist/editor/commands/comments/model.d.ts +31 -0
- package/dist/editor/commands/comments/model.js +0 -0
- package/dist/editor/commands/comments/reading.d.ts +8 -0
- package/dist/editor/commands/comments/reading.js +58 -0
- package/dist/editor/commands/formatting/editing.d.ts +32 -0
- package/dist/editor/commands/formatting/editing.js +138 -0
- package/dist/editor/commands/formatting/reading.d.ts +57 -0
- package/dist/editor/commands/formatting/reading.js +82 -0
- package/dist/editor/commands/formatting/shared.d.ts +32 -0
- package/dist/editor/commands/formatting/shared.js +53 -0
- package/dist/editor/commands/formattingCommands.d.ts +2 -0
- package/dist/editor/commands/formattingCommands.js +3 -0
- package/dist/editor/commands/historyCommands.d.ts +11 -0
- package/dist/editor/commands/historyCommands.js +16 -0
- package/dist/editor/commands/indentCommands.d.ts +15 -0
- package/dist/editor/commands/indentCommands.js +44 -0
- package/dist/editor/commands/index.d.ts +82 -0
- package/dist/editor/commands/index.js +171 -0
- package/dist/editor/commands/linkCommands.d.ts +56 -0
- package/dist/editor/commands/linkCommands.js +146 -0
- package/dist/editor/commands/listCommands.d.ts +58 -0
- package/dist/editor/commands/listCommands.js +140 -0
- package/dist/editor/commands/lockCommands.d.ts +47 -0
- package/dist/editor/commands/lockCommands.js +198 -0
- package/dist/editor/commands/noteQueries.d.ts +12 -0
- package/dist/editor/commands/noteQueries.js +29 -0
- package/dist/editor/commands/paragraphCommands.d.ts +59 -0
- package/dist/editor/commands/paragraphCommands.js +113 -0
- package/dist/editor/commands/spacingCommands.d.ts +23 -0
- package/dist/editor/commands/spacingCommands.js +48 -0
- package/dist/editor/commands/tabCommands.d.ts +5 -0
- package/dist/editor/commands/tabCommands.js +65 -0
- package/dist/editor/createEditor.d.ts +59 -0
- package/dist/editor/createEditor.js +160 -0
- package/dist/editor/documentStyles.d.ts +60 -0
- package/dist/editor/documentStyles.js +80 -0
- package/dist/editor/externalClipboard.d.ts +11 -0
- package/dist/editor/externalClipboard.js +323 -0
- package/dist/editor/imageFiles.d.ts +74 -0
- package/dist/editor/imageFiles.js +173 -0
- package/dist/editor/insertImage.d.ts +31 -0
- package/dist/editor/insertImage.js +35 -0
- package/dist/editor/insertTable.d.ts +18 -0
- package/dist/editor/insertTable.js +44 -0
- package/dist/editor/paragraphEdits.d.ts +42 -0
- package/dist/editor/paragraphEdits.js +59 -0
- package/dist/editor/plainText.d.ts +3 -0
- package/dist/editor/plainText.js +50 -0
- package/dist/editor/plugins/bookmarkProtection.d.ts +3 -0
- package/dist/editor/plugins/bookmarkProtection.js +28 -0
- package/dist/editor/plugins/columnResize.d.ts +27 -0
- package/dist/editor/plugins/columnResize.js +192 -0
- package/dist/editor/plugins/commentDecorations.d.ts +3 -0
- package/dist/editor/plugins/commentDecorations.js +23 -0
- package/dist/editor/plugins/commentReservations.d.ts +5 -0
- package/dist/editor/plugins/commentReservations.js +26 -0
- package/dist/editor/plugins/dropCaret.d.ts +10 -0
- package/dist/editor/plugins/dropCaret.js +11 -0
- package/dist/editor/plugins/imagePaste.d.ts +8 -0
- package/dist/editor/plugins/imagePaste.js +265 -0
- package/dist/editor/plugins/keymap.d.ts +5 -0
- package/dist/editor/plugins/keymap.js +94 -0
- package/dist/editor/plugins/linkPanel.d.ts +23 -0
- package/dist/editor/plugins/linkPanel.js +39 -0
- package/dist/editor/plugins/listInputRules.d.ts +14 -0
- package/dist/editor/plugins/listInputRules.js +36 -0
- package/dist/editor/plugins/lockedContent.d.ts +6 -0
- package/dist/editor/plugins/lockedContent.js +41 -0
- package/dist/editor/plugins/noteProtection.d.ts +3 -0
- package/dist/editor/plugins/noteProtection.js +25 -0
- package/dist/editor/plugins/numberingDecorations.d.ts +42 -0
- package/dist/editor/plugins/numberingDecorations.js +110 -0
- package/dist/editor/plugins/rowResize.d.ts +15 -0
- package/dist/editor/plugins/rowResize.js +196 -0
- package/dist/editor/plugins/styledParagraphs.d.ts +15 -0
- package/dist/editor/plugins/styledParagraphs.js +65 -0
- package/dist/editor/plugins/tabCaret.d.ts +3 -0
- package/dist/editor/plugins/tabCaret.js +126 -0
- package/dist/editor/plugins/tabDecorations.d.ts +11 -0
- package/dist/editor/plugins/tabDecorations.js +87 -0
- package/dist/editor/plugins/tabLayout.d.ts +16 -0
- package/dist/editor/plugins/tabLayout.js +328 -0
- package/dist/editor/plugins/tabPointer.d.ts +7 -0
- package/dist/editor/plugins/tabPointer.js +95 -0
- package/dist/editor/plugins/tableContextMenu.d.ts +21 -0
- package/dist/editor/plugins/tableContextMenu.js +88 -0
- package/dist/editor/plugins/textContextMenu.d.ts +15 -0
- package/dist/editor/plugins/textContextMenu.js +90 -0
- package/dist/editor/views/imageResize.d.ts +53 -0
- package/dist/editor/views/imageResize.js +167 -0
- package/dist/editor/views/runMarkView.d.ts +15 -0
- package/dist/editor/views/runMarkView.js +9 -0
- package/dist/editor/views/tableView.d.ts +24 -0
- package/dist/editor/views/tableView.js +32 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +38 -0
- package/dist/model/format.d.ts +240 -0
- package/dist/model/format.js +305 -0
- package/dist/model/tabStops.d.ts +17 -0
- package/dist/model/tabStops.js +22 -0
- package/dist/numbering/listTemplate.d.ts +29 -0
- package/dist/numbering/listTemplate.js +83 -0
- package/dist/numbering/markers.d.ts +24 -0
- package/dist/numbering/markers.js +93 -0
- package/dist/numbering/parseNumbering.d.ts +65 -0
- package/dist/numbering/parseNumbering.js +116 -0
- package/dist/numbering/writeNumbering.d.ts +13 -0
- package/dist/numbering/writeNumbering.js +49 -0
- package/dist/ooxml/errors.d.ts +39 -0
- package/dist/ooxml/errors.js +21 -0
- package/dist/ooxml/image.d.ts +88 -0
- package/dist/ooxml/image.js +106 -0
- package/dist/ooxml/tabStops.d.ts +3 -0
- package/dist/ooxml/tabStops.js +51 -0
- package/dist/ooxml/units.d.ts +37 -0
- package/dist/ooxml/units.js +116 -0
- package/dist/ooxml/xml.d.ts +36 -0
- package/dist/ooxml/xml.js +89 -0
- package/dist/page/PageGuides.d.ts +16 -0
- package/dist/page/PageGuides.js +114 -0
- package/dist/page/measureBlocks.d.ts +25 -0
- package/dist/page/measureBlocks.js +80 -0
- package/dist/page/pageDecorations.d.ts +36 -0
- package/dist/page/pageDecorations.js +211 -0
- package/dist/page/pageLayout.d.ts +176 -0
- package/dist/page/pageLayout.js +157 -0
- package/dist/page/tableMeasurements.d.ts +10 -0
- package/dist/page/tableMeasurements.js +115 -0
- package/dist/page/usePageLayout.d.ts +57 -0
- package/dist/page/usePageLayout.js +141 -0
- package/dist/schema/docxSchema.d.ts +9 -0
- package/dist/schema/docxSchema.js +863 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +9 -0
- package/dist/schema/locks.d.ts +112 -0
- package/dist/schema/locks.js +211 -0
- package/dist/schema/rendering.d.ts +6 -0
- package/dist/schema/rendering.js +46 -0
- package/dist/styles/classNames.d.ts +214 -0
- package/dist/styles/classNames.js +208 -0
- package/dist/styles/colors.d.ts +11 -0
- package/dist/styles/colors.js +14 -0
- package/dist/styles/fontSizes.d.ts +6 -0
- package/dist/styles/fontSizes.js +20 -0
- package/dist/styles/fontStack.d.ts +55 -0
- package/dist/styles/fontStack.js +262 -0
- package/dist/styles/fonts.d.ts +6 -0
- package/dist/styles/fonts.js +11 -0
- package/dist/styles/inlineStyle.d.ts +67 -0
- package/dist/styles/inlineStyle.js +212 -0
- package/dist/styles/lineSpacings.d.ts +11 -0
- package/dist/styles/lineSpacings.js +10 -0
- package/dist/styles.css +1650 -0
- package/dist/table/cellBorders.d.ts +12 -0
- package/dist/table/cellBorders.js +9 -0
- package/dist/table/cellFormatting.d.ts +57 -0
- package/dist/table/cellFormatting.js +173 -0
- package/dist/table/columns.d.ts +25 -0
- package/dist/table/columns.js +155 -0
- package/dist/table/commands.d.ts +19 -0
- package/dist/table/commands.js +63 -0
- package/dist/table/format.d.ts +35 -0
- package/dist/table/format.js +26 -0
- package/dist/table/gridBorders.d.ts +42 -0
- package/dist/table/gridBorders.js +192 -0
- package/dist/table/index.d.ts +16 -0
- package/dist/table/index.js +52 -0
- package/dist/table/merge.d.ts +36 -0
- package/dist/table/merge.js +125 -0
- package/dist/table/resize.d.ts +55 -0
- package/dist/table/resize.js +66 -0
- package/dist/table/rowResize.d.ts +14 -0
- package/dist/table/rowResize.js +44 -0
- package/dist/table/rows.d.ts +32 -0
- package/dist/table/rows.js +89 -0
- package/dist/table/widths.d.ts +69 -0
- package/dist/table/widths.js +97 -0
- package/dist/ui/AlignMenu.d.ts +15 -0
- package/dist/ui/AlignMenu.js +64 -0
- package/dist/ui/CellStyleGroup.d.ts +15 -0
- package/dist/ui/CellStyleGroup.js +232 -0
- package/dist/ui/ColorPicker.d.ts +13 -0
- package/dist/ui/ColorPicker.js +165 -0
- package/dist/ui/CommentsPanel.d.ts +15 -0
- package/dist/ui/CommentsPanel.js +348 -0
- package/dist/ui/FontFamilySelect.d.ts +14 -0
- package/dist/ui/FontFamilySelect.js +59 -0
- package/dist/ui/FontSizeSelect.d.ts +11 -0
- package/dist/ui/FontSizeSelect.js +49 -0
- package/dist/ui/InsertImageButton.d.ts +9 -0
- package/dist/ui/InsertImageButton.js +47 -0
- package/dist/ui/LinkCard.d.ts +12 -0
- package/dist/ui/LinkCard.js +127 -0
- package/dist/ui/LinkPanel.d.ts +9 -0
- package/dist/ui/LinkPanel.js +121 -0
- package/dist/ui/MenuChoice.d.ts +11 -0
- package/dist/ui/MenuChoice.js +32 -0
- package/dist/ui/NotesPanel.d.ts +6 -0
- package/dist/ui/NotesPanel.js +33 -0
- package/dist/ui/ParagraphStyleSelect.d.ts +11 -0
- package/dist/ui/ParagraphStyleSelect.js +62 -0
- package/dist/ui/Popover.d.ts +22 -0
- package/dist/ui/Popover.js +74 -0
- package/dist/ui/SpacingMenu.d.ts +12 -0
- package/dist/ui/SpacingMenu.js +54 -0
- package/dist/ui/TableMenu.d.ts +12 -0
- package/dist/ui/TableMenu.js +112 -0
- package/dist/ui/TableSizePicker.d.ts +9 -0
- package/dist/ui/TableSizePicker.js +53 -0
- package/dist/ui/TextMenu.d.ts +15 -0
- package/dist/ui/TextMenu.js +194 -0
- package/dist/ui/Toolbar.d.ts +19 -0
- package/dist/ui/Toolbar.js +448 -0
- package/dist/ui/ToolbarButton.d.ts +23 -0
- package/dist/ui/ToolbarButton.js +56 -0
- package/dist/ui/Tooltip.d.ts +19 -0
- package/dist/ui/Tooltip.js +47 -0
- package/dist/ui/ZoomSelect.d.ts +7 -0
- package/dist/ui/ZoomSelect.js +44 -0
- package/dist/ui/comments/CommentComposer.d.ts +17 -0
- package/dist/ui/comments/CommentComposer.js +59 -0
- package/dist/ui/comments/useCommentRailLayout.d.ts +18 -0
- package/dist/ui/comments/useCommentRailLayout.js +183 -0
- package/dist/ui/keyboardWalk.d.ts +22 -0
- package/dist/ui/keyboardWalk.js +70 -0
- package/dist/ui/openAddress.d.ts +11 -0
- package/dist/ui/openAddress.js +16 -0
- package/dist/ui/panelPlacement.d.ts +51 -0
- package/dist/ui/panelPlacement.js +71 -0
- package/dist/ui/presets.d.ts +11 -0
- package/dist/ui/presets.js +0 -0
- package/dist/ui/rovingFocus.d.ts +20 -0
- package/dist/ui/rovingFocus.js +61 -0
- package/dist/ui/runCommand.d.ts +5 -0
- package/dist/ui/runCommand.js +13 -0
- package/dist/ui/useDismiss.d.ts +6 -0
- package/dist/ui/useDismiss.js +31 -0
- package/dist/ui/useFitWidthZoom.d.ts +2 -0
- package/dist/ui/useFitWidthZoom.js +26 -0
- package/dist/ui/useGridKeyboard.d.ts +12 -0
- package/dist/ui/useGridKeyboard.js +90 -0
- package/dist/ui/useMenuKeyboard.d.ts +12 -0
- package/dist/ui/useMenuKeyboard.js +56 -0
- package/dist/ui/zoom.d.ts +4 -0
- package/dist/ui/zoom.js +21 -0
- package/package.json +120 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// src/table/gridBorders.ts
|
|
2
|
+
import { Plugin } from "prosemirror-state";
|
|
3
|
+
import { TableMap } from "prosemirror-tables";
|
|
4
|
+
import { Transform } from "prosemirror-transform";
|
|
5
|
+
import {
|
|
6
|
+
cellBorderDefaults,
|
|
7
|
+
cellMarginsOf,
|
|
8
|
+
gridEdgesOf,
|
|
9
|
+
insideBordersOf,
|
|
10
|
+
layerCellMargins,
|
|
11
|
+
layerInsideBorders,
|
|
12
|
+
NO_BORDER_DEFAULTS,
|
|
13
|
+
NO_CELL_MARGINS,
|
|
14
|
+
NO_INSIDE_BORDERS,
|
|
15
|
+
readCellProps
|
|
16
|
+
} from "../docx/tableFormatting.js";
|
|
17
|
+
import {
|
|
18
|
+
spanCount,
|
|
19
|
+
toCellFormat,
|
|
20
|
+
toCellMargins,
|
|
21
|
+
toInsideBorders,
|
|
22
|
+
toTableFormat
|
|
23
|
+
} from "../model/format.js";
|
|
24
|
+
function text(value) {
|
|
25
|
+
return typeof value === "string" ? value : null;
|
|
26
|
+
}
|
|
27
|
+
function tableCellSources(table) {
|
|
28
|
+
const tblPr = text(table.attrs.tblPr);
|
|
29
|
+
return {
|
|
30
|
+
outer: toTableFormat(table.attrs.format),
|
|
31
|
+
inside: layerInsideBorders(
|
|
32
|
+
toInsideBorders(table.attrs.styleInside) ?? NO_INSIDE_BORDERS,
|
|
33
|
+
insideBordersOf(tblPr)
|
|
34
|
+
),
|
|
35
|
+
margins: layerCellMargins(
|
|
36
|
+
toCellMargins(table.attrs.styleCellMargins) ?? NO_CELL_MARGINS,
|
|
37
|
+
cellMarginsOf(tblPr)
|
|
38
|
+
)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function cellDefaultsAt(map, pos, sources) {
|
|
42
|
+
return cellBorderDefaults(
|
|
43
|
+
gridEdgesOf(map.findCell(pos), { rows: map.height, cols: map.width }),
|
|
44
|
+
sources.outer,
|
|
45
|
+
sources.inside
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
var CELL_FORMAT_KEYS = [
|
|
49
|
+
"borderTop",
|
|
50
|
+
"borderBottom",
|
|
51
|
+
"borderLeft",
|
|
52
|
+
"borderRight",
|
|
53
|
+
"background",
|
|
54
|
+
"verticalAlign",
|
|
55
|
+
"paddingTopPt",
|
|
56
|
+
"paddingRightPt",
|
|
57
|
+
"paddingBottomPt",
|
|
58
|
+
"paddingLeftPt"
|
|
59
|
+
];
|
|
60
|
+
function sameCellFormat(a, b) {
|
|
61
|
+
if (!a || !b) return a === b;
|
|
62
|
+
return CELL_FORMAT_KEYS.every((key) => a[key] === b[key]);
|
|
63
|
+
}
|
|
64
|
+
function hasDirectBorder(cell, key) {
|
|
65
|
+
return cell.direct?.[key] !== void 0;
|
|
66
|
+
}
|
|
67
|
+
function reconcileSharedBorder(first, firstKey, second, secondKey) {
|
|
68
|
+
const firstIsDirect = hasDirectBorder(first, firstKey);
|
|
69
|
+
const secondIsDirect = hasDirectBorder(second, secondKey);
|
|
70
|
+
if (firstIsDirect === secondIsDirect) return;
|
|
71
|
+
if (firstIsDirect) {
|
|
72
|
+
second.format[secondKey] = "none";
|
|
73
|
+
} else {
|
|
74
|
+
first.format[firstKey] = "none";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function reconcileSharedBorders(map, cells) {
|
|
78
|
+
for (let row = 0; row < map.height; row += 1) {
|
|
79
|
+
for (let col = 1; col < map.width; col += 1) {
|
|
80
|
+
const leftPos = map.map[row * map.width + col - 1];
|
|
81
|
+
const rightPos = map.map[row * map.width + col];
|
|
82
|
+
if (leftPos === rightPos) continue;
|
|
83
|
+
const left = cells.get(leftPos);
|
|
84
|
+
const right = cells.get(rightPos);
|
|
85
|
+
if (left && right) {
|
|
86
|
+
reconcileSharedBorder(left, "borderRight", right, "borderLeft");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (let row = 1; row < map.height; row += 1) {
|
|
91
|
+
for (let col = 0; col < map.width; col += 1) {
|
|
92
|
+
const topPos = map.map[(row - 1) * map.width + col];
|
|
93
|
+
const bottomPos = map.map[row * map.width + col];
|
|
94
|
+
if (topPos === bottomPos) continue;
|
|
95
|
+
const top = cells.get(topPos);
|
|
96
|
+
const bottom = cells.get(bottomPos);
|
|
97
|
+
if (top && bottom) {
|
|
98
|
+
reconcileSharedBorder(top, "borderBottom", bottom, "borderTop");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function cellFixes(table) {
|
|
104
|
+
const map = TableMap.get(table);
|
|
105
|
+
const sources = tableCellSources(table);
|
|
106
|
+
const cells = /* @__PURE__ */ new Map();
|
|
107
|
+
for (const pos of new Set(map.map)) {
|
|
108
|
+
const cell = table.nodeAt(pos);
|
|
109
|
+
if (!cell) continue;
|
|
110
|
+
const tcPr = text(cell.attrs.tcPr);
|
|
111
|
+
const format = readCellProps(
|
|
112
|
+
tcPr,
|
|
113
|
+
cellDefaultsAt(map, pos, sources),
|
|
114
|
+
sources.margins
|
|
115
|
+
);
|
|
116
|
+
cells.set(pos, {
|
|
117
|
+
pos,
|
|
118
|
+
attrs: cell.attrs,
|
|
119
|
+
format: { ...format },
|
|
120
|
+
direct: readCellProps(tcPr, NO_BORDER_DEFAULTS)
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
reconcileSharedBorders(map, cells);
|
|
124
|
+
const fixes = [];
|
|
125
|
+
for (const cell of cells.values()) {
|
|
126
|
+
const format = Object.keys(cell.format).length === 0 ? null : cell.format;
|
|
127
|
+
if (sameCellFormat(format, toCellFormat(cell.attrs.format))) continue;
|
|
128
|
+
fixes.push({ pos: cell.pos, attrs: { ...cell.attrs, format } });
|
|
129
|
+
}
|
|
130
|
+
return fixes;
|
|
131
|
+
}
|
|
132
|
+
function tablesOf(doc) {
|
|
133
|
+
const tables = [];
|
|
134
|
+
doc.descendants((node, pos) => {
|
|
135
|
+
if (node.type.spec.tableRole === "table") tables.push({ pos, table: node });
|
|
136
|
+
return !node.isTextblock;
|
|
137
|
+
});
|
|
138
|
+
return tables;
|
|
139
|
+
}
|
|
140
|
+
function sameSpans(a, b) {
|
|
141
|
+
return spanCount(a.attrs.colspan) === spanCount(b.attrs.colspan) && spanCount(a.attrs.rowspan) === spanCount(b.attrs.rowspan);
|
|
142
|
+
}
|
|
143
|
+
function sameRow(a, b) {
|
|
144
|
+
return a.childCount === b.childCount && a.children.every((cell, index) => sameSpans(cell, b.child(index)));
|
|
145
|
+
}
|
|
146
|
+
function sameGrid(a, b) {
|
|
147
|
+
return a.childCount === b.childCount && a.children.every((row, index) => sameRow(row, b.child(index)));
|
|
148
|
+
}
|
|
149
|
+
function sameCellFormattingInputs(a, b) {
|
|
150
|
+
return a.children.every(
|
|
151
|
+
(row, rowIndex) => row.children.every(
|
|
152
|
+
(cell, cellIndex) => cell.attrs.tcPr === b.child(rowIndex).child(cellIndex).attrs.tcPr
|
|
153
|
+
)
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
function sameFormattingInputs(a, b) {
|
|
157
|
+
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);
|
|
158
|
+
}
|
|
159
|
+
function withDerivedGridBorders(doc) {
|
|
160
|
+
const transform = new Transform(doc);
|
|
161
|
+
for (const { pos, table } of tablesOf(doc)) {
|
|
162
|
+
for (const fix of cellFixes(table)) {
|
|
163
|
+
transform.setNodeMarkup(pos + 1 + fix.pos, null, fix.attrs);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return transform.doc;
|
|
167
|
+
}
|
|
168
|
+
function gridBorders() {
|
|
169
|
+
return new Plugin({
|
|
170
|
+
appendTransaction(transactions, oldState, newState) {
|
|
171
|
+
if (!transactions.some((transaction) => transaction.docChanged)) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const before = tablesOf(oldState.doc);
|
|
175
|
+
const tr = newState.tr;
|
|
176
|
+
tablesOf(newState.doc).forEach(({ pos, table }, index) => {
|
|
177
|
+
const was = before[index]?.table;
|
|
178
|
+
if (was && sameFormattingInputs(was, table)) return;
|
|
179
|
+
for (const fix of cellFixes(table)) {
|
|
180
|
+
tr.setNodeMarkup(pos + 1 + fix.pos, null, fix.attrs);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
return tr.docChanged ? tr : null;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
export {
|
|
188
|
+
cellDefaultsAt,
|
|
189
|
+
gridBorders,
|
|
190
|
+
tableCellSources,
|
|
191
|
+
withDerivedGridBorders
|
|
192
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public surface of table editing.
|
|
3
|
+
*
|
|
4
|
+
* Only what the toolbar needs is exported. Following the ProseMirror convention,
|
|
5
|
+
* calling a command without `dispatch` only reports whether it can run right now, and that answer
|
|
6
|
+
* takes in the lock: a structural edit that would carry a locked cell off reports that it does not
|
|
7
|
+
* apply, rather than being refused after the click (`schema/locks`).
|
|
8
|
+
*
|
|
9
|
+
* Everything here works on a table already in the document; putting a new one into the body is
|
|
10
|
+
* `insertTable` in `./commands`, which reads the page geometry the editor holds.
|
|
11
|
+
*/
|
|
12
|
+
export type { ActiveCellPadding, CellBorderPreset, MixedCellValue, } from "./cellFormatting";
|
|
13
|
+
export { activeCellBackground, activeCellBorderColor, activeCellPadding, activeCellVerticalAlign, canSetCellBorderColor, canSetCellFormatting, setCellBackground, setCellBorderColor, setCellBorders, setCellPadding, setCellVerticalAlign, } from "./cellFormatting";
|
|
14
|
+
export type { TableCommand } from "./commands";
|
|
15
|
+
export { addColumnAfter, addColumnBefore, addRowAfter, addRowBefore, deleteColumn, deleteRow, deleteTable, isInTable, mergeCells, splitCell, } from "./commands";
|
|
16
|
+
export { canMergeCells, canSplitCell } from "./merge";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/table/index.ts
|
|
2
|
+
import {
|
|
3
|
+
activeCellBackground,
|
|
4
|
+
activeCellBorderColor,
|
|
5
|
+
activeCellPadding,
|
|
6
|
+
activeCellVerticalAlign,
|
|
7
|
+
canSetCellBorderColor,
|
|
8
|
+
canSetCellFormatting,
|
|
9
|
+
setCellBackground,
|
|
10
|
+
setCellBorderColor,
|
|
11
|
+
setCellBorders,
|
|
12
|
+
setCellPadding,
|
|
13
|
+
setCellVerticalAlign
|
|
14
|
+
} from "./cellFormatting.js";
|
|
15
|
+
import {
|
|
16
|
+
addColumnAfter,
|
|
17
|
+
addColumnBefore,
|
|
18
|
+
addRowAfter,
|
|
19
|
+
addRowBefore,
|
|
20
|
+
deleteColumn,
|
|
21
|
+
deleteRow,
|
|
22
|
+
deleteTable,
|
|
23
|
+
isInTable,
|
|
24
|
+
mergeCells,
|
|
25
|
+
splitCell
|
|
26
|
+
} from "./commands.js";
|
|
27
|
+
import { canMergeCells, canSplitCell } from "./merge.js";
|
|
28
|
+
export {
|
|
29
|
+
activeCellBackground,
|
|
30
|
+
activeCellBorderColor,
|
|
31
|
+
activeCellPadding,
|
|
32
|
+
activeCellVerticalAlign,
|
|
33
|
+
addColumnAfter,
|
|
34
|
+
addColumnBefore,
|
|
35
|
+
addRowAfter,
|
|
36
|
+
addRowBefore,
|
|
37
|
+
canMergeCells,
|
|
38
|
+
canSetCellBorderColor,
|
|
39
|
+
canSetCellFormatting,
|
|
40
|
+
canSplitCell,
|
|
41
|
+
deleteColumn,
|
|
42
|
+
deleteRow,
|
|
43
|
+
deleteTable,
|
|
44
|
+
isInTable,
|
|
45
|
+
mergeCells,
|
|
46
|
+
setCellBackground,
|
|
47
|
+
setCellBorderColor,
|
|
48
|
+
setCellBorders,
|
|
49
|
+
setCellPadding,
|
|
50
|
+
setCellVerticalAlign,
|
|
51
|
+
splitCell
|
|
52
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The grid math and moving the content around are left to `prosemirror-tables`; only
|
|
3
|
+
* the formatting of the resulting cells is rewritten.
|
|
4
|
+
*/
|
|
5
|
+
import type { EditorState, Transaction } from "prosemirror-state";
|
|
6
|
+
/**
|
|
7
|
+
* Whether several cells can be merged into one.
|
|
8
|
+
* The selection has to be a rectangle spanning more than one cell, no merged cell may stick out
|
|
9
|
+
* past that rectangle, and the lock guard has to let the merge through: a locked cell may not be
|
|
10
|
+
* swallowed by another (`schema/locks`).
|
|
11
|
+
*
|
|
12
|
+
* The two queries are defined from the very transaction the commands run, so they cannot drift
|
|
13
|
+
* from them. They live here rather than beside the commands because `./commands` imports these
|
|
14
|
+
* builders, and the other way round would turn that import around.
|
|
15
|
+
*/
|
|
16
|
+
export declare function canMergeCells(state: EditorState): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether a split is possible. The cursor has to sit inside a cell that is merged horizontally or
|
|
19
|
+
* vertically, and the lock guard has to let the split through: the cells a split makes would each
|
|
20
|
+
* carry the original's lock, which is a lock planted in places it was never put (`schema/locks`).
|
|
21
|
+
*/
|
|
22
|
+
export declare function canSplitCell(state: EditorState): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* `null` if the grid does not allow the merge. The lock is not asked here: what the guard
|
|
25
|
+
* would turn down is what `canMergeCells` and the command are for, and the transaction is
|
|
26
|
+
* what they ask about.
|
|
27
|
+
*
|
|
28
|
+
* The size of the merged cell (colspan, rowspan, colwidth) keeps whatever upstream
|
|
29
|
+
* decided, and its formatting comes from the top-left cell.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildMergeCellsTransaction(state: EditorState): Transaction | null;
|
|
32
|
+
/**
|
|
33
|
+
* `null` for a cell that is not merged, or outside a table. As with the merge, the lock is asked
|
|
34
|
+
* of the finished transaction by `canSplitCell` and the command rather than here.
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildSplitCellTransaction(state: EditorState): Transaction | null;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// src/table/merge.ts
|
|
2
|
+
import {
|
|
3
|
+
mergeCells as pmMergeCells,
|
|
4
|
+
splitCell as pmSplitCell,
|
|
5
|
+
selectedRect,
|
|
6
|
+
TableMap
|
|
7
|
+
} from "prosemirror-tables";
|
|
8
|
+
import {
|
|
9
|
+
spanCount,
|
|
10
|
+
toTableWidth,
|
|
11
|
+
widthNumber,
|
|
12
|
+
withWidthNumber
|
|
13
|
+
} from "../model/format.js";
|
|
14
|
+
import { transactionAllowed } from "../schema/locks.js";
|
|
15
|
+
import { inheritCellAttrs } from "./format.js";
|
|
16
|
+
import { cellWidthForGridCol, gridSpanWidth, tableGridCols } from "./widths.js";
|
|
17
|
+
function tableAfter(tr, tableStart) {
|
|
18
|
+
const tablePos = tr.mapping.map(tableStart - 1);
|
|
19
|
+
const table = tr.doc.nodeAt(tablePos);
|
|
20
|
+
if (!table) return null;
|
|
21
|
+
return { tablePos, table, map: TableMap.get(table) };
|
|
22
|
+
}
|
|
23
|
+
function cellAt(rect, row, col) {
|
|
24
|
+
const pos = rect.map.map[row * rect.map.width + col];
|
|
25
|
+
return pos == null ? null : rect.table.nodeAt(pos);
|
|
26
|
+
}
|
|
27
|
+
function canMergeCells(state) {
|
|
28
|
+
const tr = buildMergeCellsTransaction(state);
|
|
29
|
+
return tr !== null && transactionAllowed(tr, state.doc);
|
|
30
|
+
}
|
|
31
|
+
function canSplitCell(state) {
|
|
32
|
+
const tr = buildSplitCellTransaction(state);
|
|
33
|
+
return tr !== null && transactionAllowed(tr, state.doc);
|
|
34
|
+
}
|
|
35
|
+
function coveredWidthSum(rect, type) {
|
|
36
|
+
let sum = 0;
|
|
37
|
+
let previous = null;
|
|
38
|
+
for (let col = rect.left; col < rect.right; col++) {
|
|
39
|
+
const pos = rect.map.map[rect.top * rect.map.width + col];
|
|
40
|
+
if (pos === previous) continue;
|
|
41
|
+
previous = pos;
|
|
42
|
+
const cell = pos == null ? null : rect.table.nodeAt(pos);
|
|
43
|
+
const width = cell ? toTableWidth(cell.attrs.tcW) : null;
|
|
44
|
+
const value = width ? widthNumber(width) : null;
|
|
45
|
+
if (!width || width.type !== type || value === null) return null;
|
|
46
|
+
sum += value;
|
|
47
|
+
}
|
|
48
|
+
return sum;
|
|
49
|
+
}
|
|
50
|
+
function mergedCellWidth(rect, source) {
|
|
51
|
+
const reference = toTableWidth(source.attrs.tcW);
|
|
52
|
+
if (!reference) return null;
|
|
53
|
+
const spanned = gridSpanWidth(
|
|
54
|
+
tableGridCols(rect.table),
|
|
55
|
+
rect.left,
|
|
56
|
+
rect.right,
|
|
57
|
+
reference.type
|
|
58
|
+
) ?? coveredWidthSum(rect, reference.type);
|
|
59
|
+
return spanned === null ? reference : withWidthNumber(reference, spanned);
|
|
60
|
+
}
|
|
61
|
+
function writeMergedFormat(tr, rect, source) {
|
|
62
|
+
const after = tableAfter(tr, rect.tableStart);
|
|
63
|
+
if (!after) return;
|
|
64
|
+
const { tablePos, table, map } = after;
|
|
65
|
+
const pos = map.map[rect.top * map.width + rect.left];
|
|
66
|
+
const merged = table.nodeAt(pos);
|
|
67
|
+
if (!merged) return;
|
|
68
|
+
tr.setNodeMarkup(tablePos + 1 + pos, null, {
|
|
69
|
+
...merged.attrs,
|
|
70
|
+
...inheritCellAttrs(source, { tcW: mergedCellWidth(rect, source) })
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function buildMergeCellsTransaction(state) {
|
|
74
|
+
if (!pmMergeCells(state)) return null;
|
|
75
|
+
const rect = selectedRect(state);
|
|
76
|
+
const source = cellAt(rect, rect.top, rect.left);
|
|
77
|
+
const captured = [];
|
|
78
|
+
pmMergeCells(state, (tr2) => captured.push(tr2));
|
|
79
|
+
const tr = captured[0];
|
|
80
|
+
if (!tr || !source) return null;
|
|
81
|
+
writeMergedFormat(tr, rect, source);
|
|
82
|
+
return tr;
|
|
83
|
+
}
|
|
84
|
+
function writeSplitFormats(tr, rect, source) {
|
|
85
|
+
const after = tableAfter(tr, rect.tableStart);
|
|
86
|
+
if (!after) return;
|
|
87
|
+
const { tablePos, table, map } = after;
|
|
88
|
+
const gridCols = tableGridCols(table);
|
|
89
|
+
const width = toTableWidth(source.attrs.tcW);
|
|
90
|
+
const colspan = spanCount(source.attrs.colspan);
|
|
91
|
+
for (let row = rect.top; row < rect.bottom; row++) {
|
|
92
|
+
for (let col = rect.left; col < rect.right; col++) {
|
|
93
|
+
const pos = map.map[row * map.width + col];
|
|
94
|
+
const cell = pos == null ? null : table.nodeAt(pos);
|
|
95
|
+
if (!cell) continue;
|
|
96
|
+
const isOriginalSpot = row === rect.top && col === rect.left;
|
|
97
|
+
tr.setNodeMarkup(tablePos + 1 + pos, null, {
|
|
98
|
+
...cell.attrs,
|
|
99
|
+
...inheritCellAttrs(source, {
|
|
100
|
+
tcW: cellWidthForGridCol(gridCols, col, width, colspan),
|
|
101
|
+
sdtPrefix: isOriginalSpot ? source.attrs.sdtPrefix : null,
|
|
102
|
+
sdtContentsLocked: isOriginalSpot ? source.attrs.sdtContentsLocked : false,
|
|
103
|
+
sdtDeletionLocked: isOriginalSpot ? source.attrs.sdtDeletionLocked : false
|
|
104
|
+
})
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function buildSplitCellTransaction(state) {
|
|
110
|
+
if (!pmSplitCell(state)) return null;
|
|
111
|
+
const rect = selectedRect(state);
|
|
112
|
+
const source = cellAt(rect, rect.top, rect.left);
|
|
113
|
+
const captured = [];
|
|
114
|
+
pmSplitCell(state, (tr2) => captured.push(tr2));
|
|
115
|
+
const tr = captured[0];
|
|
116
|
+
if (!tr || !source) return null;
|
|
117
|
+
writeSplitFormats(tr, rect, source);
|
|
118
|
+
return tr;
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
buildMergeCellsTransaction,
|
|
122
|
+
buildSplitCellTransaction,
|
|
123
|
+
canMergeCells,
|
|
124
|
+
canSplitCell
|
|
125
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A boundary drag moves the grid and the cell widths together exactly as a column
|
|
3
|
+
* insertion does.
|
|
4
|
+
*/
|
|
5
|
+
import type { Node as PMNode } from "prosemirror-model";
|
|
6
|
+
import type { EditorState, Transaction } from "prosemirror-state";
|
|
7
|
+
import { type PageGeometry } from "../docx/pageGeometry";
|
|
8
|
+
/**
|
|
9
|
+
* The floor a column can be narrowed to (dxa).
|
|
10
|
+
*
|
|
11
|
+
* Word's default cell padding is 0.08 inch (115 dxa) on the left and on the right, 230
|
|
12
|
+
* in total.
|
|
13
|
+
* A column narrower than that cannot fit even a single character, so the cell looks
|
|
14
|
+
* collapsed.
|
|
15
|
+
* With a little slack added, 240 dxa (12pt, about 0.42cm) is taken as the floor.
|
|
16
|
+
*/
|
|
17
|
+
export declare const MIN_COLUMN_DXA = 240;
|
|
18
|
+
/** A single boundary being dragged. `col` is the index of the grid column left of it */
|
|
19
|
+
export interface ColumnEdge {
|
|
20
|
+
/** The position where the table node sits */
|
|
21
|
+
tablePos: number;
|
|
22
|
+
col: number;
|
|
23
|
+
/**
|
|
24
|
+
* The width (dxa) the column left of the boundary wants to take. The limits are
|
|
25
|
+
* re-applied here
|
|
26
|
+
*/
|
|
27
|
+
width: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The limit a table can be widened to (dxa).
|
|
31
|
+
*
|
|
32
|
+
* The body width of the paper the document names, minus the table indent (`w:tblInd`).
|
|
33
|
+
* For a table already stored wider than that, its current width is the limit, so
|
|
34
|
+
* dragging can only narrow it.
|
|
35
|
+
*/
|
|
36
|
+
export declare function maxGridTotal(table: PMNode, geometry: PageGeometry): number;
|
|
37
|
+
/**
|
|
38
|
+
* The grid column widths after the boundary has moved. Null when nothing changes or
|
|
39
|
+
* there is no room to move into.
|
|
40
|
+
*
|
|
41
|
+
* At an inner boundary (`col` is not the last column) the left column receives only
|
|
42
|
+
* what the right column gives up, so the grid total stays the same. At the end boundary
|
|
43
|
+
* only the last column changes, so the total moves with it.
|
|
44
|
+
* No column ever ends up narrower than this table's floor, and the grid total never
|
|
45
|
+
* exceeds `maxTotal`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resizedGridCols(gridCols: number[], col: number, width: number, maxTotal: number): number[] | null;
|
|
48
|
+
/**
|
|
49
|
+
* Because it is one single transaction, a single undo returns everything to the state
|
|
50
|
+
* before the drag.
|
|
51
|
+
*
|
|
52
|
+
* The geometry is the paper the open document names, which is what the table is kept
|
|
53
|
+
* inside. The editor layer reads it off the state; this layer is handed it.
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildResizeColumnTransaction(state: EditorState, edge: ColumnEdge, geometry: PageGeometry): Transaction | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// src/table/resize.ts
|
|
2
|
+
import { bodyWidth } from "../docx/pageGeometry.js";
|
|
3
|
+
import { toTableFormat } from "../model/format.js";
|
|
4
|
+
import {
|
|
5
|
+
gridTotal,
|
|
6
|
+
rescaleCellWidths,
|
|
7
|
+
tableGridCols,
|
|
8
|
+
writeGridCols
|
|
9
|
+
} from "./widths.js";
|
|
10
|
+
var MIN_COLUMN_DXA = 240;
|
|
11
|
+
var TWIPS_PER_PT = 20;
|
|
12
|
+
function clamp(value, low, high) {
|
|
13
|
+
return Math.min(Math.max(value, low), high);
|
|
14
|
+
}
|
|
15
|
+
function minColumnDxa(gridCols) {
|
|
16
|
+
const even = Math.floor(gridTotal(gridCols) / (2 * gridCols.length));
|
|
17
|
+
return Math.min(MIN_COLUMN_DXA, Math.max(even, 1));
|
|
18
|
+
}
|
|
19
|
+
function maxGridTotal(table, geometry) {
|
|
20
|
+
const indentPt = toTableFormat(table.attrs.format)?.indentLeftPt ?? 0;
|
|
21
|
+
const room = bodyWidth(geometry).twips - Math.round(indentPt * TWIPS_PER_PT);
|
|
22
|
+
const gridCols = tableGridCols(table);
|
|
23
|
+
return Math.max(room, gridCols ? gridTotal(gridCols) : 0);
|
|
24
|
+
}
|
|
25
|
+
function resizedGridCols(gridCols, col, width, maxTotal) {
|
|
26
|
+
const last = gridCols.length - 1;
|
|
27
|
+
const current = gridCols[col];
|
|
28
|
+
if (col < 0 || col > last || typeof current !== "number") return null;
|
|
29
|
+
const floor = minColumnDxa(gridCols);
|
|
30
|
+
const inner = col < last;
|
|
31
|
+
const room = inner ? current + gridCols[col + 1] - floor : maxTotal - (gridTotal(gridCols) - current);
|
|
32
|
+
if (room < floor) return null;
|
|
33
|
+
const next = clamp(Math.round(width), floor, room);
|
|
34
|
+
if (next === current) return null;
|
|
35
|
+
return gridCols.map((entry, at) => {
|
|
36
|
+
if (at === col) return next;
|
|
37
|
+
if (inner && at === col + 1) return entry - (next - current);
|
|
38
|
+
return entry;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function tableAt(doc, pos) {
|
|
42
|
+
const node = pos >= 0 && pos < doc.content.size ? doc.nodeAt(pos) : null;
|
|
43
|
+
return node?.type.spec.tableRole === "table" ? node : null;
|
|
44
|
+
}
|
|
45
|
+
function buildResizeColumnTransaction(state, edge, geometry) {
|
|
46
|
+
const table = tableAt(state.doc, edge.tablePos);
|
|
47
|
+
const gridCols = table ? tableGridCols(table) : null;
|
|
48
|
+
if (!table || !gridCols) return null;
|
|
49
|
+
const resized = resizedGridCols(
|
|
50
|
+
gridCols,
|
|
51
|
+
edge.col,
|
|
52
|
+
edge.width,
|
|
53
|
+
maxGridTotal(table, geometry)
|
|
54
|
+
);
|
|
55
|
+
if (!resized) return null;
|
|
56
|
+
const tr = state.tr;
|
|
57
|
+
writeGridCols(tr, edge.tablePos + 1, resized);
|
|
58
|
+
rescaleCellWidths(tr, edge.tablePos + 1, resized);
|
|
59
|
+
return tr;
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
MIN_COLUMN_DXA,
|
|
63
|
+
buildResizeColumnTransaction,
|
|
64
|
+
maxGridTotal,
|
|
65
|
+
resizedGridCols
|
|
66
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Node as PMNode } from "prosemirror-model";
|
|
2
|
+
import type { EditorState, Transaction } from "prosemirror-state";
|
|
3
|
+
export declare const MIN_ROW_HEIGHT_PT = 6;
|
|
4
|
+
export interface RowResize {
|
|
5
|
+
/** Position immediately before the table. */
|
|
6
|
+
tablePos: number;
|
|
7
|
+
row: number;
|
|
8
|
+
heightPt: number;
|
|
9
|
+
}
|
|
10
|
+
/** Converts a pointer delta to a valid row-height floor, accounting for document zoom. */
|
|
11
|
+
export declare function resizedRowHeight(startPt: number, deltaPx: number, scale: number): number;
|
|
12
|
+
/** Absolute document position immediately before one row in a table. */
|
|
13
|
+
export declare function rowPositionAt(tablePos: number, table: PMNode, row: number): number;
|
|
14
|
+
export declare function buildResizeRowTransaction(state: EditorState, resize: RowResize): Transaction | null;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/table/rowResize.ts
|
|
2
|
+
import { editRowHeight } from "../docx/tableFormatting.js";
|
|
3
|
+
import { toRowFormat } from "../model/format.js";
|
|
4
|
+
import { isLockedCell } from "../schema/locks.js";
|
|
5
|
+
var MIN_ROW_HEIGHT_PT = 6;
|
|
6
|
+
function resizedRowHeight(startPt, deltaPx, scale) {
|
|
7
|
+
const effectiveScale = Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
8
|
+
const next = startPt + deltaPx / effectiveScale * (72 / 96);
|
|
9
|
+
return Math.max(MIN_ROW_HEIGHT_PT, Math.round(next * 20) / 20);
|
|
10
|
+
}
|
|
11
|
+
function rowPositionAt(tablePos, table, row) {
|
|
12
|
+
let pos = tablePos + 1;
|
|
13
|
+
for (let index = 0; index < row; index += 1)
|
|
14
|
+
pos += table.child(index).nodeSize;
|
|
15
|
+
return pos;
|
|
16
|
+
}
|
|
17
|
+
function buildResizeRowTransaction(state, resize) {
|
|
18
|
+
const table = state.doc.nodeAt(resize.tablePos);
|
|
19
|
+
if (!table || table.type.spec.tableRole !== "table" || resize.row < 0 || resize.row >= table.childCount) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const row = table.child(resize.row);
|
|
23
|
+
if (row.children.some(isLockedCell)) return null;
|
|
24
|
+
const edited = editRowHeight(
|
|
25
|
+
typeof row.attrs.trPr === "string" ? row.attrs.trPr : null,
|
|
26
|
+
resize.heightPt
|
|
27
|
+
);
|
|
28
|
+
if (!edited) return null;
|
|
29
|
+
return state.tr.setNodeMarkup(
|
|
30
|
+
rowPositionAt(resize.tablePos, table, resize.row),
|
|
31
|
+
null,
|
|
32
|
+
{
|
|
33
|
+
...row.attrs,
|
|
34
|
+
trPr: edited.trPr,
|
|
35
|
+
format: toRowFormat(edited.format)
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
MIN_ROW_HEIGHT_PT,
|
|
41
|
+
buildResizeRowTransaction,
|
|
42
|
+
resizedRowHeight,
|
|
43
|
+
rowPositionAt
|
|
44
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In docx a vertically merged cell exists as a single cell only in the row where the
|
|
3
|
+
* merge starts; in the rows below there is no cell at that position at all (how many
|
|
4
|
+
* rows the starting cell covers is counted by rowspan).
|
|
5
|
+
* So the number of cells can differ from row to row, and counting by "the nth cell"
|
|
6
|
+
* goes wrong. Everything here counts by the table's grid coordinates (TableMap).
|
|
7
|
+
*
|
|
8
|
+
* Deletion is left entirely to `prosemirror-tables`' `deleteRow`, which gets shrinking
|
|
9
|
+
* rowspans right as well.
|
|
10
|
+
*/
|
|
11
|
+
import { type EditorState, type Transaction } from "prosemirror-state";
|
|
12
|
+
/**
|
|
13
|
+
* Builds the transaction that adds a row right below the row holding the cursor.
|
|
14
|
+
* `null` when the cursor is outside a table. The cursor moves to the first cell of the
|
|
15
|
+
* new row.
|
|
16
|
+
*
|
|
17
|
+
* Split out of the command so it can be verified from document state alone, without an
|
|
18
|
+
* editor view.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildAddRowAfterTransaction(state: EditorState): Transaction | null;
|
|
21
|
+
/** The above version. Only the insertion position differs */
|
|
22
|
+
export declare function buildAddRowBeforeTransaction(state: EditorState): Transaction | null;
|
|
23
|
+
/**
|
|
24
|
+
* Builds the transaction that deletes the row holding the cursor (or the rows spanned
|
|
25
|
+
* by a multi-row selection).
|
|
26
|
+
* `null` outside a table, or when every row of the table is selected.
|
|
27
|
+
*
|
|
28
|
+
* The upstream `deleteRow` deletes every row the selection rectangle covers. With the
|
|
29
|
+
* cursor inside a merged cell the rectangle becomes that whole cell, so all the rows it
|
|
30
|
+
* covers go away with it.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildDeleteRowTransaction(state: EditorState): Transaction | null;
|