@portone/docx-editor 0.3.0 → 0.5.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 +205 -0
- package/assets/editor.png +0 -0
- package/dist/DocxEditor.d.ts +1 -1
- package/dist/DocxEditor.js +45 -25
- package/dist/core.d.ts +1 -1
- package/dist/docx/cloning.js +4 -9
- package/dist/docx/commentOnlyChange.d.ts +5 -3
- package/dist/docx/comments/grammar.d.ts +27 -10
- package/dist/docx/comments/grammar.js +18 -67
- package/dist/docx/comments/model.d.ts +5 -6
- package/dist/docx/comments/model.js +0 -9
- package/dist/docx/comments/parts.d.ts +16 -10
- package/dist/docx/comments/parts.js +65 -13
- package/dist/docx/comments/people.d.ts +11 -3
- package/dist/docx/comments/people.js +20 -6
- package/dist/docx/comments/policy.js +7 -1
- package/dist/docx/comments/reading.d.ts +4 -2
- package/dist/docx/comments/reading.js +1 -14
- package/dist/docx/comments/writing.js +78 -35
- package/dist/docx/exportDocx.js +30 -18
- package/dist/docx/exportRefs.d.ts +8 -3
- package/dist/docx/exportRefs.js +2 -1
- package/dist/docx/fidelity.js +24 -10
- package/dist/docx/fields.d.ts +42 -0
- package/dist/docx/fields.js +76 -0
- package/dist/docx/formatting/attrs.d.ts +20 -2
- package/dist/docx/formatting/attrs.js +57 -2
- package/dist/docx/formatting/context.d.ts +10 -2
- package/dist/docx/formatting/context.js +23 -5
- package/dist/docx/formatting/resolve.d.ts +10 -4
- package/dist/docx/formatting/resolve.js +31 -11
- package/dist/docx/formatting/styles.d.ts +25 -2
- package/dist/docx/formatting/styles.js +84 -3
- package/dist/docx/headersFooters.d.ts +89 -20
- package/dist/docx/headersFooters.js +163 -172
- package/dist/docx/hyperlink.d.ts +14 -4
- package/dist/docx/hyperlink.js +4 -1
- package/dist/docx/importDocx.d.ts +1 -1
- package/dist/docx/importDocx.js +135 -74
- package/dist/docx/importParagraph.d.ts +16 -4
- package/dist/docx/importParagraph.js +87 -93
- package/dist/docx/importPolicy.d.ts +70 -0
- package/dist/docx/importPolicy.js +190 -0
- package/dist/docx/importPreserved.d.ts +30 -0
- package/dist/docx/importPreserved.js +54 -0
- package/dist/docx/importTable.d.ts +2 -2
- package/dist/docx/importTable.js +107 -66
- package/dist/docx/invariants.js +42 -31
- package/dist/docx/newLists.d.ts +30 -0
- package/dist/docx/newLists.js +24 -1
- package/dist/docx/notes.d.ts +6 -1
- package/dist/docx/notes.js +6 -16
- package/dist/docx/numberingPlanner.d.ts +6 -3
- package/dist/docx/numberingPlanner.js +38 -7
- package/dist/docx/pageGeometry.d.ts +5 -14
- package/dist/docx/pageGeometry.js +0 -12
- package/dist/docx/protectionPolicy.d.ts +13 -5
- package/dist/docx/protectionPolicy.js +32 -22
- package/dist/docx/scan.d.ts +18 -8
- package/dist/docx/scan.js +17 -11
- package/dist/docx/sections.d.ts +126 -0
- package/dist/docx/sections.js +207 -0
- package/dist/docx/serializeBlock.d.ts +13 -4
- package/dist/docx/serializeBlock.js +16 -18
- package/dist/docx/serializeParagraph.d.ts +4 -0
- package/dist/docx/serializeParagraph.js +1 -0
- package/dist/docx/serializePreserved.d.ts +14 -0
- package/dist/docx/serializePreserved.js +24 -0
- package/dist/docx/serializeStory.d.ts +17 -0
- package/dist/docx/serializeStory.js +17 -0
- package/dist/docx/serializeTable.js +10 -13
- package/dist/docx/session.d.ts +24 -7
- package/dist/docx/session.js +37 -6
- package/dist/docx/story.d.ts +140 -0
- package/dist/docx/story.js +237 -0
- package/dist/docx/storyProjection.js +6 -1
- package/dist/docx/tableFormatting/conditions.d.ts +76 -0
- package/dist/docx/tableFormatting/conditions.js +196 -0
- package/dist/docx/tableFormatting/editing.d.ts +7 -3
- package/dist/docx/tableFormatting/editing.js +4 -5
- package/dist/docx/tableFormatting/reading.d.ts +49 -19
- package/dist/docx/tableFormatting/reading.js +109 -35
- package/dist/docx/tableFormatting.d.ts +1 -0
- package/dist/docx/tableFormatting.js +1 -0
- package/dist/docx/tableTemplate.js +12 -12
- package/dist/editor/clipboard/htmlReader.d.ts +30 -0
- package/dist/editor/clipboard/htmlReader.js +302 -0
- package/dist/editor/clipboard/internalChannel.d.ts +57 -0
- package/dist/editor/clipboard/internalChannel.js +58 -0
- package/dist/editor/clipboard/normalizers.d.ts +99 -0
- package/dist/editor/clipboard/normalizers.js +199 -0
- package/dist/editor/clipboard/parser.d.ts +34 -0
- package/dist/editor/clipboard/parser.js +58 -0
- package/dist/editor/clipboard/plugin.d.ts +21 -0
- package/dist/editor/clipboard/plugin.js +320 -0
- package/dist/editor/clipboard/readContext.d.ts +24 -0
- package/dist/editor/clipboard/readContext.js +19 -0
- package/dist/editor/clipboard/readers.d.ts +33 -0
- package/dist/editor/clipboard/readers.js +37 -0
- package/dist/editor/commands/comments/editing.d.ts +26 -6
- package/dist/editor/commands/comments/editing.js +175 -105
- package/dist/editor/commands/comments/model.d.ts +34 -17
- package/dist/editor/commands/comments/model.js +11 -0
- package/dist/editor/commands/comments/reading.d.ts +5 -3
- package/dist/editor/commands/comments/reading.js +8 -58
- package/dist/editor/commands/formatting/propertyCommands.js +6 -1
- package/dist/editor/commands/index.d.ts +2 -2
- package/dist/editor/commands/index.js +2 -0
- package/dist/editor/commands/listCommands.d.ts +12 -3
- package/dist/editor/commands/listCommands.js +76 -30
- package/dist/editor/commands/noteQueries.d.ts +22 -5
- package/dist/editor/commands/noteQueries.js +34 -6
- package/dist/editor/commands/paragraphCommands.js +6 -1
- package/dist/editor/createEditor.js +14 -4
- package/dist/editor/documentStyles.d.ts +26 -4
- package/dist/editor/documentStyles.js +9 -4
- package/dist/editor/editorDocument.d.ts +7 -6
- package/dist/editor/editorDocument.js +18 -6
- package/dist/editor/imageFiles.d.ts +2 -2
- package/dist/editor/imageFiles.js +2 -0
- package/dist/editor/insertTable.d.ts +1 -1
- package/dist/editor/insertTable.js +2 -2
- package/dist/editor/paragraphEdits.d.ts +16 -1
- package/dist/editor/paragraphEdits.js +13 -5
- package/dist/editor/paragraphPlacement.d.ts +11 -0
- package/dist/editor/paragraphPlacement.js +18 -0
- package/dist/editor/plainText.d.ts +12 -0
- package/dist/editor/plainText.js +2 -1
- package/dist/editor/plugins/columnResize.js +6 -3
- package/dist/editor/plugins/commentComposer.d.ts +28 -0
- package/dist/editor/plugins/commentComposer.js +46 -0
- package/dist/editor/plugins/commentDecorations.d.ts +29 -2
- package/dist/editor/plugins/commentDecorations.js +89 -15
- package/dist/editor/plugins/documentProjection.d.ts +31 -0
- package/dist/editor/plugins/documentProjection.js +22 -0
- package/dist/editor/plugins/imagePaste.js +20 -10
- package/dist/editor/plugins/linkPanel.d.ts +7 -3
- package/dist/editor/plugins/linkPanel.js +13 -27
- package/dist/editor/plugins/numberingDecorations.d.ts +10 -4
- package/dist/editor/plugins/numberingDecorations.js +43 -2
- package/dist/editor/plugins/panelState.d.ts +67 -0
- package/dist/editor/plugins/panelState.js +54 -0
- package/dist/editor/plugins/paragraphDisplay.js +9 -3
- package/dist/editor/plugins/tableContextMenu.d.ts +1 -1
- package/dist/editor/plugins/tableContextMenu.js +30 -47
- package/dist/editor/plugins/tableDisplay.js +19 -5
- package/dist/editor/plugins/textContextMenu.d.ts +1 -1
- package/dist/editor/plugins/textContextMenu.js +30 -47
- package/dist/model/format.d.ts +50 -0
- package/dist/model/format.js +65 -0
- package/dist/numbering/listRegistry.d.ts +37 -0
- package/dist/numbering/listRegistry.js +112 -0
- package/dist/numbering/listTemplate.d.ts +26 -17
- package/dist/numbering/listTemplate.js +66 -20
- package/dist/numbering/markers.d.ts +15 -6
- package/dist/numbering/markers.js +26 -59
- package/dist/numbering/parseNumbering.d.ts +70 -5
- package/dist/numbering/parseNumbering.js +100 -26
- package/dist/numbering/spellers.d.ts +15 -0
- package/dist/numbering/spellers.js +96 -0
- package/dist/numbering/writeNumbering.d.ts +5 -3
- package/dist/numbering/writeNumbering.js +15 -15
- package/dist/ooxml/conformance.d.ts +28 -0
- package/dist/ooxml/conformance.js +20 -0
- package/dist/ooxml/errors.d.ts +5 -5
- package/dist/ooxml/fragment.d.ts +11 -0
- package/dist/ooxml/fragment.js +14 -4
- package/dist/ooxml/image.d.ts +3 -4
- package/dist/ooxml/image.js +50 -5
- package/dist/ooxml/names.d.ts +15 -0
- package/dist/ooxml/names.js +10 -1
- package/dist/ooxml/partSplice.d.ts +1 -1
- package/dist/ooxml/partSplice.js +10 -3
- package/dist/ooxml/props.d.ts +8 -0
- package/dist/ooxml/props.js +14 -4
- package/dist/ooxml/rangeMarkers.d.ts +5 -0
- package/dist/ooxml/rangeMarkers.js +24 -0
- package/dist/ooxml/xml.d.ts +8 -9
- package/dist/ooxml/xml.js +6 -6
- package/dist/page/PageGuides.d.ts +8 -4
- package/dist/page/PageGuides.js +13 -37
- package/dist/page/pageLayout.d.ts +62 -13
- package/dist/page/pageLayout.js +91 -37
- package/dist/page/usePageLayout.d.ts +14 -11
- package/dist/page/usePageLayout.js +21 -29
- package/dist/schema/attrRoles.js +44 -19
- package/dist/schema/docxSchema.d.ts +9 -1
- package/dist/schema/docxSchema.js +220 -139
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.js +2 -2
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/preservedFragments.d.ts +12 -0
- package/dist/schema/preservedFragments.js +38 -0
- package/dist/schema/preservedGuards.d.ts +9 -7
- package/dist/schema/preservedGuards.js +112 -11
- package/dist/schema/protection.d.ts +34 -5
- package/dist/schema/protection.js +42 -14
- package/dist/schema/rendering.js +3 -1
- package/dist/schema/stories.d.ts +49 -0
- package/dist/schema/stories.js +78 -0
- package/dist/styles/classNames.d.ts +16 -7
- package/dist/styles/classNames.js +16 -7
- package/dist/styles.css +90 -30
- package/dist/table/cellFormatting.js +1 -2
- package/dist/table/gridBorders.d.ts +11 -15
- package/dist/table/gridBorders.js +32 -18
- package/dist/table/resize.d.ts +5 -3
- package/dist/ui/CommentsPanel.d.ts +1 -3
- package/dist/ui/CommentsPanel.js +24 -15
- package/dist/ui/NotesPanel.js +2 -2
- package/dist/ui/TextMenu.d.ts +1 -3
- package/dist/ui/TextMenu.js +10 -6
- package/dist/ui/comments/CommentComposer.d.ts +6 -1
- package/dist/ui/comments/CommentComposer.js +26 -3
- package/package.json +1 -1
- package/dist/editor/externalClipboard.d.ts +0 -11
- package/dist/editor/externalClipboard.js +0 -456
package/dist/styles.css
CHANGED
|
@@ -62,11 +62,6 @@
|
|
|
62
62
|
overflow: hidden;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
/* A body-level bookmark occupies a document-model position but draws no placeholder. */
|
|
66
|
-
.docx-editor-bookmark-block {
|
|
67
|
-
display: none;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
65
|
.docx-editor-comment-range {
|
|
71
66
|
background: #fff2a8;
|
|
72
67
|
box-shadow: inset 0 -2px #e2b714;
|
|
@@ -588,10 +583,12 @@ button.docx-editor-comment-body {
|
|
|
588
583
|
* is the same paper `A4_PORTRAIT` names in `docx/pageGeometry.ts`.
|
|
589
584
|
*
|
|
590
585
|
* The height is used only as a minimum, so that even short text feels like a full
|
|
591
|
-
* sheet and longer text simply grows it
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
586
|
+
* sheet and longer text simply grows it, and the editor supplies one grown to the
|
|
587
|
+
* last page's own bottom margin where a later section's is deeper than this one's.
|
|
588
|
+
* The body left inside these margins is what the sheet itself is drawn at. The width
|
|
589
|
+
* of a new table and the height between two page boundaries come from the paper of
|
|
590
|
+
* the section they stand in, which `page/pageLayout.ts` works out from the very same
|
|
591
|
+
* kind of geometry, so the divider on screen lands where that page actually ends.
|
|
595
592
|
*/
|
|
596
593
|
--docx-editor-page-width: 21cm;
|
|
597
594
|
--docx-editor-page-height: 29.7cm;
|
|
@@ -677,23 +674,10 @@ button.docx-editor-comment-body {
|
|
|
677
674
|
border-top: 1px dotted rgb(26 79 208 / 40%);
|
|
678
675
|
}
|
|
679
676
|
|
|
680
|
-
/*
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
min-width: 18px;
|
|
685
|
-
padding: 0 6px;
|
|
686
|
-
border-radius: 9px;
|
|
687
|
-
background: rgb(0 0 0 / 6%);
|
|
688
|
-
color: #808080;
|
|
689
|
-
font-family: system-ui, sans-serif;
|
|
690
|
-
font-size: 10px;
|
|
691
|
-
line-height: 18px;
|
|
692
|
-
text-align: center;
|
|
693
|
-
letter-spacing: 0.02em;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
/* Display-only projections of the first section's header and footer stories. */
|
|
677
|
+
/*
|
|
678
|
+
* Display-only projections of the header and footer stories of the section each page
|
|
679
|
+
* belongs to (`page/PageGuides.tsx`).
|
|
680
|
+
*/
|
|
697
681
|
.docx-editor-page-header,
|
|
698
682
|
.docx-editor-page-footer {
|
|
699
683
|
position: absolute;
|
|
@@ -720,14 +704,28 @@ button.docx-editor-comment-body {
|
|
|
720
704
|
* the space.
|
|
721
705
|
* Because box-sizing is border-box, as long as the number fits inside the space it
|
|
722
706
|
* does not push where the body starts.
|
|
707
|
+
*
|
|
708
|
+
* A level that asks for a space or for nothing after its number (w:suff) keeps no
|
|
709
|
+
* space at all, so both variables are set to zero and the body starts right after
|
|
710
|
+
* the number. Where the number sits inside the space is the level's w:lvlJc.
|
|
711
|
+
*
|
|
712
|
+
* The level dresses its number and nothing else (lvl/rPr), so its character
|
|
713
|
+
* formatting arrives as variables read here rather than as anything the paragraph
|
|
714
|
+
* wears. Where the level writes none, the number is drawn like the text it stands
|
|
715
|
+
* in front of.
|
|
723
716
|
*/
|
|
724
717
|
.docx-editor-p[data-marker]::before {
|
|
725
718
|
content: attr(data-marker);
|
|
726
719
|
display: inline-block;
|
|
727
720
|
box-sizing: border-box;
|
|
728
721
|
min-width: var(--docx-editor-marker-width, 18pt);
|
|
729
|
-
padding-right: 4pt;
|
|
730
|
-
text-align: left;
|
|
722
|
+
padding-right: var(--docx-editor-marker-gap, 4pt);
|
|
723
|
+
text-align: var(--docx-editor-marker-align, left);
|
|
724
|
+
font-weight: var(--docx-editor-marker-font-weight, inherit);
|
|
725
|
+
font-style: var(--docx-editor-marker-font-style, inherit);
|
|
726
|
+
font-size: var(--docx-editor-marker-font-size, inherit);
|
|
727
|
+
font-family: var(--docx-editor-marker-font-family, inherit);
|
|
728
|
+
color: var(--docx-editor-marker-color, inherit);
|
|
731
729
|
/* Keeps the paragraph's hanging indent (text-indent) from being inherited and shifting the number again inside its own box */
|
|
732
730
|
text-indent: 0;
|
|
733
731
|
user-select: none;
|
|
@@ -930,12 +928,21 @@ button.docx-editor-comment-body {
|
|
|
930
928
|
* held as data rather than as an `href`, so a click here places the caret the way a click on any
|
|
931
929
|
* other text does, and opening the address is the link panel's business.
|
|
932
930
|
* A color the run itself carries paints over this one, the same as any other run formatting.
|
|
931
|
+
* The line is a border rather than an underline so that it runs on across a tab, which a text
|
|
932
|
+
* decoration is not painted over.
|
|
933
933
|
*/
|
|
934
934
|
.docx-editor-link {
|
|
935
935
|
color: #1a56db;
|
|
936
936
|
border-bottom: 1px solid currentcolor;
|
|
937
937
|
}
|
|
938
938
|
|
|
939
|
+
/* A word processor underlines a link through the `Hyperlink` style, so the line above would be a second one */
|
|
940
|
+
.docx-editor-link:has([data-underline]):not(
|
|
941
|
+
:has(.docx-editor-run:not([data-underline]))
|
|
942
|
+
) {
|
|
943
|
+
border-bottom: none;
|
|
944
|
+
}
|
|
945
|
+
|
|
939
946
|
/*
|
|
940
947
|
* A content control that says its contents may not be edited (`editor/plugins/lockedContent` refuses
|
|
941
948
|
* the edits). Yellow is what the contract templates already paint their settled parts with.
|
|
@@ -959,15 +966,63 @@ button.docx-editor-comment-body {
|
|
|
959
966
|
cursor: not-allowed;
|
|
960
967
|
}
|
|
961
968
|
|
|
969
|
+
/*
|
|
970
|
+
* A preserved fragment inside a paragraph or inside a run. What it draws is the `display` the
|
|
971
|
+
* preservation rule gave it (`docx/importPolicy`), so the rule is read here as an attribute
|
|
972
|
+
* rather than as a second list of element names.
|
|
973
|
+
*/
|
|
974
|
+
.docx-editor-raw-inline,
|
|
975
|
+
.docx-editor-raw-run {
|
|
976
|
+
vertical-align: baseline;
|
|
977
|
+
}
|
|
978
|
+
|
|
962
979
|
/* Elements that, like bookmarks, must not be visible */
|
|
963
|
-
.docx-editor-raw-inline
|
|
980
|
+
.docx-editor-raw-inline[data-display="hidden"],
|
|
981
|
+
.docx-editor-raw-run[data-display="hidden"] {
|
|
964
982
|
display: inline-block;
|
|
965
983
|
width: 0;
|
|
966
984
|
overflow: hidden;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/* A character the file stands for and the editor cannot type, drawn as itself */
|
|
988
|
+
.docx-editor-raw-inline[data-display="text"],
|
|
989
|
+
.docx-editor-raw-run[data-display="text"] {
|
|
990
|
+
white-space: pre;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/*
|
|
994
|
+
* Content carried through whole that the editor has no model for: a field, a tracked change, a
|
|
995
|
+
* symbol. Small enough to read the line around it, outlined so it is plainly not ordinary text.
|
|
996
|
+
*
|
|
997
|
+
* Deliberately not `user-select: none`. A chip that carries its content whole can be selected and
|
|
998
|
+
* deleted whole, and taking it out of the selection would leave a reader dragging across it with
|
|
999
|
+
* no way to reach it.
|
|
1000
|
+
*/
|
|
1001
|
+
.docx-editor-raw-inline[data-display="chip"],
|
|
1002
|
+
.docx-editor-raw-run[data-display="chip"] {
|
|
1003
|
+
display: inline-block;
|
|
1004
|
+
max-width: 16em;
|
|
1005
|
+
overflow: hidden;
|
|
1006
|
+
padding: 0 3px;
|
|
1007
|
+
border: 1px dashed #9a9a9a;
|
|
1008
|
+
border-radius: 3px;
|
|
1009
|
+
background: #f2f2f2;
|
|
1010
|
+
color: #595959;
|
|
1011
|
+
font-size: 0.85em;
|
|
1012
|
+
font-family: system-ui, sans-serif;
|
|
1013
|
+
line-height: 1.4;
|
|
1014
|
+
white-space: nowrap;
|
|
1015
|
+
text-overflow: ellipsis;
|
|
967
1016
|
vertical-align: baseline;
|
|
968
1017
|
}
|
|
969
1018
|
|
|
970
|
-
|
|
1019
|
+
/* The chip while it is the selection, which is how a reader sees what a delete would take */
|
|
1020
|
+
.docx-editor-raw-inline[data-display="chip"].ProseMirror-selectednode,
|
|
1021
|
+
.docx-editor-raw-run[data-display="chip"].ProseMirror-selectednode {
|
|
1022
|
+
outline: 2px solid #1a73e8;
|
|
1023
|
+
outline-offset: 1px;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
971
1026
|
.docx-editor-raw-block {
|
|
972
1027
|
margin: 8pt 0;
|
|
973
1028
|
padding: 10pt 12pt;
|
|
@@ -980,6 +1035,11 @@ button.docx-editor-comment-body {
|
|
|
980
1035
|
user-select: none;
|
|
981
1036
|
}
|
|
982
1037
|
|
|
1038
|
+
/* A range marker holds a spot between blocks and stands for nothing on the page. */
|
|
1039
|
+
.docx-editor-raw-block[data-display="hidden"] {
|
|
1040
|
+
display: none;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
983
1043
|
/*
|
|
984
1044
|
* The toolbar.
|
|
985
1045
|
*
|
|
@@ -38,8 +38,7 @@ function planChanges(rect, edit) {
|
|
|
38
38
|
const next = editCellProps(
|
|
39
39
|
text(cell.attrs.tcPr),
|
|
40
40
|
edit(rect, pos),
|
|
41
|
-
cellDefaultsAt(rect.map, pos, sources)
|
|
42
|
-
sources.margins
|
|
41
|
+
cellDefaultsAt(rect.map, pos, sources)
|
|
43
42
|
);
|
|
44
43
|
if (!next) continue;
|
|
45
44
|
changes.push({
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The lines a cell draws because of where it sits in the grid.
|
|
2
|
+
* The lines and the fill a cell draws because of where it sits in the grid.
|
|
3
3
|
*
|
|
4
4
|
* Every line of a table is drawn by its cells (see `docx/tableFormatting`), so which line a side
|
|
5
|
-
* falls back on depends on where in the grid the cell sits
|
|
6
|
-
* formatting, which is what a background has to
|
|
7
|
-
*
|
|
8
|
-
* leave the table with no line along its bottom.
|
|
5
|
+
* falls back on depends on where in the grid the cell sits, and so does which parts of the table
|
|
6
|
+
* style dress it. A new cell inherits its neighbour's formatting, which is what a background has to
|
|
7
|
+
* do but not a line: the row appended under the last one would draw the table's outer line against
|
|
8
|
+
* the row above it, and deleting the last row would leave the table with no line along its bottom.
|
|
9
|
+
* A row added under the header row is likewise no header row.
|
|
9
10
|
*
|
|
10
11
|
* So the cells of a table whose grid moved derive their display values again, along the same path
|
|
11
12
|
* the import takes. What a cell wrote down itself lives in its `w:tcPr` and is read straight back
|
|
@@ -14,21 +15,16 @@
|
|
|
14
15
|
* deriver that runs them after an edit is `editor/plugins/tableDisplay`.
|
|
15
16
|
*/
|
|
16
17
|
import type { Node as PMNode } from "prosemirror-model";
|
|
17
|
-
import { type
|
|
18
|
-
import { type CellMargins, type InsideBorders, type TableFormat } from "../model/format";
|
|
18
|
+
import { type CellDefaults, type TableCellSources } from "../docx/tableFormatting";
|
|
19
19
|
import type { NodeAttrs, TableGridMap } from "./format";
|
|
20
20
|
/**
|
|
21
|
-
* What
|
|
21
|
+
* What this table lays down for its cells to draw.
|
|
22
22
|
* The values a table style laid down are not in the `tblPr`, so the table carries them separately.
|
|
23
|
+
* A node never changes once it is built, so what is read out of one is read once.
|
|
23
24
|
*/
|
|
24
|
-
export interface TableCellSources {
|
|
25
|
-
outer: TableFormat | null;
|
|
26
|
-
inside: InsideBorders;
|
|
27
|
-
margins: CellMargins;
|
|
28
|
-
}
|
|
29
25
|
export declare function tableCellSources(table: PMNode): TableCellSources;
|
|
30
|
-
/**
|
|
31
|
-
export declare function cellDefaultsAt(map: TableGridMap, pos: number, sources: TableCellSources):
|
|
26
|
+
/** What the cell at this position falls back on for everything it did not write down itself */
|
|
27
|
+
export declare function cellDefaultsAt(map: TableGridMap, pos: number, sources: TableCellSources): CellDefaults;
|
|
32
28
|
export interface CellFix {
|
|
33
29
|
/** The position of the cell within the table's content */
|
|
34
30
|
pos: number;
|
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
// src/table/gridBorders.ts
|
|
2
2
|
import { TableMap } from "prosemirror-tables";
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
cellDefaultsFor,
|
|
5
5
|
cellMarginsOf,
|
|
6
|
-
gridEdgesOf,
|
|
7
6
|
insideBordersOf,
|
|
8
7
|
layerCellMargins,
|
|
9
8
|
layerInsideBorders,
|
|
10
|
-
|
|
9
|
+
NO_BAND_SIZES,
|
|
10
|
+
NO_CELL_DEFAULTS,
|
|
11
11
|
NO_CELL_MARGINS,
|
|
12
12
|
NO_INSIDE_BORDERS,
|
|
13
|
-
|
|
13
|
+
NO_TABLE_STYLE_CONDITIONS,
|
|
14
|
+
readCellProps,
|
|
15
|
+
readTableLook,
|
|
16
|
+
tblStyleIdOf
|
|
14
17
|
} from "../docx/tableFormatting.js";
|
|
15
18
|
import {
|
|
16
19
|
spanCount,
|
|
20
|
+
toBandSizes,
|
|
17
21
|
toCellFormat,
|
|
18
22
|
toCellMargins,
|
|
19
23
|
toInsideBorders,
|
|
20
|
-
toTableFormat
|
|
24
|
+
toTableFormat,
|
|
25
|
+
toTableStyleConditions
|
|
21
26
|
} from "../model/format.js";
|
|
27
|
+
import { parsePropsXml } from "../ooxml/props.js";
|
|
22
28
|
function text(value) {
|
|
23
29
|
return typeof value === "string" ? value : null;
|
|
24
30
|
}
|
|
25
31
|
function tableCellSources(table) {
|
|
32
|
+
const known = sourcesByTable.get(table);
|
|
33
|
+
if (known) return known;
|
|
26
34
|
const tblPr = text(table.attrs.tblPr);
|
|
27
|
-
|
|
35
|
+
const props = tblPr === null ? null : parsePropsXml(tblPr);
|
|
36
|
+
const sources = {
|
|
28
37
|
outer: toTableFormat(table.attrs.format),
|
|
29
38
|
inside: layerInsideBorders(
|
|
30
39
|
toInsideBorders(table.attrs.styleInside) ?? NO_INSIDE_BORDERS,
|
|
@@ -33,14 +42,23 @@ function tableCellSources(table) {
|
|
|
33
42
|
margins: layerCellMargins(
|
|
34
43
|
toCellMargins(table.attrs.styleCellMargins) ?? NO_CELL_MARGINS,
|
|
35
44
|
cellMarginsOf(tblPr)
|
|
36
|
-
)
|
|
45
|
+
),
|
|
46
|
+
look: readTableLook(props),
|
|
47
|
+
bands: toBandSizes(table.attrs.styleBands) ?? NO_BAND_SIZES,
|
|
48
|
+
conditions: toTableStyleConditions(table.attrs.styleConditions) ?? NO_TABLE_STYLE_CONDITIONS,
|
|
49
|
+
// The style the paragraphs inside resolve against; what it lays down for the cells is already
|
|
50
|
+
// in `styleConditions`
|
|
51
|
+
styleId: tblStyleIdOf(props)
|
|
37
52
|
};
|
|
53
|
+
sourcesByTable.set(table, sources);
|
|
54
|
+
return sources;
|
|
38
55
|
}
|
|
56
|
+
var sourcesByTable = /* @__PURE__ */ new WeakMap();
|
|
39
57
|
function cellDefaultsAt(map, pos, sources) {
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
sources
|
|
58
|
+
return cellDefaultsFor(
|
|
59
|
+
map.findCell(pos),
|
|
60
|
+
{ rows: map.height, cols: map.width },
|
|
61
|
+
sources
|
|
44
62
|
);
|
|
45
63
|
}
|
|
46
64
|
var CELL_FORMAT_KEYS = [
|
|
@@ -106,16 +124,12 @@ function cellFixes(table) {
|
|
|
106
124
|
const cell = table.nodeAt(pos);
|
|
107
125
|
if (!cell) continue;
|
|
108
126
|
const tcPr = text(cell.attrs.tcPr);
|
|
109
|
-
const format = readCellProps(
|
|
110
|
-
tcPr,
|
|
111
|
-
cellDefaultsAt(map, pos, sources),
|
|
112
|
-
sources.margins
|
|
113
|
-
);
|
|
127
|
+
const format = readCellProps(tcPr, cellDefaultsAt(map, pos, sources));
|
|
114
128
|
cells.set(pos, {
|
|
115
129
|
pos,
|
|
116
130
|
attrs: cell.attrs,
|
|
117
131
|
format: { ...format },
|
|
118
|
-
direct: readCellProps(tcPr,
|
|
132
|
+
direct: readCellProps(tcPr, NO_CELL_DEFAULTS)
|
|
119
133
|
});
|
|
120
134
|
}
|
|
121
135
|
reconcileSharedBorders(map, cells);
|
|
@@ -144,7 +158,7 @@ function sameCellFormattingInputs(a, b) {
|
|
|
144
158
|
);
|
|
145
159
|
}
|
|
146
160
|
function sameFormattingInputs(a, b) {
|
|
147
|
-
return sameGrid(a, b) && a.attrs.tblPr === b.attrs.tblPr && a.attrs.format === b.attrs.format && a.attrs.styleInside === b.attrs.styleInside && a.attrs.styleCellMargins === b.attrs.styleCellMargins && sameCellFormattingInputs(a, b);
|
|
161
|
+
return sameGrid(a, b) && a.attrs.tblPr === b.attrs.tblPr && a.attrs.format === b.attrs.format && a.attrs.styleInside === b.attrs.styleInside && a.attrs.styleCellMargins === b.attrs.styleCellMargins && a.attrs.styleConditions === b.attrs.styleConditions && a.attrs.styleBands === b.attrs.styleBands && sameCellFormattingInputs(a, b);
|
|
148
162
|
}
|
|
149
163
|
export {
|
|
150
164
|
cellDefaultsAt,
|
package/dist/table/resize.d.ts
CHANGED
|
@@ -29,7 +29,8 @@ export interface ColumnEdge {
|
|
|
29
29
|
/**
|
|
30
30
|
* The limit a table can be widened to (dxa).
|
|
31
31
|
*
|
|
32
|
-
* The body width of the paper
|
|
32
|
+
* The body width of the paper handed in, which is the section's the table stands in, minus
|
|
33
|
+
* the table indent (`w:tblInd`).
|
|
33
34
|
* For a table already stored wider than that, its current width is the limit, so
|
|
34
35
|
* dragging can only narrow it.
|
|
35
36
|
*/
|
|
@@ -49,7 +50,8 @@ export declare function resizedGridCols(gridCols: number[], col: number, width:
|
|
|
49
50
|
* Because it is one single transaction, a single undo returns everything to the state
|
|
50
51
|
* before the drag.
|
|
51
52
|
*
|
|
52
|
-
* The geometry is the paper the
|
|
53
|
-
* inside. The editor layer reads it off the state; this layer
|
|
53
|
+
* The geometry is the paper of the section the table stands in, which is what the table is
|
|
54
|
+
* kept inside. The editor layer reads it off the state (`editor/documentStyles`); this layer
|
|
55
|
+
* is handed it.
|
|
54
56
|
*/
|
|
55
57
|
export declare function buildResizeColumnTransaction(state: EditorState, edge: ColumnEdge, geometry: PageGeometry): Transaction | null;
|
|
@@ -5,11 +5,9 @@ import { type CommentAuthor } from "../editor/commands/commentCommands";
|
|
|
5
5
|
export interface CommentsPanelProps {
|
|
6
6
|
view: EditorView;
|
|
7
7
|
state: EditorState;
|
|
8
|
-
composerOpen: boolean;
|
|
9
8
|
/** Whose comments the composers write. Null for a reader, who is offered none */
|
|
10
9
|
author: CommentAuthor | null;
|
|
11
|
-
closeComposer: () => void;
|
|
12
10
|
scrollContainer: HTMLElement | null;
|
|
13
11
|
allCommentsOpen: boolean;
|
|
14
12
|
}
|
|
15
|
-
export declare function CommentsPanel({ view, state,
|
|
13
|
+
export declare function CommentsPanel({ view, state, author, scrollContainer, allCommentsOpen, }: CommentsPanelProps): ReactElement;
|
package/dist/ui/CommentsPanel.js
CHANGED
|
@@ -4,7 +4,6 @@ import { useMemo, useRef, useState } from "react";
|
|
|
4
4
|
import {
|
|
5
5
|
addComment,
|
|
6
6
|
addCommentReply,
|
|
7
|
-
documentComments,
|
|
8
7
|
removeComment,
|
|
9
8
|
removeCommentReply,
|
|
10
9
|
selectComment,
|
|
@@ -12,6 +11,11 @@ import {
|
|
|
12
11
|
updateComment,
|
|
13
12
|
updateCommentReply
|
|
14
13
|
} from "../editor/commands/commentCommands.js";
|
|
14
|
+
import {
|
|
15
|
+
closeCommentComposer,
|
|
16
|
+
commentComposerRange
|
|
17
|
+
} from "../editor/plugins/commentComposer.js";
|
|
18
|
+
import { commentProjection } from "../editor/plugins/commentDecorations.js";
|
|
15
19
|
import { commentOwned } from "../schema/protection.js";
|
|
16
20
|
import { protectionOf } from "../schema/protectionState.js";
|
|
17
21
|
import { editorClassNames } from "../styles/classNames.js";
|
|
@@ -37,19 +41,19 @@ function run(view, command) {
|
|
|
37
41
|
if (applied) view.focus();
|
|
38
42
|
return applied;
|
|
39
43
|
}
|
|
44
|
+
var REFUSED_COMMENT = "This comment could not be added. The text it was written for may have been changed or locked since.";
|
|
45
|
+
var REFUSED_REPLY = "This reply could not be added. The comment it answers may have been changed or deleted since.";
|
|
40
46
|
function sameTarget(left, right) {
|
|
41
47
|
return left?.commentId === right.commentId && left.replyId === right.replyId;
|
|
42
48
|
}
|
|
43
49
|
function CommentsPanel({
|
|
44
50
|
view,
|
|
45
51
|
state,
|
|
46
|
-
composerOpen,
|
|
47
52
|
author,
|
|
48
|
-
closeComposer,
|
|
49
53
|
scrollContainer,
|
|
50
54
|
allCommentsOpen
|
|
51
55
|
}) {
|
|
52
|
-
const comments =
|
|
56
|
+
const comments = commentProjection.read(state).comments;
|
|
53
57
|
const rules = protectionOf(state);
|
|
54
58
|
const writer = author != null && rules.protection !== "readOnly" ? author : null;
|
|
55
59
|
const owned = (authorId) => writer !== null && commentOwned(rules, authorId);
|
|
@@ -57,7 +61,9 @@ function CommentsPanel({
|
|
|
57
61
|
const [editing, setEditing] = useState(null);
|
|
58
62
|
const [draft, setDraft] = useState("");
|
|
59
63
|
const [replying, setReplying] = useState(null);
|
|
60
|
-
const
|
|
64
|
+
const composerRange = commentComposerRange(state);
|
|
65
|
+
const composerOpen = composerRange !== null;
|
|
66
|
+
const composerSelectionPos = composerRange?.from ?? -1;
|
|
61
67
|
const visible = useMemo(
|
|
62
68
|
() => allCommentsOpen ? [...comments].sort((left, right) => {
|
|
63
69
|
const leftTime = Date.parse(left.date ?? "");
|
|
@@ -112,7 +118,7 @@ function CommentsPanel({
|
|
|
112
118
|
className: editorClassNames.commentsCanvas,
|
|
113
119
|
style: { height: allCommentsOpen ? void 0 : `${canvasHeight}px` },
|
|
114
120
|
children: [
|
|
115
|
-
|
|
121
|
+
composerRange !== null && writer !== null && /* @__PURE__ */ jsx(
|
|
116
122
|
"div",
|
|
117
123
|
{
|
|
118
124
|
className: editorClassNames.commentPosition,
|
|
@@ -126,16 +132,19 @@ function CommentsPanel({
|
|
|
126
132
|
author: writer,
|
|
127
133
|
label: "Comment text",
|
|
128
134
|
submitLabel: "Comment",
|
|
129
|
-
onClose:
|
|
135
|
+
onClose: () => run(view, closeCommentComposer),
|
|
130
136
|
onSubmit: (text) => run(
|
|
131
137
|
view,
|
|
132
|
-
addComment(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
addComment(
|
|
139
|
+
{
|
|
140
|
+
text,
|
|
141
|
+
author: writer.name,
|
|
142
|
+
authorId: writer.id,
|
|
143
|
+
initials: writer.initials
|
|
144
|
+
},
|
|
145
|
+
composerRange
|
|
146
|
+
)
|
|
147
|
+
) ? null : REFUSED_COMMENT
|
|
139
148
|
}
|
|
140
149
|
)
|
|
141
150
|
}
|
|
@@ -335,7 +344,7 @@ function CommentsPanel({
|
|
|
335
344
|
authorId: writer.id,
|
|
336
345
|
initials: writer.initials
|
|
337
346
|
})
|
|
338
|
-
)
|
|
347
|
+
) ? null : REFUSED_REPLY
|
|
339
348
|
}
|
|
340
349
|
)
|
|
341
350
|
] })
|
package/dist/ui/NotesPanel.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// src/ui/NotesPanel.tsx
|
|
2
|
-
import {
|
|
2
|
+
import { noteProjection } from "../editor/commands/noteQueries.js";
|
|
3
3
|
import { editorClassNames } from "../styles/classNames.js";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
function NotesPanel({
|
|
6
6
|
state,
|
|
7
7
|
pageWidth
|
|
8
8
|
}) {
|
|
9
|
-
const notes =
|
|
9
|
+
const { notes } = noteProjection.read(state);
|
|
10
10
|
if (notes.length === 0) return null;
|
|
11
11
|
return /* @__PURE__ */ jsxs(
|
|
12
12
|
"section",
|
package/dist/ui/TextMenu.d.ts
CHANGED
|
@@ -9,7 +9,5 @@ export interface TextMenuProps {
|
|
|
9
9
|
anchor: TextMenuAnchor;
|
|
10
10
|
/** Whether the entries that lock and unlock a stretch of text are offered */
|
|
11
11
|
allowLocking?: boolean;
|
|
12
|
-
/** Opens the built-in composer for the selected text. */
|
|
13
|
-
onAddComment?: () => void;
|
|
14
12
|
}
|
|
15
|
-
export declare function TextMenu({ view, state, anchor, allowLocking,
|
|
13
|
+
export declare function TextMenu({ view, state, anchor, allowLocking, }: TextMenuProps): ReactElement;
|
package/dist/ui/TextMenu.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
selectionTouchesLocked,
|
|
18
18
|
unlockSelection
|
|
19
19
|
} from "../editor/commands/lockCommands.js";
|
|
20
|
-
import {
|
|
20
|
+
import { openCommentComposer } from "../editor/plugins/commentComposer.js";
|
|
21
21
|
import {
|
|
22
22
|
closeTextMenu
|
|
23
23
|
} from "../editor/plugins/textContextMenu.js";
|
|
@@ -62,8 +62,13 @@ async function clipboardContent() {
|
|
|
62
62
|
async function pasteFromClipboard(view) {
|
|
63
63
|
const content = await clipboardContent();
|
|
64
64
|
if (!content.html && !content.text) return;
|
|
65
|
+
const data = new DataTransfer();
|
|
66
|
+
if (content.html) data.setData("text/html", content.html);
|
|
67
|
+
if (content.text) data.setData("text/plain", content.text);
|
|
68
|
+
const event = new ClipboardEvent("paste", { clipboardData: data });
|
|
65
69
|
view.focus();
|
|
66
|
-
|
|
70
|
+
if (content.html && view.pasteHTML(content.html, event)) return;
|
|
71
|
+
if (content.text) view.pasteText(content.text, event);
|
|
67
72
|
}
|
|
68
73
|
function lockItem(lock, run) {
|
|
69
74
|
const locking = {
|
|
@@ -90,8 +95,7 @@ function TextMenu({
|
|
|
90
95
|
view,
|
|
91
96
|
state,
|
|
92
97
|
anchor,
|
|
93
|
-
allowLocking = false
|
|
94
|
-
onAddComment
|
|
98
|
+
allowLocking = false
|
|
95
99
|
}) {
|
|
96
100
|
const box = useRef(null);
|
|
97
101
|
const placement = usePanelAtPoint(box, anchor);
|
|
@@ -143,8 +147,8 @@ function TextMenu({
|
|
|
143
147
|
{
|
|
144
148
|
label: "Add comment",
|
|
145
149
|
icon: MessageSquarePlus,
|
|
146
|
-
enabled:
|
|
147
|
-
run: () =>
|
|
150
|
+
enabled: canAddComment(state),
|
|
151
|
+
run: () => run(openCommentComposer)
|
|
148
152
|
}
|
|
149
153
|
]);
|
|
150
154
|
if (allowLocking && bodyOpen) {
|
|
@@ -10,7 +10,12 @@ export interface CommentComposerProps {
|
|
|
10
10
|
author: CommentAuthor;
|
|
11
11
|
label: string;
|
|
12
12
|
submitLabel: string;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Writes the comment, and answers why it was not written where it was not. The text stays in
|
|
15
|
+
* the form then, together with the reason, rather than the form standing there as if nothing
|
|
16
|
+
* had been asked of it.
|
|
17
|
+
*/
|
|
18
|
+
onSubmit: (text: string) => string | null;
|
|
14
19
|
onClose: () => void;
|
|
15
20
|
}
|
|
16
21
|
export declare function CommentComposer({ author, label, submitLabel, onSubmit, onClose, }: CommentComposerProps): ReactElement;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/ui/comments/CommentComposer.tsx
|
|
2
2
|
import {
|
|
3
|
+
useEffect,
|
|
3
4
|
useLayoutEffect,
|
|
4
5
|
useRef,
|
|
5
6
|
useState
|
|
@@ -12,7 +13,15 @@ function FocusedTextarea({
|
|
|
12
13
|
onChange
|
|
13
14
|
}) {
|
|
14
15
|
const input = useRef(null);
|
|
15
|
-
useLayoutEffect(() => input.current?.focus(), []);
|
|
16
|
+
useLayoutEffect(() => input.current?.focus({ preventScroll: true }), []);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const field = input.current;
|
|
19
|
+
if (typeof field?.scrollIntoView !== "function") return;
|
|
20
|
+
const frame = requestAnimationFrame(() => {
|
|
21
|
+
field.scrollIntoView({ block: "nearest" });
|
|
22
|
+
});
|
|
23
|
+
return () => cancelAnimationFrame(frame);
|
|
24
|
+
}, []);
|
|
16
25
|
return /* @__PURE__ */ jsx(
|
|
17
26
|
"textarea",
|
|
18
27
|
{
|
|
@@ -32,13 +41,27 @@ function CommentComposer({
|
|
|
32
41
|
onClose
|
|
33
42
|
}) {
|
|
34
43
|
const [text, setText] = useState("");
|
|
44
|
+
const [refused, setRefused] = useState(null);
|
|
35
45
|
const submit = (event) => {
|
|
36
46
|
event.preventDefault();
|
|
37
|
-
|
|
47
|
+
const reason = onSubmit(text);
|
|
48
|
+
setRefused(reason);
|
|
49
|
+
if (reason === null) onClose();
|
|
38
50
|
};
|
|
39
51
|
return /* @__PURE__ */ jsxs("form", { className: editorClassNames.commentComposer, onSubmit: submit, children: [
|
|
40
52
|
/* @__PURE__ */ jsx("div", { className: editorClassNames.commentMeta, children: author.name }),
|
|
41
|
-
/* @__PURE__ */ jsx(
|
|
53
|
+
/* @__PURE__ */ jsx(
|
|
54
|
+
FocusedTextarea,
|
|
55
|
+
{
|
|
56
|
+
label,
|
|
57
|
+
value: text,
|
|
58
|
+
onChange: (next) => {
|
|
59
|
+
setRefused(null);
|
|
60
|
+
setText(next);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
refused !== null && /* @__PURE__ */ jsx("p", { className: editorClassNames.commentMeta, role: "alert", children: refused }),
|
|
42
65
|
/* @__PURE__ */ jsxs("div", { className: editorClassNames.commentActions, children: [
|
|
43
66
|
/* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, children: "Cancel" }),
|
|
44
67
|
/* @__PURE__ */ jsx(
|
package/package.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Slice } from "prosemirror-model";
|
|
2
|
-
import { type EditorState, Plugin } from "prosemirror-state";
|
|
3
|
-
import type { EditorView } from "prosemirror-view";
|
|
4
|
-
import type { ImageToInsert } from "./insertImage";
|
|
5
|
-
export declare function richHtmlSlice(state: EditorState, document: Document, source: string, images?: ReadonlyMap<string, ImageToInsert>): Slice | null;
|
|
6
|
-
export declare function insertRichHtml(view: EditorView, source: string): boolean;
|
|
7
|
-
export declare function insertClipboardData(view: EditorView, data: {
|
|
8
|
-
html?: string;
|
|
9
|
-
text?: string;
|
|
10
|
-
}): void;
|
|
11
|
-
export declare function externalClipboard(): Plugin;
|