@portone/docx-editor 0.2.1 → 0.3.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 +109 -0
- package/CONTRIBUTING.md +5 -1
- package/dist/DocxEditor.d.ts +6 -0
- package/dist/DocxEditor.js +12 -29
- package/dist/core.d.ts +23 -8
- package/dist/core.js +9 -4
- package/dist/docx/cloning.d.ts +38 -0
- package/dist/docx/cloning.js +74 -0
- package/dist/docx/commentOnlyChange.d.ts +12 -7
- package/dist/docx/commentOnlyChange.js +9 -156
- package/dist/docx/comments/constants.d.ts +0 -1
- package/dist/docx/comments/constants.js +0 -2
- package/dist/docx/comments/grammar.d.ts +10 -4
- package/dist/docx/comments/grammar.js +12 -2
- package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
- package/dist/docx/comments/parts.js +279 -0
- package/dist/docx/comments/people.d.ts +11 -2
- package/dist/docx/comments/people.js +16 -92
- package/dist/docx/comments/policy.d.ts +7 -0
- package/dist/docx/comments/policy.js +43 -0
- package/dist/docx/comments/reading.js +8 -10
- package/dist/docx/comments/writing.d.ts +19 -7
- package/dist/docx/comments/writing.js +52 -111
- package/dist/docx/documentSettings.d.ts +7 -0
- package/dist/docx/documentSettings.js +10 -2
- package/dist/docx/exportDocx.d.ts +40 -5
- package/dist/docx/exportDocx.js +69 -71
- package/dist/docx/exportRefs.d.ts +5 -2
- package/dist/docx/exportRefs.js +3 -1
- package/dist/docx/fidelity.d.ts +43 -0
- package/dist/docx/fidelity.js +64 -0
- package/dist/docx/formatting/attrs.d.ts +27 -0
- package/dist/docx/formatting/attrs.js +31 -0
- package/dist/docx/formatting/context.d.ts +31 -0
- package/dist/docx/formatting/context.js +42 -0
- package/dist/docx/formatting/direct.d.ts +6 -5
- package/dist/docx/formatting/direct.js +52 -78
- package/dist/docx/formatting/resolve.d.ts +45 -0
- package/dist/docx/formatting/resolve.js +140 -0
- package/dist/docx/formatting/runProperties.d.ts +93 -0
- package/dist/docx/formatting/runProperties.js +316 -0
- package/dist/docx/formatting/styles.js +3 -3
- package/dist/docx/formatting/tabStops.js +7 -22
- package/dist/docx/formatting.d.ts +4 -1
- package/dist/docx/formatting.js +4 -1
- package/dist/docx/headersFooters.js +6 -13
- package/dist/docx/identities.d.ts +67 -0
- package/dist/docx/identities.js +174 -0
- package/dist/docx/importDocx.d.ts +12 -1
- package/dist/docx/importDocx.js +72 -79
- package/dist/docx/importParagraph.d.ts +1 -1
- package/dist/docx/importParagraph.js +4 -3
- package/dist/docx/importTable.d.ts +1 -1
- package/dist/docx/importTable.js +17 -1
- package/dist/docx/invariants.d.ts +33 -0
- package/dist/docx/invariants.js +256 -0
- package/dist/docx/media.d.ts +6 -4
- package/dist/docx/media.js +6 -37
- package/dist/docx/newLists.d.ts +20 -0
- package/dist/docx/newLists.js +36 -0
- package/dist/docx/notes.js +3 -7
- package/dist/docx/numberingPlanner.d.ts +8 -0
- package/dist/docx/numberingPlanner.js +19 -0
- package/dist/docx/packageParts.d.ts +42 -0
- package/dist/docx/packageParts.js +135 -0
- package/dist/docx/pageGeometry.d.ts +2 -0
- package/dist/docx/pageGeometry.js +18 -9
- package/dist/docx/paraProps.d.ts +10 -22
- package/dist/docx/paraProps.js +47 -76
- package/dist/docx/partPlan.d.ts +36 -0
- package/dist/docx/partPlan.js +59 -0
- package/dist/docx/protectionPolicy.d.ts +127 -0
- package/dist/docx/protectionPolicy.js +169 -0
- package/dist/docx/relationships.d.ts +1 -1
- package/dist/docx/relationships.js +8 -13
- package/dist/docx/runProps.d.ts +9 -22
- package/dist/docx/runProps.js +15 -168
- package/dist/docx/scan.js +20 -52
- package/dist/docx/sdt.js +9 -34
- package/dist/docx/sdtProps.d.ts +8 -1
- package/dist/docx/sdtProps.js +10 -0
- package/dist/docx/serializeBlock.d.ts +2 -0
- package/dist/docx/serializeBlock.js +8 -5
- package/dist/docx/serializeTable.js +32 -15
- package/dist/docx/session.d.ts +42 -14
- package/dist/docx/session.js +43 -17
- package/dist/docx/tableFormatting/editing.js +108 -139
- package/dist/docx/tableFormatting/reading.d.ts +16 -6
- package/dist/docx/tableFormatting/reading.js +40 -20
- package/dist/docx/tableTemplate.js +18 -7
- package/dist/download.d.ts +8 -5
- package/dist/download.js +2 -0
- package/dist/editor/clipboard/inlineFormatting.js +19 -30
- package/dist/editor/commands/comments/editing.d.ts +6 -2
- package/dist/editor/commands/comments/editing.js +19 -31
- package/dist/editor/commands/exportQueries.d.ts +15 -0
- package/dist/editor/commands/exportQueries.js +14 -0
- package/dist/editor/commands/fidelityQueries.d.ts +12 -0
- package/dist/editor/commands/fidelityQueries.js +8 -0
- package/dist/editor/commands/formatting/editing.d.ts +2 -2
- package/dist/editor/commands/formatting/editing.js +26 -108
- package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
- package/dist/editor/commands/formatting/propertyCommands.js +103 -0
- package/dist/editor/commands/formatting/shared.d.ts +3 -3
- package/dist/editor/commands/formatting/shared.js +5 -2
- package/dist/editor/commands/indentCommands.js +5 -4
- package/dist/editor/commands/index.d.ts +11 -0
- package/dist/editor/commands/index.js +5 -0
- package/dist/editor/commands/linkCommands.js +5 -6
- package/dist/editor/commands/listCommands.js +8 -10
- package/dist/editor/commands/lockCommands.d.ts +7 -1
- package/dist/editor/commands/lockCommands.js +35 -46
- package/dist/editor/commands/paragraphCommands.js +28 -31
- package/dist/editor/commands/spacingCommands.js +1 -1
- package/dist/editor/createEditor.d.ts +17 -29
- package/dist/editor/createEditor.js +58 -58
- package/dist/editor/documentStyles.d.ts +11 -35
- package/dist/editor/documentStyles.js +9 -52
- package/dist/editor/editorDocument.d.ts +56 -0
- package/dist/editor/editorDocument.js +74 -0
- package/dist/editor/externalClipboard.js +16 -45
- package/dist/editor/insertTable.js +4 -3
- package/dist/editor/paragraphEdits.d.ts +11 -18
- package/dist/editor/paragraphEdits.js +7 -16
- package/dist/editor/plugins/displayDerivation.d.ts +47 -0
- package/dist/editor/plugins/displayDerivation.js +78 -0
- package/dist/editor/plugins/imagePaste.js +4 -3
- package/dist/editor/plugins/keymap.js +18 -3
- package/dist/editor/plugins/numberingDecorations.d.ts +5 -11
- package/dist/editor/plugins/numberingDecorations.js +7 -17
- package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
- package/dist/editor/plugins/paragraphDisplay.js +51 -0
- package/dist/editor/plugins/tabLayout.js +1 -1
- package/dist/editor/plugins/tableDisplay.d.ts +6 -0
- package/dist/editor/plugins/tableDisplay.js +16 -0
- package/dist/index.d.ts +2 -0
- package/dist/model/format.d.ts +30 -8
- package/dist/model/format.js +35 -22
- package/dist/model/tabStops.d.ts +9 -0
- package/dist/model/tabStops.js +18 -0
- package/dist/numbering/listTemplate.js +24 -7
- package/dist/numbering/parseNumbering.d.ts +14 -1
- package/dist/numbering/parseNumbering.js +35 -22
- package/dist/numbering/writeNumbering.d.ts +3 -4
- package/dist/numbering/writeNumbering.js +14 -25
- package/dist/ooxml/childOrder.d.ts +34 -0
- package/dist/ooxml/childOrder.js +496 -0
- package/dist/ooxml/element.d.ts +24 -11
- package/dist/ooxml/element.js +31 -12
- package/dist/ooxml/errors.d.ts +3 -2
- package/dist/ooxml/image.d.ts +4 -0
- package/dist/ooxml/image.js +2 -5
- package/dist/ooxml/partSplice.d.ts +67 -0
- package/dist/ooxml/partSplice.js +169 -0
- package/dist/ooxml/props.d.ts +112 -0
- package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
- package/dist/ooxml/simpleTypes.d.ts +103 -0
- package/dist/ooxml/simpleTypes.js +182 -0
- package/dist/ooxml/tabStops.js +8 -27
- package/dist/ooxml/tagScan.d.ts +34 -0
- package/dist/ooxml/tagScan.js +108 -0
- package/dist/ooxml/units.d.ts +25 -13
- package/dist/ooxml/units.js +65 -31
- package/dist/ooxml/xml.d.ts +27 -6
- package/dist/ooxml/xml.js +37 -5
- package/dist/page/blockKinds.d.ts +61 -0
- package/dist/page/blockKinds.js +11 -0
- package/dist/page/kinds/index.d.ts +6 -0
- package/dist/page/kinds/index.js +10 -0
- package/dist/page/kinds/paragraphKind.d.ts +10 -0
- package/dist/page/kinds/paragraphKind.js +71 -0
- package/dist/page/kinds/tableKind.d.ts +10 -0
- package/dist/page/kinds/tableKind.js +178 -0
- package/dist/page/measureBlocks.d.ts +3 -14
- package/dist/page/measureBlocks.js +24 -45
- package/dist/page/pageDecorations.d.ts +27 -44
- package/dist/page/pageDecorations.js +70 -152
- package/dist/page/pageLayout.d.ts +2 -19
- package/dist/page/pageLayout.js +36 -6
- package/dist/page/usePageLayout.d.ts +2 -17
- package/dist/page/usePageLayout.js +3 -39
- package/dist/schema/attrRoles.d.ts +25 -18
- package/dist/schema/attrRoles.js +102 -67
- package/dist/schema/displayDerivation.d.ts +82 -0
- package/dist/schema/displayDerivation.js +130 -0
- package/dist/schema/docxSchema.d.ts +3 -0
- package/dist/schema/docxSchema.js +26 -14
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.d.ts +37 -14
- package/dist/schema/guards.js +29 -3
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/locks.d.ts +11 -44
- package/dist/schema/locks.js +0 -9
- package/dist/schema/preservedGuards.d.ts +26 -6
- package/dist/schema/preservedGuards.js +31 -1
- package/dist/schema/protection.d.ts +7 -1
- package/dist/schema/protection.js +2 -1
- package/dist/schema/sourceEquality.d.ts +1 -9
- package/dist/schema/sourceEquality.js +1 -27
- package/dist/styles/inlineStyle.js +15 -6
- package/dist/table/cellFormatting.d.ts +8 -1
- package/dist/table/cellFormatting.js +10 -18
- package/dist/table/commands.js +20 -18
- package/dist/table/format.d.ts +3 -0
- package/dist/table/format.js +3 -9
- package/dist/table/gridBorders.d.ts +14 -16
- package/dist/table/gridBorders.js +3 -41
- package/dist/table/merge.d.ts +2 -6
- package/dist/table/merge.js +5 -5
- package/package.json +7 -3
- package/dist/docx/comments/contentTypes.d.ts +0 -7
- package/dist/docx/comments/contentTypes.js +0 -38
- package/dist/docx/comments/verifying.js +0 -206
- package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
- package/dist/docx/formatting/effectiveParagraph.js +0 -81
- package/dist/docx/propsXml.d.ts +0 -67
- package/dist/docx/uniqueControls.d.ts +0 -14
- package/dist/docx/uniqueControls.js +0 -62
- package/dist/editor/plugins/commentReservations.d.ts +0 -5
- package/dist/editor/plugins/commentReservations.js +0 -26
- package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
- package/dist/editor/plugins/styledParagraphs.js +0 -65
- package/dist/page/tableMeasurements.d.ts +0 -18
- package/dist/page/tableMeasurements.js +0 -119
package/dist/docx/exportDocx.js
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
// src/docx/exportDocx.ts
|
|
2
|
-
import { toParagraphFormat } from "../model/format.js";
|
|
3
|
-
import { parseNumbering } from "../numbering/parseNumbering.js";
|
|
4
|
-
import { addListDefinitions } from "../numbering/writeNumbering.js";
|
|
5
2
|
import { DocxExportError } from "../ooxml/errors.js";
|
|
6
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
encodeUtf8,
|
|
5
|
+
parseXml,
|
|
6
|
+
W_NS,
|
|
7
|
+
withXmlParser
|
|
8
|
+
} from "../ooxml/xml.js";
|
|
7
9
|
import { sameSource } from "../schema/sourceEquality.js";
|
|
8
|
-
import {
|
|
10
|
+
import { commentsPlanner } from "./comments.js";
|
|
9
11
|
import { repackParts } from "./container.js";
|
|
12
|
+
import {
|
|
13
|
+
fidelityNotesOf
|
|
14
|
+
} from "./fidelity.js";
|
|
10
15
|
import { hyperlinkRefs } from "./hyperlink.js";
|
|
16
|
+
import { withUniqueIdentities } from "./identities.js";
|
|
17
|
+
import { problemsOf } from "./invariants.js";
|
|
11
18
|
import { NO_IMAGE_REFS, planImageMedia } from "./media.js";
|
|
19
|
+
import { numberingPlanner } from "./numberingPlanner.js";
|
|
20
|
+
import { CONTENT_TYPES_PATH, contentTypeWriter } from "./packageParts.js";
|
|
21
|
+
import {
|
|
22
|
+
assertPartsParse,
|
|
23
|
+
runPartPlanners
|
|
24
|
+
} from "./partPlan.js";
|
|
12
25
|
import {
|
|
13
26
|
readRelationships,
|
|
14
27
|
relationshipWriter,
|
|
@@ -19,7 +32,6 @@ import {
|
|
|
19
32
|
originalBlock,
|
|
20
33
|
sessionOf
|
|
21
34
|
} from "./session.js";
|
|
22
|
-
import { withUniqueControls } from "./uniqueControls.js";
|
|
23
35
|
function blockXml(node, session, refs) {
|
|
24
36
|
const imported = originalBlock(node, session);
|
|
25
37
|
if (imported && sameSource(node, imported.node)) return imported.xml;
|
|
@@ -27,7 +39,7 @@ function blockXml(node, session, refs) {
|
|
|
27
39
|
}
|
|
28
40
|
function buildDocumentXml(doc, session, refs) {
|
|
29
41
|
const pieces = [session.documentPrefix];
|
|
30
|
-
|
|
42
|
+
withUniqueIdentities(doc).forEach((child) => {
|
|
31
43
|
pieces.push(blockXml(child, session, refs));
|
|
32
44
|
});
|
|
33
45
|
pieces.push(session.documentSuffix);
|
|
@@ -85,80 +97,66 @@ function assertBookmarkPairs(documentXml) {
|
|
|
85
97
|
);
|
|
86
98
|
}
|
|
87
99
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
};
|
|
95
|
-
if (visit(node)) node.descendants(visit);
|
|
100
|
+
var PART_PLANNERS = [
|
|
101
|
+
numberingPlanner,
|
|
102
|
+
commentsPlanner
|
|
103
|
+
];
|
|
104
|
+
function exportDocx(doc, session, options) {
|
|
105
|
+
return exportDocxReport(doc, session, options).bytes;
|
|
96
106
|
}
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
collectNumIds(node, used);
|
|
100
|
-
return used;
|
|
107
|
+
function exportDocxReport(doc, session, options) {
|
|
108
|
+
return reportThrough(PART_PLANNERS, doc, session, options);
|
|
101
109
|
}
|
|
102
|
-
function
|
|
103
|
-
|
|
104
|
-
for (const block of session.blocks) collectNumIds(block.node, used);
|
|
105
|
-
return used;
|
|
106
|
-
}
|
|
107
|
-
function newNumIds(doc, session) {
|
|
108
|
-
const defined = parseNumbering(session.numberingXml).lists;
|
|
109
|
-
const atOpen = numIdsAtOpen(session);
|
|
110
|
-
return Array.from(numIdsIn(doc)).filter((numId) => !defined.has(numId) && !atOpen.has(numId)).sort((a, b) => a - b);
|
|
110
|
+
function exportThroughPlanners(planners, doc, session, options) {
|
|
111
|
+
return reportThrough(planners, doc, session, options).bytes;
|
|
111
112
|
}
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
function reportThrough(planners, doc, session, options) {
|
|
114
|
+
return withXmlParser(options?.xmlParser, () => {
|
|
115
|
+
const store = sessionOf(session);
|
|
116
|
+
const problem = problemsOf(doc, store)[0];
|
|
117
|
+
if (problem) throw new DocxExportError(problem.code, problem.message);
|
|
118
|
+
const approximated = [];
|
|
119
|
+
const bytes = writeDocx(
|
|
120
|
+
doc,
|
|
121
|
+
store,
|
|
122
|
+
{ add: (note) => approximated.push(note) },
|
|
123
|
+
planners
|
|
121
124
|
);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
};
|
|
125
|
+
return {
|
|
126
|
+
bytes,
|
|
127
|
+
notes: [...fidelityNotesOf(doc, store.mainPartPath), ...approximated]
|
|
128
|
+
};
|
|
129
|
+
});
|
|
128
130
|
}
|
|
129
|
-
function
|
|
130
|
-
const store = sessionOf(session);
|
|
131
|
+
function writeDocx(doc, store, notes, planners) {
|
|
131
132
|
const relsPath = relsPathOf(store.mainPartPath);
|
|
132
|
-
const
|
|
133
|
-
readRelationships(store.parts, relsPath)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
doc,
|
|
138
|
-
store,
|
|
139
|
-
relationships,
|
|
140
|
-
media?.parts.get("[Content_Types].xml")
|
|
141
|
-
);
|
|
133
|
+
const context = {
|
|
134
|
+
relationships: relationshipWriter(readRelationships(store.parts, relsPath)),
|
|
135
|
+
contentTypes: contentTypeWriter(store.parts)
|
|
136
|
+
};
|
|
137
|
+
const media = planImageMedia(doc, store, context);
|
|
142
138
|
const documentXml = buildDocumentXml(doc, store, {
|
|
143
139
|
images: media?.refs ?? NO_IMAGE_REFS,
|
|
144
|
-
links: hyperlinkRefs(relationships)
|
|
140
|
+
links: hyperlinkRefs(context.relationships),
|
|
141
|
+
notes
|
|
145
142
|
});
|
|
146
143
|
assertBookmarkPairs(documentXml);
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return repackParts(store.parts, replacements);
|
|
144
|
+
const parts = runPartPlanners(planners, doc, store, context, media?.parts);
|
|
145
|
+
const rels = context.relationships.part(store.parts.get(relsPath));
|
|
146
|
+
if (rels) parts.set(relsPath, rels);
|
|
147
|
+
const contentTypes = context.contentTypes.part();
|
|
148
|
+
if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
|
|
149
|
+
assertPartsParse(parts, contentTypes ?? store.parts.get(CONTENT_TYPES_PATH));
|
|
150
|
+
return repackParts(
|
|
151
|
+
store.parts,
|
|
152
|
+
new Map([
|
|
153
|
+
[store.mainPartPath, encodeUtf8(documentXml, store.documentHadBom)],
|
|
154
|
+
...parts
|
|
155
|
+
])
|
|
156
|
+
);
|
|
161
157
|
}
|
|
162
158
|
export {
|
|
163
|
-
exportDocx
|
|
159
|
+
exportDocx,
|
|
160
|
+
exportDocxReport,
|
|
161
|
+
exportThroughPlanners
|
|
164
162
|
};
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What the serializers need from the rest of the package while a body is being written: which
|
|
3
|
-
* relationship an inserted image ended up on (`docx/media`),
|
|
4
|
-
*
|
|
3
|
+
* relationship an inserted image ended up on (`docx/media`), which one each link's address lives
|
|
4
|
+
* on (`docx/hyperlink`), and where to record an approximation a writer had to make
|
|
5
|
+
* (`docx/fidelity`).
|
|
5
6
|
*
|
|
6
7
|
* They travel as one value so that a serializer taking a body apart passes on everything the
|
|
7
8
|
* pieces of it may need, whatever a later kind of content turns out to require.
|
|
8
9
|
*/
|
|
10
|
+
import { type FidelityCollector } from "./fidelity";
|
|
9
11
|
import { type LinkRefs } from "./hyperlink";
|
|
10
12
|
import { type ImageRefs } from "./media";
|
|
11
13
|
export interface ExportRefs {
|
|
12
14
|
images: ImageRefs;
|
|
13
15
|
links: LinkRefs;
|
|
16
|
+
notes: FidelityCollector;
|
|
14
17
|
}
|
|
15
18
|
/** What a serializer called on its own, outside an export, has to work with */
|
|
16
19
|
export declare const NO_EXPORT_REFS: ExportRefs;
|
package/dist/docx/exportRefs.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// src/docx/exportRefs.ts
|
|
2
|
+
import { NO_FIDELITY_COLLECTOR } from "./fidelity.js";
|
|
2
3
|
import { NO_LINK_REFS } from "./hyperlink.js";
|
|
3
4
|
import { NO_IMAGE_REFS } from "./media.js";
|
|
4
5
|
var NO_EXPORT_REFS = {
|
|
5
6
|
images: NO_IMAGE_REFS,
|
|
6
|
-
links: NO_LINK_REFS
|
|
7
|
+
links: NO_LINK_REFS,
|
|
8
|
+
notes: NO_FIDELITY_COLLECTOR
|
|
7
9
|
};
|
|
8
10
|
export {
|
|
9
11
|
NO_EXPORT_REFS
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a document holds that this editor could not model, as a list a host application can read.
|
|
3
|
+
*
|
|
4
|
+
* Opening a file quietly hides some markup, stands a placeholder in front of the rest, and a
|
|
5
|
+
* writer approximates a little more on the way back out. None of that shows on the page, so this
|
|
6
|
+
* is where it is said out loud: one note per preserved node, plus whatever a write approximated.
|
|
7
|
+
*/
|
|
8
|
+
import type { Node as PMNode } from "prosemirror-model";
|
|
9
|
+
export type FidelitySeverity =
|
|
10
|
+
/** Carried through whole, with nothing of it on screen */
|
|
11
|
+
"hidden"
|
|
12
|
+
/** Carried through whole behind a placeholder that stands in its place and cannot be edited */
|
|
13
|
+
| "placeholder"
|
|
14
|
+
/** Written back as something near what arrived rather than as what arrived */
|
|
15
|
+
| "approximated";
|
|
16
|
+
export type FidelityCode = "preserved-run-content" | "preserved-inline" | "preserved-block" | "range-marker" | "paragraph-demoted" | "table-demoted";
|
|
17
|
+
export interface FidelityNote {
|
|
18
|
+
severity: FidelitySeverity;
|
|
19
|
+
code: FidelityCode;
|
|
20
|
+
/** The package path of the part this is about, or null when the caller holds no session */
|
|
21
|
+
part: string | null;
|
|
22
|
+
/** Which block of the body as it was opened this falls in. null for a node made while editing */
|
|
23
|
+
block: number | null;
|
|
24
|
+
/** Where the node stands in the document. null for an approximation with no node behind it */
|
|
25
|
+
pos: number | null;
|
|
26
|
+
/** The original element, for example `w:bookmarkStart` */
|
|
27
|
+
element: string;
|
|
28
|
+
}
|
|
29
|
+
/** Where a writer records an approximation it had to make while a body was written */
|
|
30
|
+
export interface FidelityCollector {
|
|
31
|
+
add(note: FidelityNote): void;
|
|
32
|
+
}
|
|
33
|
+
/** What a serializer called on its own, outside an export, records its approximations to */
|
|
34
|
+
export declare const NO_FIDELITY_COLLECTOR: FidelityCollector;
|
|
35
|
+
/**
|
|
36
|
+
* One note per preserved node, in document order.
|
|
37
|
+
*
|
|
38
|
+
* The nodes carry the original element and the block they came from themselves, so the list is a
|
|
39
|
+
* projection of the document rather than something an import has to remember alongside it. A
|
|
40
|
+
* document opened and one edited for an hour are read the same way, and a `pos` is enough to take
|
|
41
|
+
* a reader to the node the note is about.
|
|
42
|
+
*/
|
|
43
|
+
export declare function fidelityNotesOf(doc: PMNode, part: string | null): FidelityNote[];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/docx/fidelity.ts
|
|
2
|
+
import { localPart } from "../ooxml/xml.js";
|
|
3
|
+
import { splitBlockKey } from "./session.js";
|
|
4
|
+
var NO_FIDELITY_COLLECTOR = { add: () => {
|
|
5
|
+
} };
|
|
6
|
+
function stringAttr(value) {
|
|
7
|
+
return typeof value === "string" ? value : null;
|
|
8
|
+
}
|
|
9
|
+
function elementNameOf(xml) {
|
|
10
|
+
return /^\s*<\s*([^\s/>]+)/.exec(xml)?.[1] ?? null;
|
|
11
|
+
}
|
|
12
|
+
function elementOf(node) {
|
|
13
|
+
return stringAttr(node.attrs.name) ?? elementNameOf(stringAttr(node.attrs.xml) ?? "");
|
|
14
|
+
}
|
|
15
|
+
function demotedBlock(element) {
|
|
16
|
+
const name = element === null ? null : localPart(element);
|
|
17
|
+
if (name === "tbl") return { severity: "placeholder", code: "table-demoted" };
|
|
18
|
+
if (name === "p") {
|
|
19
|
+
return { severity: "placeholder", code: "paragraph-demoted" };
|
|
20
|
+
}
|
|
21
|
+
return { severity: "placeholder", code: "preserved-block" };
|
|
22
|
+
}
|
|
23
|
+
function preservedBy(node, element) {
|
|
24
|
+
switch (node.type.name) {
|
|
25
|
+
case "docxRaw":
|
|
26
|
+
return demotedBlock(element);
|
|
27
|
+
case "rawBlock":
|
|
28
|
+
return { severity: "placeholder", code: "preserved-block" };
|
|
29
|
+
case "bookmarkBlock":
|
|
30
|
+
return { severity: "hidden", code: "range-marker" };
|
|
31
|
+
case "rawInline":
|
|
32
|
+
return preservedInline(element);
|
|
33
|
+
default:
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function preservedInline(element) {
|
|
38
|
+
const name = element === null ? null : localPart(element);
|
|
39
|
+
if (name === "r") return null;
|
|
40
|
+
return name === "bookmarkStart" || name === "bookmarkEnd" ? { severity: "hidden", code: "range-marker" } : { severity: "hidden", code: "preserved-inline" };
|
|
41
|
+
}
|
|
42
|
+
function blockNumberOf(node) {
|
|
43
|
+
const srcId = stringAttr(node.attrs.srcId);
|
|
44
|
+
const key = srcId === null ? null : splitBlockKey(srcId);
|
|
45
|
+
return key?.index ?? null;
|
|
46
|
+
}
|
|
47
|
+
function fidelityNotesOf(doc, part) {
|
|
48
|
+
const notes = [];
|
|
49
|
+
let block = null;
|
|
50
|
+
doc.descendants((node, pos, parent) => {
|
|
51
|
+
if (parent === doc) block = blockNumberOf(node);
|
|
52
|
+
const element = elementOf(node);
|
|
53
|
+
const preserved = preservedBy(node, element);
|
|
54
|
+
if (preserved) {
|
|
55
|
+
notes.push({ ...preserved, part, block, pos, element: element ?? "?" });
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
});
|
|
59
|
+
return notes;
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
NO_FIDELITY_COLLECTOR,
|
|
63
|
+
fidelityNotesOf
|
|
64
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The derived attrs a paragraph and the run marks inside it carry, worked out from the resolved
|
|
3
|
+
* hierarchy. Import, the plugin that formats the paragraphs an edit built, the paragraph writers
|
|
4
|
+
* and the clipboard reader all take them from here, so a paragraph is drawn the same whichever of
|
|
5
|
+
* them last touched it.
|
|
6
|
+
*/
|
|
7
|
+
import type { Mark } from "prosemirror-model";
|
|
8
|
+
import type { ParagraphFormat, RunFormat } from "../../model/format";
|
|
9
|
+
import type { FormattingContext } from "./context";
|
|
10
|
+
import { type ParagraphPlacement, type ResolvedParagraph } from "./resolve";
|
|
11
|
+
/** The two derived paragraph attrs (`format` and `styleRun` in `schema`) */
|
|
12
|
+
export interface ParagraphAttrs {
|
|
13
|
+
format: ParagraphFormat | null;
|
|
14
|
+
styleRun: RunFormat | null;
|
|
15
|
+
}
|
|
16
|
+
export declare function paragraphAttrsOf(paragraph: ResolvedParagraph): ParagraphAttrs;
|
|
17
|
+
export declare function paragraphAttrsFor(pPr: string | null, context: FormattingContext, placement?: ParagraphPlacement | null): ParagraphAttrs;
|
|
18
|
+
/**
|
|
19
|
+
* The run mark an inline wears under the resolved paragraph, or null when it needs none.
|
|
20
|
+
*
|
|
21
|
+
* A mark already there keeps the formatting it wrote down and has its display values read
|
|
22
|
+
* again, since they were laid over whatever the paragraph wore before. Text carrying no mark
|
|
23
|
+
* gets one holding nothing but the values the paragraph passes down, so it is drawn the way
|
|
24
|
+
* import draws a bare `w:r`; such a mark writes no `w:rPr` and changes nothing on the way out.
|
|
25
|
+
* An inline that is not text and carries no mark is left as it is.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runMarkUnder(mark: Mark | null, isText: boolean, paragraph: ResolvedParagraph, context: FormattingContext): Mark | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/docx/formatting/attrs.ts
|
|
2
|
+
import { docxSchema } from "../../schema/index.js";
|
|
3
|
+
import {
|
|
4
|
+
resolveParagraph,
|
|
5
|
+
resolveRun
|
|
6
|
+
} from "./resolve.js";
|
|
7
|
+
function paragraphAttrsOf(paragraph) {
|
|
8
|
+
return { format: paragraph.format, styleRun: paragraph.styleRun };
|
|
9
|
+
}
|
|
10
|
+
function paragraphAttrsFor(pPr, context, placement = null) {
|
|
11
|
+
return paragraphAttrsOf(resolveParagraph(pPr, context, placement));
|
|
12
|
+
}
|
|
13
|
+
function runMarkUnder(mark, isText, paragraph, context) {
|
|
14
|
+
if (mark) {
|
|
15
|
+
const rPr = mark.attrs.rPr;
|
|
16
|
+
const format2 = resolveRun(
|
|
17
|
+
typeof rPr === "string" ? rPr : null,
|
|
18
|
+
paragraph,
|
|
19
|
+
context
|
|
20
|
+
);
|
|
21
|
+
return mark.type.create({ ...mark.attrs, format: format2 });
|
|
22
|
+
}
|
|
23
|
+
if (!isText) return null;
|
|
24
|
+
const format = resolveRun(null, paragraph, context);
|
|
25
|
+
return format === null ? null : docxSchema.marks.run.create({ rPr: null, rAttrs: null, format });
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
paragraphAttrsFor,
|
|
29
|
+
paragraphAttrsOf,
|
|
30
|
+
runMarkUnder
|
|
31
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RunFormat } from "../../model/format";
|
|
2
|
+
import { type Numbering } from "../../numbering/parseNumbering";
|
|
3
|
+
import { type CompatSettings } from "../documentSettings";
|
|
4
|
+
import { type ThemeFonts } from "../theme";
|
|
5
|
+
import { type StyleTable } from "./styles";
|
|
6
|
+
import type { ParagraphFormatLayer } from "./tabStops";
|
|
7
|
+
/**
|
|
8
|
+
* Everything a document lays down that the §17.7.2 hierarchy is resolved against.
|
|
9
|
+
*
|
|
10
|
+
* Built once when the document is opened and read by every caller that derives a paragraph's or
|
|
11
|
+
* a run's display values, so that a value is the same whichever path asked for it.
|
|
12
|
+
*/
|
|
13
|
+
export interface FormattingContext {
|
|
14
|
+
styles: StyleTable;
|
|
15
|
+
/** The paragraph style a paragraph naming none wears (`w:default="1"`). Null when the document marks none */
|
|
16
|
+
defaultParagraphStyleId: string | null;
|
|
17
|
+
defaultTableStyleId: string | null;
|
|
18
|
+
/** `pPrDefault`, the layer at the base of the hierarchy */
|
|
19
|
+
paragraphDefaults: ParagraphFormatLayer;
|
|
20
|
+
/**
|
|
21
|
+
* `rPrDefault` read in full. It decides what a removed run property falls back to. The default
|
|
22
|
+
* font and size are supplied through CSS variables; other properties enter derived run values.
|
|
23
|
+
*/
|
|
24
|
+
runDefaults: RunFormat;
|
|
25
|
+
numbering: Numbering;
|
|
26
|
+
themeFonts: ThemeFonts;
|
|
27
|
+
compat: CompatSettings;
|
|
28
|
+
}
|
|
29
|
+
export declare const NO_FORMATTING: FormattingContext;
|
|
30
|
+
/** The context an opened document resolves against. A document without a styles part lays down nothing */
|
|
31
|
+
export declare function formattingContextOf(styles: Document | null, numbering: Numbering, themeFonts: ThemeFonts, compat?: CompatSettings): FormattingContext;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/docx/formatting/context.ts
|
|
2
|
+
import {
|
|
3
|
+
EMPTY_NUMBERING
|
|
4
|
+
} from "../../numbering/parseNumbering.js";
|
|
5
|
+
import { NO_COMPAT } from "../documentSettings.js";
|
|
6
|
+
import { NO_THEME_FONTS } from "../theme.js";
|
|
7
|
+
import { readDefaultParagraphFormat, readRunDefaults } from "./direct.js";
|
|
8
|
+
import {
|
|
9
|
+
defaultParagraphStyleIdOf,
|
|
10
|
+
defaultTableStyleIdOf,
|
|
11
|
+
NO_STYLES,
|
|
12
|
+
readStyles
|
|
13
|
+
} from "./styles.js";
|
|
14
|
+
var NO_FORMATTING = {
|
|
15
|
+
styles: NO_STYLES,
|
|
16
|
+
defaultParagraphStyleId: null,
|
|
17
|
+
defaultTableStyleId: null,
|
|
18
|
+
paragraphDefaults: {},
|
|
19
|
+
runDefaults: {},
|
|
20
|
+
numbering: EMPTY_NUMBERING,
|
|
21
|
+
themeFonts: NO_THEME_FONTS,
|
|
22
|
+
compat: NO_COMPAT
|
|
23
|
+
};
|
|
24
|
+
function formattingContextOf(styles, numbering, themeFonts, compat = NO_COMPAT) {
|
|
25
|
+
if (styles === null) {
|
|
26
|
+
return { ...NO_FORMATTING, numbering, themeFonts, compat };
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
styles: readStyles(styles, themeFonts),
|
|
30
|
+
defaultParagraphStyleId: defaultParagraphStyleIdOf(styles),
|
|
31
|
+
defaultTableStyleId: defaultTableStyleIdOf(styles),
|
|
32
|
+
paragraphDefaults: readDefaultParagraphFormat(styles),
|
|
33
|
+
runDefaults: readRunDefaults(styles, themeFonts),
|
|
34
|
+
numbering,
|
|
35
|
+
themeFonts,
|
|
36
|
+
compat
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
NO_FORMATTING,
|
|
41
|
+
formattingContextOf
|
|
42
|
+
};
|
|
@@ -8,11 +8,8 @@
|
|
|
8
8
|
import { type DocumentDefaults, type LineSpacing, type RunFormat } from "../../model/format";
|
|
9
9
|
import { type ThemeFonts } from "../theme";
|
|
10
10
|
import type { ParagraphFormatLayer } from "./tabStops";
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
* Splits the CSS name list `fontFamilyOf` produced back into individual names.
|
|
14
|
-
*/
|
|
15
|
-
export declare function fontNamesOf(cssNames: string | undefined | null): string[];
|
|
11
|
+
/** `w:spacing/@line` counts an automatic line height in 240ths of a line (§17.3.1.33) */
|
|
12
|
+
export declare const LINE_UNITS_PER_LINE = 240;
|
|
16
13
|
/**
|
|
17
14
|
* The line spacing from `w:spacing`.
|
|
18
15
|
* auto means a multiple in 240ths, and the rest are heights pinned down in twips.
|
|
@@ -23,6 +20,10 @@ export declare function readRunFormat(rPr: Element | null, themeFonts?: ThemeFon
|
|
|
23
20
|
export declare const NO_DOCUMENT_DEFAULTS: DocumentDefaults;
|
|
24
21
|
/** Reads the paragraph-property layer at the base of the OOXML hierarchy. */
|
|
25
22
|
export declare function readDefaultParagraphFormat(styles: Document): ParagraphFormatLayer;
|
|
23
|
+
/** Reads the run-property layer at the base of the OOXML hierarchy (`rPrDefault`) in full */
|
|
24
|
+
export declare function readRunDefaults(styles: Document, themeFonts?: ThemeFonts): RunFormat;
|
|
25
|
+
/** The character style a run's formatting points at (`w:rStyle`). null when it points at none */
|
|
26
|
+
export declare function runStyleIdOf(rPr: Element | null): string | null;
|
|
26
27
|
/**
|
|
27
28
|
* Reads the document default font size, font, and line spacing from docDefaults in styles.xml.
|
|
28
29
|
* What is absent is left as null, and the on-screen fallback is decided by the display layer.
|