@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,275 @@
|
|
|
1
|
+
// src/docx/importTable.ts
|
|
2
|
+
import {
|
|
3
|
+
toCellMargins,
|
|
4
|
+
toInsideBorders
|
|
5
|
+
} from "../model/format.js";
|
|
6
|
+
import { childValue, wAttr } from "../ooxml/units.js";
|
|
7
|
+
import {
|
|
8
|
+
attrString,
|
|
9
|
+
childByLocalName,
|
|
10
|
+
elementChildren,
|
|
11
|
+
serializeXml
|
|
12
|
+
} from "../ooxml/xml.js";
|
|
13
|
+
import { docxSchema } from "../schema/index.js";
|
|
14
|
+
import {
|
|
15
|
+
layerTableFormat,
|
|
16
|
+
NO_STYLES
|
|
17
|
+
} from "./formatting.js";
|
|
18
|
+
import {
|
|
19
|
+
buildParagraph,
|
|
20
|
+
NO_IMPORT_SOURCES
|
|
21
|
+
} from "./importParagraph.js";
|
|
22
|
+
import { readSdtWrapper } from "./sdt.js";
|
|
23
|
+
import {
|
|
24
|
+
cellBorderDefaults,
|
|
25
|
+
gridEdgesOf,
|
|
26
|
+
layerCellMargins,
|
|
27
|
+
layerInsideBorders,
|
|
28
|
+
NO_CELL_MARGINS,
|
|
29
|
+
NO_INSIDE_BORDERS,
|
|
30
|
+
readCellFormat,
|
|
31
|
+
readCellMarginsOf,
|
|
32
|
+
readGridCols,
|
|
33
|
+
readInsideBorders,
|
|
34
|
+
readRowFormat,
|
|
35
|
+
readTableFormat,
|
|
36
|
+
readTableWidth,
|
|
37
|
+
tblStyleIdOf
|
|
38
|
+
} from "./tableFormatting.js";
|
|
39
|
+
function readGridSpan(tcPr) {
|
|
40
|
+
const value = tcPr ? childValue(tcPr, "gridSpan") : null;
|
|
41
|
+
const parsed = value === null ? null : Number.parseInt(value, 10);
|
|
42
|
+
return parsed !== null && Number.isInteger(parsed) && parsed > 0 ? parsed : 1;
|
|
43
|
+
}
|
|
44
|
+
function readVerticalMerge(tcPr) {
|
|
45
|
+
const vMerge = tcPr ? childByLocalName(tcPr, "vMerge") : null;
|
|
46
|
+
if (!vMerge) return null;
|
|
47
|
+
return wAttr(vMerge, "val") === "restart" ? "restart" : "continue";
|
|
48
|
+
}
|
|
49
|
+
function readSdtCell(el) {
|
|
50
|
+
const wrapper = readSdtWrapper(el);
|
|
51
|
+
if (!wrapper) return null;
|
|
52
|
+
const inner = elementChildren(wrapper.content);
|
|
53
|
+
const tc = inner[0];
|
|
54
|
+
if (inner.length !== 1 || tc.localName !== "tc") return null;
|
|
55
|
+
if (readVerticalMerge(childByLocalName(tc, "tcPr")) === "continue") {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
el: tc,
|
|
60
|
+
control: {
|
|
61
|
+
prefix: wrapper.prefix,
|
|
62
|
+
contentsLocked: wrapper.contentsLocked,
|
|
63
|
+
deletionLocked: wrapper.deletionLocked
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function readRow(el) {
|
|
68
|
+
const cells = [];
|
|
69
|
+
let tblPrEx = null;
|
|
70
|
+
for (const child of elementChildren(el)) {
|
|
71
|
+
if (child.localName === "trPr") continue;
|
|
72
|
+
if (child.localName === "tblPrEx") {
|
|
73
|
+
tblPrEx = child;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const sdt = child.localName === "sdt" ? readSdtCell(child) : null;
|
|
77
|
+
if (!sdt && child.localName !== "tc") return null;
|
|
78
|
+
const tc = sdt ? sdt.el : child;
|
|
79
|
+
const tcPr = childByLocalName(tc, "tcPr");
|
|
80
|
+
cells.push({
|
|
81
|
+
el: tc,
|
|
82
|
+
gridSpan: readGridSpan(tcPr),
|
|
83
|
+
vMerge: readVerticalMerge(tcPr),
|
|
84
|
+
control: sdt ? sdt.control : null
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return cells.length > 0 ? { el, tblPrEx, cells } : null;
|
|
88
|
+
}
|
|
89
|
+
function readTableParts(el) {
|
|
90
|
+
let tblPr = null;
|
|
91
|
+
let tblGrid = null;
|
|
92
|
+
const rows = [];
|
|
93
|
+
for (const child of elementChildren(el)) {
|
|
94
|
+
if (child.localName === "tblPr") {
|
|
95
|
+
tblPr = child;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (child.localName === "tblGrid") {
|
|
99
|
+
tblGrid = child;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (child.localName !== "tr") return null;
|
|
103
|
+
const row = readRow(child);
|
|
104
|
+
if (!row) return null;
|
|
105
|
+
rows.push(row);
|
|
106
|
+
}
|
|
107
|
+
return rows.length > 0 ? { tblPr, tblGrid, rows } : null;
|
|
108
|
+
}
|
|
109
|
+
function resolveVerticalMerges(rows, width) {
|
|
110
|
+
const drafts = [];
|
|
111
|
+
let open = /* @__PURE__ */ new Map();
|
|
112
|
+
for (const [index, row] of rows.entries()) {
|
|
113
|
+
const rowDrafts = [];
|
|
114
|
+
const next = /* @__PURE__ */ new Map();
|
|
115
|
+
let col = 0;
|
|
116
|
+
for (const cell of row.cells) {
|
|
117
|
+
if (cell.vMerge === "continue") {
|
|
118
|
+
const chain = open.get(col);
|
|
119
|
+
if (!chain || chain.colspan !== cell.gridSpan) return null;
|
|
120
|
+
chain.rowspan += 1;
|
|
121
|
+
next.set(col, chain);
|
|
122
|
+
} else {
|
|
123
|
+
const draft = {
|
|
124
|
+
el: cell.el,
|
|
125
|
+
row: index,
|
|
126
|
+
col,
|
|
127
|
+
colspan: cell.gridSpan,
|
|
128
|
+
rowspan: 1,
|
|
129
|
+
control: cell.control
|
|
130
|
+
};
|
|
131
|
+
rowDrafts.push(draft);
|
|
132
|
+
if (cell.vMerge === "restart") next.set(col, draft);
|
|
133
|
+
}
|
|
134
|
+
col += cell.gridSpan;
|
|
135
|
+
}
|
|
136
|
+
if (col !== width) return null;
|
|
137
|
+
if (rowDrafts.length === 0) return null;
|
|
138
|
+
drafts.push(rowDrafts);
|
|
139
|
+
open = next;
|
|
140
|
+
}
|
|
141
|
+
return drafts;
|
|
142
|
+
}
|
|
143
|
+
function gridWidthOf(rows) {
|
|
144
|
+
const widths = rows.map(
|
|
145
|
+
(row) => row.cells.reduce((sum, cell) => sum + cell.gridSpan, 0)
|
|
146
|
+
);
|
|
147
|
+
const first = widths[0];
|
|
148
|
+
return widths.every((width) => width === first) ? first : null;
|
|
149
|
+
}
|
|
150
|
+
function buildCellBlock(el, sources) {
|
|
151
|
+
if (el.localName === "p") {
|
|
152
|
+
const paragraph = buildParagraph(el, null, sources);
|
|
153
|
+
if (paragraph) return paragraph;
|
|
154
|
+
}
|
|
155
|
+
return docxSchema.nodes.rawBlock.create({
|
|
156
|
+
xml: serializeXml(el),
|
|
157
|
+
name: el.nodeName
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function cellBorderDefaultsFor(draft, lines) {
|
|
161
|
+
return cellBorderDefaults(
|
|
162
|
+
gridEdgesOf(
|
|
163
|
+
{
|
|
164
|
+
top: draft.row,
|
|
165
|
+
bottom: draft.row + draft.rowspan,
|
|
166
|
+
left: draft.col,
|
|
167
|
+
right: draft.col + draft.colspan
|
|
168
|
+
},
|
|
169
|
+
lines
|
|
170
|
+
),
|
|
171
|
+
lines.outer,
|
|
172
|
+
lines.inside
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
function buildCell(draft, lines, sources) {
|
|
176
|
+
const tcPr = childByLocalName(draft.el, "tcPr");
|
|
177
|
+
const blocks = [];
|
|
178
|
+
for (const child of elementChildren(draft.el)) {
|
|
179
|
+
if (child.localName === "tcPr") continue;
|
|
180
|
+
blocks.push(buildCellBlock(child, sources));
|
|
181
|
+
}
|
|
182
|
+
if (blocks.length === 0) return null;
|
|
183
|
+
return docxSchema.nodes.tableCell.create(
|
|
184
|
+
{
|
|
185
|
+
colspan: draft.colspan,
|
|
186
|
+
rowspan: draft.rowspan,
|
|
187
|
+
colwidth: null,
|
|
188
|
+
tcAttrs: attrString(draft.el),
|
|
189
|
+
tcPr: tcPr ? serializeXml(tcPr) : null,
|
|
190
|
+
tcW: readTableWidth(tcPr, "tcW"),
|
|
191
|
+
format: readCellFormat(
|
|
192
|
+
tcPr,
|
|
193
|
+
cellBorderDefaultsFor(draft, lines),
|
|
194
|
+
lines.margins
|
|
195
|
+
),
|
|
196
|
+
sdtPrefix: draft.control?.prefix ?? null,
|
|
197
|
+
sdtContentsLocked: draft.control?.contentsLocked ?? false,
|
|
198
|
+
sdtDeletionLocked: draft.control?.deletionLocked ?? false
|
|
199
|
+
},
|
|
200
|
+
blocks
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
function buildRow(row, drafts, lines, sources) {
|
|
204
|
+
const cells = [];
|
|
205
|
+
for (const draft of drafts) {
|
|
206
|
+
const cell = buildCell(draft, lines, sources);
|
|
207
|
+
if (!cell) return null;
|
|
208
|
+
cells.push(cell);
|
|
209
|
+
}
|
|
210
|
+
const trPr = childByLocalName(row.el, "trPr");
|
|
211
|
+
return docxSchema.nodes.tableRow.create(
|
|
212
|
+
{
|
|
213
|
+
trAttrs: attrString(row.el),
|
|
214
|
+
tblPrEx: row.tblPrEx ? serializeXml(row.tblPrEx) : null,
|
|
215
|
+
trPr: trPr ? serializeXml(trPr) : null,
|
|
216
|
+
format: readRowFormat(trPr)
|
|
217
|
+
},
|
|
218
|
+
cells
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
function tableStyleOf(tblPr, styles, defaultTableStyleId) {
|
|
222
|
+
const styleId = tblStyleIdOf(tblPr);
|
|
223
|
+
return (styleId !== null ? styles.get(styleId) : void 0) ?? (defaultTableStyleId !== null ? styles.get(defaultTableStyleId) : void 0);
|
|
224
|
+
}
|
|
225
|
+
function buildTable(el, srcId, sources = NO_IMPORT_SOURCES, styles = NO_STYLES, defaultTableStyleId = null) {
|
|
226
|
+
const parts = readTableParts(el);
|
|
227
|
+
if (!parts) return null;
|
|
228
|
+
const gridCols = readGridCols(parts.tblGrid);
|
|
229
|
+
const width = gridWidthOf(parts.rows);
|
|
230
|
+
if (width === null || width === 0) return null;
|
|
231
|
+
if (gridCols.length > 0 && gridCols.length !== width) return null;
|
|
232
|
+
const drafts = resolveVerticalMerges(parts.rows, width);
|
|
233
|
+
if (!drafts) return null;
|
|
234
|
+
const style = tableStyleOf(parts.tblPr, styles, defaultTableStyleId);
|
|
235
|
+
const tableFormat = layerTableFormat(
|
|
236
|
+
style?.table ?? {},
|
|
237
|
+
readTableFormat(parts.tblPr)
|
|
238
|
+
);
|
|
239
|
+
const lines = {
|
|
240
|
+
rows: parts.rows.length,
|
|
241
|
+
cols: width,
|
|
242
|
+
outer: tableFormat,
|
|
243
|
+
inside: layerInsideBorders(
|
|
244
|
+
style?.tableInside ?? NO_INSIDE_BORDERS,
|
|
245
|
+
readInsideBorders(parts.tblPr)
|
|
246
|
+
),
|
|
247
|
+
margins: layerCellMargins(
|
|
248
|
+
style?.tableCellMargins ?? NO_CELL_MARGINS,
|
|
249
|
+
readCellMarginsOf(parts.tblPr, "tblCellMar")
|
|
250
|
+
)
|
|
251
|
+
};
|
|
252
|
+
const rows = [];
|
|
253
|
+
for (const [index, row] of parts.rows.entries()) {
|
|
254
|
+
const built = buildRow(row, drafts[index], lines, sources);
|
|
255
|
+
if (!built) return null;
|
|
256
|
+
rows.push(built);
|
|
257
|
+
}
|
|
258
|
+
return docxSchema.nodes.table.create(
|
|
259
|
+
{
|
|
260
|
+
srcId,
|
|
261
|
+
tblAttrs: attrString(el),
|
|
262
|
+
tblPr: parts.tblPr ? serializeXml(parts.tblPr) : null,
|
|
263
|
+
tblW: readTableWidth(parts.tblPr, "tblW"),
|
|
264
|
+
gridCols,
|
|
265
|
+
format: tableFormat,
|
|
266
|
+
// The cells need these again whenever an edit derives their display values afresh
|
|
267
|
+
styleInside: toInsideBorders(style?.tableInside),
|
|
268
|
+
styleCellMargins: toCellMargins(style?.tableCellMargins)
|
|
269
|
+
},
|
|
270
|
+
rows
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
export {
|
|
274
|
+
buildTable
|
|
275
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads and writes package image parts. Nodes keep data URLs so undoable document states own their
|
|
3
|
+
* bytes without blob-URL lifetime management; `MAX_IMAGE_BYTES` bounds the memory tradeoff.
|
|
4
|
+
*/
|
|
5
|
+
import type { Node as PMNode } from "prosemirror-model";
|
|
6
|
+
import { type RelationshipWriter } from "./relationships";
|
|
7
|
+
import type { SessionStore } from "./session";
|
|
8
|
+
/** The images the body can refer to, as data URLs keyed by relationship id */
|
|
9
|
+
export type ImageSources = ReadonlyMap<string, string>;
|
|
10
|
+
export declare const NO_IMAGES: ImageSources;
|
|
11
|
+
/**
|
|
12
|
+
* The most one image may weigh before it is left undrawn.
|
|
13
|
+
*
|
|
14
|
+
* The document state holds every image as base64 for as long as the editor is open, and
|
|
15
|
+
* base64 costs a third more than the bytes, so an untrusted document would otherwise
|
|
16
|
+
* decide by itself how much memory the session takes. An image past the cap takes the same
|
|
17
|
+
* road as one no browser can draw rather than the document being refused: nothing is lost,
|
|
18
|
+
* since the drawing and its media part still ride back out untouched.
|
|
19
|
+
* No photograph a contract carries comes near this.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_IMAGE_BYTES: number;
|
|
22
|
+
/**
|
|
23
|
+
* Every image the body part has a relationship to.
|
|
24
|
+
*
|
|
25
|
+
* A relationship we cannot follow (a linked file, a missing part, a kind no browser
|
|
26
|
+
* draws, an image past `MAX_IMAGE_BYTES`) is simply left out, and the drawing that points
|
|
27
|
+
* at it stays on the preservation path.
|
|
28
|
+
*/
|
|
29
|
+
export declare function readImageSources(parts: Map<string, Uint8Array>, mainPartPath: string): ImageSources;
|
|
30
|
+
/**
|
|
31
|
+
* What the body needs to know while it is being written out: which relationship each
|
|
32
|
+
* inserted image ended up on, and a drawing id no other drawing in the document holds.
|
|
33
|
+
*
|
|
34
|
+
* The ids are handed out one at a time rather than planned per image, because the same
|
|
35
|
+
* image inserted twice shares one media part but is still two drawings, and Word expects
|
|
36
|
+
* every drawing in a document to have an id of its own.
|
|
37
|
+
*/
|
|
38
|
+
export interface ImageRefs {
|
|
39
|
+
relIdOf(src: string): string | undefined;
|
|
40
|
+
takeDocPrId(): number;
|
|
41
|
+
}
|
|
42
|
+
/** What a serializer called on its own, outside an export, has to work with */
|
|
43
|
+
export declare const NO_IMAGE_REFS: ImageRefs;
|
|
44
|
+
export interface MediaAdditions {
|
|
45
|
+
refs: ImageRefs;
|
|
46
|
+
/** The parts to write into the zip alongside the body */
|
|
47
|
+
parts: ReadonlyMap<string, Uint8Array>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* What the package needs for the images that were inserted during editing: the media parts,
|
|
51
|
+
* the relationships pointing at them, and the content types declaring them.
|
|
52
|
+
* null when every image in the document came out of the document itself.
|
|
53
|
+
*
|
|
54
|
+
* The relationships go through the writer the export shares between its writers
|
|
55
|
+
* (`docx/relationships`), so the part is written once with everything in it.
|
|
56
|
+
*
|
|
57
|
+
* Bytes that are already in the package are not written a second time: an inserted image
|
|
58
|
+
* whose fingerprint matches one that is already there reuses its relationship.
|
|
59
|
+
*/
|
|
60
|
+
export declare function planImageMedia(doc: PMNode, session: SessionStore, relationships: RelationshipWriter): MediaAdditions | null;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// src/docx/media.ts
|
|
2
|
+
import { DocxExportError } from "../ooxml/errors.js";
|
|
3
|
+
import {
|
|
4
|
+
imageBase64Of,
|
|
5
|
+
imageMimeOf,
|
|
6
|
+
toImageSrc
|
|
7
|
+
} from "../ooxml/image.js";
|
|
8
|
+
import { decodeUtf8, encodeUtf8, R_NS } from "../ooxml/xml.js";
|
|
9
|
+
import {
|
|
10
|
+
directoryOf,
|
|
11
|
+
readRelationships,
|
|
12
|
+
relsPathOf,
|
|
13
|
+
resolveTarget
|
|
14
|
+
} from "./relationships.js";
|
|
15
|
+
var IMAGE_REL_TYPE = `${R_NS}/image`;
|
|
16
|
+
var CONTENT_TYPES_PATH = "[Content_Types].xml";
|
|
17
|
+
var EXTENSION_BY_MIME = {
|
|
18
|
+
"image/png": "png",
|
|
19
|
+
"image/jpeg": "jpeg",
|
|
20
|
+
"image/gif": "gif",
|
|
21
|
+
"image/bmp": "bmp"
|
|
22
|
+
};
|
|
23
|
+
var MIME_BY_EXTENSION = /* @__PURE__ */ new Map([
|
|
24
|
+
["png", "image/png"],
|
|
25
|
+
["jpeg", "image/jpeg"],
|
|
26
|
+
["jpg", "image/jpeg"],
|
|
27
|
+
["jpe", "image/jpeg"],
|
|
28
|
+
["gif", "image/gif"],
|
|
29
|
+
["bmp", "image/bmp"]
|
|
30
|
+
]);
|
|
31
|
+
function toBase64(bytes) {
|
|
32
|
+
const CHUNK = 32768;
|
|
33
|
+
let binary = "";
|
|
34
|
+
for (let at = 0; at < bytes.length; at += CHUNK) {
|
|
35
|
+
binary += String.fromCharCode(...bytes.subarray(at, at + CHUNK));
|
|
36
|
+
}
|
|
37
|
+
return btoa(binary);
|
|
38
|
+
}
|
|
39
|
+
function fromBase64(base64) {
|
|
40
|
+
const binary = atob(base64);
|
|
41
|
+
const bytes = new Uint8Array(binary.length);
|
|
42
|
+
for (let at = 0; at < binary.length; at += 1) {
|
|
43
|
+
bytes[at] = binary.charCodeAt(at);
|
|
44
|
+
}
|
|
45
|
+
return bytes;
|
|
46
|
+
}
|
|
47
|
+
function dataUrl(bytes, mime) {
|
|
48
|
+
return `data:${mime};base64,${toBase64(bytes)}`;
|
|
49
|
+
}
|
|
50
|
+
function mimeOfPath(path) {
|
|
51
|
+
const dot = path.lastIndexOf(".");
|
|
52
|
+
return dot === -1 ? void 0 : MIME_BY_EXTENSION.get(path.slice(dot + 1).toLowerCase());
|
|
53
|
+
}
|
|
54
|
+
var NO_IMAGES = /* @__PURE__ */ new Map();
|
|
55
|
+
var MAX_IMAGE_BYTES = 16 * 1024 * 1024;
|
|
56
|
+
function readImageSources(parts, mainPartPath) {
|
|
57
|
+
const sources = /* @__PURE__ */ new Map();
|
|
58
|
+
for (const rel of readRelationships(parts, relsPathOf(mainPartPath))) {
|
|
59
|
+
if (rel.type !== IMAGE_REL_TYPE || rel.external) continue;
|
|
60
|
+
const mime = mimeOfPath(rel.target);
|
|
61
|
+
const bytes = parts.get(resolveTarget(mainPartPath, rel.target));
|
|
62
|
+
if (!mime || !bytes || bytes.length > MAX_IMAGE_BYTES) continue;
|
|
63
|
+
sources.set(rel.id, dataUrl(bytes, mime));
|
|
64
|
+
}
|
|
65
|
+
return sources;
|
|
66
|
+
}
|
|
67
|
+
function contentKey(bytes) {
|
|
68
|
+
let a = 2166136261;
|
|
69
|
+
let b = 3266489909;
|
|
70
|
+
for (const byte of bytes) {
|
|
71
|
+
a = Math.imul(a ^ byte, 16777619) >>> 0;
|
|
72
|
+
b = Math.imul(b ^ byte, 2246822507) >>> 0;
|
|
73
|
+
}
|
|
74
|
+
const hex = (value) => value.toString(16).padStart(8, "0");
|
|
75
|
+
return `${bytes.length.toString(36)}${hex(a)}${hex(b)}`;
|
|
76
|
+
}
|
|
77
|
+
function imageRefs(relIdBySrc, firstDocPrId) {
|
|
78
|
+
let nextDocPrId = firstDocPrId;
|
|
79
|
+
return {
|
|
80
|
+
relIdOf: (src) => relIdBySrc.get(src),
|
|
81
|
+
takeDocPrId: () => {
|
|
82
|
+
const id = nextDocPrId;
|
|
83
|
+
nextDocPrId += 1;
|
|
84
|
+
return id;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
var NO_IMAGE_REFS = {
|
|
89
|
+
relIdOf: () => void 0,
|
|
90
|
+
// Never reached: an image with no relationship to point at is refused before it is drawn
|
|
91
|
+
takeDocPrId: () => 1
|
|
92
|
+
};
|
|
93
|
+
function insertedImageSrcs(doc) {
|
|
94
|
+
const srcs = [];
|
|
95
|
+
doc.descendants((node) => {
|
|
96
|
+
if (node.type.name !== "image" || typeof node.attrs.xml === "string") {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
const src = toImageSrc(node.attrs.src);
|
|
100
|
+
if (src !== null && !srcs.includes(src)) srcs.push(src);
|
|
101
|
+
return true;
|
|
102
|
+
});
|
|
103
|
+
return srcs;
|
|
104
|
+
}
|
|
105
|
+
function decodeImage(src) {
|
|
106
|
+
const mime = imageMimeOf(src);
|
|
107
|
+
if (mime === null) {
|
|
108
|
+
throw new DocxExportError(
|
|
109
|
+
"unsupported-content",
|
|
110
|
+
"an inserted image is of a kind we cannot write"
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const bytes = fromBase64(imageBase64Of(src));
|
|
115
|
+
return {
|
|
116
|
+
bytes,
|
|
117
|
+
extension: EXTENSION_BY_MIME[mime],
|
|
118
|
+
key: contentKey(bytes)
|
|
119
|
+
};
|
|
120
|
+
} catch (error) {
|
|
121
|
+
throw new DocxExportError(
|
|
122
|
+
"unsupported-content",
|
|
123
|
+
"an inserted image's bytes could not be decoded",
|
|
124
|
+
{ cause: error }
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function imageRelIdsByContent(session, rels) {
|
|
129
|
+
const byContent = /* @__PURE__ */ new Map();
|
|
130
|
+
for (const rel of rels) {
|
|
131
|
+
if (rel.type !== IMAGE_REL_TYPE || rel.external) continue;
|
|
132
|
+
const bytes = session.parts.get(
|
|
133
|
+
resolveTarget(session.mainPartPath, rel.target)
|
|
134
|
+
);
|
|
135
|
+
if (!bytes) continue;
|
|
136
|
+
const key = contentKey(bytes);
|
|
137
|
+
if (!byContent.has(key)) byContent.set(key, rel.id);
|
|
138
|
+
}
|
|
139
|
+
return byContent;
|
|
140
|
+
}
|
|
141
|
+
var DOC_PR_ID = /<(?:[\w.-]+:)?docPr\b[^>]*\bid="(\d+)"/g;
|
|
142
|
+
function maxDocPrId(session) {
|
|
143
|
+
let max = 0;
|
|
144
|
+
for (const block of session.blocks) {
|
|
145
|
+
for (const match of block.xml.matchAll(DOC_PR_ID)) {
|
|
146
|
+
max = Math.max(max, Number.parseInt(match[1], 10));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return max;
|
|
150
|
+
}
|
|
151
|
+
var TYPES_OPEN_TAG = /<(?:[\w.-]+:)?Types\b[^>]*>/;
|
|
152
|
+
function withImageContentTypes(parts, extensions) {
|
|
153
|
+
const original = parts.get(CONTENT_TYPES_PATH);
|
|
154
|
+
if (!original) {
|
|
155
|
+
throw new DocxExportError(
|
|
156
|
+
"missing-content-types",
|
|
157
|
+
`cannot add an image to a package that has no ${CONTENT_TYPES_PATH}`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
const { text, hadBom } = decodeUtf8(original);
|
|
161
|
+
const missing = Array.from(extensions).filter(
|
|
162
|
+
(extension) => !new RegExp(`<Default[^>]+Extension="${extension}"`, "i").test(text)
|
|
163
|
+
);
|
|
164
|
+
if (missing.length === 0) return null;
|
|
165
|
+
const open = TYPES_OPEN_TAG.exec(text);
|
|
166
|
+
if (!open) {
|
|
167
|
+
throw new DocxExportError(
|
|
168
|
+
"malformed-xml",
|
|
169
|
+
`${CONTENT_TYPES_PATH} has no Types element`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
const declarations = missing.map((extension) => {
|
|
173
|
+
const mime = MIME_BY_EXTENSION.get(extension);
|
|
174
|
+
return `<Default Extension="${extension}" ContentType="${mime}"/>`;
|
|
175
|
+
}).join("");
|
|
176
|
+
const at = open.index + open[0].length;
|
|
177
|
+
return encodeUtf8(text.slice(0, at) + declarations + text.slice(at), hadBom);
|
|
178
|
+
}
|
|
179
|
+
function planImageMedia(doc, session, relationships) {
|
|
180
|
+
const srcs = insertedImageSrcs(doc);
|
|
181
|
+
if (srcs.length === 0) return null;
|
|
182
|
+
const relIdByContent = imageRelIdsByContent(session, relationships.opened);
|
|
183
|
+
const directory = directoryOf(session.mainPartPath);
|
|
184
|
+
const relIdBySrc = /* @__PURE__ */ new Map();
|
|
185
|
+
const parts = /* @__PURE__ */ new Map();
|
|
186
|
+
const extensions = /* @__PURE__ */ new Set();
|
|
187
|
+
for (const src of srcs) {
|
|
188
|
+
const image = decodeImage(src);
|
|
189
|
+
const reused = relIdByContent.get(image.key);
|
|
190
|
+
if (reused !== void 0) {
|
|
191
|
+
relIdBySrc.set(src, reused);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const target = `media/image-${image.key}.${image.extension}`;
|
|
195
|
+
const relId = relationships.add({ type: IMAGE_REL_TYPE, target });
|
|
196
|
+
parts.set(directory + target, image.bytes);
|
|
197
|
+
extensions.add(image.extension);
|
|
198
|
+
relIdByContent.set(image.key, relId);
|
|
199
|
+
relIdBySrc.set(src, relId);
|
|
200
|
+
}
|
|
201
|
+
if (extensions.size > 0) {
|
|
202
|
+
const contentTypes = withImageContentTypes(session.parts, extensions);
|
|
203
|
+
if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
|
|
204
|
+
}
|
|
205
|
+
return { refs: imageRefs(relIdBySrc, maxDocPrId(session) + 1), parts };
|
|
206
|
+
}
|
|
207
|
+
export {
|
|
208
|
+
MAX_IMAGE_BYTES,
|
|
209
|
+
NO_IMAGES,
|
|
210
|
+
NO_IMAGE_REFS,
|
|
211
|
+
planImageMedia,
|
|
212
|
+
readImageSources
|
|
213
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Reads footnote and endnote bodies related from the main document story. */
|
|
2
|
+
export type NoteKind = "footnote" | "endnote";
|
|
3
|
+
export interface ImportedNote {
|
|
4
|
+
kind: NoteKind;
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
text: string;
|
|
8
|
+
type: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface ImportedNotePart {
|
|
11
|
+
partPath: string | null;
|
|
12
|
+
ordered: readonly ImportedNote[];
|
|
13
|
+
byId: ReadonlyMap<string, ImportedNote>;
|
|
14
|
+
}
|
|
15
|
+
export interface ImportedNotes {
|
|
16
|
+
footnotes: ImportedNotePart;
|
|
17
|
+
endnotes: ImportedNotePart;
|
|
18
|
+
}
|
|
19
|
+
export declare const NO_NOTES: ImportedNotes;
|
|
20
|
+
/** Reads both note parts without modifying their original package bytes. */
|
|
21
|
+
export declare function readNotes(parts: Map<string, Uint8Array>, mainPartPath: string): ImportedNotes;
|
|
22
|
+
export declare function noteById(notes: ImportedNotes, kind: NoteKind, id: string): ImportedNote | undefined;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// src/docx/notes.ts
|
|
2
|
+
import {
|
|
3
|
+
decodeUtf8,
|
|
4
|
+
elementChildren,
|
|
5
|
+
parseXml,
|
|
6
|
+
R_NS,
|
|
7
|
+
W_NS
|
|
8
|
+
} from "../ooxml/xml.js";
|
|
9
|
+
import { readRelationships, relsPathOf, resolveTarget } from "./relationships.js";
|
|
10
|
+
var EMPTY_PART = {
|
|
11
|
+
partPath: null,
|
|
12
|
+
ordered: [],
|
|
13
|
+
byId: /* @__PURE__ */ new Map()
|
|
14
|
+
};
|
|
15
|
+
var NO_NOTES = {
|
|
16
|
+
footnotes: EMPTY_PART,
|
|
17
|
+
endnotes: EMPTY_PART
|
|
18
|
+
};
|
|
19
|
+
function attribute(el, localName) {
|
|
20
|
+
return Array.from(el.attributes).find((entry) => entry.localName === localName)?.value ?? null;
|
|
21
|
+
}
|
|
22
|
+
function inlineText(node) {
|
|
23
|
+
if (node.localName === "t") return node.textContent ?? "";
|
|
24
|
+
if (node.localName === "tab") return " ";
|
|
25
|
+
if (node.localName === "br" || node.localName === "cr") return "\n";
|
|
26
|
+
if (node.localName === "noBreakHyphen") return "\u2011";
|
|
27
|
+
if (node.localName === "softHyphen") return "\xAD";
|
|
28
|
+
return elementChildren(node).map(inlineText).join("");
|
|
29
|
+
}
|
|
30
|
+
function noteText(el) {
|
|
31
|
+
return Array.from(el.getElementsByTagNameNS(W_NS, "p")).map(inlineText).join("\n");
|
|
32
|
+
}
|
|
33
|
+
function notePart(parts, mainPartPath, kind) {
|
|
34
|
+
const relationshipType = `${R_NS}/${kind}s`;
|
|
35
|
+
const relationship = readRelationships(parts, relsPathOf(mainPartPath)).find(
|
|
36
|
+
(entry) => entry.type === relationshipType && !entry.external
|
|
37
|
+
);
|
|
38
|
+
if (!relationship) return EMPTY_PART;
|
|
39
|
+
const partPath = resolveTarget(mainPartPath, relationship.target);
|
|
40
|
+
const bytes = parts.get(partPath);
|
|
41
|
+
if (!bytes) return { ...EMPTY_PART, partPath };
|
|
42
|
+
const root = parseXml(decodeUtf8(bytes).text).documentElement;
|
|
43
|
+
const elements = elementChildren(root).filter((el) => el.localName === kind);
|
|
44
|
+
const ordered = elements.flatMap((el) => {
|
|
45
|
+
const id = attribute(el, "id");
|
|
46
|
+
if (id === null) return [];
|
|
47
|
+
const type = attribute(el, "type");
|
|
48
|
+
const regular = type === null || type === "normal";
|
|
49
|
+
const label = regular ? "?" : "";
|
|
50
|
+
return [{ kind, id, label, text: noteText(el), type }];
|
|
51
|
+
});
|
|
52
|
+
const byId = /* @__PURE__ */ new Map();
|
|
53
|
+
for (const note of ordered) {
|
|
54
|
+
if (!byId.has(note.id)) byId.set(note.id, note);
|
|
55
|
+
}
|
|
56
|
+
return { partPath, ordered, byId };
|
|
57
|
+
}
|
|
58
|
+
function readNotes(parts, mainPartPath) {
|
|
59
|
+
return {
|
|
60
|
+
footnotes: notePart(parts, mainPartPath, "footnote"),
|
|
61
|
+
endnotes: notePart(parts, mainPartPath, "endnote")
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function noteById(notes, kind, id) {
|
|
65
|
+
return notes[`${kind}s`].byId.get(id);
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
NO_NOTES,
|
|
69
|
+
noteById,
|
|
70
|
+
readNotes
|
|
71
|
+
};
|