@portone/docx-editor 0.6.0 → 0.6.1
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 +24 -0
- package/dist/DocxEditor.js +84 -26
- package/dist/docx/exportDocx.d.ts +2 -1
- package/dist/docx/exportDocx.js +3 -9
- package/dist/docx/headersFooters.js +35 -23
- package/dist/docx/identities.d.ts +28 -0
- package/dist/docx/identities.js +42 -10
- package/dist/docx/importDocx.js +25 -26
- package/dist/docx/importParagraph.d.ts +1 -4
- package/dist/docx/importParagraph.js +4 -18
- package/dist/docx/invariants.d.ts +1 -1
- package/dist/docx/invariants.js +45 -4
- package/dist/docx/notes/newNote.d.ts +39 -0
- package/dist/docx/notes/newNote.js +122 -0
- package/dist/docx/notes/numbering.d.ts +27 -0
- package/dist/docx/notes/numbering.js +120 -0
- package/dist/docx/notes/reading.d.ts +58 -0
- package/dist/docx/notes/reading.js +98 -0
- package/dist/docx/notes/writing.d.ts +19 -0
- package/dist/docx/notes/writing.js +96 -0
- package/dist/docx/partPlan.d.ts +3 -0
- package/dist/docx/partPlanners.d.ts +13 -0
- package/dist/docx/partPlanners.js +48 -0
- package/dist/docx/sections.d.ts +5 -0
- package/dist/docx/sections.js +7 -2
- package/dist/docx/serializeParagraph.js +7 -2
- package/dist/docx/session.d.ts +5 -0
- package/dist/docx/session.js +6 -0
- package/dist/docx/storyParts.d.ts +112 -0
- package/dist/docx/storyParts.js +289 -0
- package/dist/editor/clipboard/htmlReader.d.ts +24 -4
- package/dist/editor/clipboard/htmlReader.js +39 -4
- package/dist/editor/clipboard/internalChannel.d.ts +30 -3
- package/dist/editor/clipboard/internalChannel.js +43 -3
- package/dist/editor/clipboard/normalizers.d.ts +35 -8
- package/dist/editor/clipboard/normalizers.js +60 -11
- package/dist/editor/clipboard/plugin.js +42 -22
- package/dist/editor/commands/index.d.ts +1 -0
- package/dist/editor/commands/index.js +18 -0
- package/dist/editor/commands/noteCommands.d.ts +47 -0
- package/dist/editor/commands/noteCommands.js +95 -0
- package/dist/editor/commands/noteQueries.d.ts +22 -3
- package/dist/editor/commands/noteQueries.js +21 -13
- package/dist/editor/createEditor.js +21 -3
- package/dist/editor/documentStyles.d.ts +3 -0
- package/dist/editor/documentStyles.js +2 -1
- package/dist/editor/editorDocument.d.ts +24 -0
- package/dist/editor/editorDocument.js +34 -4
- package/dist/editor/notes/noteSurface.d.ts +53 -0
- package/dist/editor/notes/noteSurface.js +246 -0
- package/dist/editor/plugins/compositionSelection.d.ts +20 -0
- package/dist/editor/plugins/compositionSelection.js +19 -0
- package/dist/editor/plugins/keymap.d.ts +14 -0
- package/dist/editor/plugins/keymap.js +13 -1
- package/dist/editor/plugins/noteLifecycle.d.ts +18 -0
- package/dist/editor/plugins/noteLifecycle.js +117 -0
- package/dist/editor/plugins/noteNavigation.d.ts +45 -0
- package/dist/editor/plugins/noteNavigation.js +86 -0
- package/dist/editor/plugins/noteNumbering.d.ts +13 -0
- package/dist/editor/plugins/noteNumbering.js +58 -0
- package/dist/editor/plugins/rowResize.js +2 -7
- package/dist/editor/plugins/tabLayout.js +2 -7
- package/dist/editor/stories/storyMarkup.d.ts +24 -0
- package/dist/editor/stories/storyMarkup.js +35 -0
- package/dist/editor/stories/storyState.d.ts +34 -0
- package/dist/editor/stories/storyState.js +74 -0
- package/dist/editor/stories/storyView.d.ts +115 -0
- package/dist/editor/stories/storyView.js +144 -0
- package/dist/numbering/spellers.d.ts +1 -1
- package/dist/numbering/spellers.js +6 -1
- package/dist/page/blockKinds.d.ts +23 -4
- package/dist/page/demands/footnoteDemands.d.ts +18 -0
- package/dist/page/demands/footnoteDemands.js +51 -0
- package/dist/page/demands/index.d.ts +43 -0
- package/dist/page/demands/index.js +8 -0
- package/dist/page/kinds/paragraphKind.js +7 -1
- package/dist/page/kinds/tableKind.js +9 -1
- package/dist/page/measureBlocks.d.ts +2 -0
- package/dist/page/measureBlocks.js +31 -10
- package/dist/page/pageDecorations.d.ts +9 -2
- package/dist/page/pageDecorations.js +18 -5
- package/dist/page/pageLayout.d.ts +77 -1
- package/dist/page/pageLayout.js +186 -9
- package/dist/page/usePageLayout.d.ts +57 -2
- package/dist/page/usePageLayout.js +50 -5
- package/dist/schema/attrRoles.js +3 -2
- package/dist/schema/docxSchema.js +5 -2
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.js +1 -2
- package/dist/schema/preservedGuards.d.ts +4 -6
- package/dist/schema/preservedGuards.js +0 -9
- package/dist/schema/stories.d.ts +34 -2
- package/dist/schema/stories.js +22 -5
- package/dist/styles/classNames.d.ts +21 -6
- package/dist/styles/classNames.js +21 -6
- package/dist/styles/inlineStyle.d.ts +7 -0
- package/dist/styles/inlineStyle.js +11 -5
- package/dist/styles/visualScale.d.ts +19 -0
- package/dist/styles/visualScale.js +26 -0
- package/dist/styles.css +89 -32
- package/dist/ui/InsertImageButton.d.ts +3 -1
- package/dist/ui/InsertImageButton.js +3 -2
- package/dist/ui/TableMenu.d.ts +5 -2
- package/dist/ui/TableMenu.js +18 -1
- package/dist/ui/TextMenu.d.ts +5 -2
- package/dist/ui/TextMenu.js +21 -6
- package/dist/ui/Toolbar.d.ts +17 -2
- package/dist/ui/Toolbar.js +23 -10
- package/dist/ui/comments/useCommentRailLayout.js +2 -4
- package/dist/ui/noteItems.d.ts +21 -0
- package/dist/ui/noteItems.js +30 -0
- package/dist/ui/notes/NoteAreas.d.ts +73 -0
- package/dist/ui/notes/NoteAreas.js +131 -0
- package/dist/ui/notes/NoteList.d.ts +25 -0
- package/dist/ui/notes/NoteList.js +58 -0
- package/dist/ui/notes/StoryRow.d.ts +75 -0
- package/dist/ui/notes/StoryRow.js +122 -0
- package/dist/ui/notes/noteBands.d.ts +100 -0
- package/dist/ui/notes/noteBands.js +142 -0
- package/dist/ui/notes/noteHeights.d.ts +10 -0
- package/dist/ui/notes/noteHeights.js +24 -0
- package/dist/ui/notes/noteSeparator.d.ts +12 -0
- package/dist/ui/notes/noteSeparator.js +9 -0
- package/dist/ui/notes/useStorySurface.d.ts +68 -0
- package/dist/ui/notes/useStorySurface.js +95 -0
- package/dist/ui/runCommand.d.ts +8 -1
- package/dist/ui/runCommand.js +2 -2
- package/dist/ui/shortcutLabels.d.ts +16 -0
- package/dist/ui/shortcutLabels.js +9 -0
- package/dist/ui/usePageRoom.d.ts +13 -0
- package/dist/ui/usePageRoom.js +31 -0
- package/package.json +1 -1
- package/dist/docx/notes.d.ts +0 -27
- package/dist/docx/notes.js +0 -55
- package/dist/ui/NotesPanel.d.ts +0 -6
- package/dist/ui/NotesPanel.js +0 -33
|
@@ -137,14 +137,6 @@ var preservedGuard = {
|
|
|
137
137
|
return shut;
|
|
138
138
|
}
|
|
139
139
|
};
|
|
140
|
-
function isNoteReference(node) {
|
|
141
|
-
return node.type.name === "noteReference";
|
|
142
|
-
}
|
|
143
|
-
var noteGuard = preservedNodeGuard(
|
|
144
|
-
"note",
|
|
145
|
-
isNoteReference,
|
|
146
|
-
(node) => JSON.stringify(node.attrs)
|
|
147
|
-
);
|
|
148
140
|
function endsASection(node) {
|
|
149
141
|
if (node.type.name !== "paragraph") return false;
|
|
150
142
|
const pPr = node.attrs.pPr;
|
|
@@ -174,7 +166,6 @@ var sectionGuard = {
|
|
|
174
166
|
}
|
|
175
167
|
};
|
|
176
168
|
export {
|
|
177
|
-
noteGuard,
|
|
178
169
|
preservedGuard,
|
|
179
170
|
preservedNodeGuard,
|
|
180
171
|
sectionGuard
|
package/dist/schema/stories.d.ts
CHANGED
|
@@ -7,9 +7,23 @@
|
|
|
7
7
|
* the key, the value on the node, and the two comparisons the protection rules are written over.
|
|
8
8
|
*/
|
|
9
9
|
import type { Node as PMNode } from "prosemirror-model";
|
|
10
|
-
|
|
10
|
+
/** Which of the two notes parts a note stands in */
|
|
11
|
+
export declare const NOTE_KINDS: readonly ["footnote", "endnote"];
|
|
12
|
+
export type NoteKind = (typeof NOTE_KINDS)[number];
|
|
13
|
+
/** The two kinds of story a header or footer part holds, one story to a part */
|
|
14
|
+
export declare const HEADER_FOOTER_KINDS: readonly ["header", "footer"];
|
|
15
|
+
export type HeaderFooterKind = (typeof HEADER_FOOTER_KINDS)[number];
|
|
16
|
+
export declare const STORY_KINDS: readonly ["comment", "footnote", "endnote", "header", "footer"];
|
|
17
|
+
export type StoryKind = (typeof STORY_KINDS)[number];
|
|
11
18
|
/** `comment:4`, `footnote:2`, `header:word/header1.xml` */
|
|
12
19
|
export type StoryKey = `${StoryKind}:${string}`;
|
|
20
|
+
/**
|
|
21
|
+
* What a reader listening to the page is told a note reference is.
|
|
22
|
+
*
|
|
23
|
+
* A reference whose own mark follows it in the document draws no label of the editor's
|
|
24
|
+
* (§17.11.14), so it is named by its kind alone rather than by a number that is not there.
|
|
25
|
+
*/
|
|
26
|
+
export declare function noteName(kind: NoteKind, label: string): string;
|
|
13
27
|
/** One story as the document node holds it, which is `Node.toJSON` of a document of this schema */
|
|
14
28
|
export interface StoryJson {
|
|
15
29
|
readonly type: string;
|
|
@@ -18,7 +32,25 @@ export interface StoryJson {
|
|
|
18
32
|
}
|
|
19
33
|
/** The attr the stories stand on, named here so the schema and the readers cannot spell it apart */
|
|
20
34
|
export declare const STORIES_ATTR = "stories";
|
|
21
|
-
export declare function storyKey(kind:
|
|
35
|
+
export declare function storyKey<K extends StoryKind>(kind: K, id: string): `${K}:${string}`;
|
|
36
|
+
/** The key of a story that is a note: `footnote:2`, `endnote:3` */
|
|
37
|
+
export type NoteKey = `${NoteKind}:${string}`;
|
|
38
|
+
/**
|
|
39
|
+
* The note this key names, and null for a key naming a story of another kind.
|
|
40
|
+
*
|
|
41
|
+
* A note's id never carries a colon - a note is identified by a whole number (§17.11.2, §17.11.8)
|
|
42
|
+
* - so the kind is everything up to the first one.
|
|
43
|
+
*/
|
|
44
|
+
export declare function noteKeyOf(key: StoryKey): {
|
|
45
|
+
readonly kind: NoteKind;
|
|
46
|
+
readonly id: string;
|
|
47
|
+
} | null;
|
|
48
|
+
/**
|
|
49
|
+
* The kinds of note an edit may add, delete, copy and rewrite, which is both of them: each part is
|
|
50
|
+
* written back one entry per note (`docx/notes/writing`). The lifecycle, the clipboard and the
|
|
51
|
+
* navigation all read this one list, so a kind of note added to the format joins it once.
|
|
52
|
+
*/
|
|
53
|
+
export declare const EDITABLE_NOTE_KINDS: readonly NoteKind[];
|
|
22
54
|
/**
|
|
23
55
|
* The key this text spells, or null for one that names no kind of story.
|
|
24
56
|
*
|
package/dist/schema/stories.js
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
// src/schema/stories.ts
|
|
2
2
|
import { sameSource } from "./sourceEquality.js";
|
|
3
|
-
var
|
|
3
|
+
var NOTE_KINDS = ["footnote", "endnote"];
|
|
4
|
+
var HEADER_FOOTER_KINDS = ["header", "footer"];
|
|
4
5
|
var STORY_KINDS = [
|
|
5
6
|
"comment",
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"header",
|
|
9
|
-
"footer"
|
|
7
|
+
...NOTE_KINDS,
|
|
8
|
+
...HEADER_FOOTER_KINDS
|
|
10
9
|
];
|
|
10
|
+
function noteName(kind, label) {
|
|
11
|
+
const named = kind === "endnote" ? "Endnote" : "Footnote";
|
|
12
|
+
return label === "" ? named : `${named} ${label}`;
|
|
13
|
+
}
|
|
14
|
+
var STORIES_ATTR = "stories";
|
|
11
15
|
function storyKey(kind, id) {
|
|
12
16
|
return `${kind}:${id}`;
|
|
13
17
|
}
|
|
18
|
+
function noteKeyOf(key) {
|
|
19
|
+
const at = key.indexOf(":");
|
|
20
|
+
const named = key.slice(0, at);
|
|
21
|
+
const kind = NOTE_KINDS.find((candidate) => candidate === named);
|
|
22
|
+
return kind === void 0 ? null : { kind, id: key.slice(at + 1) };
|
|
23
|
+
}
|
|
24
|
+
var EDITABLE_NOTE_KINDS = NOTE_KINDS;
|
|
14
25
|
function asStoryKey(text) {
|
|
15
26
|
const at = text.indexOf(":");
|
|
16
27
|
if (at < 1) return null;
|
|
@@ -68,8 +79,14 @@ function withoutCommentStories(doc) {
|
|
|
68
79
|
);
|
|
69
80
|
}
|
|
70
81
|
export {
|
|
82
|
+
EDITABLE_NOTE_KINDS,
|
|
83
|
+
HEADER_FOOTER_KINDS,
|
|
84
|
+
NOTE_KINDS,
|
|
71
85
|
STORIES_ATTR,
|
|
86
|
+
STORY_KINDS,
|
|
72
87
|
asStoryKey,
|
|
88
|
+
noteKeyOf,
|
|
89
|
+
noteName,
|
|
73
90
|
sameStory,
|
|
74
91
|
storiesOf,
|
|
75
92
|
storyKey,
|
|
@@ -51,7 +51,9 @@ export declare const editorClassNames: {
|
|
|
51
51
|
readonly rawRunContent: "docx-editor-raw-run";
|
|
52
52
|
/** A preserved block, drawn by the `display` its policy gave it */
|
|
53
53
|
readonly rawBlock: "docx-editor-raw-block";
|
|
54
|
-
/** The
|
|
54
|
+
/** The room the scaled page layer takes up in the scroll box */
|
|
55
|
+
readonly pageBox: "docx-editor-page-box";
|
|
56
|
+
/** The box holding both the paper and the marks overlaid on it, scaled to the reader's zoom */
|
|
55
57
|
readonly pageLayer: "docx-editor-page-layer";
|
|
56
58
|
/** All of the page marks drawn over the paper */
|
|
57
59
|
readonly pageGuides: "docx-editor-page-guides";
|
|
@@ -148,11 +150,24 @@ export declare const editorClassNames: {
|
|
|
148
150
|
readonly commentIconActions: "docx-editor-comment-icon-actions";
|
|
149
151
|
readonly commentComposer: "docx-editor-comment-composer";
|
|
150
152
|
readonly commentInput: "docx-editor-comment-input";
|
|
151
|
-
|
|
152
|
-
readonly
|
|
153
|
-
|
|
154
|
-
readonly
|
|
155
|
-
|
|
153
|
+
/** Everything drawn over the paper in the room the pages keep for notes, which only its areas take the mouse in */
|
|
154
|
+
readonly noteAreas: "docx-editor-note-areas";
|
|
155
|
+
/** The footnotes at the foot of one page: a short rule, then each footnote */
|
|
156
|
+
readonly footnoteArea: "docx-editor-footnote-area";
|
|
157
|
+
/** The endnotes drawn after the last paragraph, one box per page they run onto */
|
|
158
|
+
readonly endnoteArea: "docx-editor-endnote-area";
|
|
159
|
+
/** The short rule that sets notes apart from the text above them */
|
|
160
|
+
readonly noteSeparator: "docx-editor-note-separator";
|
|
161
|
+
/** One note, drawn from its story */
|
|
162
|
+
readonly noteRow: "docx-editor-note-row";
|
|
163
|
+
/** Attached alongside it while the caret is in that note and an editing view stands over it */
|
|
164
|
+
readonly noteRowOpen: "docx-editor-note-row-open";
|
|
165
|
+
/** The editing view one side story is edited in (`editor/stories`) */
|
|
166
|
+
readonly storyBody: "docx-editor-story-body";
|
|
167
|
+
/** A note's own reference mark, drawn as the label its reference carries */
|
|
168
|
+
readonly noteMark: "docx-editor-note-mark";
|
|
169
|
+
/** The notes listed after the last page */
|
|
170
|
+
readonly noteList: "docx-editor-note-list";
|
|
156
171
|
/** The panel drawn in place of the editor when a document was refused and the consumer wrote no panel of its own */
|
|
157
172
|
readonly rejection: "docx-editor-rejection";
|
|
158
173
|
readonly rejectionTitle: "docx-editor-rejection-title";
|
|
@@ -46,7 +46,9 @@ var editorClassNames = {
|
|
|
46
46
|
rawRunContent: `${PREFIX}-raw-run`,
|
|
47
47
|
/** A preserved block, drawn by the `display` its policy gave it */
|
|
48
48
|
rawBlock: `${PREFIX}-raw-block`,
|
|
49
|
-
/** The
|
|
49
|
+
/** The room the scaled page layer takes up in the scroll box */
|
|
50
|
+
pageBox: `${PREFIX}-page-box`,
|
|
51
|
+
/** The box holding both the paper and the marks overlaid on it, scaled to the reader's zoom */
|
|
50
52
|
pageLayer: `${PREFIX}-page-layer`,
|
|
51
53
|
/** All of the page marks drawn over the paper */
|
|
52
54
|
pageGuides: `${PREFIX}-page-guides`,
|
|
@@ -144,11 +146,24 @@ var editorClassNames = {
|
|
|
144
146
|
commentIconActions: `${PREFIX}-comment-icon-actions`,
|
|
145
147
|
commentComposer: `${PREFIX}-comment-composer`,
|
|
146
148
|
commentInput: `${PREFIX}-comment-input`,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
/** Everything drawn over the paper in the room the pages keep for notes, which only its areas take the mouse in */
|
|
150
|
+
noteAreas: `${PREFIX}-note-areas`,
|
|
151
|
+
/** The footnotes at the foot of one page: a short rule, then each footnote */
|
|
152
|
+
footnoteArea: `${PREFIX}-footnote-area`,
|
|
153
|
+
/** The endnotes drawn after the last paragraph, one box per page they run onto */
|
|
154
|
+
endnoteArea: `${PREFIX}-endnote-area`,
|
|
155
|
+
/** The short rule that sets notes apart from the text above them */
|
|
156
|
+
noteSeparator: `${PREFIX}-note-separator`,
|
|
157
|
+
/** One note, drawn from its story */
|
|
158
|
+
noteRow: `${PREFIX}-note-row`,
|
|
159
|
+
/** Attached alongside it while the caret is in that note and an editing view stands over it */
|
|
160
|
+
noteRowOpen: `${PREFIX}-note-row-open`,
|
|
161
|
+
/** The editing view one side story is edited in (`editor/stories`) */
|
|
162
|
+
storyBody: `${PREFIX}-story-body`,
|
|
163
|
+
/** A note's own reference mark, drawn as the label its reference carries */
|
|
164
|
+
noteMark: `${PREFIX}-note-mark`,
|
|
165
|
+
/** The notes listed after the last page */
|
|
166
|
+
noteList: `${PREFIX}-note-list`,
|
|
152
167
|
/** The panel drawn in place of the editor when a document was refused and the consumer wrote no panel of its own */
|
|
153
168
|
rejection: `${PREFIX}-rejection`,
|
|
154
169
|
rejectionTitle: `${PREFIX}-rejection-title`
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type CellFormat, type DocumentDefaults, type HighlightName, type LineSpacing, type ParagraphFormat, type RowFormat, type RunFormat, type TableFormat, type TableWidth } from "../model/format";
|
|
2
|
+
import { editorCssVariables } from "./classNames";
|
|
2
3
|
import { type FontFallbacks } from "./fontStack";
|
|
3
4
|
/**
|
|
4
5
|
* The value used on screen only, when nowhere in the document declares a default
|
|
@@ -65,3 +66,9 @@ export declare function cellStyle(format: CellFormat | null): string | undefined
|
|
|
65
66
|
* not drawn in a different font in every environment.
|
|
66
67
|
*/
|
|
67
68
|
export declare function documentDefaultsStyle(defaults: DocumentDefaults, fontFallbacks?: FontFallbacks): string;
|
|
69
|
+
export type DocumentDefaultsVariables = Readonly<Record<typeof editorCssVariables.fontSize | typeof editorCssVariables.lineHeight | typeof editorCssVariables.fontFamily, string>>;
|
|
70
|
+
/**
|
|
71
|
+
* The same values as the variables they are written into, for a box drawn outside the sheet that
|
|
72
|
+
* is to set its text the way the sheet does: a note drawn at the foot of a page, or after the last
|
|
73
|
+
*/
|
|
74
|
+
export declare function documentDefaultsVariables(defaults: DocumentDefaults, fontFallbacks?: FontFallbacks): DocumentDefaultsVariables;
|
|
@@ -199,12 +199,17 @@ function cellStyle(format) {
|
|
|
199
199
|
return declarations(css);
|
|
200
200
|
}
|
|
201
201
|
function documentDefaultsStyle(defaults, fontFallbacks = DEFAULT_FONT_FALLBACKS) {
|
|
202
|
+
return Object.entries(documentDefaultsVariables(defaults, fontFallbacks)).map(([name, value]) => `${name}:${value}`).join(";");
|
|
203
|
+
}
|
|
204
|
+
function documentDefaultsVariables(defaults, fontFallbacks = DEFAULT_FONT_FALLBACKS) {
|
|
202
205
|
const fontFamily = defaults.fontFamily ? withFontFallback(defaults.fontFamily, fontFallbacks) : fontFallbacks.defaultStack;
|
|
203
|
-
return
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
return {
|
|
207
|
+
[editorCssVariables.fontSize]: pt(
|
|
208
|
+
defaults.fontSizePt ?? FALLBACK_FONT_SIZE_PT
|
|
209
|
+
),
|
|
210
|
+
[editorCssVariables.lineHeight]: lineHeightValue(defaults.lineSpacing),
|
|
211
|
+
[editorCssVariables.fontFamily]: fontFamily
|
|
212
|
+
};
|
|
208
213
|
}
|
|
209
214
|
export {
|
|
210
215
|
FALLBACK_FONT_SIZE_PT,
|
|
@@ -213,6 +218,7 @@ export {
|
|
|
213
218
|
cellStyle,
|
|
214
219
|
columnWidthPx,
|
|
215
220
|
documentDefaultsStyle,
|
|
221
|
+
documentDefaultsVariables,
|
|
216
222
|
lineHeightValue,
|
|
217
223
|
paragraphStyle,
|
|
218
224
|
rowStyle,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scale an element is drawn at, read back off the transforms standing over it.
|
|
3
|
+
*
|
|
4
|
+
* The page layer is scaled with a transform rather than the `zoom` property (`./editor.css`), so
|
|
5
|
+
* the scale has to be read out of whatever the transform resolves to: a browser hands back the used
|
|
6
|
+
* matrix, while a document implementation that does not compute one hands the function back as it
|
|
7
|
+
* was written. Everything that turns a rectangle read off the screen into a measurement on the
|
|
8
|
+
* paper divides by this number, so a transform an application puts above the editor - a dialog
|
|
9
|
+
* opening on a scale, a container fitting itself to a small screen - counts as much as the layer's
|
|
10
|
+
* own: a rectangle read inside one of those is drawn at their product.
|
|
11
|
+
*
|
|
12
|
+
* The drawn width over `offsetWidth` would answer without parsing anything, but `offsetWidth` is
|
|
13
|
+
* rounded to whole pixels, and a scale a ten-thousandth out is a measurement half a pixel out by
|
|
14
|
+
* the foot of a long document, which is the drift this scaling exists to avoid.
|
|
15
|
+
*/
|
|
16
|
+
/** The horizontal scale of an element's own transform and of every transform above it */
|
|
17
|
+
export declare function visualScaleOf(element: Element | null | undefined): number;
|
|
18
|
+
/** The scale the paper a node is drawn on is being read at */
|
|
19
|
+
export declare function pageScaleAround(node: Element): number;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/styles/visualScale.ts
|
|
2
|
+
import { editorClassNames } from "./classNames.js";
|
|
3
|
+
var HORIZONTAL_SCALE = /^(?:matrix3d|matrix|scale3d|scaleX|scale)\(\s*(-?\d*\.?\d+(?:e[+-]?\d+)?)/i;
|
|
4
|
+
function styleOf(element) {
|
|
5
|
+
const view = element.ownerDocument.defaultView;
|
|
6
|
+
return view ? view.getComputedStyle(element) : null;
|
|
7
|
+
}
|
|
8
|
+
function ownScale(element) {
|
|
9
|
+
const matched = HORIZONTAL_SCALE.exec(styleOf(element)?.transform ?? "");
|
|
10
|
+
const scale = Number.parseFloat(matched?.[1] ?? "");
|
|
11
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
12
|
+
}
|
|
13
|
+
function visualScaleOf(element) {
|
|
14
|
+
let scale = 1;
|
|
15
|
+
for (let at = element ?? null; at !== null; at = at.parentElement) {
|
|
16
|
+
scale *= ownScale(at);
|
|
17
|
+
}
|
|
18
|
+
return scale;
|
|
19
|
+
}
|
|
20
|
+
function pageScaleAround(node) {
|
|
21
|
+
return visualScaleOf(node.closest(`.${editorClassNames.pageLayer}`));
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
pageScaleAround,
|
|
25
|
+
visualScaleOf
|
|
26
|
+
};
|
package/dist/styles.css
CHANGED
|
@@ -361,48 +361,82 @@ button.docx-editor-comment-body {
|
|
|
361
361
|
cursor: help;
|
|
362
362
|
}
|
|
363
363
|
|
|
364
|
-
|
|
364
|
+
/*
|
|
365
|
+
* Notes drawn from their stories (`ui/notes`): footnotes over the paper at the foot of the page
|
|
366
|
+
* that refers to them, and notes listed after the last page. The editor hands both boxes the
|
|
367
|
+
* document's own text defaults, and the text is set as `prosemirror-view` sets an editor's, so a
|
|
368
|
+
* note wraps where it would in one.
|
|
369
|
+
*/
|
|
370
|
+
.docx-editor-note-areas {
|
|
371
|
+
position: absolute;
|
|
372
|
+
pointer-events: none;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.docx-editor-footnote-area {
|
|
376
|
+
position: absolute;
|
|
377
|
+
overflow: hidden;
|
|
378
|
+
pointer-events: auto;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* The endnotes after the last paragraph, drawn over the room the layout kept for them */
|
|
382
|
+
.docx-editor-endnote-area {
|
|
383
|
+
position: absolute;
|
|
384
|
+
overflow: hidden;
|
|
385
|
+
pointer-events: auto;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.docx-editor-footnote-area,
|
|
389
|
+
.docx-editor-endnote-area,
|
|
390
|
+
.docx-editor-note-list {
|
|
365
391
|
box-sizing: border-box;
|
|
392
|
+
color: #000000;
|
|
393
|
+
font-family: var(--docx-editor-font-family, sans-serif);
|
|
394
|
+
font-size: var(--docx-editor-font-size, 10pt);
|
|
395
|
+
line-height: var(--docx-editor-line-height, 1.3);
|
|
396
|
+
white-space: break-spaces;
|
|
397
|
+
word-wrap: break-word;
|
|
398
|
+
font-variant-ligatures: none;
|
|
399
|
+
font-feature-settings: "liga" 0;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.docx-editor-note-list {
|
|
366
403
|
margin: 16px auto 24px;
|
|
367
|
-
padding:
|
|
368
|
-
border-top: 1px solid rgb(0 0 0 / 18%);
|
|
404
|
+
padding-block: 24px;
|
|
369
405
|
background: #ffffff;
|
|
370
406
|
box-shadow: 0 1px 6px rgb(0 0 0 / 18%);
|
|
371
|
-
color: #242424;
|
|
372
407
|
}
|
|
373
408
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
409
|
+
/* A one-pixel rule across the middle of the height the layout keeps for it */
|
|
410
|
+
.docx-editor-note-separator {
|
|
411
|
+
background:
|
|
412
|
+
linear-gradient(#000000, #000000) left center / 100% 1px no-repeat;
|
|
377
413
|
}
|
|
378
414
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
gap: 8px;
|
|
383
|
-
padding: 0;
|
|
384
|
-
margin: 0;
|
|
385
|
-
list-style: none;
|
|
415
|
+
/* Holds the margins of the paragraphs inside it, so a row measures as tall as it stands */
|
|
416
|
+
.docx-editor-note-row {
|
|
417
|
+
display: flow-root;
|
|
386
418
|
}
|
|
387
419
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
420
|
+
/*
|
|
421
|
+
* The note the caret is in.
|
|
422
|
+
*
|
|
423
|
+
* Neither the tint nor the ring around it takes any room, so the row measures the same height
|
|
424
|
+
* whether it is markup or the editing view, and the page keeps the room it already kept.
|
|
425
|
+
*/
|
|
426
|
+
.docx-editor-note-row-open {
|
|
427
|
+
border-radius: 2px;
|
|
428
|
+
background: rgb(49 93 168 / 7%);
|
|
429
|
+
box-shadow: 0 0 0 3px rgb(49 93 168 / 7%);
|
|
393
430
|
}
|
|
394
431
|
|
|
395
|
-
.
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
font-weight: 600;
|
|
399
|
-
white-space: nowrap;
|
|
432
|
+
/* The view one story is edited in. It sets its text from the box it is drawn in */
|
|
433
|
+
.docx-editor-story-body {
|
|
434
|
+
outline: none;
|
|
400
435
|
}
|
|
401
436
|
|
|
402
|
-
.docx-editor-note-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
overflow-wrap: anywhere;
|
|
437
|
+
.docx-editor-note-mark {
|
|
438
|
+
font-size: 0.72em;
|
|
439
|
+
line-height: 0;
|
|
406
440
|
}
|
|
407
441
|
|
|
408
442
|
/* The fallback for browsers that do not know the two properties above (Safari) */
|
|
@@ -437,20 +471,43 @@ button.docx-editor-comment-body {
|
|
|
437
471
|
background: transparent;
|
|
438
472
|
}
|
|
439
473
|
|
|
474
|
+
/*
|
|
475
|
+
* The reader's zoom scales the page layer with a transform and not with the `zoom`
|
|
476
|
+
* property, so the paper is laid out at its own size whatever it is being read at and only
|
|
477
|
+
* the painting is scaled. Under `zoom` Chromium lays every box out on whole device pixels
|
|
478
|
+
* of the scaled rendering, so a table row came out a fraction taller at one zoom than at
|
|
479
|
+
* another and a document sitting near a page boundary broke into a different number of
|
|
480
|
+
* pages for each reader.
|
|
481
|
+
*
|
|
482
|
+
* A transform leaves the layout box at its unscaled size, and a scroll box takes in both
|
|
483
|
+
* that box and the transformed one, so a shrunk layer left in the flow would keep the
|
|
484
|
+
* scroll area of a full-size one. The layer is therefore taken out of the flow, and this
|
|
485
|
+
* box stands in the flow in its place, holding the height the layer is drawn at
|
|
486
|
+
* (`ui/usePageRoom`).
|
|
487
|
+
*/
|
|
488
|
+
.docx-editor-page-box {
|
|
489
|
+
position: relative;
|
|
490
|
+
width: 100%;
|
|
491
|
+
}
|
|
492
|
+
|
|
440
493
|
/*
|
|
441
494
|
* The paper and the boundary guides overlaid on it share one positioning origin.
|
|
442
495
|
*
|
|
443
496
|
* The side padding lives here rather than on the scroll box, because Chromium does not
|
|
444
497
|
* draw a scroll box's own padding past the right edge of sideways-scrolled content.
|
|
445
498
|
* Shrink-wrapping puts the padding beyond the paper even then, and min-width keeps the
|
|
446
|
-
* layer filling the box on wide screens so the paper stays centered
|
|
499
|
+
* layer filling the box on wide screens so the paper stays centered - widened by the
|
|
500
|
+
* reciprocal of the scale, since it is the scaled layer that has to fill the box.
|
|
447
501
|
*/
|
|
448
502
|
.docx-editor-page-layer {
|
|
449
|
-
position:
|
|
450
|
-
|
|
451
|
-
|
|
503
|
+
position: absolute;
|
|
504
|
+
inset: 0 auto auto 0;
|
|
505
|
+
width: max-content;
|
|
506
|
+
min-width: calc(100% / var(--docx-editor-zoom, 1));
|
|
452
507
|
box-sizing: border-box;
|
|
453
508
|
padding: 0 16px;
|
|
509
|
+
transform: scale(var(--docx-editor-zoom, 1));
|
|
510
|
+
transform-origin: 0 0;
|
|
454
511
|
}
|
|
455
512
|
|
|
456
513
|
@media (max-width: 840px) {
|
|
@@ -5,5 +5,7 @@ import { type ReactElement } from "react";
|
|
|
5
5
|
export interface InsertImageButtonProps {
|
|
6
6
|
view: EditorView;
|
|
7
7
|
state: EditorState;
|
|
8
|
+
/** Turned off whatever the state says, which is what a surface taking no image sets */
|
|
9
|
+
disabled?: boolean;
|
|
8
10
|
}
|
|
9
|
-
export declare function InsertImageButton({ view, state, }: InsertImageButtonProps): ReactElement;
|
|
11
|
+
export declare function InsertImageButton({ view, state, disabled, }: InsertImageButtonProps): ReactElement;
|
|
@@ -11,7 +11,8 @@ import { ToolbarButton } from "./ToolbarButton.js";
|
|
|
11
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
function InsertImageButton({
|
|
13
13
|
view,
|
|
14
|
-
state
|
|
14
|
+
state,
|
|
15
|
+
disabled = false
|
|
15
16
|
}) {
|
|
16
17
|
const pickerRef = useRef(null);
|
|
17
18
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -20,7 +21,7 @@ function InsertImageButton({
|
|
|
20
21
|
{
|
|
21
22
|
label: "Insert image",
|
|
22
23
|
icon: Image,
|
|
23
|
-
disabled: !view.editable || !canInsertImage(state),
|
|
24
|
+
disabled: disabled || !view.editable || !canInsertImage(state),
|
|
24
25
|
onRun: () => pickerRef.current?.click()
|
|
25
26
|
}
|
|
26
27
|
),
|
package/dist/ui/TableMenu.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
/** Table context menu with an optional Unlock action for whole-cell locks. */
|
|
1
|
+
/** Table context menu with footnote insertion and an optional Unlock action for whole-cell locks. */
|
|
2
2
|
import type { EditorState } from "prosemirror-state";
|
|
3
3
|
import type { EditorView } from "prosemirror-view";
|
|
4
4
|
import { type ReactElement } from "react";
|
|
5
5
|
import { type TableMenuAnchor } from "../editor/plugins/tableContextMenu";
|
|
6
|
+
import type { SurfaceCapabilities } from "../editor/stories/storyView";
|
|
6
7
|
export interface TableMenuProps {
|
|
7
8
|
view: EditorView;
|
|
8
9
|
state: EditorState;
|
|
9
10
|
anchor: TableMenuAnchor;
|
|
11
|
+
/** What the surface holding the caret takes, which the entries that put something in ask */
|
|
12
|
+
takes: SurfaceCapabilities;
|
|
10
13
|
allowLocking?: boolean;
|
|
11
14
|
}
|
|
12
|
-
export declare function TableMenu({ view, state, anchor, allowLocking, }: TableMenuProps): ReactElement;
|
|
15
|
+
export declare function TableMenu({ view, state, anchor, takes, allowLocking, }: TableMenuProps): ReactElement;
|
package/dist/ui/TableMenu.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
mergeCells,
|
|
17
17
|
splitCell
|
|
18
18
|
} from "../table/index.js";
|
|
19
|
+
import { noteItems } from "./noteItems.js";
|
|
19
20
|
import { usePanelAtPoint } from "./panelPlacement.js";
|
|
20
21
|
import { commandRunner } from "./runCommand.js";
|
|
21
22
|
import { useDismiss } from "./useDismiss.js";
|
|
@@ -54,10 +55,21 @@ var UNLOCK_GROUP = {
|
|
|
54
55
|
name: "lock",
|
|
55
56
|
items: [{ label: "Unlock", command: unlockSelection }]
|
|
56
57
|
};
|
|
58
|
+
function noteGroup(takes) {
|
|
59
|
+
const notes = noteItems(takes);
|
|
60
|
+
return notes.length === 0 ? null : {
|
|
61
|
+
name: "note",
|
|
62
|
+
items: notes.map((note) => ({
|
|
63
|
+
label: note.label,
|
|
64
|
+
command: note.command
|
|
65
|
+
}))
|
|
66
|
+
};
|
|
67
|
+
}
|
|
57
68
|
function TableMenu({
|
|
58
69
|
view,
|
|
59
70
|
state,
|
|
60
71
|
anchor,
|
|
72
|
+
takes,
|
|
61
73
|
allowLocking = false
|
|
62
74
|
}) {
|
|
63
75
|
const box = useRef(null);
|
|
@@ -74,7 +86,12 @@ function TableMenu({
|
|
|
74
86
|
run(command);
|
|
75
87
|
close();
|
|
76
88
|
};
|
|
77
|
-
const
|
|
89
|
+
const note = noteGroup(takes);
|
|
90
|
+
const groups = [
|
|
91
|
+
...MENU_GROUPS,
|
|
92
|
+
...note === null ? [] : [note],
|
|
93
|
+
...allowLocking ? [UNLOCK_GROUP] : []
|
|
94
|
+
];
|
|
78
95
|
return /* @__PURE__ */ jsx(
|
|
79
96
|
"div",
|
|
80
97
|
{
|
package/dist/ui/TextMenu.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
/** Custom text context menu with clipboard, comment, and optional locking actions. */
|
|
1
|
+
/** Custom text context menu with clipboard, comment, footnote, and optional locking actions. */
|
|
2
2
|
import type { EditorState } from "prosemirror-state";
|
|
3
3
|
import type { EditorView } from "prosemirror-view";
|
|
4
4
|
import { type ReactElement } from "react";
|
|
5
5
|
import { type TextMenuAnchor } from "../editor/plugins/textContextMenu";
|
|
6
|
+
import type { SurfaceCapabilities } from "../editor/stories/storyView";
|
|
6
7
|
export interface TextMenuProps {
|
|
7
8
|
view: EditorView;
|
|
8
9
|
state: EditorState;
|
|
9
10
|
anchor: TextMenuAnchor;
|
|
11
|
+
/** What the surface holding the caret takes, which the entries that put something in ask */
|
|
12
|
+
takes: SurfaceCapabilities;
|
|
10
13
|
/** Whether the entries that lock and unlock a stretch of text are offered */
|
|
11
14
|
allowLocking?: boolean;
|
|
12
15
|
}
|
|
13
|
-
export declare function TextMenu({ view, state, anchor, allowLocking, }: TextMenuProps): ReactElement;
|
|
16
|
+
export declare function TextMenu({ view, state, anchor, takes, allowLocking, }: TextMenuProps): ReactElement;
|
package/dist/ui/TextMenu.js
CHANGED
|
@@ -23,13 +23,14 @@ import {
|
|
|
23
23
|
} from "../editor/plugins/textContextMenu.js";
|
|
24
24
|
import { editsShut } from "../schema/protectionState.js";
|
|
25
25
|
import { editorClassNames } from "../styles/classNames.js";
|
|
26
|
+
import { noteItems } from "./noteItems.js";
|
|
26
27
|
import { usePanelAtPoint } from "./panelPlacement.js";
|
|
27
28
|
import { commandRunner } from "./runCommand.js";
|
|
29
|
+
import { modifierLabels } from "./shortcutLabels.js";
|
|
28
30
|
import { ICON_SIZE } from "./ToolbarButton.js";
|
|
29
31
|
import { useDismiss } from "./useDismiss.js";
|
|
30
32
|
import { useMenuKeyboard } from "./useMenuKeyboard.js";
|
|
31
33
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
32
|
-
var MOD = typeof navigator !== "undefined" && navigator.platform.includes("Mac") ? "\u2318" : "Ctrl+";
|
|
33
34
|
function clipboardCommand(view, command) {
|
|
34
35
|
view.focus();
|
|
35
36
|
document.execCommand(command);
|
|
@@ -95,6 +96,7 @@ function TextMenu({
|
|
|
95
96
|
view,
|
|
96
97
|
state,
|
|
97
98
|
anchor,
|
|
99
|
+
takes,
|
|
98
100
|
allowLocking = false
|
|
99
101
|
}) {
|
|
100
102
|
const box = useRef(null);
|
|
@@ -108,11 +110,12 @@ function TextMenu({
|
|
|
108
110
|
const keys = useMenuKeyboard({ menu: box, onClose: close });
|
|
109
111
|
const selected = !state.selection.empty;
|
|
110
112
|
const shut = selectionTouchesLocked(state);
|
|
113
|
+
const { mod } = modifierLabels();
|
|
111
114
|
const bodyOpen = !editsShut(state);
|
|
112
115
|
const copy = {
|
|
113
116
|
label: "Copy",
|
|
114
117
|
icon: Copy,
|
|
115
|
-
hint: `${
|
|
118
|
+
hint: `${mod}C`,
|
|
116
119
|
enabled: selected,
|
|
117
120
|
run: () => clipboardCommand(view, "copy")
|
|
118
121
|
};
|
|
@@ -121,7 +124,7 @@ function TextMenu({
|
|
|
121
124
|
{
|
|
122
125
|
label: "Cut",
|
|
123
126
|
icon: Scissors,
|
|
124
|
-
hint: `${
|
|
127
|
+
hint: `${mod}X`,
|
|
125
128
|
enabled: selected && !shut,
|
|
126
129
|
run: () => clipboardCommand(view, "cut")
|
|
127
130
|
},
|
|
@@ -129,7 +132,7 @@ function TextMenu({
|
|
|
129
132
|
{
|
|
130
133
|
label: "Paste",
|
|
131
134
|
icon: ClipboardPaste,
|
|
132
|
-
hint: `${
|
|
135
|
+
hint: `${mod}V`,
|
|
133
136
|
enabled: !shut,
|
|
134
137
|
run: () => {
|
|
135
138
|
void pasteFromClipboard(view);
|
|
@@ -143,14 +146,26 @@ function TextMenu({
|
|
|
143
146
|
}
|
|
144
147
|
] : [copy]
|
|
145
148
|
];
|
|
146
|
-
|
|
149
|
+
const anchored = [
|
|
147
150
|
{
|
|
148
151
|
label: "Add comment",
|
|
149
152
|
icon: MessageSquarePlus,
|
|
150
153
|
enabled: canAddComment(state),
|
|
151
154
|
run: () => run(openCommentComposer)
|
|
152
155
|
}
|
|
153
|
-
]
|
|
156
|
+
];
|
|
157
|
+
if (bodyOpen) {
|
|
158
|
+
for (const note of noteItems(takes)) {
|
|
159
|
+
anchored.push({
|
|
160
|
+
label: note.label,
|
|
161
|
+
icon: note.icon,
|
|
162
|
+
hint: note.hint,
|
|
163
|
+
enabled: note.command(state),
|
|
164
|
+
run: () => run(note.command)
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
groups.push(anchored);
|
|
154
169
|
if (allowLocking && bodyOpen) {
|
|
155
170
|
groups.push([lockItem(selectionLock(state), run)]);
|
|
156
171
|
}
|