@manuscripts/body-editor 3.5.20 → 3.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -67,9 +67,19 @@ const addToStart = (state, dispatch) => {
67
67
  exports.addToStart = addToStart;
68
68
  const markActive = (type) => (state) => {
69
69
  const { from, $from, to, empty } = state.selection;
70
+ let hasMark = false;
71
+ state.doc.nodesBetween(from, to, (node) => {
72
+ if (node.isText) {
73
+ node.marks.forEach((m) => {
74
+ if (m.type === type && !(0, track_changes_utils_1.isDeleted)(m)) {
75
+ hasMark = true;
76
+ }
77
+ });
78
+ }
79
+ });
70
80
  return empty
71
81
  ? Boolean(type.isInSet(state.storedMarks || $from.marks()))
72
- : state.doc.rangeHasMark(from, to, type);
82
+ : state.doc.rangeHasMark(from, to, type) && hasMark;
73
83
  };
74
84
  exports.markActive = markActive;
75
85
  const isNodeSelection = (selection) => selection instanceof prosemirror_state_1.NodeSelection;
@@ -715,8 +725,7 @@ const insertContributors = (state, dispatch, view) => {
715
725
  if ((0, utils_1.getChildOfType)(state.doc, transform_1.schema.nodes.contributors, true)) {
716
726
  return false;
717
727
  }
718
- const title = (0, utils_1.getLastTitleNode)(state);
719
- const pos = title.pos + title.node.nodeSize;
728
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.contributors, state.doc);
720
729
  const contributors = state.schema.nodes.contributors.create({
721
730
  id: '',
722
731
  });
@@ -735,12 +744,7 @@ const insertAffiliation = (state, dispatch, view) => {
735
744
  if ((0, utils_1.getChildOfType)(state.doc, transform_1.schema.nodes.affiliations, true)) {
736
745
  return false;
737
746
  }
738
- const title = (0, utils_1.getLastTitleNode)(state);
739
- let pos = title.pos + title.node.nodeSize;
740
- const contributors = (0, prosemirror_utils_1.findChildrenByType)(state.doc, state.schema.nodes.contributors)[0];
741
- if (contributors) {
742
- pos = contributors.pos + contributors.node.nodeSize;
743
- }
747
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.affiliations, state.doc);
744
748
  const affiliations = state.schema.nodes.affiliations.create({
745
749
  id: '',
746
750
  });
@@ -773,8 +777,7 @@ const insertKeywords = (state, dispatch, view) => {
773
777
  if ((0, utils_1.getChildOfType)(state.doc, transform_1.schema.nodes.keywords, true)) {
774
778
  return false;
775
779
  }
776
- const abstracts = (0, prosemirror_utils_1.findChildrenByType)(state.doc, state.schema.nodes.abstracts)[0];
777
- const pos = abstracts.pos;
780
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.keywords, state.doc);
778
781
  const keywords = transform_1.schema.nodes.keywords.createAndFill({}, [
779
782
  transform_1.schema.nodes.section_title.create({}, transform_1.schema.text('Keywords')),
780
783
  transform_1.schema.nodes.keywords_element.create({}, [
@@ -1290,8 +1293,7 @@ const createHeroImage = (attrs) => transform_1.schema.nodes.hero_image.create({
1290
1293
  transform_1.schema.nodes.long_desc.create(),
1291
1294
  ]);
1292
1295
  const insertHeroImage = () => (state, dispatch, view) => {
1293
- const comments = (0, prosemirror_utils_1.findChildrenByType)(state.doc, transform_1.schema.nodes.comments)[0];
1294
- const position = comments.pos;
1296
+ const position = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.hero_image, state.doc);
1295
1297
  view?.focus();
1296
1298
  (0, exports.createBlock)(transform_1.schema.nodes.hero_image, position, state, dispatch);
1297
1299
  return true;
@@ -3,26 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findNodeByID = exports.findGraphicalAbstractFigureElement = exports.findFootnotesSection = exports.findBibliographySection = exports.findBackmatter = exports.findBody = exports.findAbstractsNode = exports.insertFootnotesSection = exports.insertAttachmentsNode = exports.insertSupplementsNode = exports.insertAwardsNode = void 0;
4
4
  const transform_1 = require("@manuscripts/transform");
5
5
  const prosemirror_utils_1 = require("prosemirror-utils");
6
+ const utils_1 = require("./utils");
6
7
  const insertAwardsNode = (tr) => {
7
8
  const doc = tr.doc;
8
9
  const awards = (0, prosemirror_utils_1.findChildrenByType)(doc, transform_1.schema.nodes.awards)[0];
9
10
  if (awards) {
10
11
  return awards;
11
12
  }
12
- const positions = [];
13
- const possibleNodesTypes = [
14
- 'doi',
15
- 'keywords',
16
- 'supplements',
17
- 'abstracts',
18
- 'body',
19
- ];
20
- doc.descendants((node, pos) => {
21
- if (possibleNodesTypes.includes(node.type.name)) {
22
- positions.push(pos);
23
- }
24
- });
25
- const pos = positions.length === 0 ? 0 : Math.min(...positions);
13
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.awards, doc);
26
14
  const node = transform_1.schema.nodes.awards.createAndFill();
27
15
  tr.insert(pos, node);
28
16
  return {
@@ -37,8 +25,7 @@ const insertSupplementsNode = (tr) => {
37
25
  if (supplements) {
38
26
  return supplements;
39
27
  }
40
- const backmatter = (0, exports.findBackmatter)(doc);
41
- const pos = backmatter.pos + backmatter.node.content.size + 1;
28
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.supplements, doc);
42
29
  const node = transform_1.schema.nodes.supplements.createAndFill();
43
30
  tr.insert(pos, node);
44
31
  return {
@@ -55,8 +42,7 @@ const insertAttachmentsNode = (tr) => {
55
42
  pos: attachmentsNodes[0].pos,
56
43
  };
57
44
  }
58
- const comments = (0, prosemirror_utils_1.findChildrenByType)(tr.doc, transform_1.schema.nodes.comments)[0];
59
- const pos = comments.pos + comments.node.content.size;
45
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.attachments, tr.doc);
60
46
  const node = transform_1.schema.nodes.attachments.create({
61
47
  id: (0, transform_1.generateNodeID)(transform_1.schema.nodes.attachments),
62
48
  });
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.getLastTitleNode = exports.filterBlockNodes = exports.getInsertPos = exports.createToggleButton = exports.isEditAllowed = exports.isBodyLocked = exports.cleanItemValues = exports.shouldRenderField = exports.hasParent = exports.isNotNull = exports.createHeader = exports.isSelectionInBody = exports.isSelectionInNode = exports.isChildOfNodeTypes = exports.findParentElement = exports.findParentSection = exports.findParentNodeWithIdValue = exports.findParentNodeWithId = exports.getChildOfType = exports.getMatchingDescendant = exports.getMatchingChild = void 0;
18
+ exports.getLastTitleNode = exports.filterBlockNodes = exports.findInsertionPosition = exports.getInsertPos = exports.createToggleButton = exports.isEditAllowed = exports.isBodyLocked = exports.cleanItemValues = exports.shouldRenderField = exports.hasParent = exports.isNotNull = exports.createHeader = exports.isSelectionInBody = exports.isSelectionInNode = exports.isChildOfNodeTypes = exports.findParentElement = exports.findParentSection = exports.findParentNodeWithIdValue = exports.findParentNodeWithId = exports.getChildOfType = exports.getMatchingDescendant = exports.getMatchingChild = void 0;
19
19
  exports.iterateChildren = iterateChildren;
20
20
  const transform_1 = require("@manuscripts/transform");
21
21
  const prosemirror_model_1 = require("prosemirror-model");
@@ -174,6 +174,16 @@ const getInsertPos = (type, parent, pos) => {
174
174
  return insertPos;
175
175
  };
176
176
  exports.getInsertPos = getInsertPos;
177
+ const findInsertionPosition = (type, doc) => {
178
+ let insertPos = 0;
179
+ doc.forEach((child, offset, index) => {
180
+ if (doc.canReplaceWith(index, index, type)) {
181
+ insertPos = offset;
182
+ }
183
+ });
184
+ return insertPos;
185
+ };
186
+ exports.findInsertionPosition = findInsertionPosition;
177
187
  const filterBlockNodes = (fragment, predicate) => {
178
188
  const updatedNodes = [];
179
189
  fragment.forEach((child) => {
@@ -20,6 +20,7 @@ const prosemirror_state_1 = require("prosemirror-state");
20
20
  const prosemirror_view_1 = require("prosemirror-view");
21
21
  const uuid_1 = require("uuid");
22
22
  const icons_1 = require("../icons");
23
+ const utils_1 = require("../lib/utils");
23
24
  const createAddSubtitleButton = (handler) => {
24
25
  const button = document.createElement('span');
25
26
  button.className = 'add-subtitle';
@@ -54,8 +55,9 @@ exports.default = () => new prosemirror_state_1.Plugin({
54
55
  prosemirror_view_1.Decoration.widget(titleEndPos, (view) => {
55
56
  return createAddSubtitleButton(() => {
56
57
  const subtitlesNode = transform_1.schema.nodes.subtitles.create({ id: (0, uuid_1.v4)() }, [transform_1.schema.nodes.subtitle.create({ id: (0, uuid_1.v4)() })]);
57
- const tr = view.state.tr.insert(titleEndPos, subtitlesNode);
58
- const subtitlePos = titleEndPos + 1;
58
+ const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.subtitles, state.doc);
59
+ const tr = view.state.tr.insert(pos, subtitlesNode);
60
+ const subtitlePos = pos + 1;
59
61
  tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, subtitlePos));
60
62
  view.dispatch(tr);
61
63
  view.focus();
@@ -79,21 +79,20 @@ exports.default = () => {
79
79
  !exports.altTitlesKey.getState(newState)) {
80
80
  return null;
81
81
  }
82
- const { title, subtitles, runningTitle, shortTitle, altTitlesSection } = exports.altTitlesKey.getState(newState);
82
+ const { title, runningTitle, shortTitle, altTitlesSection } = exports.altTitlesKey.getState(newState);
83
83
  const schema = newState.schema;
84
84
  if (!title) {
85
85
  return null;
86
86
  }
87
87
  if (!altTitlesSection) {
88
- const prev = subtitles || title;
89
- const titleEnd = prev[0].nodeSize + prev[1];
88
+ const pos = (0, utils_1.findInsertionPosition)(schema.nodes.alt_titles, tr.doc);
90
89
  const section = schema.nodes.alt_titles.create({}, [
91
90
  schema.nodes.alt_title.create({
92
91
  type: 'running',
93
92
  }),
94
93
  schema.nodes.alt_title.create({ type: 'short' }),
95
94
  ]);
96
- tr.insert(titleEnd, section);
95
+ tr.insert(pos, section);
97
96
  }
98
97
  else {
99
98
  const endPos = altTitlesSection[1] + altTitlesSection[0].nodeSize - 1;
@@ -6,6 +6,7 @@ const transform_1 = require("@manuscripts/transform");
6
6
  const prosemirror_state_1 = require("prosemirror-state");
7
7
  const prosemirror_view_1 = require("prosemirror-view");
8
8
  const commands_1 = require("../commands");
9
+ const track_changes_utils_1 = require("../lib/track-changes-utils");
9
10
  const selection_1 = require("../selection");
10
11
  exports.selectedSuggestionKey = new prosemirror_state_1.PluginKey('selected-suggestion');
11
12
  const EMPTY = {
@@ -29,10 +30,12 @@ exports.default = () => {
29
30
  const buildPluginState = (state) => {
30
31
  const selection = state.selection;
31
32
  const changes = (0, selection_1.getSelectionChangeGroup)(state);
32
- if (changes) {
33
+ if (changes.length) {
33
34
  return buildGroupOfChangesDecoration(state.doc, changes);
34
35
  }
35
- const $pos = (0, commands_1.isTextSelection)(selection) ? selection.$cursor : selection.$to;
36
+ const $pos = (0, commands_1.isTextSelection)(selection) && selection.$cursor
37
+ ? selection.$cursor
38
+ : selection.$to;
36
39
  if (!$pos) {
37
40
  return EMPTY;
38
41
  }
@@ -64,7 +67,7 @@ const getEffectiveSelection = ($pos) => {
64
67
  return current;
65
68
  }
66
69
  const parent = $pos.parent;
67
- const child = parent.childBefore($pos.parentOffset);
70
+ const child = parent.childBefore(Math.max($pos.parentOffset - 1, 0));
68
71
  const node = child.node;
69
72
  if (node) {
70
73
  const from = $pos.start() + child.offset;
@@ -96,7 +99,14 @@ const buildNodeDecoration = (doc, selection) => {
96
99
  };
97
100
  const buildTextDecoration = (doc, selection) => {
98
101
  const node = selection.node;
99
- const suggestion = getTrackedMark(node)?.attrs.dataTracked;
102
+ let suggestion = getTrackedMark(node)?.attrs.dataTracked;
103
+ if (!suggestion) {
104
+ for (const mark of node.marks) {
105
+ if ((0, track_changes_utils_1.isTracked)(mark)) {
106
+ suggestion = mark.attrs.dataTracked[0];
107
+ }
108
+ }
109
+ }
100
110
  if (!suggestion) {
101
111
  return EMPTY;
102
112
  }
@@ -52,10 +52,12 @@ const getSelectionChangeGroup = (state) => {
52
52
  selection instanceof InlineNodesSelection) &&
53
53
  selection.$from;
54
54
  if ($pos) {
55
- return track_changes_plugin_1.trackChangesPluginKey
55
+ return (track_changes_plugin_1.trackChangesPluginKey
56
56
  .getState(state)
57
- ?.changeSet.groupChanges.find((c) => isPositionAtRange(c, $pos.pos));
57
+ ?.changeSet.groupChanges.find((c) => isPositionAtRange(c, $pos.pos)) ||
58
+ []);
58
59
  }
60
+ return [];
59
61
  };
60
62
  exports.getSelectionChangeGroup = getSelectionChangeGroup;
61
63
  const isPositionAtRange = (changes, pos) => (changes.length > 1 ||
@@ -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.5.20';
4
+ exports.VERSION = '3.6.2';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -26,6 +26,7 @@ const AuthorsModal_1 = require("../components/authors/AuthorsModal");
26
26
  const authors_1 = require("../lib/authors");
27
27
  const comments_1 = require("../lib/comments");
28
28
  const track_changes_utils_1 = require("../lib/track-changes-utils");
29
+ const utils_1 = require("../lib/utils");
29
30
  const view_1 = require("../lib/view");
30
31
  const affiliations_1 = require("../plugins/affiliations");
31
32
  const selected_suggestion_1 = require("../plugins/selected-suggestion");
@@ -235,22 +236,16 @@ class ContributorsView extends block_view_1.default {
235
236
  const { view } = this;
236
237
  const { dispatch } = view;
237
238
  const affiliationsNodeType = transform_1.schema.nodes.affiliations;
238
- const contributorsNodeType = transform_1.schema.nodes.contributors;
239
- const affiliationNodeType = transform_1.schema.nodes.affiliation;
240
239
  let affiliations = (0, view_1.findChildByType)(view, affiliationsNodeType);
241
240
  if (!affiliations) {
242
- const contributors = (0, view_1.findChildByType)(view, contributorsNodeType);
243
- if (contributors) {
244
- const { tr } = this.view.state;
245
- const affiliationsNode = affiliationsNodeType.create();
246
- const insertPos = contributors.pos + contributors.node.nodeSize;
247
- dispatch(tr.insert(insertPos, affiliationsNode));
248
- affiliations = (0, view_1.findChildByType)(view, affiliationsNodeType);
249
- }
241
+ const { tr } = this.view.state;
242
+ const insertPos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.affiliations, view.state.doc);
243
+ dispatch(tr.insert(insertPos, transform_1.schema.nodes.affiliations.create()));
244
+ affiliations = (0, view_1.findChildByType)(view, affiliationsNodeType);
250
245
  }
251
246
  if (affiliations) {
252
247
  const { tr } = this.view.state;
253
- const affiliationNode = affiliationNodeType.create(attrs);
248
+ const affiliationNode = transform_1.schema.nodes.affiliation.create(attrs);
254
249
  dispatch(tr.insert(affiliations.pos + 1, affiliationNode));
255
250
  }
256
251
  };
@@ -28,7 +28,7 @@ import { createFootnote, findFootnotesContainerNode, getFootnotesElementState, }
28
28
  import { findWordBoundaries, isNodeOfType, nearestAncestor, } from './lib/helpers';
29
29
  import { templateAllows } from './lib/template';
30
30
  import { isDeleted } from './lib/track-changes-utils';
31
- import { findParentNodeWithId, getChildOfType, getInsertPos, getLastTitleNode, isBodyLocked, } from './lib/utils';
31
+ import { findInsertionPosition, findParentNodeWithId, getChildOfType, getInsertPos, isBodyLocked, } from './lib/utils';
32
32
  import { expandAccessibilitySection } from './plugins/accessibility_element';
33
33
  import { setCommentSelection } from './plugins/comments';
34
34
  import { getEditorProps } from './plugins/editor-props';
@@ -62,9 +62,19 @@ export const addToStart = (state, dispatch) => {
62
62
  };
63
63
  export const markActive = (type) => (state) => {
64
64
  const { from, $from, to, empty } = state.selection;
65
+ let hasMark = false;
66
+ state.doc.nodesBetween(from, to, (node) => {
67
+ if (node.isText) {
68
+ node.marks.forEach((m) => {
69
+ if (m.type === type && !isDeleted(m)) {
70
+ hasMark = true;
71
+ }
72
+ });
73
+ }
74
+ });
65
75
  return empty
66
76
  ? Boolean(type.isInSet(state.storedMarks || $from.marks()))
67
- : state.doc.rangeHasMark(from, to, type);
77
+ : state.doc.rangeHasMark(from, to, type) && hasMark;
68
78
  };
69
79
  export const isNodeSelection = (selection) => selection instanceof NodeSelection;
70
80
  export const blockActive = (type) => (state) => {
@@ -680,8 +690,7 @@ export const insertContributors = (state, dispatch, view) => {
680
690
  if (getChildOfType(state.doc, schema.nodes.contributors, true)) {
681
691
  return false;
682
692
  }
683
- const title = getLastTitleNode(state);
684
- const pos = title.pos + title.node.nodeSize;
693
+ const pos = findInsertionPosition(schema.nodes.contributors, state.doc);
685
694
  const contributors = state.schema.nodes.contributors.create({
686
695
  id: '',
687
696
  });
@@ -699,12 +708,7 @@ export const insertAffiliation = (state, dispatch, view) => {
699
708
  if (getChildOfType(state.doc, schema.nodes.affiliations, true)) {
700
709
  return false;
701
710
  }
702
- const title = getLastTitleNode(state);
703
- let pos = title.pos + title.node.nodeSize;
704
- const contributors = findChildrenByType(state.doc, state.schema.nodes.contributors)[0];
705
- if (contributors) {
706
- pos = contributors.pos + contributors.node.nodeSize;
707
- }
711
+ const pos = findInsertionPosition(schema.nodes.affiliations, state.doc);
708
712
  const affiliations = state.schema.nodes.affiliations.create({
709
713
  id: '',
710
714
  });
@@ -735,8 +739,7 @@ export const insertKeywords = (state, dispatch, view) => {
735
739
  if (getChildOfType(state.doc, schema.nodes.keywords, true)) {
736
740
  return false;
737
741
  }
738
- const abstracts = findChildrenByType(state.doc, state.schema.nodes.abstracts)[0];
739
- const pos = abstracts.pos;
742
+ const pos = findInsertionPosition(schema.nodes.keywords, state.doc);
740
743
  const keywords = schema.nodes.keywords.createAndFill({}, [
741
744
  schema.nodes.section_title.create({}, schema.text('Keywords')),
742
745
  schema.nodes.keywords_element.create({}, [
@@ -1231,8 +1234,7 @@ const createHeroImage = (attrs) => schema.nodes.hero_image.create({
1231
1234
  schema.nodes.long_desc.create(),
1232
1235
  ]);
1233
1236
  export const insertHeroImage = () => (state, dispatch, view) => {
1234
- const comments = findChildrenByType(state.doc, schema.nodes.comments)[0];
1235
- const position = comments.pos;
1237
+ const position = findInsertionPosition(schema.nodes.hero_image, state.doc);
1236
1238
  view?.focus();
1237
1239
  createBlock(schema.nodes.hero_image, position, state, dispatch);
1238
1240
  return true;
@@ -1,25 +1,13 @@
1
1
  import { generateNodeID, schema, } from '@manuscripts/transform';
2
2
  import { findChildren, findChildrenByType } from 'prosemirror-utils';
3
+ import { findInsertionPosition } from './utils';
3
4
  export const insertAwardsNode = (tr) => {
4
5
  const doc = tr.doc;
5
6
  const awards = findChildrenByType(doc, schema.nodes.awards)[0];
6
7
  if (awards) {
7
8
  return awards;
8
9
  }
9
- const positions = [];
10
- const possibleNodesTypes = [
11
- 'doi',
12
- 'keywords',
13
- 'supplements',
14
- 'abstracts',
15
- 'body',
16
- ];
17
- doc.descendants((node, pos) => {
18
- if (possibleNodesTypes.includes(node.type.name)) {
19
- positions.push(pos);
20
- }
21
- });
22
- const pos = positions.length === 0 ? 0 : Math.min(...positions);
10
+ const pos = findInsertionPosition(schema.nodes.awards, doc);
23
11
  const node = schema.nodes.awards.createAndFill();
24
12
  tr.insert(pos, node);
25
13
  return {
@@ -33,8 +21,7 @@ export const insertSupplementsNode = (tr) => {
33
21
  if (supplements) {
34
22
  return supplements;
35
23
  }
36
- const backmatter = findBackmatter(doc);
37
- const pos = backmatter.pos + backmatter.node.content.size + 1;
24
+ const pos = findInsertionPosition(schema.nodes.supplements, doc);
38
25
  const node = schema.nodes.supplements.createAndFill();
39
26
  tr.insert(pos, node);
40
27
  return {
@@ -50,8 +37,7 @@ export const insertAttachmentsNode = (tr) => {
50
37
  pos: attachmentsNodes[0].pos,
51
38
  };
52
39
  }
53
- const comments = findChildrenByType(tr.doc, schema.nodes.comments)[0];
54
- const pos = comments.pos + comments.node.content.size;
40
+ const pos = findInsertionPosition(schema.nodes.attachments, tr.doc);
55
41
  const node = schema.nodes.attachments.create({
56
42
  id: generateNodeID(schema.nodes.attachments),
57
43
  });
@@ -154,6 +154,15 @@ export const getInsertPos = (type, parent, pos) => {
154
154
  });
155
155
  return insertPos;
156
156
  };
157
+ export const findInsertionPosition = (type, doc) => {
158
+ let insertPos = 0;
159
+ doc.forEach((child, offset, index) => {
160
+ if (doc.canReplaceWith(index, index, type)) {
161
+ insertPos = offset;
162
+ }
163
+ });
164
+ return insertPos;
165
+ };
157
166
  export const filterBlockNodes = (fragment, predicate) => {
158
167
  const updatedNodes = [];
159
168
  fragment.forEach((child) => {
@@ -18,6 +18,7 @@ import { Plugin, TextSelection } from 'prosemirror-state';
18
18
  import { Decoration, DecorationSet } from 'prosemirror-view';
19
19
  import { v4 as uuidv4 } from 'uuid';
20
20
  import { addAuthorIcon } from '../icons';
21
+ import { findInsertionPosition } from '../lib/utils';
21
22
  const createAddSubtitleButton = (handler) => {
22
23
  const button = document.createElement('span');
23
24
  button.className = 'add-subtitle';
@@ -52,8 +53,9 @@ export default () => new Plugin({
52
53
  Decoration.widget(titleEndPos, (view) => {
53
54
  return createAddSubtitleButton(() => {
54
55
  const subtitlesNode = schema.nodes.subtitles.create({ id: uuidv4() }, [schema.nodes.subtitle.create({ id: uuidv4() })]);
55
- const tr = view.state.tr.insert(titleEndPos, subtitlesNode);
56
- const subtitlePos = titleEndPos + 1;
56
+ const pos = findInsertionPosition(schema.nodes.subtitles, state.doc);
57
+ const tr = view.state.tr.insert(pos, subtitlesNode);
58
+ const subtitlePos = pos + 1;
57
59
  tr.setSelection(TextSelection.create(tr.doc, subtitlePos));
58
60
  view.dispatch(tr);
59
61
  view.focus();
@@ -2,7 +2,7 @@ import { skipTracking } from '@manuscripts/track-changes-plugin';
2
2
  import { schema, } from '@manuscripts/transform';
3
3
  import { Plugin, PluginKey } from 'prosemirror-state';
4
4
  import { Decoration, DecorationSet } from 'prosemirror-view';
5
- import { createToggleButton } from '../lib/utils';
5
+ import { createToggleButton, findInsertionPosition } from '../lib/utils';
6
6
  function getTitlesData(doc) {
7
7
  let title;
8
8
  let subtitles;
@@ -76,21 +76,20 @@ export default () => {
76
76
  !altTitlesKey.getState(newState)) {
77
77
  return null;
78
78
  }
79
- const { title, subtitles, runningTitle, shortTitle, altTitlesSection } = altTitlesKey.getState(newState);
79
+ const { title, runningTitle, shortTitle, altTitlesSection } = altTitlesKey.getState(newState);
80
80
  const schema = newState.schema;
81
81
  if (!title) {
82
82
  return null;
83
83
  }
84
84
  if (!altTitlesSection) {
85
- const prev = subtitles || title;
86
- const titleEnd = prev[0].nodeSize + prev[1];
85
+ const pos = findInsertionPosition(schema.nodes.alt_titles, tr.doc);
87
86
  const section = schema.nodes.alt_titles.create({}, [
88
87
  schema.nodes.alt_title.create({
89
88
  type: 'running',
90
89
  }),
91
90
  schema.nodes.alt_title.create({ type: 'short' }),
92
91
  ]);
93
- tr.insert(titleEnd, section);
92
+ tr.insert(pos, section);
94
93
  }
95
94
  else {
96
95
  const endPos = altTitlesSection[1] + altTitlesSection[0].nodeSize - 1;
@@ -3,6 +3,7 @@ import { schema, } from '@manuscripts/transform';
3
3
  import { Plugin, PluginKey } from 'prosemirror-state';
4
4
  import { Decoration, DecorationSet } from 'prosemirror-view';
5
5
  import { isTextSelection } from '../commands';
6
+ import { isTracked } from '../lib/track-changes-utils';
6
7
  import { getSelectionChangeGroup } from '../selection';
7
8
  export const selectedSuggestionKey = new PluginKey('selected-suggestion');
8
9
  const EMPTY = {
@@ -26,10 +27,12 @@ export default () => {
26
27
  const buildPluginState = (state) => {
27
28
  const selection = state.selection;
28
29
  const changes = getSelectionChangeGroup(state);
29
- if (changes) {
30
+ if (changes.length) {
30
31
  return buildGroupOfChangesDecoration(state.doc, changes);
31
32
  }
32
- const $pos = isTextSelection(selection) ? selection.$cursor : selection.$to;
33
+ const $pos = isTextSelection(selection) && selection.$cursor
34
+ ? selection.$cursor
35
+ : selection.$to;
33
36
  if (!$pos) {
34
37
  return EMPTY;
35
38
  }
@@ -61,7 +64,7 @@ const getEffectiveSelection = ($pos) => {
61
64
  return current;
62
65
  }
63
66
  const parent = $pos.parent;
64
- const child = parent.childBefore($pos.parentOffset);
67
+ const child = parent.childBefore(Math.max($pos.parentOffset - 1, 0));
65
68
  const node = child.node;
66
69
  if (node) {
67
70
  const from = $pos.start() + child.offset;
@@ -93,7 +96,14 @@ const buildNodeDecoration = (doc, selection) => {
93
96
  };
94
97
  const buildTextDecoration = (doc, selection) => {
95
98
  const node = selection.node;
96
- const suggestion = getTrackedMark(node)?.attrs.dataTracked;
99
+ let suggestion = getTrackedMark(node)?.attrs.dataTracked;
100
+ if (!suggestion) {
101
+ for (const mark of node.marks) {
102
+ if (isTracked(mark)) {
103
+ suggestion = mark.attrs.dataTracked[0];
104
+ }
105
+ }
106
+ }
97
107
  if (!suggestion) {
98
108
  return EMPTY;
99
109
  }
@@ -47,10 +47,12 @@ export const getSelectionChangeGroup = (state) => {
47
47
  selection instanceof InlineNodesSelection) &&
48
48
  selection.$from;
49
49
  if ($pos) {
50
- return trackChangesPluginKey
50
+ return (trackChangesPluginKey
51
51
  .getState(state)
52
- ?.changeSet.groupChanges.find((c) => isPositionAtRange(c, $pos.pos));
52
+ ?.changeSet.groupChanges.find((c) => isPositionAtRange(c, $pos.pos)) ||
53
+ []);
53
54
  }
55
+ return [];
54
56
  };
55
57
  const isPositionAtRange = (changes, pos) => (changes.length > 1 ||
56
58
  changes[0].dataTracked.operation === CHANGE_OPERATION.structure) &&
@@ -1,2 +1,2 @@
1
- export const VERSION = '3.5.20';
1
+ export const VERSION = '3.6.2';
2
2
  export const MATHJAX_VERSION = '3.2.2';
@@ -20,6 +20,7 @@ import { AuthorsModal, } from '../components/authors/AuthorsModal';
20
20
  import { authorComparator, authorLabel, } from '../lib/authors';
21
21
  import { handleComment } from '../lib/comments';
22
22
  import { addTrackChangesAttributes, isDeleted, } from '../lib/track-changes-utils';
23
+ import { findInsertionPosition } from '../lib/utils';
23
24
  import { deleteNode, findChildByID, findChildByType, findChildrenAttrsByType, updateNodeAttrs, } from '../lib/view';
24
25
  import { affiliationsKey } from '../plugins/affiliations';
25
26
  import { selectedSuggestionKey } from '../plugins/selected-suggestion';
@@ -229,22 +230,16 @@ export class ContributorsView extends BlockView {
229
230
  const { view } = this;
230
231
  const { dispatch } = view;
231
232
  const affiliationsNodeType = schema.nodes.affiliations;
232
- const contributorsNodeType = schema.nodes.contributors;
233
- const affiliationNodeType = schema.nodes.affiliation;
234
233
  let affiliations = findChildByType(view, affiliationsNodeType);
235
234
  if (!affiliations) {
236
- const contributors = findChildByType(view, contributorsNodeType);
237
- if (contributors) {
238
- const { tr } = this.view.state;
239
- const affiliationsNode = affiliationsNodeType.create();
240
- const insertPos = contributors.pos + contributors.node.nodeSize;
241
- dispatch(tr.insert(insertPos, affiliationsNode));
242
- affiliations = findChildByType(view, affiliationsNodeType);
243
- }
235
+ const { tr } = this.view.state;
236
+ const insertPos = findInsertionPosition(schema.nodes.affiliations, view.state.doc);
237
+ dispatch(tr.insert(insertPos, schema.nodes.affiliations.create()));
238
+ affiliations = findChildByType(view, affiliationsNodeType);
244
239
  }
245
240
  if (affiliations) {
246
241
  const { tr } = this.view.state;
247
- const affiliationNode = affiliationNodeType.create(attrs);
242
+ const affiliationNode = schema.nodes.affiliation.create(attrs);
248
243
  dispatch(tr.insert(affiliations.pos + 1, affiliationNode));
249
244
  }
250
245
  };
@@ -14,14 +14,14 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { TrackedAttrs } from '@manuscripts/track-changes-plugin';
17
- import { Attrs, Fragment, Node as ProsemirrorNode } from 'prosemirror-model';
18
- export declare function isDeleted(node: ProsemirrorNode): boolean;
17
+ import { Attrs, Fragment, Mark, Node as ProsemirrorNode } from 'prosemirror-model';
18
+ export declare function isDeleted(node: ProsemirrorNode | Mark): boolean;
19
19
  export declare function isShadowDelete(node: ProsemirrorNode): boolean;
20
20
  export declare function isPendingInsert(node: ProsemirrorNode): boolean;
21
21
  export declare function isPending(node: ProsemirrorNode): boolean;
22
22
  export declare function isPendingSetAttrs(node: ProsemirrorNode): boolean;
23
23
  export declare function getChangeClasses(dataTracked?: TrackedAttrs[]): string[];
24
- export declare function isTracked(node: ProsemirrorNode): boolean;
24
+ export declare function isTracked(node: ProsemirrorNode | Mark): boolean;
25
25
  export declare const getAttrsTrackingButton: (changeID: string) => HTMLButtonElement;
26
26
  export declare function isHidden(node: ProsemirrorNode): boolean;
27
27
  export declare function isDeletedText(node: ProsemirrorNode): boolean;
@@ -36,6 +36,7 @@ export declare const isBodyLocked: (state: EditorState) => boolean;
36
36
  export declare const isEditAllowed: (state: EditorState) => boolean;
37
37
  export declare const createToggleButton: (listener: () => void) => HTMLButtonElement;
38
38
  export declare const getInsertPos: (type: ManuscriptNodeType, parent: ManuscriptNode, pos: number) => number;
39
+ export declare const findInsertionPosition: (type: ManuscriptNodeType, doc: ManuscriptNode) => number;
39
40
  export declare const filterBlockNodes: (fragment: Fragment, predicate: (node: ProseMirrorNode) => boolean) => Fragment;
40
41
  export declare const getLastTitleNode: (state: ManuscriptEditorState) => {
41
42
  node: ProseMirrorNode;
@@ -22,5 +22,5 @@ export declare class NodesSelection extends NodeSelection {
22
22
  constructor($from: ResolvedPos, $to: ResolvedPos);
23
23
  toJSON(): NodesSelectionJSON;
24
24
  }
25
- export declare const getSelectionChangeGroup: (state: ManuscriptEditorState) => TrackedChange[] | undefined;
25
+ export declare const getSelectionChangeGroup: (state: ManuscriptEditorState) => TrackedChange[];
26
26
  export {};
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "3.5.20";
1
+ export declare const VERSION = "3.6.2";
2
2
  export declare const MATHJAX_VERSION = "3.2.2";
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": "3.5.20",
4
+ "version": "3.6.2",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -40,8 +40,8 @@
40
40
  "@iarna/word-count": "1.1.2",
41
41
  "@manuscripts/json-schema": "2.2.12",
42
42
  "@manuscripts/style-guide": "3.3.2",
43
- "@manuscripts/track-changes-plugin": "2.0.13",
44
- "@manuscripts/transform": "4.2.20",
43
+ "@manuscripts/track-changes-plugin": "2.1.0",
44
+ "@manuscripts/transform": "4.3.2",
45
45
  "@popperjs/core": "2.11.8",
46
46
  "citeproc": "2.4.63",
47
47
  "codemirror": "5.65.19",
@@ -975,7 +975,8 @@ figure .selected-suggestion {
975
975
  background-color: transparent !important;
976
976
  }
977
977
 
978
- .selected-suggestion[data-track-status='pending'] .block:not(.box-element):not(.trans-abstract),
978
+ .selected-suggestion[data-track-status='pending']
979
+ .block:not(.box-element):not(.trans-abstract),
979
980
  .block:has(figure.selected-suggestion),
980
981
  figure.block:has(.equation.selected-suggestion) {
981
982
  box-shadow: inset 6px 0 0 black, inset 9px 0 0 lightgray;
@@ -1042,7 +1043,7 @@ figure.block:has(.equation.selected-suggestion) {
1042
1043
  }
1043
1044
 
1044
1045
  .selected-suggestion[data-track-status='pending'][data-track-op='delete']
1045
- .block:not(.box-element):not(.trans-abstract) {
1046
+ .block:not(.box-element):not(.trans-abstract) {
1046
1047
  box-shadow: inset 6px 0 0 var(--deleted-color),
1047
1048
  inset 9px 0 0 var(--deleted-pending-bg-color) !important;
1048
1049
  animation: fadeOutBackground 3s forwards;
@@ -1050,7 +1051,10 @@ figure.block:has(.equation.selected-suggestion) {
1050
1051
  }
1051
1052
 
1052
1053
  /* Updated Block */
1053
- .tracking-visible .ProseMirror [data-track-op='set_attrs'] .block:not(.trans-abstract),
1054
+ .tracking-visible
1055
+ .ProseMirror
1056
+ [data-track-op='set_attrs']
1057
+ .block:not(.trans-abstract),
1054
1058
  .tracking-visible .block:has(figure[data-track-op='set_attrs']),
1055
1059
  .tracking-visible figure.block:has(.equation.set_attrs),
1056
1060
  .tracking-visible
@@ -1067,7 +1071,9 @@ figure.block:has(.equation.selected-suggestion) {
1067
1071
  box-shadow: inset 3px 0 0 var(--updated-border-color);
1068
1072
  }
1069
1073
 
1070
- .tracking-visible .selected-suggestion[data-track-op='set_attrs'] .block:not(.trans-abstract),
1074
+ .tracking-visible
1075
+ .selected-suggestion[data-track-op='set_attrs']
1076
+ .block:not(.trans-abstract),
1071
1077
  .tracking-visible
1072
1078
  .block:has(figure.selected-suggestion[data-track-op='set_attrs']),
1073
1079
  .tracking-visible .selected-suggestion[data-track-op='node_split'] .block,
@@ -1147,6 +1153,26 @@ figure.block:has(.equation.selected-suggestion) {
1147
1153
  border-color: var(--updated-border-color);
1148
1154
  }
1149
1155
 
1156
+ b[data-track-status='pending'][data-track-op='insert'],
1157
+ i[data-track-status='pending'][data-track-op='insert'],
1158
+ sup[data-track-status='pending'][data-track-op='insert'],
1159
+ sub[data-track-status='pending'][data-track-op='insert'],
1160
+ u[data-track-status='pending'][data-track-op='insert'],
1161
+ s[data-track-status='pending'][data-track-op='insert'] {
1162
+ background: var(--inserted-pending-bg-color);
1163
+ color: var(--inserted-pending-color);
1164
+ }
1165
+
1166
+ b[data-track-status='pending'][data-track-op='delete'],
1167
+ i[data-track-status='pending'][data-track-op='delete'],
1168
+ sup[data-track-status='pending'][data-track-op='delete'],
1169
+ sub[data-track-status='pending'][data-track-op='delete'],
1170
+ u[data-track-status='pending'][data-track-op='delete'],
1171
+ s[data-track-status='pending'][data-track-op='delete'] {
1172
+ background: var(--deleted-pending-bg-color);
1173
+ color: var(--deleted-color);
1174
+ }
1175
+
1150
1176
  /* Needed for the snapshot comparison */
1151
1177
  .tracking-visible
1152
1178
  .block-list
@@ -1582,7 +1608,7 @@ th:hover > .table-context-menu-button,
1582
1608
  border: 1px solid #f2f2f2;
1583
1609
  box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.12);
1584
1610
  background-color: #ffffff;
1585
-
1611
+
1586
1612
  position: absolute;
1587
1613
  top: -8px;
1588
1614
  right: -8px;
@@ -1668,7 +1694,8 @@ th:hover > .table-context-menu-button,
1668
1694
  margin-bottom: 30px;
1669
1695
  }
1670
1696
 
1671
- .hero-image-container, .attachments-container {
1697
+ .hero-image-container,
1698
+ .attachments-container {
1672
1699
  border: 1px solid #c9c9c9;
1673
1700
  border-radius: 4px;
1674
1701
  background: #ffffff;
@@ -1812,7 +1839,7 @@ th:hover > .table-context-menu-button,
1812
1839
  }
1813
1840
  .ProseMirror .abstracts .add-translation-text {
1814
1841
  font-size: 14px;
1815
- color:#353535
1842
+ color: #353535;
1816
1843
  }
1817
1844
  .ProseMirror .abstracts .add-translation-container .add-button {
1818
1845
  margin: 0;
@@ -1838,7 +1865,7 @@ th:hover > .table-context-menu-button,
1838
1865
  display: flex;
1839
1866
  align-items: center;
1840
1867
  font-size: 14px;
1841
- color: #6E6E6E;
1868
+ color: #6e6e6e;
1842
1869
  cursor: pointer;
1843
1870
  }
1844
1871
  .abstracts-language-dropdown {
@@ -1846,7 +1873,7 @@ th:hover > .table-context-menu-button,
1846
1873
  top: -86px !important;
1847
1874
  }
1848
1875
 
1849
- .ProseMirror .block-trans_abstract p.empty-node[data-placeholder] {
1876
+ .ProseMirror .block-trans_abstract p.empty-node[data-placeholder] {
1850
1877
  font-style: italic;
1851
1878
  color: #c9c9c9;
1852
1879
  margin: 0;
@@ -1930,7 +1957,7 @@ th:hover > .table-context-menu-button,
1930
1957
  cursor: pointer;
1931
1958
  }
1932
1959
 
1933
- .attachments-container .attachment-header {
1960
+ .attachments-container .attachment-header {
1934
1961
  display: flex;
1935
1962
  align-items: center;
1936
1963
  margin-bottom: 12px;
@@ -1978,11 +2005,11 @@ th:hover > .table-context-menu-button,
1978
2005
  margin-bottom: 12px;
1979
2006
  }
1980
2007
 
1981
-
1982
- .block-attachments:has(.attachment-item:empty), .block-attachments.empty-node {
2008
+ .block-attachments:has(.attachment-item:empty),
2009
+ .block-attachments.empty-node {
1983
2010
  display: none !important;
1984
2011
  }
1985
2012
 
1986
2013
  .ProseMirror a.link:empty::before {
1987
- content: "\00a0";
2014
+ content: '\00a0';
1988
2015
  }