@manuscripts/body-editor 3.17.2 → 3.17.5

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 (38) hide show
  1. package/dist/cjs/commands.js +37 -21
  2. package/dist/cjs/components/references/ReferenceSearch.js +1 -1
  3. package/dist/cjs/configs/editor-views.js +1 -0
  4. package/dist/cjs/lib/__tests__/plugins.test.js +1 -1
  5. package/dist/cjs/lib/context-menu.js +4 -1
  6. package/dist/cjs/menus.js +1 -1
  7. package/dist/cjs/node-type-icons.js +1 -0
  8. package/dist/cjs/plugins/section_category.js +5 -2
  9. package/dist/cjs/plugins/translations.js +8 -20
  10. package/dist/cjs/versions.js +1 -1
  11. package/dist/cjs/views/link_editable.js +55 -4
  12. package/dist/es/commands.js +34 -19
  13. package/dist/es/components/references/ReferenceSearch.js +1 -1
  14. package/dist/es/configs/editor-views.js +1 -0
  15. package/dist/es/lib/__tests__/plugins.test.js +1 -1
  16. package/dist/es/lib/context-menu.js +4 -1
  17. package/dist/es/menus.js +1 -1
  18. package/dist/es/node-type-icons.js +1 -0
  19. package/dist/es/plugins/section_category.js +6 -3
  20. package/dist/es/plugins/translations.js +9 -21
  21. package/dist/es/versions.js +1 -1
  22. package/dist/es/views/link_editable.js +55 -4
  23. package/dist/types/commands.d.ts +3 -2
  24. package/dist/types/versions.d.ts +1 -1
  25. package/dist/types/views/link_editable.d.ts +5 -1
  26. package/package.json +3 -3
  27. package/src/commands.ts +56 -35
  28. package/src/components/references/ReferenceSearch.tsx +1 -8
  29. package/src/configs/editor-views.ts +1 -0
  30. package/src/lib/__tests__/plugins.test.ts +1 -1
  31. package/src/lib/context-menu.ts +4 -1
  32. package/src/menus.tsx +1 -1
  33. package/src/node-type-icons.tsx +1 -0
  34. package/src/plugins/section_category.ts +7 -2
  35. package/src/plugins/translations.ts +16 -27
  36. package/src/versions.ts +1 -1
  37. package/src/views/link_editable.ts +73 -4
  38. package/styles/Editor.css +7 -0
@@ -15,8 +15,8 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.ignoreAtomBlockNodeForward = exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.insertTransGraphicalAbstract = exports.insertTransAbstract = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertKeywords = exports.insertAward = exports.insertAffiliation = exports.insertContributors = exports.insertGraphicalAbstract = exports.insertBackmatterSection = exports.insertAbstractSection = exports.insertSection = exports.insertHeadshotGrid = exports.insertBoxElement = exports.insertInlineFootnote = exports.insertFootnotesElement = exports.insertTableElementFooter = exports.insertInlineEquation = exports.insertCrossReference = exports.canInsertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.findPosBeforeFirstSubsection = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertAttachment = exports.updateSupplementWeblink = exports.insertSupplementWeblink = exports.insertSupplement = exports.insertTable = exports.insertEmbed = exports.insertFigure = exports.insertGeneralTableFootnote = exports.insertInlineTableFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = exports.addToStart = void 0;
19
- exports.paste = exports.copySelection = exports.exitEditorToContainer = exports.ignoreEnterInSubtitles = exports.insertHeroImage = exports.activateSearchReplace = exports.activateSearch = exports.autoComplete = exports.addColumns = exports.addHeaderRow = exports.addRows = exports.addInlineComment = exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = void 0;
18
+ exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.insertTransGraphicalAbstract = exports.insertTransAbstract = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertKeywords = exports.insertAward = exports.insertAffiliation = exports.insertContributors = exports.insertGraphicalAbstract = exports.insertBackmatterSection = exports.insertAbstractSection = exports.insertSection = exports.insertHeadshotGrid = exports.insertBoxElement = exports.insertInlineFootnote = exports.insertFootnotesElement = exports.insertTableElementFooter = exports.insertInlineEquation = exports.insertCrossReference = exports.canInsertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.findPosBeforeFirstSubsection = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertAttachment = exports.updateSupplementWeblink = exports.convertLinkToSupplementWeblink = exports.insertSupplementWeblink = exports.insertSupplement = exports.insertTable = exports.insertEmbed = exports.insertFigure = exports.insertGeneralTableFootnote = exports.insertInlineTableFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = exports.addToStart = void 0;
19
+ exports.paste = exports.copySelection = exports.exitEditorToContainer = exports.ignoreEnterInSubtitles = exports.insertHeroImage = exports.activateSearchReplace = exports.activateSearch = exports.autoComplete = exports.addColumns = exports.addHeaderRow = exports.addRows = exports.addInlineComment = exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = exports.ignoreAtomBlockNodeForward = void 0;
20
20
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
21
21
  const transform_1 = require("@manuscripts/transform");
22
22
  const prosemirror_model_1 = require("prosemirror-model");
@@ -325,6 +325,28 @@ const insertSupplementWeblink = (url, title, view) => {
325
325
  return true;
326
326
  };
327
327
  exports.insertSupplementWeblink = insertSupplementWeblink;
328
+ const convertLinkToSupplementWeblink = (pos, node, view) => {
329
+ const href = node.attrs.href;
330
+ if (!href) {
331
+ return false;
332
+ }
333
+ const text = node.textContent.trim();
334
+ const id = (0, transform_1.generateNodeID)(transform_1.schema.nodes.supplement);
335
+ const supplement = transform_1.schema.nodes.supplement.createAndFill({ id, href }, createAndFillCaption());
336
+ const crossReference = transform_1.schema.nodes.cross_reference.create({
337
+ id: (0, transform_1.generateNodeID)(transform_1.schema.nodes.cross_reference),
338
+ rids: [id],
339
+ label: text,
340
+ });
341
+ const tr = view.state.tr;
342
+ tr.replaceWith(pos, pos + node.nodeSize, crossReference);
343
+ (0, doc_1.upsertSupplementsSection)(tr, supplement);
344
+ tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, pos));
345
+ view.focus();
346
+ view.dispatch(tr);
347
+ return true;
348
+ };
349
+ exports.convertLinkToSupplementWeblink = convertLinkToSupplementWeblink;
328
350
  const updateSupplementWeblink = (pos, url, title, view) => {
329
351
  const node = view.state.doc.nodeAt(pos);
330
352
  if (!node) {
@@ -732,16 +754,14 @@ const insertAbstractSection = (category) => (state, dispatch, view) => {
732
754
  return false;
733
755
  }
734
756
  const abstracts = (0, doc_1.findAbstractsNode)(state.doc);
735
- const sections = (0, prosemirror_utils_1.findChildrenByType)(abstracts.node, transform_1.schema.nodes.section);
736
- if (sections.some((s) => s.node.attrs.category === category.id)) {
757
+ const abstractNodes = (0, prosemirror_utils_1.findChildrenByType)(abstracts.node, transform_1.schema.nodes.abstract);
758
+ if (abstractNodes.some((s) => s.node.attrs.category === category.id)) {
737
759
  return false;
738
760
  }
739
- const ga = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.graphical_abstract_section)[0];
740
- let pos = ga ? ga.pos : abstracts.pos + abstracts.node.content.size + 1;
741
- if (category.id === 'abstract') {
742
- pos = abstracts.pos + 1;
743
- }
744
- const node = transform_1.schema.nodes.section.create({ category: category.id }, [
761
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.abstract, abstracts.node) +
762
+ abstracts.pos +
763
+ 1;
764
+ const node = transform_1.schema.nodes.abstract.create({ category: category.id }, [
745
765
  transform_1.schema.nodes.section_title.create({}, transform_1.schema.text(category.titles[0])),
746
766
  transform_1.schema.nodes.paragraph.create({ placeholder: 'Type abstract here...' }),
747
767
  ]);
@@ -793,9 +813,9 @@ const insertGraphicalAbstract = (category) => (state, dispatch, view) => {
793
813
  if (sections.some((s) => s.node.attrs.category === category.id)) {
794
814
  return false;
795
815
  }
796
- const ga = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.graphical_abstract_section)[0];
797
- let pos = abstracts.pos + abstracts.node.content.size + 1;
798
- pos = ga && category.id === 'abstract-key-image' ? ga.pos : pos;
816
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.graphical_abstract_section, abstracts.node) +
817
+ abstracts.pos +
818
+ 1;
799
819
  const node = transform_1.schema.nodes.graphical_abstract_section.createAndFill({ category: category.id }, [
800
820
  transform_1.schema.nodes.section_title.create({}, transform_1.schema.text(category.titles[0])),
801
821
  createAndFillFigureElement(state),
@@ -1007,7 +1027,7 @@ const insertTOCSection = () => {
1007
1027
  return false;
1008
1028
  };
1009
1029
  exports.insertTOCSection = insertTOCSection;
1010
- const insertTransAbstract = (state, dispatch, category, insertAfterPos) => {
1030
+ const insertTransAbstract = (state, dispatch, category) => {
1011
1031
  if (!(0, template_1.templateAllows)(state, transform_1.schema.nodes.trans_abstract)) {
1012
1032
  return false;
1013
1033
  }
@@ -1022,9 +1042,7 @@ const insertTransAbstract = (state, dispatch, category, insertAfterPos) => {
1022
1042
  category,
1023
1043
  }, [title, paragraph]);
1024
1044
  const abstracts = (0, doc_1.findAbstractsNode)(state.doc);
1025
- const pos = insertAfterPos != null
1026
- ? insertAfterPos
1027
- : abstracts.pos + abstracts.node.nodeSize - 1;
1045
+ const pos = abstracts.node.content.size + abstracts.pos + 1;
1028
1046
  const tr = state.tr.insert(pos, node);
1029
1047
  const selection = prosemirror_state_1.TextSelection.create(tr.doc, pos + 1);
1030
1048
  tr.setSelection(selection).scrollIntoView();
@@ -1032,7 +1050,7 @@ const insertTransAbstract = (state, dispatch, category, insertAfterPos) => {
1032
1050
  return true;
1033
1051
  };
1034
1052
  exports.insertTransAbstract = insertTransAbstract;
1035
- const insertTransGraphicalAbstract = (category, insertAfterPos) => (state, dispatch, view) => {
1053
+ const insertTransGraphicalAbstract = (category) => (state, dispatch, view) => {
1036
1054
  if (!(0, template_1.templateAllows)(state, transform_1.schema.nodes.trans_graphical_abstract)) {
1037
1055
  return false;
1038
1056
  }
@@ -1041,9 +1059,7 @@ const insertTransGraphicalAbstract = (category, insertAfterPos) => (state, dispa
1041
1059
  }
1042
1060
  const lang = state.doc.attrs.primaryLanguageCode || 'en';
1043
1061
  const abstracts = (0, doc_1.findAbstractsNode)(state.doc);
1044
- const pos = insertAfterPos != null
1045
- ? insertAfterPos
1046
- : abstracts.pos + abstracts.node.content.size + 1;
1062
+ const pos = abstracts.node.content.size + abstracts.pos + 1;
1047
1063
  const node = transform_1.schema.nodes.trans_graphical_abstract.createAndFill({
1048
1064
  lang,
1049
1065
  category: category.id,
@@ -89,7 +89,7 @@ const AddReferenceActions = (0, styled_components_1.default)(style_guide_1.Butto
89
89
  }
90
90
  }
91
91
  `;
92
- const ReferenceSearch = ({ query: initialQuery, sources, items, onAdd, onCite, onCancel, }) => {
92
+ const ReferenceSearch = ({ query: initialQuery, sources, items, onAdd, onCite, onCancel }) => {
93
93
  const [query, setQuery] = (0, react_1.useState)(initialQuery || '');
94
94
  const [selections, setSelections] = (0, react_1.useState)(new Map());
95
95
  const toggleSelection = (item) => {
@@ -118,6 +118,7 @@ exports.default = (props, dispatch) => {
118
118
  headshot_element: (0, headshot_element_1.default)(props, dispatch),
119
119
  headshot_image: (0, headshot_image_editable_1.default)(props, dispatch),
120
120
  abstracts: (0, abstracts_1.default)(props),
121
+ abstract: (0, section_1.default)(props),
121
122
  trans_abstract: (0, translated_abstract_editable_1.default)(props),
122
123
  trans_graphical_abstract: (0, trans_graphical_abstract_editable_1.default)(props),
123
124
  attachment: (0, attachment_1.default)(props, dispatch),
@@ -17,7 +17,7 @@ const style_guide_1 = require("@manuscripts/style-guide");
17
17
  const userProfile = {
18
18
  _id: 'MPUserProfile:1',
19
19
  userID: 'MPUser:1',
20
- connectID: 'connectID1'
20
+ connectID: 'connectID1',
21
21
  };
22
22
  const history = (0, history_1.createMemoryHistory)();
23
23
  const buildProps = (doc) => ({
@@ -263,7 +263,10 @@ class ContextMenu {
263
263
  menu.appendChild(this.createMenuSection((section) => {
264
264
  let nodeName = transform_1.nodeNames.get(type) || '';
265
265
  if (type === transform_1.schema.nodes.section_title) {
266
- nodeName = transform_1.nodeNames.get(transform_1.schema.nodes.section);
266
+ const containerType = $pos.parent.type;
267
+ nodeName =
268
+ transform_1.nodeNames.get(containerType) ??
269
+ transform_1.nodeNames.get(transform_1.schema.nodes.section);
267
270
  }
268
271
  section.appendChild(this.createMenuItem(`Delete ${nodeName}`, () => {
269
272
  this.deleteNode(type);
package/dist/cjs/menus.js CHANGED
@@ -489,7 +489,7 @@ const getEditorMenus = (editor) => {
489
489
  };
490
490
  const ABSTRACT_ID = 'abstract';
491
491
  const abstractSection = allAbstractsCategories.find((s) => s.id === ABSTRACT_ID);
492
- const ABSTRACT_GRAPHICAL_ID = 'abstract-graphical';
492
+ const ABSTRACT_GRAPHICAL_ID = 'graphical';
493
493
  const graphicalAbstractSection = allAbstractsCategories.find((s) => s.id === ABSTRACT_GRAPHICAL_ID);
494
494
  const abstractsSubmenuList = allAbstractsCategories.filter((c) => c.id !== ABSTRACT_ID && c.id !== ABSTRACT_GRAPHICAL_ID);
495
495
  const metadata = {
@@ -38,6 +38,7 @@ const icons = new Map([
38
38
  [nodes.paragraph, style_guide_1.OutlineParagraphIcon],
39
39
  [nodes.pullquote_element, style_guide_1.OutlinePullQuoteIcon],
40
40
  [nodes.section, style_guide_1.OutlineSectionIcon],
41
+ [nodes.abstract, style_guide_1.OutlineSectionIcon],
41
42
  [nodes.table_element, style_guide_1.OutlineTableIcon],
42
43
  [nodes.graphical_abstract_section, style_guide_1.OutlineSectionIcon],
43
44
  [nodes.trans_graphical_abstract, style_guide_1.OutlineSectionIcon],
@@ -82,7 +82,7 @@ const buildPluginState = (state, props) => {
82
82
  if (node.type === transform_1.schema.nodes.box_element) {
83
83
  return false;
84
84
  }
85
- if ((0, transform_1.isSectionNode)(node)) {
85
+ if ((0, transform_1.isSectionNode)(node) || (0, transform_1.isAbstractNode)(node)) {
86
86
  const categoryID = node.attrs.category;
87
87
  const category = categories.get(categoryID);
88
88
  const $pos = state.doc.resolve(pos);
@@ -100,7 +100,10 @@ const buildPluginState = (state, props) => {
100
100
  return { decorations: prosemirror_view_1.DecorationSet.create(state.doc, decorations) };
101
101
  };
102
102
  const getUsedSectionCategoryIDs = (state) => {
103
- const sections = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.section);
103
+ const sections = [
104
+ ...(0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.section),
105
+ ...(0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.abstract),
106
+ ];
104
107
  const used = new Set();
105
108
  sections.forEach(({ node }) => {
106
109
  if (node.attrs.category) {
@@ -21,8 +21,8 @@ const prosemirror_view_1 = require("prosemirror-view");
21
21
  const commands_1 = require("../commands");
22
22
  const icons_1 = require("../icons");
23
23
  const languages_1 = require("../lib/languages");
24
- const template_1 = require("../lib/template");
25
24
  const navigation_utils_1 = require("../lib/navigation-utils");
25
+ const template_1 = require("../lib/template");
26
26
  const createMenuItem = (props, contents, handler, isSelected = false, tabIndex) => {
27
27
  const item = document.createElement('div');
28
28
  item.className = `menu-item ${isSelected ? 'selected' : ''}`;
@@ -60,10 +60,6 @@ const createLanguageMenu = (props, selectedCode, onSelect) => {
60
60
  });
61
61
  return { menu, destroy };
62
62
  };
63
- const getInsertionPos = (doc, nodePos) => {
64
- const node = doc.nodeAt(nodePos);
65
- return node ? nodePos + node.nodeSize : null;
66
- };
67
63
  exports.default = (props) => new prosemirror_state_1.Plugin({
68
64
  props: {
69
65
  decorations: (state) => {
@@ -74,14 +70,11 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
74
70
  const canEditTransGraphicalAbstract = can.editArticle &&
75
71
  (0, template_1.templateAllows)(state, transform_1.schema.nodes.trans_graphical_abstract);
76
72
  const widgets = [];
77
- state.doc.descendants((node, pos, parent) => {
78
- const isAbstractSection = (node.type === transform_1.schema.nodes.section ||
79
- node.type === transform_1.schema.nodes.graphical_abstract_section) &&
80
- parent?.type === transform_1.schema.nodes.abstracts;
73
+ state.doc.descendants((node, pos) => {
74
+ const isAbstractSection = (0, transform_1.isAbstractNode)(node) || (0, transform_1.isGraphicalAbstractSectionNode)(node);
81
75
  if (isAbstractSection) {
82
- const isGraphical = node.type === transform_1.schema.nodes.graphical_abstract_section;
83
76
  const category = props.sectionCategories.get(node.attrs.category);
84
- const canEdit = isGraphical
77
+ const canEdit = (0, transform_1.isGraphicalAbstractSectionNode)(node)
85
78
  ? canEditTransGraphicalAbstract &&
86
79
  category &&
87
80
  (0, commands_1.insertTransGraphicalAbstract)(category)(state)
@@ -96,15 +89,11 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
96
89
  const handleActivate = (event) => {
97
90
  event.preventDefault();
98
91
  event.stopPropagation();
99
- const insertPos = getInsertionPos(view.state.doc, pos);
100
- if (insertPos == null) {
101
- return;
102
- }
103
- if (isGraphical && category) {
104
- (0, commands_1.insertTransGraphicalAbstract)(category, insertPos)(view.state, view.dispatch, view);
92
+ if ((0, transform_1.isGraphicalAbstractSectionNode)(node) && category) {
93
+ (0, commands_1.insertTransGraphicalAbstract)(category)(view.state, view.dispatch, view);
105
94
  }
106
95
  else {
107
- (0, commands_1.insertTransAbstract)(view.state, view.dispatch, node.attrs.category, insertPos);
96
+ (0, commands_1.insertTransAbstract)(view.state, view.dispatch, node.attrs.category);
108
97
  }
109
98
  };
110
99
  $span.addEventListener('mousedown', handleActivate);
@@ -113,8 +102,7 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
113
102
  }, { key: `add-trans-${node.attrs.id}-${pos}` }));
114
103
  }
115
104
  }
116
- const isTransNode = node.type === transform_1.schema.nodes.trans_abstract ||
117
- node.type === transform_1.schema.nodes.trans_graphical_abstract;
105
+ const isTransNode = (0, transform_1.isTransAbstractNode)(node) || (0, transform_1.isTransGraphicalAbstractNode)(node);
118
106
  if (isTransNode) {
119
107
  const canEdit = node.type === transform_1.schema.nodes.trans_abstract
120
108
  ? canEditTransAbstract
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MATHJAX_VERSION = exports.VERSION = void 0;
4
- exports.VERSION = '3.17.2';
4
+ exports.VERSION = '3.17.5';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -19,14 +19,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.LinkEditableView = void 0;
22
+ const style_guide_1 = require("@manuscripts/style-guide");
23
+ const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
22
24
  const transform_1 = require("@manuscripts/transform");
23
25
  const prosemirror_state_1 = require("prosemirror-state");
26
+ const commands_1 = require("../commands");
24
27
  const LinkForm_1 = require("../components/views/LinkForm");
25
28
  const url_1 = require("../lib/url");
26
29
  const creators_1 = require("./creators");
27
30
  const link_1 = require("./link");
28
31
  const ReactSubView_1 = __importDefault(require("./ReactSubView"));
29
- const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
30
32
  class LinkEditableView extends link_1.LinkView {
31
33
  constructor() {
32
34
  super(...arguments);
@@ -41,7 +43,7 @@ class LinkEditableView extends link_1.LinkView {
41
43
  this.dom.addEventListener('click', this.handleClick);
42
44
  };
43
45
  this.selectNode = () => {
44
- if (!(0, track_changes_plugin_1.isDeleted)(this.node)) {
46
+ if (!(0, track_changes_plugin_1.isDeleted)(this.node) && !this.node.attrs.href) {
45
47
  this.showForm();
46
48
  }
47
49
  };
@@ -51,6 +53,50 @@ class LinkEditableView extends link_1.LinkView {
51
53
  this.deselectNode = () => {
52
54
  this.closeForm();
53
55
  };
56
+ this.showContextMenu = () => {
57
+ if (!this.props.getCapabilities().editArticle) {
58
+ return;
59
+ }
60
+ this.closeForm();
61
+ const href = this.node.attrs.href;
62
+ const componentProps = {
63
+ actions: [
64
+ {
65
+ label: 'Edit',
66
+ action: this.handleEdit,
67
+ icon: 'Edit',
68
+ },
69
+ {
70
+ label: 'Convert to Weblink',
71
+ action: this.handleConvertToWebLink,
72
+ icon: 'ConvertToWebLink',
73
+ },
74
+ {
75
+ label: 'Open Link',
76
+ action: this.handleOpenLink,
77
+ icon: 'ExternalLink',
78
+ disabled: !(0, url_1.allowedHref)(href),
79
+ },
80
+ ],
81
+ };
82
+ this.popperContainer = (0, ReactSubView_1.default)(this.props, style_guide_1.ContextMenu, componentProps, this.node, this.getPos, this.view, ['context-menu', 'link-context-menu']);
83
+ this.props.popper.show(this.dom, this.popperContainer, 'bottom');
84
+ };
85
+ this.handleEdit = () => {
86
+ this.closeForm();
87
+ this.showForm();
88
+ };
89
+ this.handleConvertToWebLink = () => {
90
+ this.closeForm();
91
+ (0, commands_1.convertLinkToSupplementWeblink)(this.getPos(), this.node, this.view);
92
+ };
93
+ this.handleOpenLink = () => {
94
+ const href = this.node.attrs.href;
95
+ if ((0, url_1.allowedHref)(href)) {
96
+ window.open(href, '_blank', 'noopener,noreferrer');
97
+ }
98
+ this.closeForm();
99
+ };
54
100
  this.showForm = () => {
55
101
  if (!this.props.getCapabilities().editArticle) {
56
102
  return;
@@ -71,9 +117,14 @@ class LinkEditableView extends link_1.LinkView {
71
117
  this.props.popper.show(this.dom, this.popperContainer, 'bottom');
72
118
  };
73
119
  this.handleClick = (e) => {
74
- if (this.props.getCapabilities().editArticle) {
75
- e.preventDefault();
120
+ if (!this.props.getCapabilities().editArticle) {
121
+ return;
122
+ }
123
+ e.preventDefault();
124
+ if ((0, track_changes_plugin_1.isDeleted)(this.node) || !this.node.attrs.href) {
125
+ return;
76
126
  }
127
+ this.showContextMenu();
77
128
  };
78
129
  this.handleCancel = () => {
79
130
  const attrs = this.node.attrs;
@@ -307,6 +307,27 @@ export const insertSupplementWeblink = (url, title, view) => {
307
307
  view.dispatch(tr.scrollIntoView());
308
308
  return true;
309
309
  };
310
+ export const convertLinkToSupplementWeblink = (pos, node, view) => {
311
+ const href = node.attrs.href;
312
+ if (!href) {
313
+ return false;
314
+ }
315
+ const text = node.textContent.trim();
316
+ const id = generateNodeID(schema.nodes.supplement);
317
+ const supplement = schema.nodes.supplement.createAndFill({ id, href }, createAndFillCaption());
318
+ const crossReference = schema.nodes.cross_reference.create({
319
+ id: generateNodeID(schema.nodes.cross_reference),
320
+ rids: [id],
321
+ label: text,
322
+ });
323
+ const tr = view.state.tr;
324
+ tr.replaceWith(pos, pos + node.nodeSize, crossReference);
325
+ upsertSupplementsSection(tr, supplement);
326
+ tr.setSelection(TextSelection.create(tr.doc, pos));
327
+ view.focus();
328
+ view.dispatch(tr);
329
+ return true;
330
+ };
310
331
  export const updateSupplementWeblink = (pos, url, title, view) => {
311
332
  const node = view.state.doc.nodeAt(pos);
312
333
  if (!node) {
@@ -696,16 +717,14 @@ export const insertAbstractSection = (category) => (state, dispatch, view) => {
696
717
  return false;
697
718
  }
698
719
  const abstracts = findAbstractsNode(state.doc);
699
- const sections = findChildrenByType(abstracts.node, schema.nodes.section);
700
- if (sections.some((s) => s.node.attrs.category === category.id)) {
720
+ const abstractNodes = findChildrenByType(abstracts.node, schema.nodes.abstract);
721
+ if (abstractNodes.some((s) => s.node.attrs.category === category.id)) {
701
722
  return false;
702
723
  }
703
- const ga = findChildrenByType(state.doc, schema.nodes.graphical_abstract_section)[0];
704
- let pos = ga ? ga.pos : abstracts.pos + abstracts.node.content.size + 1;
705
- if (category.id === 'abstract') {
706
- pos = abstracts.pos + 1;
707
- }
708
- const node = schema.nodes.section.create({ category: category.id }, [
724
+ const pos = findInsertionPosition(schema.nodes.abstract, abstracts.node) +
725
+ abstracts.pos +
726
+ 1;
727
+ const node = schema.nodes.abstract.create({ category: category.id }, [
709
728
  schema.nodes.section_title.create({}, schema.text(category.titles[0])),
710
729
  schema.nodes.paragraph.create({ placeholder: 'Type abstract here...' }),
711
730
  ]);
@@ -755,9 +774,9 @@ export const insertGraphicalAbstract = (category) => (state, dispatch, view) =>
755
774
  if (sections.some((s) => s.node.attrs.category === category.id)) {
756
775
  return false;
757
776
  }
758
- const ga = findChildrenByType(state.doc, schema.nodes.graphical_abstract_section)[0];
759
- let pos = abstracts.pos + abstracts.node.content.size + 1;
760
- pos = ga && category.id === 'abstract-key-image' ? ga.pos : pos;
777
+ const pos = findInsertionPosition(schema.nodes.graphical_abstract_section, abstracts.node) +
778
+ abstracts.pos +
779
+ 1;
761
780
  const node = schema.nodes.graphical_abstract_section.createAndFill({ category: category.id }, [
762
781
  schema.nodes.section_title.create({}, schema.text(category.titles[0])),
763
782
  createAndFillFigureElement(state),
@@ -961,7 +980,7 @@ export const insertBibliographySection = () => {
961
980
  export const insertTOCSection = () => {
962
981
  return false;
963
982
  };
964
- export const insertTransAbstract = (state, dispatch, category, insertAfterPos) => {
983
+ export const insertTransAbstract = (state, dispatch, category) => {
965
984
  if (!templateAllows(state, schema.nodes.trans_abstract)) {
966
985
  return false;
967
986
  }
@@ -976,16 +995,14 @@ export const insertTransAbstract = (state, dispatch, category, insertAfterPos) =
976
995
  category,
977
996
  }, [title, paragraph]);
978
997
  const abstracts = findAbstractsNode(state.doc);
979
- const pos = insertAfterPos != null
980
- ? insertAfterPos
981
- : abstracts.pos + abstracts.node.nodeSize - 1;
998
+ const pos = abstracts.node.content.size + abstracts.pos + 1;
982
999
  const tr = state.tr.insert(pos, node);
983
1000
  const selection = TextSelection.create(tr.doc, pos + 1);
984
1001
  tr.setSelection(selection).scrollIntoView();
985
1002
  dispatch(tr);
986
1003
  return true;
987
1004
  };
988
- export const insertTransGraphicalAbstract = (category, insertAfterPos) => (state, dispatch, view) => {
1005
+ export const insertTransGraphicalAbstract = (category) => (state, dispatch, view) => {
989
1006
  if (!templateAllows(state, schema.nodes.trans_graphical_abstract)) {
990
1007
  return false;
991
1008
  }
@@ -994,9 +1011,7 @@ export const insertTransGraphicalAbstract = (category, insertAfterPos) => (state
994
1011
  }
995
1012
  const lang = state.doc.attrs.primaryLanguageCode || 'en';
996
1013
  const abstracts = findAbstractsNode(state.doc);
997
- const pos = insertAfterPos != null
998
- ? insertAfterPos
999
- : abstracts.pos + abstracts.node.content.size + 1;
1014
+ const pos = abstracts.node.content.size + abstracts.pos + 1;
1000
1015
  const node = schema.nodes.trans_graphical_abstract.createAndFill({
1001
1016
  lang,
1002
1017
  category: category.id,
@@ -50,7 +50,7 @@ const AddReferenceActions = styled(ButtonGroup) `
50
50
  }
51
51
  }
52
52
  `;
53
- export const ReferenceSearch = ({ query: initialQuery, sources, items, onAdd, onCite, onCancel, }) => {
53
+ export const ReferenceSearch = ({ query: initialQuery, sources, items, onAdd, onCite, onCancel }) => {
54
54
  const [query, setQuery] = useState(initialQuery || '');
55
55
  const [selections, setSelections] = useState(new Map());
56
56
  const toggleSelection = (item) => {
@@ -113,6 +113,7 @@ export default (props, dispatch) => {
113
113
  headshot_element: headshotElement(props, dispatch),
114
114
  headshot_image: headshotImage(props, dispatch),
115
115
  abstracts: abstracts(props),
116
+ abstract: section(props),
116
117
  trans_abstract: transAbstract(props),
117
118
  trans_graphical_abstract: transGraphicalAbstract(props),
118
119
  attachment: attachment(props, dispatch),
@@ -12,7 +12,7 @@ import { defaultTheme } from '@manuscripts/style-guide';
12
12
  const userProfile = {
13
13
  _id: 'MPUserProfile:1',
14
14
  userID: 'MPUser:1',
15
- connectID: 'connectID1'
15
+ connectID: 'connectID1',
16
16
  };
17
17
  const history = createMemoryHistory();
18
18
  const buildProps = (doc) => ({
@@ -259,7 +259,10 @@ export class ContextMenu {
259
259
  menu.appendChild(this.createMenuSection((section) => {
260
260
  let nodeName = nodeNames.get(type) || '';
261
261
  if (type === schema.nodes.section_title) {
262
- nodeName = nodeNames.get(schema.nodes.section);
262
+ const containerType = $pos.parent.type;
263
+ nodeName =
264
+ nodeNames.get(containerType) ??
265
+ nodeNames.get(schema.nodes.section);
263
266
  }
264
267
  section.appendChild(this.createMenuItem(`Delete ${nodeName}`, () => {
265
268
  this.deleteNode(type);
package/dist/es/menus.js CHANGED
@@ -486,7 +486,7 @@ export const getEditorMenus = (editor) => {
486
486
  };
487
487
  const ABSTRACT_ID = 'abstract';
488
488
  const abstractSection = allAbstractsCategories.find((s) => s.id === ABSTRACT_ID);
489
- const ABSTRACT_GRAPHICAL_ID = 'abstract-graphical';
489
+ const ABSTRACT_GRAPHICAL_ID = 'graphical';
490
490
  const graphicalAbstractSection = allAbstractsCategories.find((s) => s.id === ABSTRACT_GRAPHICAL_ID);
491
491
  const abstractsSubmenuList = allAbstractsCategories.filter((c) => c.id !== ABSTRACT_ID && c.id !== ABSTRACT_GRAPHICAL_ID);
492
492
  const metadata = {
@@ -32,6 +32,7 @@ const icons = new Map([
32
32
  [nodes.paragraph, OutlineParagraphIcon],
33
33
  [nodes.pullquote_element, OutlinePullQuoteIcon],
34
34
  [nodes.section, OutlineSectionIcon],
35
+ [nodes.abstract, OutlineSectionIcon],
35
36
  [nodes.table_element, OutlineTableIcon],
36
37
  [nodes.graphical_abstract_section, OutlineSectionIcon],
37
38
  [nodes.trans_graphical_abstract, OutlineSectionIcon],
@@ -1,4 +1,4 @@
1
- import { getGroupCategories, isSectionNode, schema, } from '@manuscripts/transform';
1
+ import { getGroupCategories, isAbstractNode, isSectionNode, schema, } from '@manuscripts/transform';
2
2
  import { Plugin, PluginKey } from 'prosemirror-state';
3
3
  import { findChildrenByType, findParentNodeOfTypeClosestToPos, } from 'prosemirror-utils';
4
4
  import { Decoration, DecorationSet } from 'prosemirror-view';
@@ -79,7 +79,7 @@ const buildPluginState = (state, props) => {
79
79
  if (node.type === schema.nodes.box_element) {
80
80
  return false;
81
81
  }
82
- if (isSectionNode(node)) {
82
+ if (isSectionNode(node) || isAbstractNode(node)) {
83
83
  const categoryID = node.attrs.category;
84
84
  const category = categories.get(categoryID);
85
85
  const $pos = state.doc.resolve(pos);
@@ -97,7 +97,10 @@ const buildPluginState = (state, props) => {
97
97
  return { decorations: DecorationSet.create(state.doc, decorations) };
98
98
  };
99
99
  const getUsedSectionCategoryIDs = (state) => {
100
- const sections = findChildrenByType(state.doc, schema.nodes.section);
100
+ const sections = [
101
+ ...findChildrenByType(state.doc, schema.nodes.section),
102
+ ...findChildrenByType(state.doc, schema.nodes.abstract),
103
+ ];
101
104
  const used = new Set();
102
105
  sections.forEach(({ node }) => {
103
106
  if (node.attrs.category) {
@@ -13,14 +13,14 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { schema } from '@manuscripts/transform';
16
+ import { isAbstractNode, isGraphicalAbstractSectionNode, isTransAbstractNode, isTransGraphicalAbstractNode, schema, } from '@manuscripts/transform';
17
17
  import { Plugin } from 'prosemirror-state';
18
18
  import { Decoration, DecorationSet } from 'prosemirror-view';
19
19
  import { insertTransAbstract, insertTransGraphicalAbstract } from '../commands';
20
20
  import { addAuthorIcon, translateIcon } from '../icons';
21
21
  import { getLanguage, getLanguageLabel } from '../lib/languages';
22
+ import { createKeyboardInteraction, handleEnterKey, } from '../lib/navigation-utils';
22
23
  import { templateAllows } from '../lib/template';
23
- import { handleEnterKey, createKeyboardInteraction, } from '../lib/navigation-utils';
24
24
  const createMenuItem = (props, contents, handler, isSelected = false, tabIndex) => {
25
25
  const item = document.createElement('div');
26
26
  item.className = `menu-item ${isSelected ? 'selected' : ''}`;
@@ -58,10 +58,6 @@ const createLanguageMenu = (props, selectedCode, onSelect) => {
58
58
  });
59
59
  return { menu, destroy };
60
60
  };
61
- const getInsertionPos = (doc, nodePos) => {
62
- const node = doc.nodeAt(nodePos);
63
- return node ? nodePos + node.nodeSize : null;
64
- };
65
61
  export default (props) => new Plugin({
66
62
  props: {
67
63
  decorations: (state) => {
@@ -72,14 +68,11 @@ export default (props) => new Plugin({
72
68
  const canEditTransGraphicalAbstract = can.editArticle &&
73
69
  templateAllows(state, schema.nodes.trans_graphical_abstract);
74
70
  const widgets = [];
75
- state.doc.descendants((node, pos, parent) => {
76
- const isAbstractSection = (node.type === schema.nodes.section ||
77
- node.type === schema.nodes.graphical_abstract_section) &&
78
- parent?.type === schema.nodes.abstracts;
71
+ state.doc.descendants((node, pos) => {
72
+ const isAbstractSection = isAbstractNode(node) || isGraphicalAbstractSectionNode(node);
79
73
  if (isAbstractSection) {
80
- const isGraphical = node.type === schema.nodes.graphical_abstract_section;
81
74
  const category = props.sectionCategories.get(node.attrs.category);
82
- const canEdit = isGraphical
75
+ const canEdit = isGraphicalAbstractSectionNode(node)
83
76
  ? canEditTransGraphicalAbstract &&
84
77
  category &&
85
78
  insertTransGraphicalAbstract(category)(state)
@@ -94,15 +87,11 @@ export default (props) => new Plugin({
94
87
  const handleActivate = (event) => {
95
88
  event.preventDefault();
96
89
  event.stopPropagation();
97
- const insertPos = getInsertionPos(view.state.doc, pos);
98
- if (insertPos == null) {
99
- return;
100
- }
101
- if (isGraphical && category) {
102
- insertTransGraphicalAbstract(category, insertPos)(view.state, view.dispatch, view);
90
+ if (isGraphicalAbstractSectionNode(node) && category) {
91
+ insertTransGraphicalAbstract(category)(view.state, view.dispatch, view);
103
92
  }
104
93
  else {
105
- insertTransAbstract(view.state, view.dispatch, node.attrs.category, insertPos);
94
+ insertTransAbstract(view.state, view.dispatch, node.attrs.category);
106
95
  }
107
96
  };
108
97
  $span.addEventListener('mousedown', handleActivate);
@@ -111,8 +100,7 @@ export default (props) => new Plugin({
111
100
  }, { key: `add-trans-${node.attrs.id}-${pos}` }));
112
101
  }
113
102
  }
114
- const isTransNode = node.type === schema.nodes.trans_abstract ||
115
- node.type === schema.nodes.trans_graphical_abstract;
103
+ const isTransNode = isTransAbstractNode(node) || isTransGraphicalAbstractNode(node);
116
104
  if (isTransNode) {
117
105
  const canEdit = node.type === schema.nodes.trans_abstract
118
106
  ? canEditTransAbstract