@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,863 @@
|
|
|
1
|
+
// src/schema/docxSchema.ts
|
|
2
|
+
import { Schema } from "prosemirror-model";
|
|
3
|
+
import {
|
|
4
|
+
spanCount,
|
|
5
|
+
toCellFormat,
|
|
6
|
+
toCellMargins,
|
|
7
|
+
toColWidth,
|
|
8
|
+
toGridCols,
|
|
9
|
+
toInsideBorders,
|
|
10
|
+
toParagraphFormat,
|
|
11
|
+
toRowFormat,
|
|
12
|
+
toRunFormat,
|
|
13
|
+
toTableFormat,
|
|
14
|
+
toTableWidth
|
|
15
|
+
} from "../model/format.js";
|
|
16
|
+
import { toImageExtent, toImageSrc } from "../ooxml/image.js";
|
|
17
|
+
import { editorAttributes, editorClassNames } from "../styles/classNames.js";
|
|
18
|
+
import { DEFAULT_FONT_FALLBACKS } from "../styles/fontStack.js";
|
|
19
|
+
import {
|
|
20
|
+
cellStyle,
|
|
21
|
+
columnWidthPx,
|
|
22
|
+
paragraphStyle,
|
|
23
|
+
rowStyle,
|
|
24
|
+
tableStyle
|
|
25
|
+
} from "../styles/inlineStyle.js";
|
|
26
|
+
import { imageNodeSpec, runMarkSpec } from "./rendering.js";
|
|
27
|
+
import { imageNodeSpec as imageNodeSpec2, runMarkSpec as runMarkSpec2 } from "./rendering.js";
|
|
28
|
+
function text(value) {
|
|
29
|
+
return typeof value === "string" ? value : void 0;
|
|
30
|
+
}
|
|
31
|
+
function numberText(value) {
|
|
32
|
+
return typeof value === "number" ? `${value}` : void 0;
|
|
33
|
+
}
|
|
34
|
+
function parseInt10(value, fallback) {
|
|
35
|
+
if (value === null) return fallback;
|
|
36
|
+
const parsed = Number.parseInt(value, 10);
|
|
37
|
+
return Number.isNaN(parsed) ? fallback : parsed;
|
|
38
|
+
}
|
|
39
|
+
function parseNumberList(value) {
|
|
40
|
+
if (!value) return [];
|
|
41
|
+
return value.split(",").map((entry) => Number.parseFloat(entry)).filter((entry) => Number.isFinite(entry));
|
|
42
|
+
}
|
|
43
|
+
function numberListText(values) {
|
|
44
|
+
return values.length > 0 ? values.join(",") : void 0;
|
|
45
|
+
}
|
|
46
|
+
function parseJson(value) {
|
|
47
|
+
if (!value) return null;
|
|
48
|
+
try {
|
|
49
|
+
const parsed = JSON.parse(value);
|
|
50
|
+
return parsed;
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function formatJson(format) {
|
|
56
|
+
return format ? JSON.stringify(format) : void 0;
|
|
57
|
+
}
|
|
58
|
+
function isPageBreak(brAttrs) {
|
|
59
|
+
return typeof brAttrs === "string" && /(^|\s)(\w+:)?type="page"/.test(brAttrs);
|
|
60
|
+
}
|
|
61
|
+
function srcIdOf(dom) {
|
|
62
|
+
const raw = dom.getAttribute("data-src");
|
|
63
|
+
if (raw === null) return null;
|
|
64
|
+
const parsed = Number.parseInt(raw, 10);
|
|
65
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
66
|
+
}
|
|
67
|
+
var TABLE_PLACEHOLDER = "Table (unsupported layout, original is preserved)";
|
|
68
|
+
var UNKNOWN_PLACEHOLDER = "Unsupported content (not editable, original is preserved)";
|
|
69
|
+
var TABLE_NAMES = ["w:tbl", "tbl"];
|
|
70
|
+
function rawBlockDom(name) {
|
|
71
|
+
if (name !== void 0 && TABLE_NAMES.includes(name)) {
|
|
72
|
+
return {
|
|
73
|
+
className: editorClassNames.tablePlaceholder,
|
|
74
|
+
label: TABLE_PLACEHOLDER
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return { className: editorClassNames.rawBlock, label: UNKNOWN_PLACEHOLDER };
|
|
78
|
+
}
|
|
79
|
+
var DOCX_RAW_SELECTOR = [
|
|
80
|
+
editorClassNames.rawBlock,
|
|
81
|
+
editorClassNames.tablePlaceholder
|
|
82
|
+
].map((className) => `div[data-src].${className}`).join(", ");
|
|
83
|
+
var docxSchema = new Schema({
|
|
84
|
+
nodes: {
|
|
85
|
+
doc: { content: "block+" },
|
|
86
|
+
paragraph: {
|
|
87
|
+
group: "block",
|
|
88
|
+
content: "inline*",
|
|
89
|
+
// Leading and trailing whitespace carries meaning in docx text, so it is not stripped when the DOM is read back
|
|
90
|
+
whitespace: "pre",
|
|
91
|
+
attrs: {
|
|
92
|
+
srcId: { default: null },
|
|
93
|
+
/** The attribute string of the `<w:p>` opening tag. null when there is none */
|
|
94
|
+
pAttrs: { default: null },
|
|
95
|
+
/** The whole `<w:pPr>...</w:pPr>` XML. null when there is none */
|
|
96
|
+
pPr: { default: null },
|
|
97
|
+
/** The display values derived from reading pPr */
|
|
98
|
+
format: { default: null },
|
|
99
|
+
/**
|
|
100
|
+
* The character formatting the style this paragraph wears lays down, drawn as the
|
|
101
|
+
* paragraph's own CSS so that text carrying no run of its own inherits it.
|
|
102
|
+
* It is derived from the style table the same way `format` is, and like `format` it never
|
|
103
|
+
* goes back into the document.
|
|
104
|
+
*/
|
|
105
|
+
styleRun: { default: null }
|
|
106
|
+
},
|
|
107
|
+
toDOM(node) {
|
|
108
|
+
const format = toParagraphFormat(node.attrs.format);
|
|
109
|
+
const styleRun = toRunFormat(node.attrs.styleRun);
|
|
110
|
+
return [
|
|
111
|
+
"p",
|
|
112
|
+
{
|
|
113
|
+
class: editorClassNames.paragraph,
|
|
114
|
+
style: paragraphStyle(format, styleRun),
|
|
115
|
+
"data-src": node.attrs.srcId === null ? void 0 : `${node.attrs.srcId}`,
|
|
116
|
+
"data-pattrs": text(node.attrs.pAttrs),
|
|
117
|
+
"data-ppr": text(node.attrs.pPr),
|
|
118
|
+
"data-fmt": formatJson(format),
|
|
119
|
+
"data-style-run": formatJson(styleRun),
|
|
120
|
+
[editorAttributes.pageBreakBefore]: format?.pageBreakBefore ? "" : void 0
|
|
121
|
+
},
|
|
122
|
+
0
|
|
123
|
+
];
|
|
124
|
+
},
|
|
125
|
+
parseDOM: [
|
|
126
|
+
{
|
|
127
|
+
tag: `p.${editorClassNames.paragraph}`,
|
|
128
|
+
getAttrs: (dom) => ({
|
|
129
|
+
srcId: srcIdOf(dom),
|
|
130
|
+
pAttrs: dom.getAttribute("data-pattrs"),
|
|
131
|
+
pPr: dom.getAttribute("data-ppr"),
|
|
132
|
+
format: toParagraphFormat(parseJson(dom.getAttribute("data-fmt"))),
|
|
133
|
+
styleRun: toRunFormat(
|
|
134
|
+
parseJson(dom.getAttribute("data-style-run"))
|
|
135
|
+
)
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
/**
|
|
141
|
+
* A table carries the original `<w:tblPr>` and `<w:tblGrid>` untouched, and when an
|
|
142
|
+
* edited table is written back the new XML is built from those two.
|
|
143
|
+
*/
|
|
144
|
+
table: {
|
|
145
|
+
group: "block",
|
|
146
|
+
content: "tableRow+",
|
|
147
|
+
tableRole: "table",
|
|
148
|
+
isolating: true,
|
|
149
|
+
attrs: {
|
|
150
|
+
srcId: { default: null },
|
|
151
|
+
/** The attribute string of the `<w:tbl>` opening tag */
|
|
152
|
+
tblAttrs: { default: null },
|
|
153
|
+
/** The whole `<w:tblPr>...</w:tblPr>` XML */
|
|
154
|
+
tblPr: { default: null },
|
|
155
|
+
/** The table width read out of tblPr */
|
|
156
|
+
tblW: { default: null },
|
|
157
|
+
/** The `w:gridCol` widths (dxa) in order */
|
|
158
|
+
gridCols: { default: [] },
|
|
159
|
+
format: { default: null },
|
|
160
|
+
/** The lines between cells the table style laid down, so an edit can derive them again */
|
|
161
|
+
styleInside: { default: null },
|
|
162
|
+
/** The cell margins the table style laid down, carried along for the same reason */
|
|
163
|
+
styleCellMargins: { default: null }
|
|
164
|
+
},
|
|
165
|
+
toDOM(node) {
|
|
166
|
+
const format = toTableFormat(node.attrs.format);
|
|
167
|
+
const width = toTableWidth(node.attrs.tblW);
|
|
168
|
+
const gridCols = toGridCols(node.attrs.gridCols);
|
|
169
|
+
const attrs = {
|
|
170
|
+
class: editorClassNames.table,
|
|
171
|
+
style: tableStyle(format, width),
|
|
172
|
+
"data-src": node.attrs.srcId === null ? void 0 : `${node.attrs.srcId}`,
|
|
173
|
+
"data-tblattrs": text(node.attrs.tblAttrs),
|
|
174
|
+
"data-tblpr": text(node.attrs.tblPr),
|
|
175
|
+
"data-tblw": formatJson(width),
|
|
176
|
+
"data-cols": numberListText(gridCols),
|
|
177
|
+
"data-fmt": formatJson(format),
|
|
178
|
+
"data-style-inside": formatJson(
|
|
179
|
+
toInsideBorders(node.attrs.styleInside)
|
|
180
|
+
),
|
|
181
|
+
"data-style-margins": formatJson(
|
|
182
|
+
toCellMargins(node.attrs.styleCellMargins)
|
|
183
|
+
)
|
|
184
|
+
};
|
|
185
|
+
const body = ["tbody", 0];
|
|
186
|
+
if (gridCols.length === 0) return ["table", attrs, body];
|
|
187
|
+
const cols = gridCols.map((dxa) => [
|
|
188
|
+
"col",
|
|
189
|
+
{ style: `width:${columnWidthPx(dxa)}px` }
|
|
190
|
+
]);
|
|
191
|
+
return ["table", attrs, ["colgroup", ...cols], body];
|
|
192
|
+
},
|
|
193
|
+
parseDOM: [
|
|
194
|
+
// `data-cols` carries the column widths, so the colgroup we drew is not read back
|
|
195
|
+
{ tag: "colgroup", ignore: true },
|
|
196
|
+
{
|
|
197
|
+
tag: `table.${editorClassNames.table}`,
|
|
198
|
+
getAttrs: (dom) => ({
|
|
199
|
+
srcId: srcIdOf(dom),
|
|
200
|
+
tblAttrs: dom.getAttribute("data-tblattrs"),
|
|
201
|
+
tblPr: dom.getAttribute("data-tblpr"),
|
|
202
|
+
tblW: toTableWidth(parseJson(dom.getAttribute("data-tblw"))),
|
|
203
|
+
gridCols: parseNumberList(dom.getAttribute("data-cols")),
|
|
204
|
+
format: toTableFormat(parseJson(dom.getAttribute("data-fmt"))),
|
|
205
|
+
styleInside: toInsideBorders(
|
|
206
|
+
parseJson(dom.getAttribute("data-style-inside"))
|
|
207
|
+
),
|
|
208
|
+
styleCellMargins: toCellMargins(
|
|
209
|
+
parseJson(dom.getAttribute("data-style-margins"))
|
|
210
|
+
)
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
},
|
|
215
|
+
tableRow: {
|
|
216
|
+
content: "tableCell+",
|
|
217
|
+
tableRole: "row",
|
|
218
|
+
attrs: {
|
|
219
|
+
/** The attribute string of the `<w:tr>` opening tag */
|
|
220
|
+
trAttrs: { default: null },
|
|
221
|
+
/** The whole `<w:tblPrEx>...</w:tblPrEx>` XML, carried along without being read */
|
|
222
|
+
tblPrEx: { default: null },
|
|
223
|
+
/** The whole `<w:trPr>...</w:trPr>` XML */
|
|
224
|
+
trPr: { default: null },
|
|
225
|
+
format: { default: null }
|
|
226
|
+
},
|
|
227
|
+
toDOM(node) {
|
|
228
|
+
const format = toRowFormat(node.attrs.format);
|
|
229
|
+
return [
|
|
230
|
+
"tr",
|
|
231
|
+
{
|
|
232
|
+
class: editorClassNames.tableRow,
|
|
233
|
+
style: rowStyle(format),
|
|
234
|
+
"data-trattrs": text(node.attrs.trAttrs),
|
|
235
|
+
"data-tblprex": text(node.attrs.tblPrEx),
|
|
236
|
+
"data-trpr": text(node.attrs.trPr),
|
|
237
|
+
"data-fmt": formatJson(format)
|
|
238
|
+
},
|
|
239
|
+
0
|
|
240
|
+
];
|
|
241
|
+
},
|
|
242
|
+
parseDOM: [
|
|
243
|
+
{
|
|
244
|
+
tag: "tr",
|
|
245
|
+
getAttrs: (dom) => ({
|
|
246
|
+
trAttrs: dom.getAttribute("data-trattrs"),
|
|
247
|
+
tblPrEx: dom.getAttribute("data-tblprex"),
|
|
248
|
+
trPr: dom.getAttribute("data-trpr"),
|
|
249
|
+
format: toRowFormat(parseJson(dom.getAttribute("data-fmt")))
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
},
|
|
254
|
+
/**
|
|
255
|
+
* A vertically merged cell exists only as the one cell that starts the merge, and
|
|
256
|
+
* `rowspan` counts how many rows it covers.
|
|
257
|
+
* The empty cells on the continuing rows are rebuilt on export.
|
|
258
|
+
*/
|
|
259
|
+
tableCell: {
|
|
260
|
+
content: "block+",
|
|
261
|
+
tableRole: "cell",
|
|
262
|
+
isolating: true,
|
|
263
|
+
attrs: {
|
|
264
|
+
colspan: { default: 1 },
|
|
265
|
+
rowspan: { default: 1 },
|
|
266
|
+
colwidth: { default: null },
|
|
267
|
+
/** The attribute string of the `<w:tc>` opening tag */
|
|
268
|
+
tcAttrs: { default: null },
|
|
269
|
+
/** The whole `<w:tcPr>...</w:tcPr>` XML. It still holds the original vMerge and gridSpan */
|
|
270
|
+
tcPr: { default: null },
|
|
271
|
+
/** The cell width read out of tcPr */
|
|
272
|
+
tcW: { default: null },
|
|
273
|
+
format: { default: null },
|
|
274
|
+
/** The opening XML of the `<w:sdt>` content control this cell sat inside */
|
|
275
|
+
sdtPrefix: { default: null },
|
|
276
|
+
/**
|
|
277
|
+
* The two clauses of that control's lock, which mean the same as `contentsLocked` and
|
|
278
|
+
* `deletionLocked` on the sdt mark. Both only ever stand alongside an `sdtPrefix`, since
|
|
279
|
+
* the lock lives inside that very XML.
|
|
280
|
+
*/
|
|
281
|
+
sdtContentsLocked: { default: false },
|
|
282
|
+
sdtDeletionLocked: { default: false }
|
|
283
|
+
},
|
|
284
|
+
toDOM(node) {
|
|
285
|
+
const format = toCellFormat(node.attrs.format);
|
|
286
|
+
const colspan = spanCount(node.attrs.colspan);
|
|
287
|
+
const rowspan = spanCount(node.attrs.rowspan);
|
|
288
|
+
const colwidth = toColWidth(node.attrs.colwidth);
|
|
289
|
+
const locked = node.attrs.sdtContentsLocked === true;
|
|
290
|
+
return [
|
|
291
|
+
"td",
|
|
292
|
+
{
|
|
293
|
+
class: locked ? `${editorClassNames.tableCell} ${editorClassNames.cellLocked}` : editorClassNames.tableCell,
|
|
294
|
+
style: cellStyle(format),
|
|
295
|
+
colspan: colspan > 1 ? `${colspan}` : void 0,
|
|
296
|
+
rowspan: rowspan > 1 ? `${rowspan}` : void 0,
|
|
297
|
+
"data-colwidth": colwidth ? numberListText(colwidth) : void 0,
|
|
298
|
+
"data-tcattrs": text(node.attrs.tcAttrs),
|
|
299
|
+
"data-tcpr": text(node.attrs.tcPr),
|
|
300
|
+
"data-tcw": formatJson(toTableWidth(node.attrs.tcW)),
|
|
301
|
+
"data-fmt": formatJson(format),
|
|
302
|
+
"data-sdt-prefix": text(node.attrs.sdtPrefix),
|
|
303
|
+
"data-sdt-contents-locked": locked ? "1" : void 0,
|
|
304
|
+
"data-sdt-deletion-locked": node.attrs.sdtDeletionLocked === true ? "1" : void 0
|
|
305
|
+
},
|
|
306
|
+
0
|
|
307
|
+
];
|
|
308
|
+
},
|
|
309
|
+
parseDOM: [
|
|
310
|
+
{
|
|
311
|
+
tag: "td",
|
|
312
|
+
getAttrs: (dom) => ({
|
|
313
|
+
colspan: parseInt10(dom.getAttribute("colspan"), 1),
|
|
314
|
+
rowspan: parseInt10(dom.getAttribute("rowspan"), 1),
|
|
315
|
+
colwidth: toColWidth(
|
|
316
|
+
parseNumberList(dom.getAttribute("data-colwidth"))
|
|
317
|
+
),
|
|
318
|
+
tcAttrs: dom.getAttribute("data-tcattrs"),
|
|
319
|
+
tcPr: dom.getAttribute("data-tcpr"),
|
|
320
|
+
tcW: toTableWidth(parseJson(dom.getAttribute("data-tcw"))),
|
|
321
|
+
format: toCellFormat(parseJson(dom.getAttribute("data-fmt"))),
|
|
322
|
+
sdtPrefix: dom.getAttribute("data-sdt-prefix"),
|
|
323
|
+
sdtContentsLocked: dom.getAttribute("data-sdt-contents-locked") === "1",
|
|
324
|
+
sdtDeletionLocked: dom.getAttribute("data-sdt-deletion-locked") === "1"
|
|
325
|
+
})
|
|
326
|
+
}
|
|
327
|
+
]
|
|
328
|
+
},
|
|
329
|
+
/**
|
|
330
|
+
* The node that carries, as original XML, a block inside a table cell that we do
|
|
331
|
+
* not model (a nested table, for instance).
|
|
332
|
+
* Unlike a body block it has no original fragment number, so it carries its own
|
|
333
|
+
* XML around with it.
|
|
334
|
+
*/
|
|
335
|
+
rawBlock: {
|
|
336
|
+
group: "block",
|
|
337
|
+
atom: true,
|
|
338
|
+
selectable: false,
|
|
339
|
+
attrs: {
|
|
340
|
+
xml: { default: null },
|
|
341
|
+
/** The original element name (for example `w:tbl`) */
|
|
342
|
+
name: { default: null }
|
|
343
|
+
},
|
|
344
|
+
toDOM(node) {
|
|
345
|
+
return [
|
|
346
|
+
"div",
|
|
347
|
+
{
|
|
348
|
+
class: `${editorClassNames.rawBlock} ${editorClassNames.rawXmlBlock}`,
|
|
349
|
+
"data-xml": text(node.attrs.xml),
|
|
350
|
+
"data-name": text(node.attrs.name)
|
|
351
|
+
},
|
|
352
|
+
UNKNOWN_PLACEHOLDER
|
|
353
|
+
];
|
|
354
|
+
},
|
|
355
|
+
parseDOM: [
|
|
356
|
+
{
|
|
357
|
+
tag: `div.${editorClassNames.rawXmlBlock}`,
|
|
358
|
+
getAttrs: (dom) => ({
|
|
359
|
+
xml: dom.getAttribute("data-xml"),
|
|
360
|
+
name: dom.getAttribute("data-name")
|
|
361
|
+
})
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
},
|
|
365
|
+
/** The node that carries a non-paragraph body block (a table we could not model, sectPr, an unknown element) exactly as it came */
|
|
366
|
+
docxRaw: {
|
|
367
|
+
group: "block",
|
|
368
|
+
atom: true,
|
|
369
|
+
selectable: false,
|
|
370
|
+
attrs: {
|
|
371
|
+
srcId: { default: null },
|
|
372
|
+
/** The original element name (for example `w:tbl`) */
|
|
373
|
+
name: { default: null }
|
|
374
|
+
},
|
|
375
|
+
toDOM(node) {
|
|
376
|
+
const { className, label } = rawBlockDom(text(node.attrs.name));
|
|
377
|
+
return [
|
|
378
|
+
"div",
|
|
379
|
+
{
|
|
380
|
+
class: className,
|
|
381
|
+
"data-src": node.attrs.srcId === null ? "" : `${node.attrs.srcId}`,
|
|
382
|
+
"data-name": text(node.attrs.name)
|
|
383
|
+
},
|
|
384
|
+
label
|
|
385
|
+
];
|
|
386
|
+
},
|
|
387
|
+
parseDOM: [
|
|
388
|
+
{
|
|
389
|
+
tag: DOCX_RAW_SELECTOR,
|
|
390
|
+
getAttrs: (dom) => ({
|
|
391
|
+
srcId: srcIdOf(dom),
|
|
392
|
+
name: dom.getAttribute("data-name")
|
|
393
|
+
})
|
|
394
|
+
}
|
|
395
|
+
]
|
|
396
|
+
},
|
|
397
|
+
/** A bookmark range marker that occurs directly under w:body rather than inside a paragraph */
|
|
398
|
+
bookmarkBlock: {
|
|
399
|
+
group: "block",
|
|
400
|
+
atom: true,
|
|
401
|
+
isolating: true,
|
|
402
|
+
selectable: false,
|
|
403
|
+
attrs: {
|
|
404
|
+
srcId: { default: null },
|
|
405
|
+
name: { default: null }
|
|
406
|
+
},
|
|
407
|
+
toDOM(node) {
|
|
408
|
+
return [
|
|
409
|
+
"div",
|
|
410
|
+
{
|
|
411
|
+
class: editorClassNames.bookmarkBlock,
|
|
412
|
+
"data-src": node.attrs.srcId === null ? "" : `${node.attrs.srcId}`,
|
|
413
|
+
"data-name": text(node.attrs.name),
|
|
414
|
+
hidden: "hidden"
|
|
415
|
+
}
|
|
416
|
+
];
|
|
417
|
+
},
|
|
418
|
+
parseDOM: [
|
|
419
|
+
{
|
|
420
|
+
tag: `div.${editorClassNames.bookmarkBlock}`,
|
|
421
|
+
getAttrs: (dom) => ({
|
|
422
|
+
srcId: srcIdOf(dom),
|
|
423
|
+
name: dom.getAttribute("data-name")
|
|
424
|
+
})
|
|
425
|
+
}
|
|
426
|
+
]
|
|
427
|
+
},
|
|
428
|
+
hardBreak: {
|
|
429
|
+
group: "inline",
|
|
430
|
+
inline: true,
|
|
431
|
+
marks: "run sdt link",
|
|
432
|
+
attrs: { brAttrs: { default: null } },
|
|
433
|
+
toDOM(node) {
|
|
434
|
+
return [
|
|
435
|
+
"br",
|
|
436
|
+
{
|
|
437
|
+
"data-battrs": text(node.attrs.brAttrs),
|
|
438
|
+
[editorAttributes.breakType]: isPageBreak(node.attrs.brAttrs) ? "page" : void 0
|
|
439
|
+
}
|
|
440
|
+
];
|
|
441
|
+
},
|
|
442
|
+
parseDOM: [
|
|
443
|
+
{
|
|
444
|
+
tag: "br",
|
|
445
|
+
getAttrs: (dom) => ({ brAttrs: dom.getAttribute("data-battrs") })
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
},
|
|
449
|
+
/**
|
|
450
|
+
* `src` carries the bytes themselves as a data URL (see `docx/media` for why), and
|
|
451
|
+
* `extent` the size the drawing records, in EMU.
|
|
452
|
+
* An imported image also holds its whole original `<w:drawing>` XML, so an image
|
|
453
|
+
* nobody touched goes back out byte for byte and a resize rewrites nothing but the
|
|
454
|
+
* two extents. An image inserted during editing has no such XML, and the export
|
|
455
|
+
* builds a drawing for it from the bytes.
|
|
456
|
+
*/
|
|
457
|
+
image: {
|
|
458
|
+
group: "inline",
|
|
459
|
+
inline: true,
|
|
460
|
+
draggable: true,
|
|
461
|
+
marks: "run sdt link",
|
|
462
|
+
attrs: {
|
|
463
|
+
/** The image bytes as a data URL */
|
|
464
|
+
src: { default: null },
|
|
465
|
+
/** The display size in EMU, as `{ cx, cy }` */
|
|
466
|
+
extent: { default: null },
|
|
467
|
+
/** The alternative text from `wp:docPr descr`. null when there is none */
|
|
468
|
+
alt: { default: null },
|
|
469
|
+
/** The whole original `<w:drawing>` XML. null for an image inserted during editing */
|
|
470
|
+
xml: { default: null }
|
|
471
|
+
},
|
|
472
|
+
toDOM(node) {
|
|
473
|
+
return imageNodeSpec(node.attrs);
|
|
474
|
+
},
|
|
475
|
+
parseDOM: [
|
|
476
|
+
{
|
|
477
|
+
tag: `img.${editorClassNames.image}`,
|
|
478
|
+
getAttrs: (dom) => ({
|
|
479
|
+
src: toImageSrc(dom.getAttribute("src")),
|
|
480
|
+
extent: toImageExtent(parseJson(dom.getAttribute("data-extent"))),
|
|
481
|
+
alt: dom.getAttribute("alt") || null,
|
|
482
|
+
xml: dom.getAttribute("data-xml")
|
|
483
|
+
})
|
|
484
|
+
}
|
|
485
|
+
]
|
|
486
|
+
},
|
|
487
|
+
commentStart: {
|
|
488
|
+
group: "inline",
|
|
489
|
+
inline: true,
|
|
490
|
+
atom: true,
|
|
491
|
+
selectable: false,
|
|
492
|
+
marks: "sdt link",
|
|
493
|
+
attrs: {
|
|
494
|
+
id: { default: null },
|
|
495
|
+
xml: { default: null }
|
|
496
|
+
},
|
|
497
|
+
toDOM(node) {
|
|
498
|
+
return [
|
|
499
|
+
"span",
|
|
500
|
+
{
|
|
501
|
+
class: editorClassNames.commentMarker,
|
|
502
|
+
"data-comment-marker": "start",
|
|
503
|
+
"data-comment-id": text(node.attrs.id),
|
|
504
|
+
"data-xml": text(node.attrs.xml)
|
|
505
|
+
}
|
|
506
|
+
];
|
|
507
|
+
},
|
|
508
|
+
parseDOM: [
|
|
509
|
+
{
|
|
510
|
+
tag: `span.${editorClassNames.commentMarker}[data-comment-marker="start"]`,
|
|
511
|
+
getAttrs: (dom) => ({
|
|
512
|
+
id: dom.getAttribute("data-comment-id"),
|
|
513
|
+
xml: dom.getAttribute("data-xml")
|
|
514
|
+
})
|
|
515
|
+
}
|
|
516
|
+
]
|
|
517
|
+
},
|
|
518
|
+
commentEnd: {
|
|
519
|
+
group: "inline",
|
|
520
|
+
inline: true,
|
|
521
|
+
atom: true,
|
|
522
|
+
selectable: false,
|
|
523
|
+
marks: "sdt link",
|
|
524
|
+
attrs: {
|
|
525
|
+
id: { default: null },
|
|
526
|
+
xml: { default: null }
|
|
527
|
+
},
|
|
528
|
+
toDOM(node) {
|
|
529
|
+
return [
|
|
530
|
+
"span",
|
|
531
|
+
{
|
|
532
|
+
class: editorClassNames.commentMarker,
|
|
533
|
+
"data-comment-marker": "end",
|
|
534
|
+
"data-comment-id": text(node.attrs.id),
|
|
535
|
+
"data-xml": text(node.attrs.xml)
|
|
536
|
+
}
|
|
537
|
+
];
|
|
538
|
+
},
|
|
539
|
+
parseDOM: [
|
|
540
|
+
{
|
|
541
|
+
tag: `span.${editorClassNames.commentMarker}[data-comment-marker="end"]`,
|
|
542
|
+
getAttrs: (dom) => ({
|
|
543
|
+
id: dom.getAttribute("data-comment-id"),
|
|
544
|
+
xml: dom.getAttribute("data-xml")
|
|
545
|
+
})
|
|
546
|
+
}
|
|
547
|
+
]
|
|
548
|
+
},
|
|
549
|
+
commentReference: {
|
|
550
|
+
group: "inline",
|
|
551
|
+
inline: true,
|
|
552
|
+
atom: true,
|
|
553
|
+
selectable: false,
|
|
554
|
+
marks: "run sdt link",
|
|
555
|
+
attrs: {
|
|
556
|
+
id: { default: null },
|
|
557
|
+
referenceXml: { default: null },
|
|
558
|
+
author: { default: null },
|
|
559
|
+
initials: { default: null },
|
|
560
|
+
date: { default: null },
|
|
561
|
+
text: { default: "" },
|
|
562
|
+
commentXml: { default: null },
|
|
563
|
+
imported: { default: false },
|
|
564
|
+
paraId: { default: null },
|
|
565
|
+
resolved: { default: false },
|
|
566
|
+
extensionXml: { default: null },
|
|
567
|
+
threadImported: { default: false },
|
|
568
|
+
replies: { default: [] }
|
|
569
|
+
},
|
|
570
|
+
toDOM(node) {
|
|
571
|
+
return [
|
|
572
|
+
"span",
|
|
573
|
+
{
|
|
574
|
+
class: editorClassNames.commentMarker,
|
|
575
|
+
"data-comment-marker": "reference",
|
|
576
|
+
"data-comment-id": text(node.attrs.id),
|
|
577
|
+
"data-reference-xml": text(node.attrs.referenceXml),
|
|
578
|
+
"data-comment-author": text(node.attrs.author),
|
|
579
|
+
"data-comment-initials": text(node.attrs.initials),
|
|
580
|
+
"data-comment-date": text(node.attrs.date),
|
|
581
|
+
"data-comment-text": text(node.attrs.text),
|
|
582
|
+
"data-comment-xml": text(node.attrs.commentXml),
|
|
583
|
+
"data-comment-imported": node.attrs.imported === true ? "1" : void 0,
|
|
584
|
+
"data-comment-para-id": text(node.attrs.paraId),
|
|
585
|
+
"data-comment-resolved": node.attrs.resolved === true ? "1" : void 0,
|
|
586
|
+
"data-comment-extension-xml": text(node.attrs.extensionXml),
|
|
587
|
+
"data-comment-thread-imported": node.attrs.threadImported === true ? "1" : void 0,
|
|
588
|
+
"data-comment-replies": JSON.stringify(node.attrs.replies ?? [])
|
|
589
|
+
}
|
|
590
|
+
];
|
|
591
|
+
},
|
|
592
|
+
parseDOM: [
|
|
593
|
+
{
|
|
594
|
+
tag: `span.${editorClassNames.commentMarker}[data-comment-marker="reference"]`,
|
|
595
|
+
getAttrs: (dom) => ({
|
|
596
|
+
id: dom.getAttribute("data-comment-id"),
|
|
597
|
+
referenceXml: dom.getAttribute("data-reference-xml"),
|
|
598
|
+
author: dom.getAttribute("data-comment-author"),
|
|
599
|
+
initials: dom.getAttribute("data-comment-initials"),
|
|
600
|
+
date: dom.getAttribute("data-comment-date"),
|
|
601
|
+
text: dom.getAttribute("data-comment-text") ?? "",
|
|
602
|
+
commentXml: dom.getAttribute("data-comment-xml"),
|
|
603
|
+
imported: dom.getAttribute("data-comment-imported") === "1",
|
|
604
|
+
paraId: dom.getAttribute("data-comment-para-id"),
|
|
605
|
+
resolved: dom.getAttribute("data-comment-resolved") === "1",
|
|
606
|
+
extensionXml: dom.getAttribute("data-comment-extension-xml"),
|
|
607
|
+
threadImported: dom.getAttribute("data-comment-thread-imported") === "1",
|
|
608
|
+
replies: parseJson(dom.getAttribute("data-comment-replies")) ?? []
|
|
609
|
+
})
|
|
610
|
+
}
|
|
611
|
+
]
|
|
612
|
+
},
|
|
613
|
+
noteReference: {
|
|
614
|
+
group: "inline",
|
|
615
|
+
inline: true,
|
|
616
|
+
atom: true,
|
|
617
|
+
selectable: false,
|
|
618
|
+
marks: "run sdt link",
|
|
619
|
+
attrs: {
|
|
620
|
+
kind: { default: "footnote" },
|
|
621
|
+
id: { default: null },
|
|
622
|
+
label: { default: "?" },
|
|
623
|
+
text: { default: "" },
|
|
624
|
+
customMarkFollows: { default: false },
|
|
625
|
+
referenceXml: { default: null }
|
|
626
|
+
},
|
|
627
|
+
toDOM(node) {
|
|
628
|
+
const kind = node.attrs.kind === "endnote" ? "Endnote" : "Footnote";
|
|
629
|
+
const label = text(node.attrs.label) ?? "?";
|
|
630
|
+
const body = text(node.attrs.text) ?? "";
|
|
631
|
+
return [
|
|
632
|
+
"sup",
|
|
633
|
+
{
|
|
634
|
+
class: editorClassNames.noteReference,
|
|
635
|
+
"data-note-kind": text(node.attrs.kind),
|
|
636
|
+
"data-note-id": text(node.attrs.id),
|
|
637
|
+
"data-note-label": label,
|
|
638
|
+
"data-note-text": body,
|
|
639
|
+
"data-custom-mark-follows": node.attrs.customMarkFollows === true ? "1" : void 0,
|
|
640
|
+
"data-reference-xml": text(node.attrs.referenceXml),
|
|
641
|
+
"aria-label": `${kind} ${label}`,
|
|
642
|
+
title: body
|
|
643
|
+
},
|
|
644
|
+
node.attrs.customMarkFollows === true ? "" : label
|
|
645
|
+
];
|
|
646
|
+
},
|
|
647
|
+
parseDOM: [
|
|
648
|
+
{
|
|
649
|
+
tag: `sup.${editorClassNames.noteReference}`,
|
|
650
|
+
getAttrs: (dom) => ({
|
|
651
|
+
kind: dom.getAttribute("data-note-kind") === "endnote" ? "endnote" : "footnote",
|
|
652
|
+
id: dom.getAttribute("data-note-id"),
|
|
653
|
+
label: dom.getAttribute("data-note-label") ?? "?",
|
|
654
|
+
text: dom.getAttribute("data-note-text") ?? "",
|
|
655
|
+
customMarkFollows: dom.getAttribute("data-custom-mark-follows") === "1",
|
|
656
|
+
referenceXml: dom.getAttribute("data-reference-xml")
|
|
657
|
+
})
|
|
658
|
+
}
|
|
659
|
+
]
|
|
660
|
+
},
|
|
661
|
+
/** The node that carries a non-run element inside a paragraph (a bookmark, for instance) exactly as it came */
|
|
662
|
+
rawInline: {
|
|
663
|
+
group: "inline",
|
|
664
|
+
inline: true,
|
|
665
|
+
atom: true,
|
|
666
|
+
marks: "sdt link",
|
|
667
|
+
attrs: { xml: { default: null } },
|
|
668
|
+
toDOM(node) {
|
|
669
|
+
return [
|
|
670
|
+
"span",
|
|
671
|
+
{
|
|
672
|
+
class: editorClassNames.rawInline,
|
|
673
|
+
"data-xml": text(node.attrs.xml)
|
|
674
|
+
}
|
|
675
|
+
];
|
|
676
|
+
},
|
|
677
|
+
parseDOM: [
|
|
678
|
+
{
|
|
679
|
+
tag: `span.${editorClassNames.rawInline}`,
|
|
680
|
+
getAttrs: (dom) => ({ xml: dom.getAttribute("data-xml") })
|
|
681
|
+
}
|
|
682
|
+
]
|
|
683
|
+
},
|
|
684
|
+
text: { group: "inline" }
|
|
685
|
+
},
|
|
686
|
+
marks: {
|
|
687
|
+
/**
|
|
688
|
+
* The content control (`w:sdt`) a stretch of inline content sits inside.
|
|
689
|
+
*
|
|
690
|
+
* It is declared ahead of the run mark on purpose: the mark declared first is drawn
|
|
691
|
+
* outside on screen, so one control can hold the several runs it wrapped in the file.
|
|
692
|
+
*/
|
|
693
|
+
sdt: {
|
|
694
|
+
// A character typed against either edge of the control belongs outside it
|
|
695
|
+
inclusive: false,
|
|
696
|
+
attrs: {
|
|
697
|
+
/** The opening XML of the `<w:sdt>`, the same string a wrapped cell carries */
|
|
698
|
+
sdtPrefix: { default: null },
|
|
699
|
+
/**
|
|
700
|
+
* Which control this is, counted through the document as it was opened, and never
|
|
701
|
+
* written back to the file. Two controls whose XML is identical would otherwise wear
|
|
702
|
+
* the very same mark and their text would run into one. The first control gets 0, so
|
|
703
|
+
* a control made during editing needs no number of its own.
|
|
704
|
+
*/
|
|
705
|
+
sdtKey: { default: 0 },
|
|
706
|
+
/**
|
|
707
|
+
* The two clauses of the control's lock: whether its contents may not be edited, and
|
|
708
|
+
* whether the control itself may not be deleted, not even whole. The `w:lock` inside
|
|
709
|
+
* sdtPrefix is where both come from, and reading it once on import saves parsing that
|
|
710
|
+
* string again on every draw.
|
|
711
|
+
* The two are independent: a control may be un-editable yet removable, or editable yet
|
|
712
|
+
* not removable.
|
|
713
|
+
*/
|
|
714
|
+
contentsLocked: { default: false },
|
|
715
|
+
deletionLocked: { default: false }
|
|
716
|
+
},
|
|
717
|
+
toDOM(mark) {
|
|
718
|
+
const locked = mark.attrs.contentsLocked === true;
|
|
719
|
+
return [
|
|
720
|
+
"span",
|
|
721
|
+
{
|
|
722
|
+
class: locked ? `${editorClassNames.sdt} ${editorClassNames.sdtLocked}` : editorClassNames.sdt,
|
|
723
|
+
"data-sdt-prefix": text(mark.attrs.sdtPrefix),
|
|
724
|
+
"data-sdt-key": numberText(mark.attrs.sdtKey),
|
|
725
|
+
"data-sdt-contents-locked": locked ? "1" : void 0,
|
|
726
|
+
"data-sdt-deletion-locked": mark.attrs.deletionLocked === true ? "1" : void 0
|
|
727
|
+
},
|
|
728
|
+
0
|
|
729
|
+
];
|
|
730
|
+
},
|
|
731
|
+
parseDOM: [
|
|
732
|
+
{
|
|
733
|
+
tag: `span.${editorClassNames.sdt}`,
|
|
734
|
+
getAttrs: (dom) => {
|
|
735
|
+
const prefix = dom.getAttribute("data-sdt-prefix");
|
|
736
|
+
if (prefix === null) return false;
|
|
737
|
+
return {
|
|
738
|
+
sdtPrefix: prefix,
|
|
739
|
+
sdtKey: parseInt10(dom.getAttribute("data-sdt-key"), 0),
|
|
740
|
+
contentsLocked: dom.getAttribute("data-sdt-contents-locked") === "1",
|
|
741
|
+
deletionLocked: dom.getAttribute("data-sdt-deletion-locked") === "1"
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
]
|
|
746
|
+
},
|
|
747
|
+
/**
|
|
748
|
+
* The hyperlink (`w:hyperlink`) a stretch of inline content sits inside.
|
|
749
|
+
*
|
|
750
|
+
* It stands between the control and the run for the same reason the control stands outside
|
|
751
|
+
* both: a link wraps whole runs in the file, and a link inside a content control has to come
|
|
752
|
+
* back out inside it (`docx/serializeParagraph`).
|
|
753
|
+
*/
|
|
754
|
+
link: {
|
|
755
|
+
// A character typed against either edge of a link belongs outside it, and that is also what
|
|
756
|
+
// decides whether a caret counts as standing in one (`editor/commands/linkCommands`)
|
|
757
|
+
inclusive: false,
|
|
758
|
+
attrs: {
|
|
759
|
+
/**
|
|
760
|
+
* The opening XML of the `<w:hyperlink>`, which carries everything about the link we never
|
|
761
|
+
* read: `w:tooltip`, `w:history`, `w:docLocation`, `w:anchor`. null for a link made in the
|
|
762
|
+
* editor, which the export writes an opening tag for.
|
|
763
|
+
*/
|
|
764
|
+
linkPrefix: { default: null },
|
|
765
|
+
/**
|
|
766
|
+
* The address, read through the relationship the wrapper names. null for a link that names
|
|
767
|
+
* a bookmark alone, or one whose relationship leads nowhere we can follow: the wrapper still
|
|
768
|
+
* travels, and no address is offered for it.
|
|
769
|
+
*/
|
|
770
|
+
href: { default: null },
|
|
771
|
+
/**
|
|
772
|
+
* Which link this is, counted through the document as it was opened, and never written back
|
|
773
|
+
* to the file. Two links written exactly alike would otherwise wear the very same mark and
|
|
774
|
+
* the text they cover would run into one wrapper. The first link gets 0, so a link made
|
|
775
|
+
* during editing needs no number of its own.
|
|
776
|
+
*/
|
|
777
|
+
linkKey: { default: 0 }
|
|
778
|
+
},
|
|
779
|
+
toDOM(mark) {
|
|
780
|
+
return [
|
|
781
|
+
"span",
|
|
782
|
+
{
|
|
783
|
+
class: editorClassNames.link,
|
|
784
|
+
// The address is drawn as data rather than as an `href`, so that nothing on the page
|
|
785
|
+
// navigates: a click in the text places the caret, and opening the address is offered
|
|
786
|
+
// by the link panel instead
|
|
787
|
+
"data-href": text(mark.attrs.href),
|
|
788
|
+
"data-link-prefix": text(mark.attrs.linkPrefix),
|
|
789
|
+
"data-link-key": numberText(mark.attrs.linkKey)
|
|
790
|
+
},
|
|
791
|
+
0
|
|
792
|
+
];
|
|
793
|
+
},
|
|
794
|
+
parseDOM: [
|
|
795
|
+
{
|
|
796
|
+
tag: `span.${editorClassNames.link}`,
|
|
797
|
+
getAttrs: (dom) => {
|
|
798
|
+
const prefix = dom.getAttribute("data-link-prefix");
|
|
799
|
+
const href = dom.getAttribute("data-href");
|
|
800
|
+
if (prefix === null && href === null) return false;
|
|
801
|
+
return {
|
|
802
|
+
linkPrefix: prefix,
|
|
803
|
+
href,
|
|
804
|
+
linkKey: parseInt10(dom.getAttribute("data-link-key"), 0)
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
]
|
|
809
|
+
},
|
|
810
|
+
/**
|
|
811
|
+
* The run mark carries the original XML untouched, so even formatting we cannot
|
|
812
|
+
* interpret survives editing unchanged.
|
|
813
|
+
*/
|
|
814
|
+
run: {
|
|
815
|
+
attrs: {
|
|
816
|
+
rPr: { default: null },
|
|
817
|
+
rAttrs: { default: null },
|
|
818
|
+
/** The display values derived from reading rPr */
|
|
819
|
+
format: { default: null }
|
|
820
|
+
},
|
|
821
|
+
toDOM(mark) {
|
|
822
|
+
return runMarkSpec(mark.attrs, DEFAULT_FONT_FALLBACKS);
|
|
823
|
+
},
|
|
824
|
+
parseDOM: [
|
|
825
|
+
{
|
|
826
|
+
tag: `span.${editorClassNames.run}`,
|
|
827
|
+
getAttrs: (dom) => ({
|
|
828
|
+
rAttrs: dom.getAttribute("data-rattrs"),
|
|
829
|
+
rPr: dom.getAttribute("data-rpr"),
|
|
830
|
+
format: toRunFormat(parseJson(dom.getAttribute("data-fmt")))
|
|
831
|
+
})
|
|
832
|
+
}
|
|
833
|
+
]
|
|
834
|
+
},
|
|
835
|
+
/** A text tab whose mark retains the attributes of the source `w:tab`. */
|
|
836
|
+
tab: {
|
|
837
|
+
inclusive: false,
|
|
838
|
+
attrs: { tabAttrs: { default: null } },
|
|
839
|
+
toDOM(mark) {
|
|
840
|
+
return [
|
|
841
|
+
"span",
|
|
842
|
+
{
|
|
843
|
+
class: editorClassNames.tab,
|
|
844
|
+
"data-tattrs": text(mark.attrs.tabAttrs)
|
|
845
|
+
},
|
|
846
|
+
0
|
|
847
|
+
];
|
|
848
|
+
},
|
|
849
|
+
parseDOM: [
|
|
850
|
+
{
|
|
851
|
+
tag: `span.${editorClassNames.tab}`,
|
|
852
|
+
getAttrs: (dom) => ({ tabAttrs: dom.getAttribute("data-tattrs") })
|
|
853
|
+
}
|
|
854
|
+
]
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
});
|
|
858
|
+
export {
|
|
859
|
+
docxSchema,
|
|
860
|
+
imageNodeSpec2 as imageNodeSpec,
|
|
861
|
+
isPageBreak,
|
|
862
|
+
runMarkSpec2 as runMarkSpec
|
|
863
|
+
};
|