@portone/docx-editor 0.6.0 → 0.6.2

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.
Files changed (146) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/DocxEditor.js +84 -26
  3. package/dist/core.d.ts +4 -3
  4. package/dist/docx/exportDocx.d.ts +3 -2
  5. package/dist/docx/exportDocx.js +6 -10
  6. package/dist/docx/headersFooters.js +35 -23
  7. package/dist/docx/identities.d.ts +30 -0
  8. package/dist/docx/identities.js +43 -10
  9. package/dist/docx/importDocx.js +25 -26
  10. package/dist/docx/importParagraph.d.ts +1 -4
  11. package/dist/docx/importParagraph.js +4 -18
  12. package/dist/docx/invariants.d.ts +13 -10
  13. package/dist/docx/invariants.js +300 -116
  14. package/dist/docx/newLists.js +12 -3
  15. package/dist/docx/notes/newNote.d.ts +39 -0
  16. package/dist/docx/notes/newNote.js +122 -0
  17. package/dist/docx/notes/numbering.d.ts +27 -0
  18. package/dist/docx/notes/numbering.js +113 -0
  19. package/dist/docx/notes/reading.d.ts +58 -0
  20. package/dist/docx/notes/reading.js +98 -0
  21. package/dist/docx/notes/references.d.ts +33 -0
  22. package/dist/docx/notes/references.js +37 -0
  23. package/dist/docx/notes/writing.d.ts +19 -0
  24. package/dist/docx/notes/writing.js +95 -0
  25. package/dist/docx/partPlan.d.ts +3 -0
  26. package/dist/docx/partPlanners.d.ts +13 -0
  27. package/dist/docx/partPlanners.js +48 -0
  28. package/dist/docx/sections.d.ts +5 -0
  29. package/dist/docx/sections.js +7 -2
  30. package/dist/docx/serializeParagraph.js +7 -2
  31. package/dist/docx/serializePreserved.d.ts +5 -1
  32. package/dist/docx/serializePreserved.js +24 -7
  33. package/dist/docx/session.d.ts +5 -0
  34. package/dist/docx/session.js +6 -0
  35. package/dist/docx/storyParts.d.ts +133 -0
  36. package/dist/docx/storyParts.js +314 -0
  37. package/dist/editor/clipboard/htmlReader.d.ts +24 -4
  38. package/dist/editor/clipboard/htmlReader.js +39 -4
  39. package/dist/editor/clipboard/internalChannel.d.ts +30 -3
  40. package/dist/editor/clipboard/internalChannel.js +43 -3
  41. package/dist/editor/clipboard/normalizers.d.ts +35 -8
  42. package/dist/editor/clipboard/normalizers.js +60 -11
  43. package/dist/editor/clipboard/plugin.js +42 -22
  44. package/dist/editor/commands/exportQueries.d.ts +4 -3
  45. package/dist/editor/commands/index.d.ts +2 -1
  46. package/dist/editor/commands/index.js +18 -0
  47. package/dist/editor/commands/noteCommands.d.ts +47 -0
  48. package/dist/editor/commands/noteCommands.js +95 -0
  49. package/dist/editor/commands/noteQueries.d.ts +22 -3
  50. package/dist/editor/commands/noteQueries.js +21 -13
  51. package/dist/editor/createEditor.js +21 -3
  52. package/dist/editor/documentStyles.d.ts +3 -0
  53. package/dist/editor/documentStyles.js +2 -1
  54. package/dist/editor/editorDocument.d.ts +24 -0
  55. package/dist/editor/editorDocument.js +34 -4
  56. package/dist/editor/notes/noteSurface.d.ts +53 -0
  57. package/dist/editor/notes/noteSurface.js +246 -0
  58. package/dist/editor/plugins/compositionSelection.d.ts +20 -0
  59. package/dist/editor/plugins/compositionSelection.js +19 -0
  60. package/dist/editor/plugins/keymap.d.ts +14 -0
  61. package/dist/editor/plugins/keymap.js +13 -1
  62. package/dist/editor/plugins/noteLifecycle.d.ts +18 -0
  63. package/dist/editor/plugins/noteLifecycle.js +117 -0
  64. package/dist/editor/plugins/noteNavigation.d.ts +45 -0
  65. package/dist/editor/plugins/noteNavigation.js +86 -0
  66. package/dist/editor/plugins/noteNumbering.d.ts +13 -0
  67. package/dist/editor/plugins/noteNumbering.js +58 -0
  68. package/dist/editor/plugins/rowResize.js +2 -7
  69. package/dist/editor/plugins/tabLayout.js +2 -7
  70. package/dist/editor/stories/storyMarkup.d.ts +24 -0
  71. package/dist/editor/stories/storyMarkup.js +35 -0
  72. package/dist/editor/stories/storyState.d.ts +34 -0
  73. package/dist/editor/stories/storyState.js +74 -0
  74. package/dist/editor/stories/storyView.d.ts +115 -0
  75. package/dist/editor/stories/storyView.js +144 -0
  76. package/dist/index.d.ts +2 -2
  77. package/dist/numbering/spellers.d.ts +1 -1
  78. package/dist/numbering/spellers.js +6 -1
  79. package/dist/ooxml/errors.d.ts +135 -2
  80. package/dist/ooxml/errors.js +6 -0
  81. package/dist/page/blockKinds.d.ts +23 -4
  82. package/dist/page/demands/footnoteDemands.d.ts +18 -0
  83. package/dist/page/demands/footnoteDemands.js +51 -0
  84. package/dist/page/demands/index.d.ts +43 -0
  85. package/dist/page/demands/index.js +8 -0
  86. package/dist/page/kinds/paragraphKind.js +7 -1
  87. package/dist/page/kinds/tableKind.js +9 -1
  88. package/dist/page/measureBlocks.d.ts +2 -0
  89. package/dist/page/measureBlocks.js +31 -10
  90. package/dist/page/pageDecorations.d.ts +9 -2
  91. package/dist/page/pageDecorations.js +18 -5
  92. package/dist/page/pageLayout.d.ts +77 -1
  93. package/dist/page/pageLayout.js +186 -9
  94. package/dist/page/usePageLayout.d.ts +57 -2
  95. package/dist/page/usePageLayout.js +50 -5
  96. package/dist/schema/attrRoles.js +3 -2
  97. package/dist/schema/docxSchema.js +5 -2
  98. package/dist/schema/editGuard.d.ts +1 -1
  99. package/dist/schema/guards.js +1 -2
  100. package/dist/schema/preservedGuards.d.ts +4 -6
  101. package/dist/schema/preservedGuards.js +0 -9
  102. package/dist/schema/stories.d.ts +42 -2
  103. package/dist/schema/stories.js +28 -5
  104. package/dist/styles/classNames.d.ts +21 -6
  105. package/dist/styles/classNames.js +21 -6
  106. package/dist/styles/inlineStyle.d.ts +7 -0
  107. package/dist/styles/inlineStyle.js +11 -5
  108. package/dist/styles/visualScale.d.ts +19 -0
  109. package/dist/styles/visualScale.js +26 -0
  110. package/dist/styles.css +89 -32
  111. package/dist/ui/InsertImageButton.d.ts +3 -1
  112. package/dist/ui/InsertImageButton.js +3 -2
  113. package/dist/ui/TableMenu.d.ts +5 -2
  114. package/dist/ui/TableMenu.js +18 -1
  115. package/dist/ui/TextMenu.d.ts +5 -2
  116. package/dist/ui/TextMenu.js +21 -6
  117. package/dist/ui/Toolbar.d.ts +17 -2
  118. package/dist/ui/Toolbar.js +23 -10
  119. package/dist/ui/comments/useCommentRailLayout.js +2 -4
  120. package/dist/ui/noteItems.d.ts +21 -0
  121. package/dist/ui/noteItems.js +30 -0
  122. package/dist/ui/notes/NoteAreas.d.ts +73 -0
  123. package/dist/ui/notes/NoteAreas.js +131 -0
  124. package/dist/ui/notes/NoteList.d.ts +25 -0
  125. package/dist/ui/notes/NoteList.js +58 -0
  126. package/dist/ui/notes/StoryRow.d.ts +75 -0
  127. package/dist/ui/notes/StoryRow.js +122 -0
  128. package/dist/ui/notes/noteBands.d.ts +100 -0
  129. package/dist/ui/notes/noteBands.js +142 -0
  130. package/dist/ui/notes/noteHeights.d.ts +10 -0
  131. package/dist/ui/notes/noteHeights.js +24 -0
  132. package/dist/ui/notes/noteSeparator.d.ts +12 -0
  133. package/dist/ui/notes/noteSeparator.js +9 -0
  134. package/dist/ui/notes/useStorySurface.d.ts +68 -0
  135. package/dist/ui/notes/useStorySurface.js +95 -0
  136. package/dist/ui/runCommand.d.ts +8 -1
  137. package/dist/ui/runCommand.js +2 -2
  138. package/dist/ui/shortcutLabels.d.ts +16 -0
  139. package/dist/ui/shortcutLabels.js +9 -0
  140. package/dist/ui/usePageRoom.d.ts +13 -0
  141. package/dist/ui/usePageRoom.js +31 -0
  142. package/package.json +1 -1
  143. package/dist/docx/notes.d.ts +0 -27
  144. package/dist/docx/notes.js +0 -55
  145. package/dist/ui/NotesPanel.d.ts +0 -6
  146. package/dist/ui/NotesPanel.js +0 -33
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Puts a note into the document and writes what one says, exported once per kind the way
3
+ * `toggleBold` and `toggleItalic` are rather than as one command taking a kind. Deleting and
4
+ * copying a reference need no command: the edit that does either settles the note it calls
5
+ * (`editor/plugins/noteLifecycle`).
6
+ */
7
+ import type { Node as PMNode } from "prosemirror-model";
8
+ import type { Command, EditorState } from "prosemirror-state";
9
+ import type { NoteKind } from "../../schema/stories";
10
+ /** Writes what one note of this kind says; an editing view's edit reaches the document this way */
11
+ export declare function noteBodyCommand(kind: NoteKind, id: string, body: PMNode): Command;
12
+ /**
13
+ * Puts a footnote reference at the end of the selection, calling a new, empty footnote, and asks
14
+ * for that footnote to be opened. The footnote is written in the document's footnote styles where
15
+ * it defines them, and in superscript where it does not.
16
+ */
17
+ export declare const insertFootnote: Command;
18
+ /** Whether a footnote can go in at the end of the selection */
19
+ export declare function canInsertFootnote(state: EditorState): boolean;
20
+ /**
21
+ * Replaces what one footnote says with a `doc` node of `docxSchema`. It applies where an edit at
22
+ * the footnote's first reference would, and never to a separator, a footnote the text does not
23
+ * refer to, or a body saying what the footnote already says.
24
+ */
25
+ export declare function setFootnoteBody(id: string, body: PMNode): Command;
26
+ /**
27
+ * Puts the caret just after a footnote's reference and opens the footnote for editing, which is
28
+ * what a press on its number runs. It applies under every mode, since opening a note is reading
29
+ * it; a footnote opened where the body is shut takes no typing.
30
+ */
31
+ export declare function openFootnote(id: string): Command;
32
+ /**
33
+ * Puts an endnote reference at the end of the selection, calling a new, empty endnote, and asks
34
+ * for that endnote to be opened; `insertFootnote` for an endnote, which is drawn after the last
35
+ * paragraph of the document rather than at the foot of a page.
36
+ */
37
+ export declare const insertEndnote: Command;
38
+ /** Whether an endnote can go in at the end of the selection */
39
+ export declare function canInsertEndnote(state: EditorState): boolean;
40
+ /** Replaces what one endnote says with a `doc` node of `docxSchema`, as `setFootnoteBody` does */
41
+ export declare function setEndnoteBody(id: string, body: PMNode): Command;
42
+ /**
43
+ * Puts the caret just after an endnote's reference and opens the endnote for editing;
44
+ * `openFootnote` for an endnote, which stands at the end of the document, so this is also what
45
+ * takes a reader to it.
46
+ */
47
+ export declare function openEndnote(id: string): Command;
@@ -0,0 +1,95 @@
1
+ // src/editor/commands/noteCommands.ts
2
+ import {
3
+ newNoteStory,
4
+ nextNoteId,
5
+ noteNumberRunProps,
6
+ takenNoteIds
7
+ } from "../../docx/notes/newNote.js";
8
+ import { sameStory, setStory, storyKey, storyOf } from "../../docx/story.js";
9
+ import { docxSchema } from "../../schema/index.js";
10
+ import { guardedCommand } from "../../schema/guards.js";
11
+ import { isWrapperType } from "../../schema/wrappers.js";
12
+ import { documentOf } from "../editorDocument.js";
13
+ import {
14
+ noteReferenceAt,
15
+ openNoteCommand,
16
+ requestNote
17
+ } from "../plugins/noteNavigation.js";
18
+ function wrappersBefore(doc, pos) {
19
+ const $pos = doc.resolve(pos);
20
+ return ($pos.nodeBefore?.marks ?? $pos.marks()).filter(
21
+ (mark) => isWrapperType(mark.type)
22
+ );
23
+ }
24
+ function insertNoteTransaction(state, kind) {
25
+ const at = state.selection.to;
26
+ const $at = state.doc.resolve(at);
27
+ const type = docxSchema.nodes.noteReference;
28
+ if (!$at.parent.canReplaceWith($at.index(), $at.index(), type)) return null;
29
+ const { formatting, reservedNoteKeys } = documentOf(state);
30
+ const id = nextNoteId(takenNoteIds(state.doc, kind, reservedNoteKeys));
31
+ const reference = type.create({ kind, id }, null, [
32
+ docxSchema.marks.run.create({ rPr: noteNumberRunProps(kind, formatting) }),
33
+ ...wrappersBefore(state.doc, at)
34
+ ]);
35
+ const key = storyKey(kind, id);
36
+ return requestNote(
37
+ setStory(
38
+ state.tr.insert(at, reference),
39
+ key,
40
+ newNoteStory(kind, formatting)
41
+ ),
42
+ key
43
+ );
44
+ }
45
+ function insertNoteCommand(kind) {
46
+ return guardedCommand((state) => insertNoteTransaction(state, kind));
47
+ }
48
+ function noteBodyTransaction(state, kind, id, body) {
49
+ const key = storyKey(kind, id);
50
+ if (body.type !== docxSchema.nodes.doc) return null;
51
+ if (documentOf(state).specialNotes.has(key)) return null;
52
+ const found = noteReferenceAt(state.doc, kind, id);
53
+ if (found === null) return null;
54
+ if (sameStory(storyOf(state.doc, key), body)) return null;
55
+ return setStory(state.tr, key, body).setNodeMarkup(
56
+ found.pos,
57
+ null,
58
+ found.node.attrs,
59
+ found.node.marks
60
+ );
61
+ }
62
+ function noteBodyCommand(kind, id, body) {
63
+ return guardedCommand((state) => noteBodyTransaction(state, kind, id, body));
64
+ }
65
+ var insertFootnote = insertNoteCommand("footnote");
66
+ function canInsertFootnote(state) {
67
+ return insertFootnote(state);
68
+ }
69
+ function setFootnoteBody(id, body) {
70
+ return noteBodyCommand("footnote", id, body);
71
+ }
72
+ function openFootnote(id) {
73
+ return openNoteCommand("footnote", id);
74
+ }
75
+ var insertEndnote = insertNoteCommand("endnote");
76
+ function canInsertEndnote(state) {
77
+ return insertEndnote(state);
78
+ }
79
+ function setEndnoteBody(id, body) {
80
+ return noteBodyCommand("endnote", id, body);
81
+ }
82
+ function openEndnote(id) {
83
+ return openNoteCommand("endnote", id);
84
+ }
85
+ export {
86
+ canInsertEndnote,
87
+ canInsertFootnote,
88
+ insertEndnote,
89
+ insertFootnote,
90
+ noteBodyCommand,
91
+ openEndnote,
92
+ openFootnote,
93
+ setEndnoteBody,
94
+ setFootnoteBody
95
+ };
@@ -1,7 +1,9 @@
1
1
  /** Document-level readers for imported footnotes and endnotes. */
2
+ import type { Node as PMNode } from "prosemirror-model";
2
3
  import type { EditorState } from "prosemirror-state";
3
4
  import { DecorationSet } from "prosemirror-view";
4
- import type { NoteKind } from "../../docx/notes";
5
+ import { type StoryKey } from "../../docx/story";
6
+ import type { NoteKind } from "../../schema/stories";
5
7
  export interface DocumentNote {
6
8
  readonly kind: NoteKind;
7
9
  readonly id: string;
@@ -9,6 +11,17 @@ export interface DocumentNote {
9
11
  readonly text: string;
10
12
  readonly referencePos: number;
11
13
  }
14
+ /** One note the body refers to, as the notes drawn around the page draw it */
15
+ export interface NoteRow {
16
+ readonly key: StoryKey;
17
+ readonly kind: NoteKind;
18
+ readonly id: string;
19
+ readonly label: string;
20
+ /** The note's story, the same node for as long as it says the same thing (`schema/stories`) */
21
+ readonly story: PMNode;
22
+ /** Where the first reference to it stands, which is the place in the text it is called from */
23
+ readonly referencePos: number;
24
+ }
12
25
  interface NoteProjection {
13
26
  notes: readonly DocumentNote[];
14
27
  /**
@@ -17,11 +30,17 @@ interface NoteProjection {
17
30
  * says is a story on the document and not an attr of the reference.
18
31
  */
19
32
  tooltips: DecorationSet;
33
+ /** The footnotes whose story the document holds, by story key, in first-reference order */
34
+ footnotes: ReadonlyMap<StoryKey, NoteRow>;
35
+ /** The endnotes whose story the document holds, in first-reference order */
36
+ endnotes: readonly NoteRow[];
37
+ /** Every note of both kinds by story key, which the surface over the open note reads rows from */
38
+ rows: ReadonlyMap<StoryKey, NoteRow>;
20
39
  }
21
40
  /**
22
41
  * Which notes the document refers to is the document's to decide, so the list is worked out once
23
- * per edit (`editor/plugins/documentProjection`) rather than once per render of the panel under
24
- * the page.
42
+ * per edit (`editor/plugins/documentProjection`) rather than once per render of the notes drawn
43
+ * around the page.
25
44
  */
26
45
  export declare const noteProjection: import("../plugins/documentProjection").DocumentProjection<NoteProjection>;
27
46
  /** The distinct notes referenced by the main document story, in first-reference order. */
@@ -8,35 +8,43 @@ function stringAttr(value) {
8
8
  function noteKindOf(node) {
9
9
  return node.attrs.kind === "endnote" ? "endnote" : "footnote";
10
10
  }
11
- function noteText(doc, kind, id) {
12
- return storyText(storyOf(doc, storyKey(kind, id)));
13
- }
14
11
  function deriveNotes(doc) {
15
12
  const notes = [];
16
13
  const tooltips = [];
14
+ const footnotes = /* @__PURE__ */ new Map();
15
+ const endnotes = [];
16
+ const rows = /* @__PURE__ */ new Map();
17
17
  const seen = /* @__PURE__ */ new Set();
18
18
  doc.descendants((node, pos) => {
19
19
  if (node.type.name !== "noteReference") return true;
20
20
  const id = stringAttr(node.attrs.id);
21
21
  if (id === null) return true;
22
22
  const kind = noteKindOf(node);
23
- const text = noteText(doc, kind, id);
23
+ const key = storyKey(kind, id);
24
+ const story = storyOf(doc, key);
25
+ const text = storyText(story);
24
26
  if (text !== "") {
25
27
  tooltips.push(Decoration.node(pos, pos + node.nodeSize, { title: text }));
26
28
  }
27
- const key = `${kind}:${id}`;
28
29
  if (seen.has(key)) return true;
29
30
  seen.add(key);
30
- notes.push({
31
- kind,
32
- id,
33
- label: stringAttr(node.attrs.label) ?? "?",
34
- text,
35
- referencePos: pos
36
- });
31
+ const label = stringAttr(node.attrs.label) ?? "?";
32
+ notes.push({ kind, id, label, text, referencePos: pos });
33
+ if (story !== null) {
34
+ const row = { key, kind, id, label, story, referencePos: pos };
35
+ rows.set(key, row);
36
+ if (kind === "footnote") footnotes.set(key, row);
37
+ else endnotes.push(row);
38
+ }
37
39
  return true;
38
40
  });
39
- return { notes, tooltips: DecorationSet.create(doc, tooltips) };
41
+ return {
42
+ notes,
43
+ tooltips: DecorationSet.create(doc, tooltips),
44
+ footnotes,
45
+ endnotes,
46
+ rows
47
+ };
40
48
  }
41
49
  var noteProjection = documentProjection(
42
50
  "docxEditorNotes",
@@ -6,6 +6,7 @@ import { keymap } from "prosemirror-keymap";
6
6
  import { EditorState } from "prosemirror-state";
7
7
  import { tableEditing } from "prosemirror-tables";
8
8
  import { EditorView } from "prosemirror-view";
9
+ import { withNoteLabels } from "../docx/notes/numbering.js";
9
10
  import { pageDecorations } from "../page/pageDecorations.js";
10
11
  import { pageGeometryStyle, pagePixels } from "../page/pageLayout.js";
11
12
  import { editsShut } from "../schema/protectionState.js";
@@ -27,6 +28,7 @@ import { columnResize } from "./plugins/columnResize.js";
27
28
  import { commentComposer } from "./plugins/commentComposer.js";
28
29
  import { commentDecorations } from "./plugins/commentDecorations.js";
29
30
  import { commentRestoration } from "./plugins/commentRestoration.js";
31
+ import { compositionSelection } from "./plugins/compositionSelection.js";
30
32
  import {
31
33
  displayDerivation,
32
34
  withDerivedDisplay
@@ -37,6 +39,9 @@ import { docxKeymap, historyKeys } from "./plugins/keymap.js";
37
39
  import { linkPanel } from "./plugins/linkPanel.js";
38
40
  import { listInputRules } from "./plugins/listInputRules.js";
39
41
  import { lockedContent } from "./plugins/lockedContent.js";
42
+ import { noteLifecycle } from "./plugins/noteLifecycle.js";
43
+ import { noteNavigation } from "./plugins/noteNavigation.js";
44
+ import { noteNumbering } from "./plugins/noteNumbering.js";
40
45
  import { numberingMarkers } from "./plugins/numberingDecorations.js";
41
46
  import { rowResize } from "./plugins/rowResize.js";
42
47
  import { tabCaret } from "./plugins/tabCaret.js";
@@ -58,8 +63,13 @@ function createEditorState(doc, options = {}) {
58
63
  } = options;
59
64
  return EditorState.create({
60
65
  // The values the document arrived with were worked out against whatever opened it; the
61
- // state's are worked out against its own snapshot, tables' shared lines included
62
- doc: withDerivedDisplay(doc, document),
66
+ // state's are worked out against its own snapshot, tables' shared lines and note labels
67
+ // included
68
+ doc: withNoteLabels(
69
+ withDerivedDisplay(doc, document),
70
+ document.noteNumbering,
71
+ document.specialNotes
72
+ ),
63
73
  plugins: [
64
74
  // Consumer plugins lead the array. ProseMirror walks the plugins in order and takes the
65
75
  // first answer for a keypress, a paste, a drop or any other DOM event, so this is the
@@ -70,9 +80,12 @@ function createEditorState(doc, options = {}) {
70
80
  editorDocument(document),
71
81
  // Refuses every edit no guard in `schema/guards` lets through, whoever asked for it. It is
72
82
  // not optional: a document that locked a part of itself stays locked in every consumer, and
73
- // the preserved bookmark markers and note references stay where the file put them.
83
+ // the preserved bookmark markers stay where the file put them.
74
84
  lockedContent(),
75
85
  documentProtection({ protection, author, editableComments }),
86
+ // Ahead of the keys and the clipboard: the plugin registered first sees a DOM event first,
87
+ // and this one hands every composition on
88
+ compositionSelection(),
76
89
  history(),
77
90
  keymap(docxKeymap),
78
91
  historyKeys(),
@@ -100,8 +113,13 @@ function createEditorState(doc, options = {}) {
100
113
  // A comment outlives the text it was written for: an edit that sweeps its reference away has
101
114
  // it put back where the deletion left, detached from the page (`plugins/commentRestoration`)
102
115
  commentRestoration(),
116
+ // A note goes with the last reference to it, and a copied reference gets a note of its own.
117
+ // It stands ahead of the numbering, which then labels what it settled
118
+ noteLifecycle(),
119
+ noteNumbering(),
103
120
  // What the notes under the page are, worked out from the document the same way
104
121
  noteProjection.plugin,
122
+ noteNavigation(),
105
123
  // Adjacent text tabs still need separate DOM ranges for layout and pointer selection.
106
124
  tabDecorations(),
107
125
  tabPointer(),
@@ -36,6 +36,9 @@ export declare function documentGeometry(state: EditorState): PageGeometry;
36
36
  * section is where the document says it is, and the snapshot holds the first section's paper
37
37
  * alone. Reading it walks every block, so a caller drawing a whole document asks once and looks
38
38
  * its positions up (`page/pageLayout`) rather than calling this per block.
39
+ *
40
+ * A side story writes down no section, so its own blocks say nothing about the paper: what it is
41
+ * drawn on is the paper of the place it is called from, which its snapshot carries.
39
42
  */
40
43
  export declare function sectionGeometryAt(state: EditorState, pos: number): PageGeometry;
41
44
  /** The document-wide interval between automatic tab stops, in points. */
@@ -19,7 +19,8 @@ function documentGeometry(state) {
19
19
  return documentOf(state).geometry;
20
20
  }
21
21
  function sectionGeometryAt(state, pos) {
22
- return sectionAt(state.doc, pos).props.geometry;
22
+ const document = documentOf(state);
23
+ return document.sideStory ? document.geometry : sectionAt(state.doc, pos).props.geometry;
23
24
  }
24
25
  function documentDefaultTabStopPt(state) {
25
26
  return documentOf(state).defaultTabStopPt;
@@ -10,9 +10,11 @@
10
10
  import type { Node as PMNode } from "prosemirror-model";
11
11
  import { type EditorState, Plugin } from "prosemirror-state";
12
12
  import { type FormattingContext, type ParagraphStyleOption } from "../docx/formatting";
13
+ import { type NoteNumbering } from "../docx/notes/reading";
13
14
  import { type PageGeometry } from "../docx/pageGeometry";
14
15
  import type { SessionStore } from "../docx/session";
15
16
  import type { DocumentDefaults } from "../model/format";
17
+ import { type StoryKey } from "../schema/stories";
16
18
  /** The document-level values one editing state is built on */
17
19
  export interface EditorDocument {
18
20
  /** The document these values were read from. Null for a state built without one */
@@ -30,12 +32,26 @@ export interface EditorDocument {
30
32
  readonly canStartNewList: boolean;
31
33
  /** The paper the document is written on, which decides the width a new table is fitted to */
32
34
  readonly geometry: PageGeometry;
35
+ /**
36
+ * Whether these values stand for a side story rather than for the body, whose paper is then the
37
+ * geometry above rather than anything the story's own blocks say (`editor/documentStyles`).
38
+ */
39
+ readonly sideStory: boolean;
33
40
  /** The distance between automatic tab stops when no custom stop applies */
34
41
  readonly defaultTabStopPt: number;
35
42
  /** Every id already present in the opened Comments part, including unreferenced entries */
36
43
  readonly reservedCommentIds: ReadonlySet<string>;
37
44
  /** Every paragraph id present in the opened comment parts, including orphan extension entries */
38
45
  readonly reservedCommentParaIds: ReadonlySet<string>;
46
+ /** How the document counts its footnotes and endnotes, which the note labels are spelled in */
47
+ readonly noteNumbering: NoteNumbering;
48
+ /** The note entries that lay out the page rather than number a note: separators and the continuation notice */
49
+ readonly specialNotes: ReadonlySet<StoryKey>;
50
+ /**
51
+ * Every entry of an editable kind the opened notes parts hold, separators and entries no
52
+ * reference names included, which a new note may not take the id of
53
+ */
54
+ readonly reservedNoteKeys: ReadonlySet<StoryKey>;
39
55
  }
40
56
  /** What a state built without an opened document answers: the same as nothing being written down */
41
57
  export declare const NO_DOCUMENT: EditorDocument;
@@ -51,6 +67,14 @@ export declare function documentOf(state: EditorState): EditorDocument;
51
67
  * both leave the same object behind, allowing the sheet's style to be cached against that identity.
52
68
  */
53
69
  export declare function editorDocument(document: EditorDocument): Plugin<EditorDocument>;
70
+ /**
71
+ * The snapshot one side story is edited against: the document's own values, with the two a story
72
+ * answers differently.
73
+ *
74
+ * A story has nowhere of its own to write a list definition, and the paper its text wraps at is
75
+ * the paper of the place it is called from rather than anything the story says.
76
+ */
77
+ export declare function storyDocument(document: EditorDocument, geometry: PageGeometry): EditorDocument;
54
78
  /** The comment ids the opened document already spent, which a new comment may not take */
55
79
  export declare function reservedCommentIds(state: EditorState): ReadonlySet<string>;
56
80
  /** The paragraph ids the opened comment parts already spent */
@@ -6,9 +6,17 @@ import {
6
6
  NO_FORMATTING
7
7
  } from "../docx/formatting.js";
8
8
  import { canDefineNewList } from "../docx/newLists.js";
9
+ import {
10
+ DEFAULT_NOTE_NUMBERING
11
+ } from "../docx/notes/reading.js";
9
12
  import { A4_PORTRAIT } from "../docx/pageGeometry.js";
10
13
  import { NEW_LISTS_ATTR, newListsOf } from "../numbering/listRegistry.js";
14
+ import {
15
+ EDITABLE_NOTE_KINDS,
16
+ STORIES_ATTR
17
+ } from "../schema/stories.js";
11
18
  var NO_IDS = /* @__PURE__ */ new Set();
19
+ var NO_NOTE_KEYS = /* @__PURE__ */ new Set();
12
20
  var NO_PARAGRAPH_STYLES = [];
13
21
  var NO_DOCUMENT = {
14
22
  session: null,
@@ -17,9 +25,13 @@ var NO_DOCUMENT = {
17
25
  paragraphStyles: NO_PARAGRAPH_STYLES,
18
26
  canStartNewList: true,
19
27
  geometry: A4_PORTRAIT,
28
+ sideStory: false,
20
29
  defaultTabStopPt: DEFAULT_TAB_STOP_PT,
21
30
  reservedCommentIds: NO_IDS,
22
- reservedCommentParaIds: NO_IDS
31
+ reservedCommentParaIds: NO_IDS,
32
+ noteNumbering: DEFAULT_NOTE_NUMBERING,
33
+ specialNotes: NO_NOTE_KEYS,
34
+ reservedNoteKeys: NO_NOTE_KEYS
23
35
  };
24
36
  function reservedParaIds(session) {
25
37
  const paraIds = /* @__PURE__ */ new Set();
@@ -46,9 +58,17 @@ function editorDocumentOf(session, doc) {
46
58
  paragraphStyles: session.paragraphStyles,
47
59
  canStartNewList: canDefineNewList(session),
48
60
  geometry: session.geometry,
61
+ sideStory: false,
49
62
  defaultTabStopPt: session.defaultTabStopPt,
50
63
  reservedCommentIds: new Set(session.comments.byId.keys()),
51
- reservedCommentParaIds: reservedParaIds(session)
64
+ reservedCommentParaIds: reservedParaIds(session),
65
+ noteNumbering: session.noteNumbering,
66
+ specialNotes: session.specialNotes,
67
+ reservedNoteKeys: new Set(
68
+ Array.from(session.stories.values()).flatMap(
69
+ (story) => EDITABLE_NOTE_KINDS.some((kind) => kind === story.kind) ? [story.key] : []
70
+ )
71
+ )
52
72
  };
53
73
  }
54
74
  var editorDocumentKey = new PluginKey("docxEditorDocument");
@@ -61,15 +81,24 @@ function derived(current, doc) {
61
81
  formatting: formattingWithNewLists(current.formatting, doc)
62
82
  } : editorDocumentOf(current.session, doc);
63
83
  }
84
+ function onlyStoriesMoved(next, before) {
85
+ const names = Object.keys(next.attrs);
86
+ return next.attrs[STORIES_ATTR] !== before.attrs[STORIES_ATTR] && names.length === Object.keys(before.attrs).length && names.every(
87
+ (name) => name === STORIES_ATTR || next.attrs[name] === before.attrs[name]
88
+ );
89
+ }
64
90
  function editorDocument(document) {
65
91
  return new Plugin({
66
92
  key: editorDocumentKey,
67
93
  state: {
68
94
  init: () => document,
69
- apply: (tr, current, old) => tr.doc.attrs === old.doc.attrs ? current : derived(current, tr.doc)
95
+ apply: (tr, current, old) => tr.doc.attrs === old.doc.attrs || onlyStoriesMoved(tr.doc, old.doc) ? current : derived(current, tr.doc)
70
96
  }
71
97
  });
72
98
  }
99
+ function storyDocument(document, geometry) {
100
+ return { ...document, sideStory: true, canStartNewList: false, geometry };
101
+ }
73
102
  function reservedCommentIds(state) {
74
103
  return documentOf(state).reservedCommentIds;
75
104
  }
@@ -82,5 +111,6 @@ export {
82
111
  editorDocument,
83
112
  editorDocumentOf,
84
113
  reservedCommentIds,
85
- reservedCommentParaIds
114
+ reservedCommentParaIds,
115
+ storyDocument
86
116
  };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * What a footnote or an endnote draws and does differently from any other story.
3
+ *
4
+ * A note's story opens with a mark of its own (`w:footnoteRef`, `w:endnoteRef`), which the file
5
+ * keeps as a preserved chip. Word draws that mark as the number the reference carries, so it is
6
+ * drawn here as that label in superscript, the way the reference in the body is.
7
+ *
8
+ * The rest is what the story view asks a kind of story for (`editor/stories`): the host every
9
+ * edit leaves through, and the extensions that give a note its chip, its key rule, the number it
10
+ * keeps through an edit, and what a paste into one may carry.
11
+ */
12
+ import type { EditorView } from "prosemirror-view";
13
+ import { type StoryKey } from "../../schema/stories";
14
+ import { type SliceNormalizer } from "../clipboard/normalizers";
15
+ import type { StoryNodeSpecs } from "../stories/storyMarkup";
16
+ import { type StoryExtensions, type StoryHost } from "../stories/storyView";
17
+ /** The node specs a note's story is drawn with, its own reference mark drawn as `labelOf` answers */
18
+ export declare function noteNodeSpecs(labelOf: () => string): StoryNodeSpecs;
19
+ /**
20
+ * Takes out of a paste what the notes part cannot be written with: an image, and a link.
21
+ *
22
+ * Either needs a relationship of the part it stands in, and the notes part writer writes none, so
23
+ * both would go out naming a relationship the file does not hold. A link or an image the file
24
+ * itself wrote inside a note stays; this is about what a paste would add.
25
+ */
26
+ export declare const dropUnwritableContent: SliceNormalizer;
27
+ /**
28
+ * Takes a note reference out of a paste: a note may not hold a note.
29
+ *
30
+ * The lifecycle, the numbering and the writer all walk the body alone, so a reference inside a
31
+ * story would call a note nothing numbers, counts or settles, and one copied from beside the note
32
+ * it was pasted into would have that note calling itself. The text it stood in stays, the way the
33
+ * other anchors leave theirs (`editor/clipboard/normalizers`).
34
+ */
35
+ export declare const dropNoteReferences: SliceNormalizer;
36
+ /**
37
+ * Puts the caret back just after the reference that calls this note and takes the body's focus,
38
+ * which is what leaves the note: Escape and a press on the note's own number both run it.
39
+ */
40
+ export declare function returnToReference(main: EditorView, key: StoryKey): void;
41
+ /**
42
+ * The host a note's editing view writes through, whichever kind of note stands under the key.
43
+ *
44
+ * Every edit leaves as that kind's own body command, so a lock around the reference and the
45
+ * editing protection judge a note edit where they judge a body edit, and the main document keeps
46
+ * the one history both share.
47
+ */
48
+ export declare function noteHost(main: EditorView, activate: StoryHost["activate"]): StoryHost;
49
+ /**
50
+ * What a note adds to the story view: its chip, the number it keeps first, its key rule, and what
51
+ * a paste may bring in
52
+ */
53
+ export declare function noteExtensions(main: EditorView, key: StoryKey, labelOf: () => string): StoryExtensions;