@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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/editor/clipboard/inlineFormatting.ts
|
|
2
|
-
import {
|
|
2
|
+
import { rPrOf } from "../../docx/formatting.js";
|
|
3
|
+
import { readRunProps } from "../../docx/runProps.js";
|
|
4
|
+
import { HALF_POINTS_PER_PT, ST_HpsMeasure } from "../../ooxml/simpleTypes.js";
|
|
3
5
|
import { docxSchema } from "../../schema/index.js";
|
|
4
6
|
import { editorClassNames } from "../../styles/classNames.js";
|
|
5
7
|
var IGNORED_TAGS = /* @__PURE__ */ new Set([
|
|
@@ -76,8 +78,8 @@ function fontSizePt(value) {
|
|
|
76
78
|
const amount = Number.parseFloat(match[1] ?? "");
|
|
77
79
|
if (!Number.isFinite(amount) || amount <= 0) return null;
|
|
78
80
|
const points = match[2]?.toLowerCase() === "px" ? amount * 0.75 : amount;
|
|
79
|
-
const
|
|
80
|
-
return
|
|
81
|
+
const half = Math.round(points * HALF_POINTS_PER_PT);
|
|
82
|
+
return ST_HpsMeasure.format(half) === null ? null : half / HALF_POINTS_PER_PT;
|
|
81
83
|
}
|
|
82
84
|
function legacyFontSize(value) {
|
|
83
85
|
const sizes = [8, 10, 12, 14, 18, 24, 36];
|
|
@@ -150,34 +152,21 @@ function contextFor(parent, element, readElementStyle = true) {
|
|
|
150
152
|
function withInlineStyle(context, style) {
|
|
151
153
|
return { ...context, style: { ...context.style, ...style } };
|
|
152
154
|
}
|
|
155
|
+
function settingsOf(style) {
|
|
156
|
+
const settings = {};
|
|
157
|
+
if (style.bold) settings.bold = true;
|
|
158
|
+
if (style.italic) settings.italic = true;
|
|
159
|
+
if (style.underline) settings.underline = "single";
|
|
160
|
+
if (style.strike) settings.strike = true;
|
|
161
|
+
if (style.fontSizePt !== void 0) settings.fontSizePt = style.fontSizePt;
|
|
162
|
+
if (style.fontFamily !== void 0) settings.fontFamily = style.fontFamily;
|
|
163
|
+
if (style.color !== void 0) settings.color = style.color;
|
|
164
|
+
if (style.background !== void 0) settings.background = style.background;
|
|
165
|
+
return settings;
|
|
166
|
+
}
|
|
153
167
|
function runMark(style) {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
if (style.italic) edits.push({ kind: "toggle", toggle: "italic", on: true });
|
|
157
|
-
if (style.underline) {
|
|
158
|
-
edits.push({ kind: "toggle", toggle: "underline", on: true });
|
|
159
|
-
}
|
|
160
|
-
if (style.strike) edits.push({ kind: "toggle", toggle: "strike", on: true });
|
|
161
|
-
if (style.fontSizePt !== void 0) {
|
|
162
|
-
edits.push({ kind: "fontSize", pt: style.fontSizePt });
|
|
163
|
-
}
|
|
164
|
-
if (style.fontFamily !== void 0) {
|
|
165
|
-
edits.push({ kind: "fontFamily", name: style.fontFamily });
|
|
166
|
-
}
|
|
167
|
-
if (style.color !== void 0)
|
|
168
|
-
edits.push({ kind: "color", hex: style.color });
|
|
169
|
-
if (style.background !== void 0) {
|
|
170
|
-
edits.push({ kind: "background", hex: style.background });
|
|
171
|
-
}
|
|
172
|
-
let props = {
|
|
173
|
-
rPr: null,
|
|
174
|
-
format: null
|
|
175
|
-
};
|
|
176
|
-
for (const edit of edits) {
|
|
177
|
-
const next = editRunProps(props, null, edit);
|
|
178
|
-
if (next) props = next;
|
|
179
|
-
}
|
|
180
|
-
return props.rPr === null ? null : docxSchema.marks.run.create({ rPr: props.rPr, format: props.format });
|
|
168
|
+
const rPr = rPrOf(settingsOf(style));
|
|
169
|
+
return rPr === null ? null : docxSchema.marks.run.create({ rPr, format: readRunProps(rPr) });
|
|
181
170
|
}
|
|
182
171
|
function marksFor(context) {
|
|
183
172
|
const marks = [];
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
/** Edits Word comments through their range markers and reference nodes. */
|
|
2
2
|
import { type Command, type EditorState } from "prosemirror-state";
|
|
3
3
|
import type { NewComment } from "./model";
|
|
4
|
-
/** Whether a non-empty selection in one paragraph can receive a comment. */
|
|
5
|
-
export declare function canAddComment(state: EditorState): boolean;
|
|
6
4
|
/** Adds a plain-text comment to the current text selection. */
|
|
7
5
|
export declare function addComment(comment: NewComment): Command;
|
|
6
|
+
/**
|
|
7
|
+
* Whether a non-empty selection in one paragraph can receive a comment.
|
|
8
|
+
* This is the command itself asked without a dispatch, over a comment standing in for the one the
|
|
9
|
+
* user would write, so the button and the click cannot answer differently.
|
|
10
|
+
*/
|
|
11
|
+
export declare function canAddComment(state: EditorState): boolean;
|
|
8
12
|
/** Replaces the plain-text body of one comment, retaining its author and anchor. */
|
|
9
13
|
export declare function updateComment(id: string, text: string): Command;
|
|
10
14
|
/** Marks a comment thread resolved or open without deleting it. */
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "prosemirror-state";
|
|
5
5
|
import { commentParaId } from "../../../docx/comments.js";
|
|
6
6
|
import { docxSchema } from "../../../schema/index.js";
|
|
7
|
-
import {
|
|
7
|
+
import { guardedCommand } from "../../../schema/guards.js";
|
|
8
8
|
import {
|
|
9
9
|
reservedCommentIds,
|
|
10
10
|
reservedCommentParaIds
|
|
11
|
-
} from "../../
|
|
11
|
+
} from "../../editorDocument.js";
|
|
12
12
|
import { documentComments, repliesAttr, stringAttr } from "./reading.js";
|
|
13
13
|
function validCommentSelection(state) {
|
|
14
14
|
const { selection } = state;
|
|
@@ -113,27 +113,21 @@ function addCommentTransaction(state, comment) {
|
|
|
113
113
|
null,
|
|
114
114
|
startMarks
|
|
115
115
|
);
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
return state.tr.insert(to, end).insert(to + 1, reference).insert(from, start);
|
|
117
|
+
}
|
|
118
|
+
function addComment(comment) {
|
|
119
|
+
return guardedCommand((state) => addCommentTransaction(state, comment));
|
|
118
120
|
}
|
|
119
121
|
function canAddComment(state) {
|
|
120
|
-
return
|
|
122
|
+
return addComment({
|
|
121
123
|
text: "comment",
|
|
122
124
|
author: "Author",
|
|
123
125
|
date: "1970-01-01T00:00:00.000Z"
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
function addComment(comment) {
|
|
127
|
-
return (state, dispatch) => {
|
|
128
|
-
const transaction = addCommentTransaction(state, comment);
|
|
129
|
-
if (!transaction) return false;
|
|
130
|
-
dispatch?.(transaction);
|
|
131
|
-
return true;
|
|
132
|
-
};
|
|
126
|
+
})(state);
|
|
133
127
|
}
|
|
134
128
|
function updateComment(id, text) {
|
|
135
|
-
return (state
|
|
136
|
-
if (text.trim().length === 0) return
|
|
129
|
+
return guardedCommand((state) => {
|
|
130
|
+
if (text.trim().length === 0) return null;
|
|
137
131
|
let transaction = state.tr;
|
|
138
132
|
let changed = false;
|
|
139
133
|
state.doc.descendants((node, pos) => {
|
|
@@ -148,13 +142,11 @@ function updateComment(id, text) {
|
|
|
148
142
|
}
|
|
149
143
|
return true;
|
|
150
144
|
});
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return true;
|
|
154
|
-
};
|
|
145
|
+
return changed ? transaction : null;
|
|
146
|
+
});
|
|
155
147
|
}
|
|
156
148
|
function updateReference(id, change) {
|
|
157
|
-
return (state
|
|
149
|
+
return guardedCommand((state) => {
|
|
158
150
|
let transaction = state.tr;
|
|
159
151
|
let changed = false;
|
|
160
152
|
state.doc.descendants((node, pos) => {
|
|
@@ -168,10 +160,8 @@ function updateReference(id, change) {
|
|
|
168
160
|
}
|
|
169
161
|
return false;
|
|
170
162
|
});
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return true;
|
|
174
|
-
};
|
|
163
|
+
return changed ? transaction : null;
|
|
164
|
+
});
|
|
175
165
|
}
|
|
176
166
|
function setCommentResolved(id, resolved) {
|
|
177
167
|
return (state, dispatch) => updateReference(id, (node) => {
|
|
@@ -261,7 +251,7 @@ function removeCommentReply(commentId, replyId) {
|
|
|
261
251
|
});
|
|
262
252
|
}
|
|
263
253
|
function removeComment(id) {
|
|
264
|
-
return (state
|
|
254
|
+
return guardedCommand((state) => {
|
|
265
255
|
const positions = [];
|
|
266
256
|
state.doc.descendants((node, pos) => {
|
|
267
257
|
if ((node.type.name === "commentStart" || node.type.name === "commentEnd" || node.type.name === "commentReference") && stringAttr(node.attrs.id) === id) {
|
|
@@ -269,15 +259,13 @@ function removeComment(id) {
|
|
|
269
259
|
}
|
|
270
260
|
return true;
|
|
271
261
|
});
|
|
272
|
-
if (positions.length === 0) return
|
|
262
|
+
if (positions.length === 0) return null;
|
|
273
263
|
const transaction = state.tr;
|
|
274
264
|
for (const marker of positions.sort((a, b) => b.pos - a.pos)) {
|
|
275
265
|
transaction.delete(marker.pos, marker.pos + marker.size);
|
|
276
266
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
return true;
|
|
280
|
-
};
|
|
267
|
+
return transaction;
|
|
268
|
+
});
|
|
281
269
|
}
|
|
282
270
|
function selectComment(id) {
|
|
283
271
|
return (state, dispatch) => {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Document-level readers for whether the document as it stands can be written back. */
|
|
2
|
+
import type { EditorState } from "prosemirror-state";
|
|
3
|
+
import { type ExportProblem } from "../../docx/invariants";
|
|
4
|
+
export type { ExportProblem } from "../../docx/invariants";
|
|
5
|
+
/**
|
|
6
|
+
* Every reason writing the document back would be refused, in the order `exportDocx` would raise
|
|
7
|
+
* them, each with the code and message the refusal would carry and the position in the document
|
|
8
|
+
* where there is one. Empty when the file would be written.
|
|
9
|
+
*
|
|
10
|
+
* A state built without an opened document has no file to write back into, so nothing about it
|
|
11
|
+
* can be refused and it reports no problem.
|
|
12
|
+
*/
|
|
13
|
+
export declare function documentExportProblems(state: EditorState): readonly ExportProblem[];
|
|
14
|
+
/** Whether the document as it stands can be written back, which is what an export control is drawn from */
|
|
15
|
+
export declare function canExport(state: EditorState): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/editor/commands/exportQueries.ts
|
|
2
|
+
import { exportProblems } from "../../docx/invariants.js";
|
|
3
|
+
import { documentOf } from "../editorDocument.js";
|
|
4
|
+
function documentExportProblems(state) {
|
|
5
|
+
const { session } = documentOf(state);
|
|
6
|
+
return session === null ? [] : exportProblems(state.doc, session);
|
|
7
|
+
}
|
|
8
|
+
function canExport(state) {
|
|
9
|
+
return documentExportProblems(state).length === 0;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
canExport,
|
|
13
|
+
documentExportProblems
|
|
14
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Document-level reader for what the open document holds that the editor cannot model. */
|
|
2
|
+
import type { EditorState } from "prosemirror-state";
|
|
3
|
+
import { type FidelityNote } from "../../docx/fidelity";
|
|
4
|
+
export type { FidelityCode, FidelityNote, FidelitySeverity, } from "../../docx/fidelity";
|
|
5
|
+
/**
|
|
6
|
+
* What the document standing in the editor hides, stands a placeholder in front of, or approximates.
|
|
7
|
+
*
|
|
8
|
+
* The notes are read off the document as it is now, so a note goes away as soon as an edit removes
|
|
9
|
+
* what it was about. `part` is null: an editor state carries the document and not the file it came
|
|
10
|
+
* from, and `importDocx` is where a note can name the part it belongs to.
|
|
11
|
+
*/
|
|
12
|
+
export declare function documentFidelity(state: EditorState): readonly FidelityNote[];
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** The character formatting commands the package exports, each built from the property it edits. */
|
|
2
2
|
import type { Command, EditorState } from "prosemirror-state";
|
|
3
|
-
export type { RunToggle } from "../../../docx/runProps";
|
|
4
3
|
/**
|
|
5
4
|
* Whether character formatting reaches anything where the selection stands, which is what a
|
|
6
5
|
* control offering it is drawn from.
|
|
@@ -13,6 +12,7 @@ export type { RunToggle } from "../../../docx/runProps";
|
|
|
13
12
|
export declare function canFormatText(state: EditorState): boolean;
|
|
14
13
|
export declare const toggleBold: Command;
|
|
15
14
|
export declare const toggleItalic: Command;
|
|
15
|
+
/** Switching the underline on writes a single one; a run already underlined keeps the kind it has */
|
|
16
16
|
export declare const toggleUnderline: Command;
|
|
17
17
|
export declare const toggleStrike: Command;
|
|
18
18
|
/** Sets the font size in points. Null withdraws the setting and falls back to the document default */
|
|
@@ -1,130 +1,48 @@
|
|
|
1
1
|
// src/editor/commands/formatting/editing.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
matchesRunEdit
|
|
6
|
-
} from "../../../docx/runProps.js";
|
|
7
|
-
import { docxSchema } from "../../../schema/index.js";
|
|
8
|
-
import {
|
|
9
|
-
insertionInsideLocked,
|
|
10
|
-
rangeTouchesLocked
|
|
11
|
-
} from "../../../schema/locks.js";
|
|
12
|
-
import { editsShut } from "../../../schema/protectionState.js";
|
|
13
|
-
import {
|
|
14
|
-
activePieces,
|
|
15
|
-
caretPiece,
|
|
16
|
-
text,
|
|
17
|
-
textPieces
|
|
18
|
-
} from "./shared.js";
|
|
19
|
-
function editedMark(target, edit) {
|
|
20
|
-
const next = editRunProps(
|
|
21
|
-
{ rPr: text(target.mark?.attrs.rPr), format: target.format },
|
|
22
|
-
target.pPr,
|
|
23
|
-
edit
|
|
24
|
-
);
|
|
25
|
-
if (!next) return null;
|
|
26
|
-
return docxSchema.marks.run.create({
|
|
27
|
-
...target.mark?.attrs,
|
|
28
|
-
rPr: next.rPr,
|
|
29
|
-
format: next.format
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
function planChanges(pieces, edit) {
|
|
33
|
-
const changes = [];
|
|
34
|
-
for (const target of pieces) {
|
|
35
|
-
const mark = editedMark(target, edit);
|
|
36
|
-
if (!mark) return null;
|
|
37
|
-
changes.push({ from: target.from, to: target.to, mark });
|
|
38
|
-
}
|
|
39
|
-
return changes;
|
|
40
|
-
}
|
|
41
|
-
function applyToSelection(state, dispatch, edit) {
|
|
42
|
-
const pieces = textPieces(state).filter(
|
|
43
|
-
(target) => (
|
|
44
|
-
// Text already in the desired state is left untouched, so its original XML survives
|
|
45
|
-
!matchesRunEdit(target.format, edit) && // A locked stretch is left out rather than refused: the guard turns down the whole
|
|
46
|
-
// transaction, so asking for it would leave the rest of the selection unformatted too
|
|
47
|
-
!rangeTouchesLocked(state.doc, target.from, target.to)
|
|
48
|
-
)
|
|
49
|
-
);
|
|
50
|
-
const changes = pieces.length > 0 ? planChanges(pieces, edit) : null;
|
|
51
|
-
if (!changes) return false;
|
|
52
|
-
if (dispatch) {
|
|
53
|
-
const tr = state.tr;
|
|
54
|
-
for (const change of changes) {
|
|
55
|
-
tr.addMark(change.from, change.to, change.mark);
|
|
56
|
-
}
|
|
57
|
-
dispatch(tr);
|
|
58
|
-
}
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
function applyToCaret(state, dispatch, edit) {
|
|
62
|
-
const target = caretPiece(state);
|
|
63
|
-
if (matchesRunEdit(target.format, edit)) return false;
|
|
64
|
-
const mark = editedMark(target, edit);
|
|
65
|
-
if (!mark) return false;
|
|
66
|
-
if (dispatch) {
|
|
67
|
-
const marks = state.storedMarks ?? state.selection.$from.marks();
|
|
68
|
-
dispatch(state.tr.setStoredMarks(mark.addToSet(marks)));
|
|
69
|
-
}
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
function runEditCommand(edit) {
|
|
73
|
-
return (state, dispatch) => {
|
|
74
|
-
if (editsShut(state)) return false;
|
|
75
|
-
return state.selection.empty ? applyToCaret(state, dispatch, edit) : applyToSelection(state, dispatch, edit);
|
|
76
|
-
};
|
|
77
|
-
}
|
|
2
|
+
import { editShut, openStretches } from "../../../schema/guards.js";
|
|
3
|
+
import { runPropertyCommands } from "./propertyCommands.js";
|
|
4
|
+
import { textPieces } from "./shared.js";
|
|
78
5
|
function canFormatText(state) {
|
|
79
|
-
if (editsShut(state)) return false;
|
|
80
6
|
if (state.selection.empty) {
|
|
81
|
-
return !
|
|
7
|
+
return !editShut(state, { kind: "insert", at: state.selection.from });
|
|
82
8
|
}
|
|
83
|
-
return textPieces(state).
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
};
|
|
98
|
-
return runEditCommand(edit)(state, dispatch);
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
var toggleBold = toggleCommand("bold");
|
|
102
|
-
var toggleItalic = toggleCommand("italic");
|
|
103
|
-
var toggleUnderline = toggleCommand("underline");
|
|
104
|
-
var toggleStrike = toggleCommand("strike");
|
|
9
|
+
return openStretches(state, textPieces(state), "mark").length > 0;
|
|
10
|
+
}
|
|
11
|
+
var bold = runPropertyCommands("bold");
|
|
12
|
+
var italic = runPropertyCommands("italic");
|
|
13
|
+
var underline = runPropertyCommands("underline");
|
|
14
|
+
var strike = runPropertyCommands("strike");
|
|
15
|
+
var fontSize = runPropertyCommands("fontSizePt");
|
|
16
|
+
var fontFamily = runPropertyCommands("fontFamily");
|
|
17
|
+
var textColor = runPropertyCommands("color");
|
|
18
|
+
var textBackground = runPropertyCommands("background");
|
|
19
|
+
var toggleBold = bold.toggle(true);
|
|
20
|
+
var toggleItalic = italic.toggle(true);
|
|
21
|
+
var toggleUnderline = underline.toggle("single");
|
|
22
|
+
var toggleStrike = strike.toggle(true);
|
|
105
23
|
function setFontSize(pt) {
|
|
106
|
-
return
|
|
24
|
+
return fontSize.set(pt);
|
|
107
25
|
}
|
|
108
26
|
function setFontFamily(name) {
|
|
109
|
-
return
|
|
27
|
+
return fontFamily.set(name);
|
|
110
28
|
}
|
|
111
29
|
function setTextColor(hex) {
|
|
112
|
-
return
|
|
30
|
+
return textColor.set(hex);
|
|
113
31
|
}
|
|
114
32
|
function setTextBackground(hex) {
|
|
115
|
-
return
|
|
33
|
+
return textBackground.set(hex);
|
|
116
34
|
}
|
|
117
35
|
function isBoldActive(state) {
|
|
118
|
-
return
|
|
36
|
+
return bold.isActive(state);
|
|
119
37
|
}
|
|
120
38
|
function isItalicActive(state) {
|
|
121
|
-
return
|
|
39
|
+
return italic.isActive(state);
|
|
122
40
|
}
|
|
123
41
|
function isUnderlineActive(state) {
|
|
124
|
-
return
|
|
42
|
+
return underline.isActive(state);
|
|
125
43
|
}
|
|
126
44
|
function isStrikeActive(state) {
|
|
127
|
-
return
|
|
45
|
+
return strike.isActive(state);
|
|
128
46
|
}
|
|
129
47
|
export {
|
|
130
48
|
canFormatText,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The commands and the query one run property is edited and read through, built from the
|
|
3
|
+
* property's row in the run property table.
|
|
4
|
+
*
|
|
5
|
+
* Each edit preserves the run's untouched XML: the row says which children of the rPr change,
|
|
6
|
+
* and the mark keeps every other attr it wore.
|
|
7
|
+
*/
|
|
8
|
+
import type { Command, EditorState } from "prosemirror-state";
|
|
9
|
+
import { type EditableRunKey, type RunSetting } from "../../../docx/formatting";
|
|
10
|
+
export interface RunPropertyCommands<K extends EditableRunKey> {
|
|
11
|
+
/** Writes the value into the selection. Null withdraws the run's own setting, so the layers below decide again */
|
|
12
|
+
set(value: RunSetting<K> | null): Command;
|
|
13
|
+
/** Whether the property is on where the selection stands. It counts as on only when it is on everywhere */
|
|
14
|
+
isActive(state: EditorState): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The same toggle convention as Word: if every character in the selection is already on, turn
|
|
17
|
+
* them all off; otherwise switch them all on as `on`.
|
|
18
|
+
*/
|
|
19
|
+
toggle(on: RunSetting<K>): Command;
|
|
20
|
+
}
|
|
21
|
+
export declare function runPropertyCommands<K extends EditableRunKey>(key: K): RunPropertyCommands<K>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/editor/commands/formatting/propertyCommands.ts
|
|
2
|
+
import {
|
|
3
|
+
inheritedRunFormat,
|
|
4
|
+
RUN_PROPERTIES,
|
|
5
|
+
resolveParagraph,
|
|
6
|
+
resolveRun
|
|
7
|
+
} from "../../../docx/formatting.js";
|
|
8
|
+
import {
|
|
9
|
+
editRunProps,
|
|
10
|
+
matchesRunEdit
|
|
11
|
+
} from "../../../docx/runProps.js";
|
|
12
|
+
import { docxSchema } from "../../../schema/index.js";
|
|
13
|
+
import { editShut, openStretches } from "../../../schema/guards.js";
|
|
14
|
+
import { documentFormatting } from "../../documentStyles.js";
|
|
15
|
+
import {
|
|
16
|
+
activePieces,
|
|
17
|
+
caretPiece,
|
|
18
|
+
text,
|
|
19
|
+
textPieces
|
|
20
|
+
} from "./shared.js";
|
|
21
|
+
function editedMark(state, target, edit) {
|
|
22
|
+
const context = documentFormatting(state);
|
|
23
|
+
const rPr = text(target.mark?.attrs.rPr);
|
|
24
|
+
const paragraph = resolveParagraph(target.pPr, context);
|
|
25
|
+
const next = editRunProps(
|
|
26
|
+
{ rPr, format: target.format },
|
|
27
|
+
inheritedRunFormat(rPr, paragraph, context),
|
|
28
|
+
edit
|
|
29
|
+
);
|
|
30
|
+
if (!next) return null;
|
|
31
|
+
return docxSchema.marks.run.create({
|
|
32
|
+
...target.mark?.attrs,
|
|
33
|
+
rPr: next.rPr,
|
|
34
|
+
format: resolveRun(next.rPr, paragraph, context)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function planChanges(state, pieces, edit) {
|
|
38
|
+
const changes = [];
|
|
39
|
+
for (const target of pieces) {
|
|
40
|
+
const mark = editedMark(state, target, edit);
|
|
41
|
+
if (!mark) return null;
|
|
42
|
+
changes.push({ from: target.from, to: target.to, mark });
|
|
43
|
+
}
|
|
44
|
+
return changes;
|
|
45
|
+
}
|
|
46
|
+
function applyToSelection(state, dispatch, edit) {
|
|
47
|
+
const pieces = openStretches(
|
|
48
|
+
state,
|
|
49
|
+
// Text already in the desired state is left untouched, so its original XML survives
|
|
50
|
+
textPieces(state).filter((target) => !matchesRunEdit(target.format, edit)),
|
|
51
|
+
"mark"
|
|
52
|
+
);
|
|
53
|
+
const changes = pieces.length > 0 ? planChanges(state, pieces, edit) : null;
|
|
54
|
+
if (!changes) return false;
|
|
55
|
+
if (dispatch) {
|
|
56
|
+
const tr = state.tr;
|
|
57
|
+
for (const change of changes) {
|
|
58
|
+
tr.addMark(change.from, change.to, change.mark);
|
|
59
|
+
}
|
|
60
|
+
dispatch(tr);
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
function applyToCaret(state, dispatch, edit) {
|
|
65
|
+
if (editShut(state, { kind: "insert", at: state.selection.from })) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const target = caretPiece(state);
|
|
69
|
+
if (matchesRunEdit(target.format, edit)) return false;
|
|
70
|
+
const mark = editedMark(state, target, edit);
|
|
71
|
+
if (!mark) return false;
|
|
72
|
+
if (dispatch) {
|
|
73
|
+
const marks = state.storedMarks ?? state.selection.$from.marks();
|
|
74
|
+
dispatch(state.tr.setStoredMarks(mark.addToSet(marks)));
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
function runEditCommand(edit) {
|
|
79
|
+
return (state, dispatch) => state.selection.empty ? applyToCaret(state, dispatch, edit) : applyToSelection(state, dispatch, edit);
|
|
80
|
+
}
|
|
81
|
+
function runPropertyCommands(key) {
|
|
82
|
+
const property = RUN_PROPERTIES[key];
|
|
83
|
+
const isOn = (target) => property.isOn(target.format ?? {});
|
|
84
|
+
const set = (value) => runEditCommand({ key, value });
|
|
85
|
+
return {
|
|
86
|
+
set,
|
|
87
|
+
isActive: (state) => {
|
|
88
|
+
const pieces = activePieces(state);
|
|
89
|
+
return pieces.length > 0 && pieces.every(isOn);
|
|
90
|
+
},
|
|
91
|
+
toggle: (on) => (state, dispatch) => {
|
|
92
|
+
const pieces = openStretches(
|
|
93
|
+
state,
|
|
94
|
+
state.selection.empty ? [caretPiece(state)] : textPieces(state),
|
|
95
|
+
"mark"
|
|
96
|
+
);
|
|
97
|
+
return set(pieces.every(isOn) ? null : on)(state, dispatch);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
runPropertyCommands
|
|
103
|
+
};
|
|
@@ -25,8 +25,8 @@ export declare function textPieces(state: EditorState): TextPiece[];
|
|
|
25
25
|
/** When the selection is collapsed, the formatting that text typed next will follow */
|
|
26
26
|
export declare function caretPiece(state: EditorState): TextPiece;
|
|
27
27
|
/**
|
|
28
|
-
* The
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* The formatting a toolbar reads, excluding locked text as it does during editing.
|
|
29
|
+
* Document protection prevents edits, but must not hide the selected text's actual formatting.
|
|
30
|
+
* Commands separately ask all guards before deciding what they can change.
|
|
31
31
|
*/
|
|
32
32
|
export declare function activePieces(state: EditorState): TextPiece[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/editor/commands/formatting/shared.ts
|
|
2
2
|
import { toRunFormat } from "../../../model/format.js";
|
|
3
3
|
import { docxSchema } from "../../../schema/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { lockGuard } from "../../../schema/locks.js";
|
|
5
5
|
function text(value) {
|
|
6
6
|
return typeof value === "string" ? value : null;
|
|
7
7
|
}
|
|
@@ -41,7 +41,10 @@ function caretPiece(state) {
|
|
|
41
41
|
function activePieces(state) {
|
|
42
42
|
if (state.selection.empty) return [caretPiece(state)];
|
|
43
43
|
return textPieces(state).filter(
|
|
44
|
-
(target) => !
|
|
44
|
+
(target) => !lockGuard.shuts(
|
|
45
|
+
{ kind: "mark", from: target.from, to: target.to },
|
|
46
|
+
state
|
|
47
|
+
)
|
|
45
48
|
);
|
|
46
49
|
}
|
|
47
50
|
export {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/editor/commands/indentCommands.ts
|
|
2
2
|
import { withLeftIndent, withListNumbering } from "../../docx/paraProps.js";
|
|
3
3
|
import { toParagraphFormat } from "../../model/format.js";
|
|
4
|
+
import { TWIPS_PER_PT } from "../../ooxml/simpleTypes.js";
|
|
4
5
|
import { editParagraphs, paragraphPPr } from "../paragraphEdits.js";
|
|
5
6
|
import { documentNumbering } from "../plugins/numberingDecorations.js";
|
|
6
7
|
import { listLevelChange, listRefOf } from "./listCommands.js";
|
|
@@ -8,7 +9,7 @@ var STEP_TWIPS = 720;
|
|
|
8
9
|
function leftIndentTwips(node) {
|
|
9
10
|
const format = toParagraphFormat(node.attrs.format);
|
|
10
11
|
const pt = format?.indentStartPt ?? format?.indentLeftPt ?? 0;
|
|
11
|
-
return Math.round(pt *
|
|
12
|
+
return Math.round(pt * TWIPS_PER_PT);
|
|
12
13
|
}
|
|
13
14
|
function steppedLeftTwips(node, delta) {
|
|
14
15
|
const left = leftIndentTwips(node);
|
|
@@ -18,13 +19,13 @@ function steppedLeftTwips(node, delta) {
|
|
|
18
19
|
function indentStep(delta) {
|
|
19
20
|
return (state, dispatch) => {
|
|
20
21
|
const numbering = documentNumbering(state);
|
|
21
|
-
return editParagraphs(state, dispatch, (node
|
|
22
|
+
return editParagraphs(state, dispatch, (node) => {
|
|
22
23
|
if (listRefOf(node)) {
|
|
23
24
|
const change = listLevelChange(numbering, node, delta);
|
|
24
|
-
return change && withListNumbering(paragraphPPr(node), change
|
|
25
|
+
return change && withListNumbering(paragraphPPr(node), change);
|
|
25
26
|
}
|
|
26
27
|
const left = steppedLeftTwips(node, delta);
|
|
27
|
-
return left === null ? null : withLeftIndent(paragraphPPr(node), left
|
|
28
|
+
return left === null ? null : withLeftIndent(paragraphPPr(node), left);
|
|
28
29
|
});
|
|
29
30
|
};
|
|
30
31
|
}
|
|
@@ -13,6 +13,8 @@ export type { ParagraphStyleOption } from "../../docx/formatting";
|
|
|
13
13
|
export type { RunToggle } from "../../docx/runProps";
|
|
14
14
|
export type { LineSpacing, ParagraphAlign } from "../../model/format";
|
|
15
15
|
export type { ListKind } from "../../numbering/listTemplate";
|
|
16
|
+
/** The codes a problem below is reported under, which are the ones `DocxExportError` is thrown with */
|
|
17
|
+
export type { DocxExportErrorCode } from "../../ooxml/errors";
|
|
16
18
|
/** The size an image is shown at, which the insert command asks for */
|
|
17
19
|
export type { ImageExtent } from "../../ooxml/image";
|
|
18
20
|
/**
|
|
@@ -56,6 +58,15 @@ export { insertLineBreak, insertPageBreak } from "./breakCommands";
|
|
|
56
58
|
export { canRunCommand } from "./canRunCommand";
|
|
57
59
|
export type { CommentAuthor, DocumentComment, DocumentCommentReply, NewComment, } from "./commentCommands";
|
|
58
60
|
export { addComment, addCommentReply, canAddComment, canEditComment, documentComments, removeComment, removeCommentReply, selectComment, setCommentResolved, updateComment, updateCommentReply, } from "./commentCommands";
|
|
61
|
+
/**
|
|
62
|
+
* Whether the document as it stands can be written back, and every reason it could not, each
|
|
63
|
+
* with the code `exportDocx` would throw it under. `canExport` is what an export control is
|
|
64
|
+
* drawn from, and `downloadDocx` answers `blocked` with the same list.
|
|
65
|
+
*/
|
|
66
|
+
export type { ExportProblem } from "./exportQueries";
|
|
67
|
+
export { canExport, documentExportProblems } from "./exportQueries";
|
|
68
|
+
export type { FidelityCode, FidelityNote, FidelitySeverity, } from "./fidelityQueries";
|
|
69
|
+
export { documentFidelity } from "./fidelityQueries";
|
|
59
70
|
export type { ActiveFontFamily, ActiveFontSize, } from "./formattingCommands";
|
|
60
71
|
export { activeFontFamily, activeFontSize, activeTextBackground, activeTextColor, canFormatText, documentFontNames, isBoldActive, isItalicActive, isStrikeActive, isUnderlineActive, setFontFamily, setFontSize, setTextBackground, setTextColor, toggleBold, toggleItalic, toggleStrike, toggleUnderline, } from "./formattingCommands";
|
|
61
72
|
/**
|