@manuscripts/body-editor 1.11.5 → 1.11.6-LEAN-3307.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.insertTableFootnote = exports.addInlineComment = exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = exports.ignoreAtomBlockNodeForward = exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.ifInTableBody = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertSection = exports.insertGraphicalAbstract = exports.insertInlineFootnote = exports.insertInlineEquation = exports.insertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertFileAsFigure = exports.insertGeneralFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = void 0;
18
+ exports.insertTableFootnote = exports.addInlineComment = exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = exports.ignoreAtomBlockNodeForward = exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.ifInTableBody = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertKeywords = exports.insertContributors = exports.insertAbstract = exports.insertBackMatterSection = exports.insertSection = exports.insertGraphicalAbstract = exports.insertInlineFootnote = exports.insertInlineEquation = exports.insertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertFileAsFigure = exports.insertGeneralFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = void 0;
19
19
  const json_schema_1 = require("@manuscripts/json-schema");
20
20
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
21
21
  const transform_1 = require("@manuscripts/transform");
@@ -362,7 +362,7 @@ const insertInlineFootnote = (kind) => (state, dispatch) => {
362
362
  return true;
363
363
  };
364
364
  exports.insertInlineFootnote = insertInlineFootnote;
365
- const insertGraphicalAbstract = (state, dispatch) => {
365
+ const insertGraphicalAbstract = (state, dispatch, view) => {
366
366
  if ((0, utils_1.getChildOfType)(state.doc, transform_1.schema.nodes.graphical_abstract_section, true)) {
367
367
  return false;
368
368
  }
@@ -375,29 +375,141 @@ const insertGraphicalAbstract = (state, dispatch) => {
375
375
  const tr = state.tr.insert(pos, section);
376
376
  if (dispatch) {
377
377
  const selection = prosemirror_state_1.TextSelection.create(tr.doc, pos + 1);
378
+ if (view) {
379
+ view.focus();
380
+ }
378
381
  dispatch(tr.setSelection(selection).scrollIntoView());
379
382
  }
380
383
  return true;
381
384
  };
382
385
  exports.insertGraphicalAbstract = insertGraphicalAbstract;
383
- const insertSection = (subsection = false) => (state, dispatch) => {
384
- const pos = findPosAfterParentSection(state.selection.$from);
385
- if (pos === null || (0, transform_1.isInBibliographySection)(state.selection.$from)) {
386
+ const insertSection = (subsection = false) => (state, dispatch, view) => {
387
+ let pos = findPosAfterParentSection(state.selection.$from);
388
+ const body = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.body)[0];
389
+ if ((0, transform_1.isInBibliographySection)(state.selection.$from)) {
386
390
  return false;
387
391
  }
392
+ if (pos === null) {
393
+ pos = body.pos + body.node.content.size + 1;
394
+ }
388
395
  const adjustment = subsection ? -1 : 0;
389
396
  const tr = state.tr.insert(pos + adjustment, state.schema.nodes.section.createAndFill());
390
397
  if (dispatch) {
391
398
  const selection = prosemirror_state_1.TextSelection.create(tr.doc, pos + adjustment + 2);
399
+ if (view) {
400
+ view.focus();
401
+ }
392
402
  dispatch(tr.setSelection(selection).scrollIntoView());
393
403
  }
394
404
  return true;
395
405
  };
396
406
  exports.insertSection = insertSection;
407
+ const insertBackMatterSection = (category) => (state, dispatch, view) => {
408
+ const bibliographySection = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.bibliography_section)[0];
409
+ const backmatter = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.backmatter)[0];
410
+ let pos;
411
+ if (bibliographySection) {
412
+ pos = bibliographySection.pos;
413
+ }
414
+ else {
415
+ pos = backmatter.pos + backmatter.node.content.size + 1;
416
+ }
417
+ const tr = state.tr.insert(pos, state.schema.nodes.section.createAndFill({
418
+ category: category,
419
+ }));
420
+ if (dispatch) {
421
+ const selection = prosemirror_state_1.TextSelection.create(tr.doc, pos);
422
+ if (view) {
423
+ view.focus();
424
+ }
425
+ dispatch(tr.setSelection(selection).scrollIntoView());
426
+ }
427
+ return true;
428
+ };
429
+ exports.insertBackMatterSection = insertBackMatterSection;
397
430
  const findSelectedList = (0, prosemirror_utils_1.findParentNodeOfType)([
398
431
  transform_1.schema.nodes.ordered_list,
399
432
  transform_1.schema.nodes.bullet_list,
400
433
  ]);
434
+ const insertAbstract = (state, dispatch, view) => {
435
+ if ((0, utils_1.getMatchingChild)(state.doc, (node) => node.attrs.category === 'MPSectionCategory:abstract', true)) {
436
+ return false;
437
+ }
438
+ const abstracts = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.abstracts)[0];
439
+ const pos = abstracts.pos + 1;
440
+ const section = transform_1.schema.nodes.section.createAndFill({ category: 'MPSectionCategory:abstract' }, [
441
+ transform_1.schema.nodes.section_title.create({}, transform_1.schema.text('Abstract')),
442
+ transform_1.schema.nodes.paragraph.create({ placeholder: 'Type abstract here...' }),
443
+ ]);
444
+ const tr = state.tr.insert(pos, section);
445
+ if (dispatch) {
446
+ const sectionStart = tr.doc.resolve(pos);
447
+ const sectionNode = sectionStart.nodeAfter;
448
+ if (sectionNode && sectionNode.firstChild) {
449
+ const paragraphPos = pos + sectionNode.firstChild.nodeSize + 2;
450
+ const selection = prosemirror_state_1.TextSelection.create(tr.doc, paragraphPos);
451
+ if (view) {
452
+ view.focus();
453
+ }
454
+ dispatch(tr.setSelection(selection).scrollIntoView());
455
+ }
456
+ }
457
+ return true;
458
+ };
459
+ exports.insertAbstract = insertAbstract;
460
+ const insertContributors = (state, dispatch, view) => {
461
+ if ((0, utils_1.getChildOfType)(state.doc, transform_1.schema.nodes.contributors, true)) {
462
+ return false;
463
+ }
464
+ const title = (0, prosemirror_utils_1.findChildrenByType)(state.doc, state.schema.nodes.title)[0];
465
+ const pos = title.pos + title.node.nodeSize;
466
+ const contributors = state.schema.nodes.contributors.create({
467
+ id: '',
468
+ firstInitials: true,
469
+ });
470
+ const affiliations = state.schema.nodes.affiliations.create({ id: '' });
471
+ const fragment = prosemirror_model_1.Fragment.fromArray([contributors, affiliations]);
472
+ const tr = state.tr.insert(pos, fragment);
473
+ if (dispatch) {
474
+ const selection = prosemirror_state_1.NodeSelection.create(tr.doc, pos);
475
+ if (view) {
476
+ view.focus();
477
+ }
478
+ dispatch(tr.setSelection(selection).scrollIntoView());
479
+ }
480
+ return true;
481
+ };
482
+ exports.insertContributors = insertContributors;
483
+ const insertKeywords = (state, dispatch, view) => {
484
+ if ((0, utils_1.getChildOfType)(state.doc, transform_1.schema.nodes.keywords, true)) {
485
+ return false;
486
+ }
487
+ const supplements = (0, prosemirror_utils_1.findChildrenByType)(state.doc, state.schema.nodes.supplements)[0];
488
+ const abstracts = (0, prosemirror_utils_1.findChildrenByType)(state.doc, state.schema.nodes.abstracts)[0];
489
+ let pos;
490
+ if (supplements) {
491
+ pos = supplements.pos + supplements.node.nodeSize;
492
+ }
493
+ else {
494
+ pos = abstracts.pos;
495
+ }
496
+ const keywords = transform_1.schema.nodes.keywords.createAndFill({}, [
497
+ transform_1.schema.nodes.section_title.create({}, transform_1.schema.text('Keywords')),
498
+ transform_1.schema.nodes.keywords_element.create({}, [
499
+ transform_1.schema.nodes.keyword_group.create({}, []),
500
+ ]),
501
+ ]);
502
+ const tr = state.tr.insert(pos, keywords);
503
+ if (dispatch) {
504
+ const selection = prosemirror_state_1.NodeSelection.create(tr.doc, pos);
505
+ if (view) {
506
+ view.focus();
507
+ }
508
+ dispatch(tr.setSelection(selection).scrollIntoView());
509
+ }
510
+ return true;
511
+ };
512
+ exports.insertKeywords = insertKeywords;
401
513
  const findRootList = ($pos) => {
402
514
  for (let i = 0; i < $pos.depth; i++) {
403
515
  const node = $pos.node(i);
@@ -692,14 +804,17 @@ const addNodeComment = (node, state, dispatch) => {
692
804
  };
693
805
  const comment = transform_1.schema.nodes.comment.create(attrs);
694
806
  const comments = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.comments)[0];
695
- const pos = comments.pos + 1;
696
- const tr = state.tr.insert(pos, comment);
697
- const key = (0, comments_1.getCommentKey)(attrs, undefined, node);
698
- (0, comments_2.setCommentSelection)(tr, key, attrs.id, true);
699
- if (dispatch) {
700
- dispatch(tr);
807
+ if (comments) {
808
+ const pos = comments.pos + 1;
809
+ const tr = state.tr.insert(pos, comment);
810
+ const key = (0, comments_1.getCommentKey)(attrs, undefined, node);
811
+ (0, comments_2.setCommentSelection)(tr, key, attrs.id, true);
812
+ if (dispatch) {
813
+ dispatch(tr);
814
+ }
815
+ return true;
701
816
  }
702
- return true;
817
+ return false;
703
818
  };
704
819
  exports.addNodeComment = addNodeComment;
705
820
  const addInlineComment = (state, dispatch) => {
@@ -725,36 +840,39 @@ const addInlineComment = (state, dispatch) => {
725
840
  };
726
841
  const comment = transform_1.schema.nodes.comment.create(attrs);
727
842
  const comments = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.comments)[0];
728
- const pos = comments.pos + 1;
729
- const tr = state.tr.insert(pos, comment);
730
- if (from === to) {
731
- const point = transform_1.schema.nodes.highlight_marker.create({
732
- id: comment.attrs.id,
733
- tid: node.attrs.id,
734
- position: 'point',
735
- });
736
- tr.insert(from, point);
737
- }
738
- else {
739
- const start = transform_1.schema.nodes.highlight_marker.create({
740
- id: comment.attrs.id,
741
- tid: node.attrs.id,
742
- position: 'start',
743
- });
744
- const end = transform_1.schema.nodes.highlight_marker.create({
745
- id: comment.attrs.id,
746
- tid: node.attrs.id,
747
- position: 'end',
748
- });
749
- tr.insert(from, start).insert(to + 1, end);
750
- }
751
- const range = (0, comments_1.getCommentRange)(attrs);
752
- const key = (0, comments_1.getCommentKey)(attrs, range, node);
753
- (0, comments_2.setCommentSelection)(tr, key, attrs.id, true);
754
- if (dispatch) {
755
- dispatch(tr);
843
+ if (comments) {
844
+ const pos = comments.pos + 1;
845
+ const tr = state.tr.insert(pos, comment);
846
+ if (from === to) {
847
+ const point = transform_1.schema.nodes.highlight_marker.create({
848
+ id: comment.attrs.id,
849
+ tid: node.attrs.id,
850
+ position: 'point',
851
+ });
852
+ tr.insert(from, point);
853
+ }
854
+ else {
855
+ const start = transform_1.schema.nodes.highlight_marker.create({
856
+ id: comment.attrs.id,
857
+ tid: node.attrs.id,
858
+ position: 'start',
859
+ });
860
+ const end = transform_1.schema.nodes.highlight_marker.create({
861
+ id: comment.attrs.id,
862
+ tid: node.attrs.id,
863
+ position: 'end',
864
+ });
865
+ tr.insert(from, start).insert(to + 1, end);
866
+ }
867
+ const range = (0, comments_1.getCommentRange)(attrs);
868
+ const key = (0, comments_1.getCommentKey)(attrs, range, node);
869
+ (0, comments_2.setCommentSelection)(tr, key, attrs.id, true);
870
+ if (dispatch) {
871
+ dispatch(tr);
872
+ }
873
+ return true;
756
874
  }
757
- return true;
875
+ return false;
758
876
  };
759
877
  exports.addInlineComment = addInlineComment;
760
878
  const insertTableFootnote = (node, position, view, inlineFootnote) => {
package/dist/cjs/menus.js CHANGED
@@ -72,6 +72,92 @@ const getEditorMenus = (editor) => {
72
72
  label: 'Insert',
73
73
  isEnabled: true,
74
74
  submenu: [
75
+ {
76
+ id: 'front-matter',
77
+ label: 'Article Metadata',
78
+ isEnabled: true,
79
+ submenu: [
80
+ {
81
+ id: 'insert-abstract',
82
+ label: 'Abstract',
83
+ isEnabled: isCommandValid(commands_1.insertAbstract),
84
+ run: doCommand(commands_1.insertAbstract),
85
+ },
86
+ {
87
+ id: 'insert-graphical-abstract',
88
+ label: 'Graphical Abstract',
89
+ isEnabled: isCommandValid(commands_1.insertGraphicalAbstract),
90
+ run: doCommand(commands_1.insertGraphicalAbstract),
91
+ },
92
+ {
93
+ id: 'insert-contributors',
94
+ label: 'Authors & Affiliations',
95
+ isEnabled: isCommandValid(commands_1.insertContributors),
96
+ run: doCommand(commands_1.insertContributors),
97
+ },
98
+ {
99
+ id: 'insert-keywords',
100
+ label: 'Keywords',
101
+ isEnabled: isCommandValid(commands_1.insertKeywords),
102
+ run: doCommand(commands_1.insertKeywords),
103
+ },
104
+ ],
105
+ },
106
+ {
107
+ id: 'back-matter',
108
+ label: 'Author Notes',
109
+ isEnabled: true,
110
+ submenu: [
111
+ {
112
+ id: 'insert-acknowledgements',
113
+ label: 'Acknowledgements',
114
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:acknowledgement')),
115
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:acknowledgement')),
116
+ },
117
+ {
118
+ id: 'insert-availability',
119
+ label: 'Availability',
120
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:availability')),
121
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:availability')),
122
+ },
123
+ {
124
+ id: 'insert-coi-statement',
125
+ label: 'COI Statement',
126
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:competing-interests')),
127
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:competing-interests')),
128
+ },
129
+ {
130
+ id: 'insert-con',
131
+ label: 'Contributed-by Information',
132
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:con')),
133
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:con')),
134
+ },
135
+ {
136
+ id: 'insert-ethics-statement',
137
+ label: 'Ethics Statement',
138
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:ethics-statement')),
139
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:ethics-statement')),
140
+ },
141
+ {
142
+ id: 'insert-financial-disclosure',
143
+ label: 'Financial Disclosure',
144
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:financial-disclosure')),
145
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:financial-disclosure')),
146
+ },
147
+ {
148
+ id: 'insert-supplementary-material',
149
+ label: 'Supplementary Material',
150
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:supplementary-material')),
151
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:supplementary-material')),
152
+ },
153
+ {
154
+ id: 'insert-supported-by',
155
+ label: 'Supported By',
156
+ isEnabled: isCommandValid((0, commands_1.insertBackMatterSection)('MPSectionCategory:supported-by')),
157
+ run: doCommand((0, commands_1.insertBackMatterSection)('MPSectionCategory:supported-by')),
158
+ },
159
+ ],
160
+ },
75
161
  {
76
162
  id: 'insert-section',
77
163
  label: 'Section',
@@ -82,12 +168,6 @@ const getEditorMenus = (editor) => {
82
168
  isEnabled: isCommandValid((0, commands_1.insertSection)()),
83
169
  run: doCommand((0, commands_1.insertSection)()),
84
170
  },
85
- {
86
- id: 'insert-graphical-abstract',
87
- label: 'Graphical Abstract',
88
- isEnabled: isCommandValid(commands_1.insertGraphicalAbstract),
89
- run: doCommand(commands_1.insertGraphicalAbstract),
90
- },
91
171
  {
92
172
  id: 'insert-subsection',
93
173
  label: 'Subsection',
@@ -44,6 +44,7 @@ class ContributorsView extends block_view_1.default {
44
44
  this.updateContents();
45
45
  };
46
46
  this.updateContents = () => {
47
+ var _a;
47
48
  const affs = affiliations_1.affiliationsKey.getState(this.view.state);
48
49
  if (!affs) {
49
50
  return;
@@ -58,6 +59,10 @@ class ContributorsView extends block_view_1.default {
58
59
  this.createEditButton();
59
60
  this.createLegend();
60
61
  this.updateSelection();
62
+ if (((_a = this.container) === null || _a === void 0 ? void 0 : _a.dataset.firstInitials) == 'true') {
63
+ this.handleEdit('');
64
+ this.container.dataset.firstInitials = '';
65
+ }
61
66
  };
62
67
  this.buildAuthors = (affs) => {
63
68
  const wrapper = document.createElement('div');
@@ -131,6 +136,7 @@ class ContributorsView extends block_view_1.default {
131
136
  this.dom.appendChild(this.inner);
132
137
  this.container = document.createElement('div');
133
138
  this.container.classList.add('contributors');
139
+ this.container.setAttribute('data-first-initials', this.node.attrs.firstInitials);
134
140
  this.inner.appendChild(this.container);
135
141
  };
136
142
  this.createDOM = () => {
@@ -25,10 +25,14 @@ class TitleView extends base_node_view_1.BaseNodeView {
25
25
  this.createDOM();
26
26
  };
27
27
  this.createDOM = () => {
28
+ const attrs = this.node.attrs;
28
29
  this.dom = document.createElement('div');
29
30
  this.dom.classList.add('manuscript-title');
30
31
  this.contentDOM = document.createElement('div');
31
32
  this.contentDOM.classList.add('article-titles');
33
+ if (!this.node.childCount && attrs.placeholder) {
34
+ this.contentDOM.setAttribute('data-placeholder', attrs.placeholder);
35
+ }
32
36
  this.dom.appendChild(this.contentDOM);
33
37
  };
34
38
  }
@@ -16,7 +16,7 @@
16
16
  import { buildContribution, ObjectTypes } from '@manuscripts/json-schema';
17
17
  import { skipTracking } from '@manuscripts/track-changes-plugin';
18
18
  import { generateID, isElementNodeType, isFootnoteNode, isInBibliographySection, isListNode, isParagraphNode, isSectionNodeType, schema, } from '@manuscripts/transform';
19
- import { NodeRange } from 'prosemirror-model';
19
+ import { Fragment, NodeRange } from 'prosemirror-model';
20
20
  import { wrapInList } from 'prosemirror-schema-list';
21
21
  import { NodeSelection, TextSelection, } from 'prosemirror-state';
22
22
  import { findWrapping, liftTarget, ReplaceAroundStep, } from 'prosemirror-transform';
@@ -24,7 +24,7 @@ import { findChildrenByType, findParentNodeOfType, } from 'prosemirror-utils';
24
24
  import { getCommentKey, getCommentRange } from './lib/comments';
25
25
  import { isNodeOfType, nearestAncestor } from './lib/helpers';
26
26
  import { isDeleted, isRejectedInsert } from './lib/track-changes-utils';
27
- import { findParentNodeWithId, getChildOfType } from './lib/utils';
27
+ import { findParentNodeWithId, getChildOfType, getMatchingChild, } from './lib/utils';
28
28
  import { setCommentSelection } from './plugins/comments';
29
29
  import { getEditorProps } from './plugins/editor-props';
30
30
  import { getNewFootnotePos } from './plugins/footnotes/footnotes-utils';
@@ -342,7 +342,7 @@ export const insertInlineFootnote = (kind) => (state, dispatch) => {
342
342
  }
343
343
  return true;
344
344
  };
345
- export const insertGraphicalAbstract = (state, dispatch) => {
345
+ export const insertGraphicalAbstract = (state, dispatch, view) => {
346
346
  if (getChildOfType(state.doc, schema.nodes.graphical_abstract_section, true)) {
347
347
  return false;
348
348
  }
@@ -355,19 +355,51 @@ export const insertGraphicalAbstract = (state, dispatch) => {
355
355
  const tr = state.tr.insert(pos, section);
356
356
  if (dispatch) {
357
357
  const selection = TextSelection.create(tr.doc, pos + 1);
358
+ if (view) {
359
+ view.focus();
360
+ }
358
361
  dispatch(tr.setSelection(selection).scrollIntoView());
359
362
  }
360
363
  return true;
361
364
  };
362
- export const insertSection = (subsection = false) => (state, dispatch) => {
363
- const pos = findPosAfterParentSection(state.selection.$from);
364
- if (pos === null || isInBibliographySection(state.selection.$from)) {
365
+ export const insertSection = (subsection = false) => (state, dispatch, view) => {
366
+ let pos = findPosAfterParentSection(state.selection.$from);
367
+ const body = findChildrenByType(state.doc, schema.nodes.body)[0];
368
+ if (isInBibliographySection(state.selection.$from)) {
365
369
  return false;
366
370
  }
371
+ if (pos === null) {
372
+ pos = body.pos + body.node.content.size + 1;
373
+ }
367
374
  const adjustment = subsection ? -1 : 0;
368
375
  const tr = state.tr.insert(pos + adjustment, state.schema.nodes.section.createAndFill());
369
376
  if (dispatch) {
370
377
  const selection = TextSelection.create(tr.doc, pos + adjustment + 2);
378
+ if (view) {
379
+ view.focus();
380
+ }
381
+ dispatch(tr.setSelection(selection).scrollIntoView());
382
+ }
383
+ return true;
384
+ };
385
+ export const insertBackMatterSection = (category) => (state, dispatch, view) => {
386
+ const bibliographySection = findChildrenByType(state.doc, schema.nodes.bibliography_section)[0];
387
+ const backmatter = findChildrenByType(state.doc, schema.nodes.backmatter)[0];
388
+ let pos;
389
+ if (bibliographySection) {
390
+ pos = bibliographySection.pos;
391
+ }
392
+ else {
393
+ pos = backmatter.pos + backmatter.node.content.size + 1;
394
+ }
395
+ const tr = state.tr.insert(pos, state.schema.nodes.section.createAndFill({
396
+ category: category,
397
+ }));
398
+ if (dispatch) {
399
+ const selection = TextSelection.create(tr.doc, pos);
400
+ if (view) {
401
+ view.focus();
402
+ }
371
403
  dispatch(tr.setSelection(selection).scrollIntoView());
372
404
  }
373
405
  return true;
@@ -376,6 +408,82 @@ const findSelectedList = findParentNodeOfType([
376
408
  schema.nodes.ordered_list,
377
409
  schema.nodes.bullet_list,
378
410
  ]);
411
+ export const insertAbstract = (state, dispatch, view) => {
412
+ if (getMatchingChild(state.doc, (node) => node.attrs.category === 'MPSectionCategory:abstract', true)) {
413
+ return false;
414
+ }
415
+ const abstracts = findChildrenByType(state.doc, schema.nodes.abstracts)[0];
416
+ const pos = abstracts.pos + 1;
417
+ const section = schema.nodes.section.createAndFill({ category: 'MPSectionCategory:abstract' }, [
418
+ schema.nodes.section_title.create({}, schema.text('Abstract')),
419
+ schema.nodes.paragraph.create({ placeholder: 'Type abstract here...' }),
420
+ ]);
421
+ const tr = state.tr.insert(pos, section);
422
+ if (dispatch) {
423
+ const sectionStart = tr.doc.resolve(pos);
424
+ const sectionNode = sectionStart.nodeAfter;
425
+ if (sectionNode && sectionNode.firstChild) {
426
+ const paragraphPos = pos + sectionNode.firstChild.nodeSize + 2;
427
+ const selection = TextSelection.create(tr.doc, paragraphPos);
428
+ if (view) {
429
+ view.focus();
430
+ }
431
+ dispatch(tr.setSelection(selection).scrollIntoView());
432
+ }
433
+ }
434
+ return true;
435
+ };
436
+ export const insertContributors = (state, dispatch, view) => {
437
+ if (getChildOfType(state.doc, schema.nodes.contributors, true)) {
438
+ return false;
439
+ }
440
+ const title = findChildrenByType(state.doc, state.schema.nodes.title)[0];
441
+ const pos = title.pos + title.node.nodeSize;
442
+ const contributors = state.schema.nodes.contributors.create({
443
+ id: '',
444
+ firstInitials: true,
445
+ });
446
+ const affiliations = state.schema.nodes.affiliations.create({ id: '' });
447
+ const fragment = Fragment.fromArray([contributors, affiliations]);
448
+ const tr = state.tr.insert(pos, fragment);
449
+ if (dispatch) {
450
+ const selection = NodeSelection.create(tr.doc, pos);
451
+ if (view) {
452
+ view.focus();
453
+ }
454
+ dispatch(tr.setSelection(selection).scrollIntoView());
455
+ }
456
+ return true;
457
+ };
458
+ export const insertKeywords = (state, dispatch, view) => {
459
+ if (getChildOfType(state.doc, schema.nodes.keywords, true)) {
460
+ return false;
461
+ }
462
+ const supplements = findChildrenByType(state.doc, state.schema.nodes.supplements)[0];
463
+ const abstracts = findChildrenByType(state.doc, state.schema.nodes.abstracts)[0];
464
+ let pos;
465
+ if (supplements) {
466
+ pos = supplements.pos + supplements.node.nodeSize;
467
+ }
468
+ else {
469
+ pos = abstracts.pos;
470
+ }
471
+ const keywords = schema.nodes.keywords.createAndFill({}, [
472
+ schema.nodes.section_title.create({}, schema.text('Keywords')),
473
+ schema.nodes.keywords_element.create({}, [
474
+ schema.nodes.keyword_group.create({}, []),
475
+ ]),
476
+ ]);
477
+ const tr = state.tr.insert(pos, keywords);
478
+ if (dispatch) {
479
+ const selection = NodeSelection.create(tr.doc, pos);
480
+ if (view) {
481
+ view.focus();
482
+ }
483
+ dispatch(tr.setSelection(selection).scrollIntoView());
484
+ }
485
+ return true;
486
+ };
379
487
  const findRootList = ($pos) => {
380
488
  for (let i = 0; i < $pos.depth; i++) {
381
489
  const node = $pos.node(i);
@@ -658,14 +766,17 @@ export const addNodeComment = (node, state, dispatch) => {
658
766
  };
659
767
  const comment = schema.nodes.comment.create(attrs);
660
768
  const comments = findChildrenByType(state.doc, schema.nodes.comments)[0];
661
- const pos = comments.pos + 1;
662
- const tr = state.tr.insert(pos, comment);
663
- const key = getCommentKey(attrs, undefined, node);
664
- setCommentSelection(tr, key, attrs.id, true);
665
- if (dispatch) {
666
- dispatch(tr);
769
+ if (comments) {
770
+ const pos = comments.pos + 1;
771
+ const tr = state.tr.insert(pos, comment);
772
+ const key = getCommentKey(attrs, undefined, node);
773
+ setCommentSelection(tr, key, attrs.id, true);
774
+ if (dispatch) {
775
+ dispatch(tr);
776
+ }
777
+ return true;
667
778
  }
668
- return true;
779
+ return false;
669
780
  };
670
781
  export const addInlineComment = (state, dispatch) => {
671
782
  const selection = state.selection;
@@ -690,36 +801,39 @@ export const addInlineComment = (state, dispatch) => {
690
801
  };
691
802
  const comment = schema.nodes.comment.create(attrs);
692
803
  const comments = findChildrenByType(state.doc, schema.nodes.comments)[0];
693
- const pos = comments.pos + 1;
694
- const tr = state.tr.insert(pos, comment);
695
- if (from === to) {
696
- const point = schema.nodes.highlight_marker.create({
697
- id: comment.attrs.id,
698
- tid: node.attrs.id,
699
- position: 'point',
700
- });
701
- tr.insert(from, point);
702
- }
703
- else {
704
- const start = schema.nodes.highlight_marker.create({
705
- id: comment.attrs.id,
706
- tid: node.attrs.id,
707
- position: 'start',
708
- });
709
- const end = schema.nodes.highlight_marker.create({
710
- id: comment.attrs.id,
711
- tid: node.attrs.id,
712
- position: 'end',
713
- });
714
- tr.insert(from, start).insert(to + 1, end);
715
- }
716
- const range = getCommentRange(attrs);
717
- const key = getCommentKey(attrs, range, node);
718
- setCommentSelection(tr, key, attrs.id, true);
719
- if (dispatch) {
720
- dispatch(tr);
804
+ if (comments) {
805
+ const pos = comments.pos + 1;
806
+ const tr = state.tr.insert(pos, comment);
807
+ if (from === to) {
808
+ const point = schema.nodes.highlight_marker.create({
809
+ id: comment.attrs.id,
810
+ tid: node.attrs.id,
811
+ position: 'point',
812
+ });
813
+ tr.insert(from, point);
814
+ }
815
+ else {
816
+ const start = schema.nodes.highlight_marker.create({
817
+ id: comment.attrs.id,
818
+ tid: node.attrs.id,
819
+ position: 'start',
820
+ });
821
+ const end = schema.nodes.highlight_marker.create({
822
+ id: comment.attrs.id,
823
+ tid: node.attrs.id,
824
+ position: 'end',
825
+ });
826
+ tr.insert(from, start).insert(to + 1, end);
827
+ }
828
+ const range = getCommentRange(attrs);
829
+ const key = getCommentKey(attrs, range, node);
830
+ setCommentSelection(tr, key, attrs.id, true);
831
+ if (dispatch) {
832
+ dispatch(tr);
833
+ }
834
+ return true;
721
835
  }
722
- return true;
836
+ return false;
723
837
  };
724
838
  export const insertTableFootnote = (node, position, view, inlineFootnote) => {
725
839
  var _a;
package/dist/es/menus.js CHANGED
@@ -17,7 +17,7 @@ import { schema } from '@manuscripts/transform';
17
17
  import { toggleMark } from 'prosemirror-commands';
18
18
  import { redo, undo } from 'prosemirror-history';
19
19
  import { addColumnAfter, addColumnBefore, addRowAfter, addRowBefore, deleteColumn, deleteRow, } from 'prosemirror-tables';
20
- import { addInlineComment, blockActive, canInsert, ifInTableBody, insertBlock, insertCrossReference, insertGraphicalAbstract, insertInlineCitation, insertInlineEquation, insertInlineFootnote, insertLink, insertList, insertSection, markActive, } from './commands';
20
+ import { addInlineComment, blockActive, canInsert, ifInTableBody, insertAbstract, insertBackMatterSection, insertBlock, insertContributors, insertCrossReference, insertGraphicalAbstract, insertInlineCitation, insertInlineEquation, insertInlineFootnote, insertKeywords, insertLink, insertList, insertSection, markActive, } from './commands';
21
21
  import { deleteClosestParentElement, findClosestParentElementNodeName, } from './lib/hierarchy';
22
22
  export const getEditorMenus = (editor) => {
23
23
  const { isCommandValid, state } = editor;
@@ -69,6 +69,92 @@ export const getEditorMenus = (editor) => {
69
69
  label: 'Insert',
70
70
  isEnabled: true,
71
71
  submenu: [
72
+ {
73
+ id: 'front-matter',
74
+ label: 'Article Metadata',
75
+ isEnabled: true,
76
+ submenu: [
77
+ {
78
+ id: 'insert-abstract',
79
+ label: 'Abstract',
80
+ isEnabled: isCommandValid(insertAbstract),
81
+ run: doCommand(insertAbstract),
82
+ },
83
+ {
84
+ id: 'insert-graphical-abstract',
85
+ label: 'Graphical Abstract',
86
+ isEnabled: isCommandValid(insertGraphicalAbstract),
87
+ run: doCommand(insertGraphicalAbstract),
88
+ },
89
+ {
90
+ id: 'insert-contributors',
91
+ label: 'Authors & Affiliations',
92
+ isEnabled: isCommandValid(insertContributors),
93
+ run: doCommand(insertContributors),
94
+ },
95
+ {
96
+ id: 'insert-keywords',
97
+ label: 'Keywords',
98
+ isEnabled: isCommandValid(insertKeywords),
99
+ run: doCommand(insertKeywords),
100
+ },
101
+ ],
102
+ },
103
+ {
104
+ id: 'back-matter',
105
+ label: 'Author Notes',
106
+ isEnabled: true,
107
+ submenu: [
108
+ {
109
+ id: 'insert-acknowledgements',
110
+ label: 'Acknowledgements',
111
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:acknowledgement')),
112
+ run: doCommand(insertBackMatterSection('MPSectionCategory:acknowledgement')),
113
+ },
114
+ {
115
+ id: 'insert-availability',
116
+ label: 'Availability',
117
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:availability')),
118
+ run: doCommand(insertBackMatterSection('MPSectionCategory:availability')),
119
+ },
120
+ {
121
+ id: 'insert-coi-statement',
122
+ label: 'COI Statement',
123
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:competing-interests')),
124
+ run: doCommand(insertBackMatterSection('MPSectionCategory:competing-interests')),
125
+ },
126
+ {
127
+ id: 'insert-con',
128
+ label: 'Contributed-by Information',
129
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:con')),
130
+ run: doCommand(insertBackMatterSection('MPSectionCategory:con')),
131
+ },
132
+ {
133
+ id: 'insert-ethics-statement',
134
+ label: 'Ethics Statement',
135
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:ethics-statement')),
136
+ run: doCommand(insertBackMatterSection('MPSectionCategory:ethics-statement')),
137
+ },
138
+ {
139
+ id: 'insert-financial-disclosure',
140
+ label: 'Financial Disclosure',
141
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:financial-disclosure')),
142
+ run: doCommand(insertBackMatterSection('MPSectionCategory:financial-disclosure')),
143
+ },
144
+ {
145
+ id: 'insert-supplementary-material',
146
+ label: 'Supplementary Material',
147
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:supplementary-material')),
148
+ run: doCommand(insertBackMatterSection('MPSectionCategory:supplementary-material')),
149
+ },
150
+ {
151
+ id: 'insert-supported-by',
152
+ label: 'Supported By',
153
+ isEnabled: isCommandValid(insertBackMatterSection('MPSectionCategory:supported-by')),
154
+ run: doCommand(insertBackMatterSection('MPSectionCategory:supported-by')),
155
+ },
156
+ ],
157
+ },
72
158
  {
73
159
  id: 'insert-section',
74
160
  label: 'Section',
@@ -79,12 +165,6 @@ export const getEditorMenus = (editor) => {
79
165
  isEnabled: isCommandValid(insertSection()),
80
166
  run: doCommand(insertSection()),
81
167
  },
82
- {
83
- id: 'insert-graphical-abstract',
84
- label: 'Graphical Abstract',
85
- isEnabled: isCommandValid(insertGraphicalAbstract),
86
- run: doCommand(insertGraphicalAbstract),
87
- },
88
168
  {
89
169
  id: 'insert-subsection',
90
170
  label: 'Subsection',
@@ -38,6 +38,7 @@ export class ContributorsView extends BlockView {
38
38
  this.updateContents();
39
39
  };
40
40
  this.updateContents = () => {
41
+ var _a;
41
42
  const affs = affiliationsKey.getState(this.view.state);
42
43
  if (!affs) {
43
44
  return;
@@ -52,6 +53,10 @@ export class ContributorsView extends BlockView {
52
53
  this.createEditButton();
53
54
  this.createLegend();
54
55
  this.updateSelection();
56
+ if (((_a = this.container) === null || _a === void 0 ? void 0 : _a.dataset.firstInitials) == 'true') {
57
+ this.handleEdit('');
58
+ this.container.dataset.firstInitials = '';
59
+ }
55
60
  };
56
61
  this.buildAuthors = (affs) => {
57
62
  const wrapper = document.createElement('div');
@@ -125,6 +130,7 @@ export class ContributorsView extends BlockView {
125
130
  this.dom.appendChild(this.inner);
126
131
  this.container = document.createElement('div');
127
132
  this.container.classList.add('contributors');
133
+ this.container.setAttribute('data-first-initials', this.node.attrs.firstInitials);
128
134
  this.inner.appendChild(this.container);
129
135
  };
130
136
  this.createDOM = () => {
@@ -22,10 +22,14 @@ export class TitleView extends BaseNodeView {
22
22
  this.createDOM();
23
23
  };
24
24
  this.createDOM = () => {
25
+ const attrs = this.node.attrs;
25
26
  this.dom = document.createElement('div');
26
27
  this.dom.classList.add('manuscript-title');
27
28
  this.contentDOM = document.createElement('div');
28
29
  this.contentDOM.classList.add('article-titles');
30
+ if (!this.node.childCount && attrs.placeholder) {
31
+ this.contentDOM.setAttribute('data-placeholder', attrs.placeholder);
32
+ }
29
33
  this.dom.appendChild(this.contentDOM);
30
34
  };
31
35
  }
@@ -38,8 +38,12 @@ export declare const insertInlineCitation: (state: ManuscriptEditorState, dispat
38
38
  export declare const insertCrossReference: (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
39
39
  export declare const insertInlineEquation: (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
40
40
  export declare const insertInlineFootnote: (kind: 'footnote' | 'endnote') => (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
41
- export declare const insertGraphicalAbstract: (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
42
- export declare const insertSection: (subsection?: boolean) => (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
41
+ export declare const insertGraphicalAbstract: (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
42
+ export declare const insertSection: (subsection?: boolean) => (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
43
+ export declare const insertBackMatterSection: (category: string) => (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
44
+ export declare const insertAbstract: (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
45
+ export declare const insertContributors: (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
46
+ export declare const insertKeywords: (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
43
47
  export declare const insertList: (type: ManuscriptNodeType, style?: string) => (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
44
48
  export declare const insertBibliographySection: () => boolean;
45
49
  export declare const insertTOCSection: () => boolean;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@manuscripts/body-editor",
3
3
  "description": "Prosemirror components for editing and viewing manuscripts",
4
- "version": "1.11.5",
4
+ "version": "1.11.6-LEAN-3307.2",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -28,11 +28,11 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@iarna/word-count": "^1.1.2",
31
- "@manuscripts/json-schema": "2.2.8",
32
- "@manuscripts/library": "1.3.7",
33
- "@manuscripts/style-guide": "1.12.13",
31
+ "@manuscripts/json-schema": "2.2.9-LEAN-3307.0",
32
+ "@manuscripts/library": "1.3.8-LEAN-3307.0",
33
+ "@manuscripts/style-guide": "1.12.14-LEAN-3307.0",
34
34
  "@manuscripts/track-changes-plugin": "1.7.12",
35
- "@manuscripts/transform": "2.3.6",
35
+ "@manuscripts/transform": "2.3.7-LEAN-3307.3",
36
36
  "astrocite-eutils": "^0.16.4",
37
37
  "mathjax-full": "^3.2.2",
38
38
  "codemirror": "^5.58.1",
@@ -934,3 +934,7 @@ span.accepted .selected-suggestion,
934
934
  .ProseMirror li.ProseMirror-selectednode:after {
935
935
  content: none;
936
936
  }
937
+
938
+ .ProseMirror .manuscript-title.empty-node .article-titles::before {
939
+ content: attr(data-placeholder);
940
+ }
package/styles/Editor.css CHANGED
@@ -562,6 +562,15 @@
562
562
  .ProseMirror .empty-node:hover::before {
563
563
  color: #6e6e6e;
564
564
  }
565
+ .ProseMirror .empty-node .article-titles::before {
566
+ position: absolute;
567
+ color: #c9c9c9;
568
+ font-style: italic;
569
+ font-family: "PT Sans";
570
+ font-size: 28px;
571
+ font-weight: 400;
572
+ line-height: 40px;
573
+ }
565
574
 
566
575
  .ProseMirror .empty-node[data-placeholder]::before {
567
576
  content: attr(data-placeholder); /* TODO: innerHTML? */