@manuscripts/body-editor 3.12.67 → 3.13.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/dist/cjs/components/toolbar/type-selector/styles.js +2 -1
- package/dist/cjs/versions.js +1 -1
- package/dist/es/components/toolbar/type-selector/styles.js +2 -1
- package/dist/es/versions.js +1 -1
- package/dist/types/components/toolbar/type-selector/styles.d.ts +2 -2
- package/dist/types/lib/footnotes.d.ts +4 -2
- package/dist/types/lib/utils.d.ts +5 -4
- package/dist/types/versions.d.ts +1 -1
- package/package.json +37 -36
- package/{dist/es/lib/statistics.js → src/__mocks__/styleMock.ts} +2 -14
- package/src/assets.ts +20 -0
- package/src/classes/collabProvider.ts +38 -0
- package/src/clipboard.ts +54 -0
- package/src/commands.ts +2109 -0
- package/src/components/ChangeHandlingForm.tsx +54 -0
- package/src/components/LanguageDropdown/index.tsx +343 -0
- package/src/components/affiliations/AffiliationForm.tsx +238 -0
- package/src/components/affiliations/AffiliationItem.tsx +151 -0
- package/src/components/affiliations/AffiliationList.tsx +71 -0
- package/src/components/affiliations/AffiliationsModal.tsx +676 -0
- package/src/components/affiliations/AffiliationsPanel.tsx +76 -0
- package/src/components/affiliations/CreateAffiliationModal.tsx +135 -0
- package/src/components/authors/AuthorDetailsForm.tsx +438 -0
- package/src/components/authors/AuthorList.tsx +81 -0
- package/src/components/authors/AuthorsModal.tsx +642 -0
- package/src/components/authors/AuthorsPanel.tsx +69 -0
- package/src/components/authors/CreateAuthorModal.tsx +172 -0
- package/src/components/authors/CreditDrawer.tsx +71 -0
- package/src/components/authors/DraggableAuthor.tsx +228 -0
- package/src/components/authors/useManageAffiliations.tsx +77 -0
- package/src/components/authors/useManageCredit.tsx +63 -0
- package/src/components/authors-affiliations/AuthorsAndAffiliationsModals.tsx +170 -0
- package/src/components/authors-affiliations/GenericPanel.tsx +164 -0
- package/src/components/authors-affiliations/ModalTabs.tsx +100 -0
- package/src/components/awards/AwardForm.tsx +338 -0
- package/src/components/awards/AwardModal.tsx +120 -0
- package/src/components/awards/DeleteAwardDiaolog.tsx +52 -0
- package/src/components/dialog/ConfirmationDialog.tsx +131 -0
- package/src/components/form/CreateModalStyles.tsx +37 -0
- package/src/components/form/FormFooter.tsx +54 -0
- package/src/components/form/FormPlaceholder.tsx +71 -0
- package/src/components/form/ModalFormActions.tsx +88 -0
- package/src/components/form/UnsavedLabel.tsx +49 -0
- package/src/components/hooks/use-debounce.ts +56 -0
- package/src/components/hooks/useAffiliationShowsErrorIndicator.ts +51 -0
- package/src/components/hooks/useAuthorShowsErrorIndicator.ts +73 -0
- package/src/components/keyboard-shortcuts-modal/FormattedShortcut.tsx +56 -0
- package/src/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.tsx +283 -0
- package/src/components/keyboard-shortcuts-modal/keyboard-shortcuts.ts +304 -0
- package/src/components/keywords/AddKeywordInline.tsx +284 -0
- package/src/components/keywords/DeleteKeywordDialog.tsx +52 -0
- package/src/components/modal-drawer/GenericDrawer.tsx +65 -0
- package/src/components/modal-drawer/GenericDrawerGroup.tsx +125 -0
- package/src/components/outline/DraggableTree.tsx +438 -0
- package/src/components/outline/ManuscriptOutline.tsx +127 -0
- package/src/components/outline/Outline.tsx +141 -0
- package/src/components/references/BibliographyItemSource.ts +80 -0
- package/src/components/references/CitationEditor.tsx +301 -0
- package/src/components/references/CitationViewer.tsx +62 -0
- package/src/components/references/ImportBibliographyForm.tsx +232 -0
- package/src/components/references/ImportBibliographyModal.tsx +159 -0
- package/src/components/references/ReferenceForm/PersonDropDown.tsx +93 -0
- package/src/components/references/ReferenceForm/ReferenceForm.tsx +701 -0
- package/src/components/references/ReferenceForm/config.ts +133 -0
- package/src/components/references/ReferenceForm/styled-components.ts +156 -0
- package/src/components/references/ReferenceLine.tsx +43 -0
- package/src/components/references/ReferenceSearch.tsx +163 -0
- package/src/components/references/ReferenceSearchResults.tsx +113 -0
- package/src/components/references/ReferenceSearchResultsPlaceholder.tsx +71 -0
- package/src/components/references/ReferenceSearchSection.tsx +124 -0
- package/src/components/references/ReferencesEditor.tsx +61 -0
- package/src/components/references/ReferencesModal.tsx +352 -0
- package/src/components/references/SearchInput.tsx +98 -0
- package/src/components/toolbar/InsertEmbedDialog.tsx +222 -0
- package/src/components/toolbar/InsertTableDialog.tsx +208 -0
- package/src/components/toolbar/ListMenuItem.tsx +203 -0
- package/src/components/toolbar/helpers.ts +547 -0
- package/src/components/toolbar/type-selector/OptionComponent.tsx +89 -0
- package/src/components/toolbar/type-selector/TypeSelector.tsx +157 -0
- package/src/components/toolbar/type-selector/styles.ts +79 -0
- package/src/components/views/CrossReferenceItems.tsx +199 -0
- package/src/components/views/DeleteEmbedDialog.tsx +83 -0
- package/src/components/views/DeleteFootnoteDialog.tsx +54 -0
- package/src/components/views/FigureDropdown.tsx +423 -0
- package/src/components/views/FootnotesSelector.tsx +255 -0
- package/src/components/views/InsertSpecialCharacter.tsx +245 -0
- package/src/components/views/LinkForm.tsx +220 -0
- package/src/components/views/TableCellContextMenu.tsx +241 -0
- package/src/configs/ManuscriptsEditor.ts +140 -0
- package/src/configs/editor-plugins.ts +119 -0
- package/src/configs/editor-views.ts +139 -0
- package/src/icons.ts +62 -0
- package/src/index.ts +65 -0
- package/src/keys/highlight.ts +65 -0
- package/src/keys/index.ts +33 -0
- package/src/keys/keyword.ts +69 -0
- package/src/keys/list.ts +156 -0
- package/src/keys/misc.ts +112 -0
- package/src/keys/title.ts +221 -0
- package/src/lib/__tests__/__fixtures__/doc.json +388 -0
- package/src/lib/__tests__/__snapshots__/paste.test.ts.snap +24 -0
- package/src/lib/__tests__/authors.test.ts +202 -0
- package/src/lib/__tests__/helpers.test.ts +46 -0
- package/src/lib/__tests__/paste.test.ts +57 -0
- package/src/lib/__tests__/plugins.test.ts +176 -0
- package/src/lib/__tests__/url.test.ts +31 -0
- package/src/lib/array-reducer.ts +68 -0
- package/src/lib/authors-and-affiliations.ts +81 -0
- package/src/lib/authors.ts +67 -0
- package/src/lib/capabilities.ts +55 -0
- package/src/lib/codemirror.ts +37 -0
- package/src/lib/comments.ts +123 -0
- package/src/lib/context-menu.ts +745 -0
- package/src/lib/copy.ts +30 -0
- package/src/lib/crossref.ts +90 -0
- package/src/lib/dnd.ts +29 -0
- package/src/lib/doc.ts +167 -0
- package/src/lib/dompurify.ts +28 -0
- package/src/lib/files.ts +180 -0
- package/src/lib/footnotes.ts +83 -0
- package/src/lib/get-media-type.ts +105 -0
- package/src/lib/helpers.ts +199 -0
- package/src/lib/hierarchy.ts +117 -0
- package/src/lib/languages.ts +37 -0
- package/src/lib/lists.ts +56 -0
- package/src/lib/math.ts +111 -0
- package/src/lib/media.ts +334 -0
- package/src/lib/navigation-utils.ts +235 -0
- package/src/lib/normalize.ts +70 -0
- package/src/lib/paste.ts +304 -0
- package/src/lib/placeholder.ts +32 -0
- package/src/lib/platform.ts +18 -0
- package/src/lib/plugins.ts +22 -0
- package/src/lib/popper.ts +180 -0
- package/src/lib/position-menu.ts +184 -0
- package/src/lib/references.ts +94 -0
- package/src/lib/template.ts +29 -0
- package/src/lib/track-changes-utils.ts +34 -0
- package/{dist/types/lib/statistics.d.ts → src/lib/url.ts} +11 -8
- package/src/lib/use-do-with-debounce.ts +39 -0
- package/src/lib/utils.ts +323 -0
- package/src/lib/view.ts +100 -0
- package/src/menus.tsx +684 -0
- package/src/node-type-icons.tsx +83 -0
- package/src/plugins/__tests__/__fixtures__/deleted-footnote.json +140 -0
- package/src/plugins/__tests__/__fixtures__/inserted-footnote.json +153 -0
- package/src/plugins/__tests__/footnotes.test.ts +67 -0
- package/src/plugins/accessibility_element.ts +219 -0
- package/src/plugins/add-subtitle.ts +102 -0
- package/src/plugins/affiliations.ts +136 -0
- package/src/plugins/alt-titles.ts +219 -0
- package/src/plugins/bibliography.ts +235 -0
- package/src/plugins/comments.ts +328 -0
- package/src/plugins/cross-references.ts +70 -0
- package/src/plugins/detect-inconsistency/detect-inconsistency-utils.ts +102 -0
- package/src/plugins/detect-inconsistency/index.ts +55 -0
- package/src/plugins/detect-inconsistency/validators.ts +283 -0
- package/src/plugins/doi.ts +66 -0
- package/src/plugins/editor-props.ts +39 -0
- package/src/plugins/elements.ts +60 -0
- package/src/plugins/footnotes.ts +298 -0
- package/src/plugins/link.ts +53 -0
- package/src/plugins/lock-body.ts +136 -0
- package/src/plugins/move-node.ts +55 -0
- package/src/plugins/objects.ts +125 -0
- package/src/plugins/paragraphs.ts +90 -0
- package/src/plugins/persist.ts +64 -0
- package/src/plugins/persistent-cursor.ts +66 -0
- package/src/plugins/placeholder.ts +219 -0
- package/src/plugins/prevent-empty.ts +50 -0
- package/src/plugins/search-replace/index.ts +157 -0
- package/src/plugins/search-replace/lib.ts +95 -0
- package/src/plugins/section_category.ts +212 -0
- package/src/plugins/section_title/autocompletion.ts +87 -0
- package/src/plugins/section_title/index.ts +105 -0
- package/src/plugins/selected-suggestion.ts +243 -0
- package/src/plugins/tables-cursor-fix.ts +143 -0
- package/src/plugins/translations.ts +263 -0
- package/src/rules.ts +60 -0
- package/src/selection.ts +112 -0
- package/src/testing/default-capabilities.ts +48 -0
- package/src/testing/default-editor-data.ts +73 -0
- package/src/testing/empty-editor-doc.json +62 -0
- package/src/testing/polyfill-dom.ts +43 -0
- package/src/testing/section-categories.json +161 -0
- package/src/testing/setup-editor.ts +55 -0
- package/src/tests.ts +42 -0
- package/src/toolbar.tsx +259 -0
- package/src/types/@citation-js/core.d.ts +16 -0
- package/src/types/@citation-js/index.d.ts +16 -0
- package/src/types/@citation-js/plugin-bibtex.d.ts +16 -0
- package/src/types/@citation-js/plugin-csl.d.ts +16 -0
- package/src/types/@citation-js/plugin-doi.d.ts +16 -0
- package/src/types/@citation-js/plugin-enw.d.ts +16 -0
- package/src/types/@citation-js/plugin-pubmed.d.ts +16 -0
- package/src/types/@citation-js/plugin-ris.d.ts +16 -0
- package/src/types/citeproc.d.ts +124 -0
- package/src/types/css.d.ts +16 -0
- package/src/types/json.d.ts +17 -0
- package/src/types/prosemirror-dev-tools.d.ts +16 -0
- package/src/types/prosemirror-dropcursor.d.ts +16 -0
- package/src/types/styled-components.d.ts +23 -0
- package/src/types.ts +49 -0
- package/src/useEditor.ts +244 -0
- package/src/versions.ts +3 -0
- package/src/views/ReactSubView.tsx +145 -0
- package/src/views/abstracts.ts +46 -0
- package/src/views/accessibility_element.ts +86 -0
- package/src/views/affiliations.ts +254 -0
- package/src/views/alt_title.ts +85 -0
- package/src/views/alt_titles_section.ts +97 -0
- package/src/views/attachment.ts +160 -0
- package/src/views/attachments.ts +72 -0
- package/src/views/author_notes.ts +96 -0
- package/src/views/award.ts +194 -0
- package/src/views/awards.ts +59 -0
- package/src/views/base_node_view.ts +85 -0
- package/src/views/bibliography_element.ts +313 -0
- package/src/views/block_view.ts +100 -0
- package/src/views/blockquote_element.ts +26 -0
- package/src/views/blockquote_element_editable.ts +24 -0
- package/src/views/box_element.ts +33 -0
- package/src/views/caption.ts +37 -0
- package/src/views/caption_title.ts +33 -0
- package/src/views/citation.ts +67 -0
- package/src/views/citation_editable.ts +312 -0
- package/src/views/contributors.ts +341 -0
- package/src/views/creators.ts +82 -0
- package/src/views/cross_reference.ts +74 -0
- package/src/views/cross_reference_editable.ts +113 -0
- package/src/views/editable_block.ts +141 -0
- package/src/views/embed.ts +345 -0
- package/src/views/empty.ts +26 -0
- package/src/views/equation.ts +47 -0
- package/src/views/equation_editable.ts +84 -0
- package/src/views/equation_element.ts +29 -0
- package/src/views/equation_element_editable.ts +21 -0
- package/src/views/figure.ts +84 -0
- package/src/views/figure_editable.ts +361 -0
- package/src/views/figure_element.ts +197 -0
- package/src/views/figure_element_editable.ts +21 -0
- package/src/views/footnote.ts +236 -0
- package/src/views/footnotes_element.ts +54 -0
- package/src/views/general_table_footnote.ts +140 -0
- package/src/views/hero_image.ts +76 -0
- package/src/views/hero_image_editable.ts +21 -0
- package/src/views/image_element.ts +373 -0
- package/src/views/image_element_editable.ts +21 -0
- package/src/views/inline_equation.ts +47 -0
- package/src/views/inline_equation_editable.ts +70 -0
- package/src/views/inline_footnote.ts +264 -0
- package/src/views/inline_footnote_editable.ts +20 -0
- package/src/views/keyword.ts +127 -0
- package/src/views/keyword_group.ts +109 -0
- package/src/views/link.ts +27 -0
- package/src/views/link_editable.ts +169 -0
- package/src/views/list.ts +46 -0
- package/src/views/list_item.ts +26 -0
- package/src/views/paragraph.ts +26 -0
- package/src/views/paragraph_editable.ts +21 -0
- package/src/views/placeholder.ts +35 -0
- package/src/views/placeholder_element.ts +38 -0
- package/src/views/placeholder_element_editable.ts +21 -0
- package/src/views/pullquote_element.ts +106 -0
- package/src/views/pullquote_element_editable.ts +24 -0
- package/src/views/quote_image_editable.ts +84 -0
- package/src/views/section.ts +64 -0
- package/src/views/section_label.ts +20 -0
- package/src/views/section_title.ts +87 -0
- package/src/views/section_title_editable.ts +21 -0
- package/src/views/subtitle.ts +42 -0
- package/src/views/subtitle_editable.ts +20 -0
- package/src/views/subtitles.ts +34 -0
- package/src/views/subtitles_editable.ts +21 -0
- package/src/views/supplement.ts +236 -0
- package/src/views/supplement_editable.ts +20 -0
- package/src/views/supplements.ts +65 -0
- package/src/views/supplements_editable.ts +21 -0
- package/src/views/table_cell.ts +150 -0
- package/src/views/table_element.ts +33 -0
- package/src/views/table_element_editable.ts +21 -0
- package/src/views/table_element_footer.ts +41 -0
- package/src/views/title.ts +46 -0
- package/src/views/title_editable.ts +20 -0
- package/src/views/trans_graphical_abstract.ts +55 -0
- package/src/views/trans_graphical_abstract_editable.ts +21 -0
- package/src/views/translated_abstract.ts +53 -0
- package/src/views/translated_abstract_editable.ts +21 -0
- package/dist/cjs/lib/statistics.js +0 -38
package/src/lib/paste.ts
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2019 Atypon Systems LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
generateNodeID,
|
|
19
|
+
isElementNodeType,
|
|
20
|
+
ManuscriptEditorView,
|
|
21
|
+
ManuscriptSlice,
|
|
22
|
+
schema,
|
|
23
|
+
} from '@manuscripts/transform'
|
|
24
|
+
import { Fragment, Slice } from 'prosemirror-model'
|
|
25
|
+
import { NodeSelection, TextSelection } from 'prosemirror-state'
|
|
26
|
+
import { findParentNode } from 'prosemirror-utils'
|
|
27
|
+
|
|
28
|
+
import { allowedHref } from './url'
|
|
29
|
+
import { getDeepestSubsectionPosition } from '../components/toolbar/helpers'
|
|
30
|
+
|
|
31
|
+
const removeFirstParagraphIfEmpty = (slice: ManuscriptSlice) => {
|
|
32
|
+
const firstChild = slice.content.firstChild
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
firstChild &&
|
|
36
|
+
firstChild.type === firstChild.type.schema.nodes.paragraph &&
|
|
37
|
+
firstChild.textContent === ''
|
|
38
|
+
) {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
slice.content = slice.content.cut(firstChild.nodeSize)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const updateInlineFootnoteToNewRids = (
|
|
45
|
+
slice: Slice,
|
|
46
|
+
footnotesIdsMap: Map<string, string>
|
|
47
|
+
) => {
|
|
48
|
+
slice.content.descendants((node) => {
|
|
49
|
+
if (node.type === schema.nodes.inline_footnote) {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
node.attrs.rids = node.attrs.rids.map((rid) => footnotesIdsMap.get(rid))
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// remove `id` from pasted content
|
|
57
|
+
const removeIDs = (slice: ManuscriptSlice) => {
|
|
58
|
+
const footnotesIdsMap = new Map()
|
|
59
|
+
slice.content.descendants((node) => {
|
|
60
|
+
let id = null
|
|
61
|
+
if (node.type === schema.nodes.footnote) {
|
|
62
|
+
// will keep id for footnote to not lose connection with inline_footnote
|
|
63
|
+
const newId = generateNodeID(node.type)
|
|
64
|
+
footnotesIdsMap.set(node.attrs.id, newId)
|
|
65
|
+
id = newId
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (node.attrs.id) {
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
node.attrs.id = id
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
updateInlineFootnoteToNewRids(slice, footnotesIdsMap)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const wrapInSection = (slice: ManuscriptSlice) => {
|
|
78
|
+
if (slice.content.firstChild?.type === schema.nodes.section_title) {
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
slice.content = Fragment.from(
|
|
81
|
+
schema.nodes.section.create({}, slice.content)
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const closeAtomSlice = (slice: ManuscriptSlice) => {
|
|
87
|
+
// close slice to prevent drop of node https://github.com/ProseMirror/prosemirror-transform/blob/137ff74738bd1b50d49416cd6cfdbbf52cb059ef/src/replace.ts#L231
|
|
88
|
+
if (slice.content.firstChild?.isAtom) {
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
slice.openStart = 0
|
|
91
|
+
// @ts-ignore
|
|
92
|
+
slice.openEnd = 0
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const transformPasted = (slice: ManuscriptSlice): ManuscriptSlice => {
|
|
97
|
+
wrapInSection(slice)
|
|
98
|
+
|
|
99
|
+
removeFirstParagraphIfEmpty(slice)
|
|
100
|
+
|
|
101
|
+
removeIDs(slice)
|
|
102
|
+
|
|
103
|
+
closeAtomSlice(slice)
|
|
104
|
+
|
|
105
|
+
return slice
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const transformPastedHTML = (html: string) => {
|
|
109
|
+
const doc = new DOMParser().parseFromString(html, 'text/html')
|
|
110
|
+
wrapHeadingWithSection(doc)
|
|
111
|
+
wrapTableWithFigure(doc)
|
|
112
|
+
console.log(doc.body.innerHTML)
|
|
113
|
+
return doc.body.innerHTML
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const wrapHeadingWithSection = (doc: Document) => {
|
|
117
|
+
if (!doc.body.querySelector('h1, h2, h3, h4, h5, h6')) {
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const getHeadingLevel = (element: Element) => {
|
|
122
|
+
const level = element.tagName.match(/^H(\d)$/)
|
|
123
|
+
return level ? parseInt(level[1]) : -1
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const root = doc.createElement('div')
|
|
127
|
+
const google_doc_document = doc.body.querySelector(
|
|
128
|
+
'b[id^="docs-internal-guid"]'
|
|
129
|
+
)
|
|
130
|
+
const elements = Array.from(
|
|
131
|
+
google_doc_document?.children || doc.body.children
|
|
132
|
+
)
|
|
133
|
+
const stack = [{ level: 0, element: root as Element }]
|
|
134
|
+
|
|
135
|
+
for (const element of elements) {
|
|
136
|
+
const headingLevel = getHeadingLevel(element)
|
|
137
|
+
if (headingLevel > 0) {
|
|
138
|
+
while (
|
|
139
|
+
stack.length > 1 &&
|
|
140
|
+
stack[stack.length - 1].level >= headingLevel
|
|
141
|
+
) {
|
|
142
|
+
stack.pop()
|
|
143
|
+
}
|
|
144
|
+
const section = doc.createElement('section')
|
|
145
|
+
section.appendChild(element.cloneNode(true))
|
|
146
|
+
|
|
147
|
+
stack[stack.length - 1].element.appendChild(section)
|
|
148
|
+
stack.push({ level: headingLevel, element: section })
|
|
149
|
+
} else {
|
|
150
|
+
stack[stack.length - 1].element.appendChild(element.cloneNode(true))
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
doc.body.innerHTML = root.innerHTML
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const wrapTableWithFigure = (doc: Document) => {
|
|
158
|
+
// add figure which is table_element node in DOM
|
|
159
|
+
doc.body.querySelectorAll('table').forEach((table) => {
|
|
160
|
+
if (table.parentElement?.tagName !== 'FIGURE') {
|
|
161
|
+
const tableElement = doc.createElement('figure')
|
|
162
|
+
tableElement.className = 'table'
|
|
163
|
+
table.removeAttribute('data-pm-slice')
|
|
164
|
+
table.parentElement?.insertBefore(tableElement, table)
|
|
165
|
+
tableElement.append(table)
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const handlePaste = (
|
|
171
|
+
view: ManuscriptEditorView,
|
|
172
|
+
event: ClipboardEvent,
|
|
173
|
+
slice: Slice
|
|
174
|
+
) => {
|
|
175
|
+
if (event.type !== 'paste') {
|
|
176
|
+
return false
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const {
|
|
180
|
+
state: { tr, selection },
|
|
181
|
+
dispatch,
|
|
182
|
+
} = view
|
|
183
|
+
|
|
184
|
+
tr.setMeta('uiEvent', 'paste')
|
|
185
|
+
tr.setMeta('paste', true)
|
|
186
|
+
|
|
187
|
+
const clipboardData = event.clipboardData
|
|
188
|
+
|
|
189
|
+
const text = clipboardData?.getData('text/plain')
|
|
190
|
+
if (text && allowedHref(text)) {
|
|
191
|
+
const link = schema.nodes.link.create({ href: text }, schema.text(text))
|
|
192
|
+
dispatch(tr.insert(selection.from, Fragment.from(link)).scrollIntoView())
|
|
193
|
+
return true
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// TODO:: all the cases below should be removed when figuring out issue of open slice sides from track-changes plugin
|
|
197
|
+
|
|
198
|
+
const parent = findParentNode(
|
|
199
|
+
(node) =>
|
|
200
|
+
node.type === schema.nodes.section || node.type === schema.nodes.body
|
|
201
|
+
)(selection)
|
|
202
|
+
if (
|
|
203
|
+
(slice.content.firstChild?.type === schema.nodes.section ||
|
|
204
|
+
slice.content.lastChild?.type === schema.nodes.section) &&
|
|
205
|
+
parent
|
|
206
|
+
) {
|
|
207
|
+
const $pos = tr.doc.resolve(
|
|
208
|
+
getDeepestSubsectionPosition(parent.node, parent.pos)
|
|
209
|
+
)
|
|
210
|
+
const insertPos = $pos.end()
|
|
211
|
+
tr.insert(insertPos, slice.content)
|
|
212
|
+
dispatch(
|
|
213
|
+
tr
|
|
214
|
+
.setSelection(
|
|
215
|
+
//@ts-ignore
|
|
216
|
+
NodeSelection.create(tr.doc, tr.steps[0]['to'] || insertPos)
|
|
217
|
+
)
|
|
218
|
+
.scrollIntoView()
|
|
219
|
+
)
|
|
220
|
+
return true
|
|
221
|
+
}
|
|
222
|
+
if (
|
|
223
|
+
(slice.content.firstChild?.type === schema.nodes.body ||
|
|
224
|
+
slice.content.lastChild?.type === schema.nodes.backmatter) &&
|
|
225
|
+
parent
|
|
226
|
+
) {
|
|
227
|
+
const $pos = tr.doc.resolve(
|
|
228
|
+
getDeepestSubsectionPosition(parent.node, parent.pos)
|
|
229
|
+
)
|
|
230
|
+
const insertPos = $pos.end()
|
|
231
|
+
tr.insert(
|
|
232
|
+
insertPos,
|
|
233
|
+
slice.content.firstChild!.content.append(slice.content.lastChild!.content)
|
|
234
|
+
)
|
|
235
|
+
dispatch(
|
|
236
|
+
tr
|
|
237
|
+
.setSelection(
|
|
238
|
+
NodeSelection.create(tr.doc, tr.doc.resolve(insertPos).after())
|
|
239
|
+
)
|
|
240
|
+
.scrollIntoView()
|
|
241
|
+
)
|
|
242
|
+
return true
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (
|
|
246
|
+
selection instanceof TextSelection &&
|
|
247
|
+
isElement(slice) &&
|
|
248
|
+
slice.openStart !== 1 &&
|
|
249
|
+
slice.openEnd !== 1 &&
|
|
250
|
+
selection.$anchor.parentOffset > 0 &&
|
|
251
|
+
selection.$head.parentOffset > 0 &&
|
|
252
|
+
selection.$from.node().type === schema.nodes.paragraph
|
|
253
|
+
) {
|
|
254
|
+
const { $from, $to } = selection
|
|
255
|
+
const side = (
|
|
256
|
+
!$from.parentOffset && $to.index() < $to.parent.childCount ? $from : $to
|
|
257
|
+
).pos
|
|
258
|
+
// will use closed sides for elements(list) as in prosemirror-transform Fitter will
|
|
259
|
+
// join content in the element with side we need to insert depending on the schema,
|
|
260
|
+
// so for list first list item will be joined and that will make it hard for us
|
|
261
|
+
// to tracked and required changes in the schema
|
|
262
|
+
tr.replace(side, side, new Slice(slice.content, 0, 0))
|
|
263
|
+
dispatch(
|
|
264
|
+
tr.setSelection(TextSelection.create(tr.doc, side + 1)).scrollIntoView()
|
|
265
|
+
)
|
|
266
|
+
return true
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (
|
|
270
|
+
selection instanceof TextSelection &&
|
|
271
|
+
selection.$from.depth === slice.openStart &&
|
|
272
|
+
selection.$anchor.parentOffset === 0 &&
|
|
273
|
+
selection.$head.parentOffset === 0 &&
|
|
274
|
+
selection.$from.node().type === schema.nodes.paragraph
|
|
275
|
+
) {
|
|
276
|
+
const { $from, $to } = selection
|
|
277
|
+
const side =
|
|
278
|
+
(!$from.parentOffset && $to.index() < $to.parent.childCount ? $from : $to)
|
|
279
|
+
.pos - 1
|
|
280
|
+
if (isElement(slice) && slice.openStart !== 1 && slice.openEnd !== 1) {
|
|
281
|
+
tr.replace(side, side, new Slice(slice.content, 0, 0))
|
|
282
|
+
} else {
|
|
283
|
+
tr.replace(side, side, slice)
|
|
284
|
+
}
|
|
285
|
+
dispatch(
|
|
286
|
+
tr.setSelection(TextSelection.create(tr.doc, side + 1)).scrollIntoView()
|
|
287
|
+
)
|
|
288
|
+
return true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return false
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const isElement = (slice: Slice) => {
|
|
295
|
+
const { firstChild, lastChild } = slice.content
|
|
296
|
+
return (
|
|
297
|
+
(firstChild &&
|
|
298
|
+
isElementNodeType(firstChild.type) &&
|
|
299
|
+
firstChild.type !== schema.nodes.paragraph) ||
|
|
300
|
+
(lastChild &&
|
|
301
|
+
isElementNodeType(lastChild.type) &&
|
|
302
|
+
lastChild.type !== schema.nodes.paragraph)
|
|
303
|
+
)
|
|
304
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2019 Atypon Systems LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export function createPlaceholderContent(label = 'a component') {
|
|
18
|
+
const el = document.createElement('div')
|
|
19
|
+
el.innerHTML = `
|
|
20
|
+
<div class="placeholder-item-icon">
|
|
21
|
+
<svg width="24" height="24">
|
|
22
|
+
<path d="M12 1.5c5.799 0 10.5 4.701 10.5 10.5S17.799 22.5 12 22.5 1.5 17.799 1.5 12 6.2 1.5 12 1.5zM12 0c6.627 0 12 5.373 12 12s-5.373 12-12 12S0 18.627 0 12 5.372 0 12 0zm0 18.2a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM12.02 6a.9.9 0 0 0-.9.9v7.2a.9.9 0 1 0 1.8 0V6.9a.9.9 0 0 0-.9-.9z" fill="#DC5030" fill-rule="evenodd"/>
|
|
23
|
+
</svg>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="placeholder-item-message">
|
|
26
|
+
<div class="message-content">
|
|
27
|
+
A problem occured while loading ${label}. If the problem persists please contact support.</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
`
|
|
31
|
+
return el
|
|
32
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2019 Atypon Systems LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export const isMac =
|
|
18
|
+
typeof navigator !== 'undefined' && /Mac/.test(navigator.userAgent)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2024 Atypon Systems LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { Transaction } from 'prosemirror-state'
|
|
17
|
+
|
|
18
|
+
export const INIT_META = 'INIT'
|
|
19
|
+
|
|
20
|
+
export const isInit = (tr: Transaction) => {
|
|
21
|
+
return tr.getMeta(INIT_META)
|
|
22
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2019 Atypon Systems LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
createPopper,
|
|
19
|
+
Instance,
|
|
20
|
+
Placement,
|
|
21
|
+
StrictModifiers,
|
|
22
|
+
} from '@popperjs/core'
|
|
23
|
+
import { createKeyboardInteraction } from './navigation-utils'
|
|
24
|
+
|
|
25
|
+
export class PopperManager {
|
|
26
|
+
private activePopper?: Instance
|
|
27
|
+
private handleDocumentClick?: (e: Event) => void
|
|
28
|
+
private triggerElement?: Element
|
|
29
|
+
private container?: HTMLElement
|
|
30
|
+
|
|
31
|
+
public show(
|
|
32
|
+
target: Element,
|
|
33
|
+
contents: HTMLElement,
|
|
34
|
+
placement: Placement = 'bottom',
|
|
35
|
+
showArrow = true,
|
|
36
|
+
modifiers: Array<Partial<StrictModifiers>> = [],
|
|
37
|
+
autoFocus = true
|
|
38
|
+
) {
|
|
39
|
+
// destroy any existing popper first
|
|
40
|
+
// checking activePopper is in destroy() method
|
|
41
|
+
this.destroy()
|
|
42
|
+
|
|
43
|
+
// Store the trigger element to return focus later
|
|
44
|
+
this.triggerElement = target
|
|
45
|
+
|
|
46
|
+
window.requestAnimationFrame(() => {
|
|
47
|
+
const container = document.createElement('div')
|
|
48
|
+
container.className = 'popper'
|
|
49
|
+
this.container = container
|
|
50
|
+
|
|
51
|
+
container.addEventListener('click', (e) => {
|
|
52
|
+
e.stopPropagation()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const closeAndRestoreFocus = (e: KeyboardEvent) => {
|
|
56
|
+
e.preventDefault()
|
|
57
|
+
e.stopPropagation()
|
|
58
|
+
this.destroy()
|
|
59
|
+
if (this.triggerElement instanceof HTMLElement) {
|
|
60
|
+
this.triggerElement.focus()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const isMenu =
|
|
64
|
+
contents.classList.contains('context-menu') ||
|
|
65
|
+
contents.classList.contains('menu')
|
|
66
|
+
createKeyboardInteraction({
|
|
67
|
+
container,
|
|
68
|
+
additionalKeys: {
|
|
69
|
+
Escape: closeAndRestoreFocus,
|
|
70
|
+
Tab: isMenu ? closeAndRestoreFocus : undefined,
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
if (showArrow) {
|
|
75
|
+
const arrow = document.createElement('div')
|
|
76
|
+
arrow.className = 'popper-arrow'
|
|
77
|
+
container.appendChild(arrow)
|
|
78
|
+
modifiers.push({
|
|
79
|
+
name: 'arrow',
|
|
80
|
+
options: {
|
|
81
|
+
element: arrow,
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
} else {
|
|
85
|
+
modifiers.push({
|
|
86
|
+
name: 'arrow',
|
|
87
|
+
options: {
|
|
88
|
+
element: null,
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
container.appendChild(contents)
|
|
94
|
+
document.body.appendChild(container)
|
|
95
|
+
|
|
96
|
+
this.activePopper = createPopper(target, container, {
|
|
97
|
+
placement,
|
|
98
|
+
modifiers,
|
|
99
|
+
onFirstUpdate: () => {
|
|
100
|
+
this.addContainerClass(target)
|
|
101
|
+
this.focusInput(container, autoFocus)
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
this.handleDocumentClick = (e) => {
|
|
106
|
+
const node = e.target as Node
|
|
107
|
+
if (!container.contains(node) && !target.contains(node)) {
|
|
108
|
+
this.destroy()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// add EventListener for checking if click was done outside of editor
|
|
112
|
+
// only if popper has class 'context-menu'
|
|
113
|
+
if (
|
|
114
|
+
contents.classList.contains('context-menu') ||
|
|
115
|
+
contents.classList.contains('language') ||
|
|
116
|
+
contents.classList.contains('section-category')
|
|
117
|
+
) {
|
|
118
|
+
window.addEventListener('click', this.handleDocumentClick)
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public destroy() {
|
|
124
|
+
if (this.activePopper) {
|
|
125
|
+
this.removeContainerClass(
|
|
126
|
+
this.activePopper.state.elements.reference as Element
|
|
127
|
+
)
|
|
128
|
+
this.activePopper.destroy()
|
|
129
|
+
this.activePopper.state.elements.popper.remove()
|
|
130
|
+
if (this.handleDocumentClick) {
|
|
131
|
+
window.removeEventListener('click', this.handleDocumentClick)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
delete this.activePopper
|
|
135
|
+
delete this.container
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public getContainer(): HTMLElement | undefined {
|
|
140
|
+
return this.container
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public update() {
|
|
144
|
+
if (this.activePopper) {
|
|
145
|
+
this.activePopper.update()
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public isActive = () => !!this.activePopper
|
|
150
|
+
|
|
151
|
+
private focusInput(container: HTMLDivElement, autoFocus = true) {
|
|
152
|
+
const input = container.querySelector('input') as HTMLElement | null
|
|
153
|
+
if (input) {
|
|
154
|
+
input.focus()
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
if (autoFocus) {
|
|
158
|
+
const button = container.querySelector(
|
|
159
|
+
'button:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
160
|
+
) as HTMLElement | null
|
|
161
|
+
button?.focus()
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private addContainerClass(referenceElement: Element) {
|
|
166
|
+
const container = referenceElement.closest('.ProseMirror')
|
|
167
|
+
|
|
168
|
+
if (container) {
|
|
169
|
+
container.classList.add('popper-open')
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private removeContainerClass(referenceElement: Element) {
|
|
174
|
+
const container = referenceElement.closest('.ProseMirror')
|
|
175
|
+
|
|
176
|
+
if (container) {
|
|
177
|
+
container.classList.remove('popper-open')
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|