@manuscripts/body-editor 1.9.5 → 1.9.7-LEAN-3136

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 (41) hide show
  1. package/dist/cjs/commands.js +26 -8
  2. package/dist/cjs/configs/ManuscriptsEditor.js +20 -14
  3. package/dist/cjs/configs/editor-views.js +1 -1
  4. package/dist/cjs/lib/context-menu.js +5 -2
  5. package/dist/cjs/plugins/affiliations.js +3 -0
  6. package/dist/cjs/plugins/bibliography/index.js +1 -1
  7. package/dist/cjs/plugins/footnotes/footnotes-utils.js +33 -1
  8. package/dist/cjs/plugins/footnotes/index.js +77 -25
  9. package/dist/cjs/plugins/highlight/index.js +6 -5
  10. package/dist/cjs/plugins/selected-suggestion-ui.js +8 -4
  11. package/dist/cjs/plugins/table-footnote.js +3 -0
  12. package/dist/cjs/views/base_node_view.js +1 -1
  13. package/dist/cjs/views/bibliography_element.js +6 -0
  14. package/dist/cjs/views/citation.js +3 -0
  15. package/dist/cjs/views/citation_editable.js +6 -0
  16. package/dist/cjs/views/footnotes_element.js +3 -1
  17. package/dist/cjs/views/inline_footnote.js +17 -2
  18. package/dist/es/commands.js +27 -9
  19. package/dist/es/configs/ManuscriptsEditor.js +20 -14
  20. package/dist/es/configs/editor-views.js +1 -1
  21. package/dist/es/lib/context-menu.js +5 -2
  22. package/dist/es/plugins/affiliations.js +3 -0
  23. package/dist/es/plugins/bibliography/index.js +1 -1
  24. package/dist/es/plugins/footnotes/footnotes-utils.js +31 -0
  25. package/dist/es/plugins/footnotes/index.js +78 -26
  26. package/dist/es/plugins/highlight/index.js +6 -5
  27. package/dist/es/plugins/selected-suggestion-ui.js +8 -4
  28. package/dist/es/plugins/table-footnote.js +3 -0
  29. package/dist/es/views/base_node_view.js +1 -1
  30. package/dist/es/views/bibliography_element.js +6 -0
  31. package/dist/es/views/citation.js +3 -0
  32. package/dist/es/views/citation_editable.js +6 -0
  33. package/dist/es/views/footnotes_element.js +3 -1
  34. package/dist/es/views/inline_footnote.js +17 -2
  35. package/dist/types/plugins/bibliography/index.d.ts +1 -1
  36. package/dist/types/plugins/footnotes/footnotes-utils.d.ts +1 -0
  37. package/dist/types/plugins/footnotes/index.d.ts +5 -3
  38. package/dist/types/views/footnotes_element.d.ts +3 -3
  39. package/package.json +4 -4
  40. package/styles/AdvancedEditor.css +6 -8
  41. package/styles/Editor.css +7 -3
@@ -59,7 +59,10 @@ const blockActive = (type) => (state) => {
59
59
  };
60
60
  exports.blockActive = blockActive;
61
61
  const canInsert = (type) => (state) => {
62
- const { $from } = state.selection;
62
+ const { $from, $to } = state.selection;
63
+ if ($from.node().type === transform_1.schema.nodes.title && $from.pos === $to.pos) {
64
+ return false;
65
+ }
63
66
  for (let d = $from.depth; d >= 0; d--) {
64
67
  const index = $from.index(d);
65
68
  if ($from.node(d).canReplaceWith(index, index, type)) {
@@ -324,12 +327,24 @@ const insertInlineFootnote = (kind) => (state, dispatch) => {
324
327
  let selectionPos;
325
328
  if (!footnotesSection) {
326
329
  const section = state.schema.nodes.footnotes_section.create({}, [
327
- state.schema.nodes.section_title.create({}, state.schema.text('Notes')),
330
+ state.schema.nodes.section_title.create({}, state.schema.text('Footnotes')),
328
331
  state.schema.nodes.footnotes_element.create({}, footnote),
329
332
  ]);
330
333
  const backmatter = (0, prosemirror_utils_1.findChildrenByType)(tr.doc, transform_1.schema.nodes.backmatter)[0];
331
- tr.insert(backmatter.pos + 1, section);
332
- selectionPos = backmatter.pos + section.nodeSize - 3;
334
+ const sectionPos = backmatter.pos + 1;
335
+ tr.insert(sectionPos, section);
336
+ let footnotePos = 0;
337
+ section.descendants((n, pos) => {
338
+ if ((0, transform_1.isFootnoteNode)(n)) {
339
+ footnotePos = pos;
340
+ n.descendants((childNode, childPos) => {
341
+ if ((0, transform_1.isParagraphNode)(childNode)) {
342
+ footnotePos += childPos;
343
+ }
344
+ });
345
+ }
346
+ });
347
+ selectionPos = sectionPos + footnotePos;
333
348
  }
334
349
  else {
335
350
  const footnoteElement = (0, prosemirror_utils_1.findChildrenByType)(footnotesSection.node, transform_1.schema.nodes.footnotes_element);
@@ -341,7 +356,7 @@ const insertInlineFootnote = (kind) => (state, dispatch) => {
341
356
  selectionPos = pos + 2;
342
357
  }
343
358
  if (dispatch && selectionPos) {
344
- const selection = prosemirror_state_1.TextSelection.create(tr.doc, selectionPos);
359
+ const selection = prosemirror_state_1.TextSelection.near(tr.doc.resolve(selectionPos));
345
360
  dispatch(tr.setSelection(selection).scrollIntoView());
346
361
  }
347
362
  return true;
@@ -708,10 +723,13 @@ const addBlockComment = (node, state, dispatch) => {
708
723
  [highlight_1.SET_COMMENT]: comment,
709
724
  });
710
725
  tr.setMeta('addToHistory', false);
711
- if (dispatch && isAllowedType(type)) {
712
- dispatch(tr);
726
+ if (isAllowedType(type)) {
727
+ dispatch && dispatch(tr);
728
+ return true;
729
+ }
730
+ else {
731
+ return false;
713
732
  }
714
- return true;
715
733
  };
716
734
  const addHighlightComment = (node, state, dispatch) => {
717
735
  const { attrs: { id }, type, } = node;
@@ -32,18 +32,24 @@ const createEditorState = (props) => prosemirror_state_1.EditorState.create({
32
32
  plugins: (0, editor_plugins_1.default)(props),
33
33
  });
34
34
  exports.createEditorState = createEditorState;
35
- const createEditorView = (props, root, state, dispatch) => new prosemirror_view_1.EditorView(root, {
36
- state,
37
- editable: () => props.getCapabilities().editArticle,
38
- scrollMargin: {
39
- top: 100,
40
- bottom: 100,
41
- left: 0,
42
- right: 0,
43
- },
44
- dispatchTransaction: dispatch,
45
- nodeViews: (0, editor_views_1.default)(props, dispatch),
46
- attributes: props.attributes,
47
- transformPasted: paste_1.transformPasted,
48
- });
35
+ const createEditorView = (props, root, state, dispatch) => {
36
+ const view = new prosemirror_view_1.EditorView(root, {
37
+ state,
38
+ editable: () => props.getCapabilities().editArticle,
39
+ scrollMargin: {
40
+ top: 100,
41
+ bottom: 100,
42
+ left: 0,
43
+ right: 0,
44
+ },
45
+ dispatchTransaction: dispatch,
46
+ nodeViews: (0, editor_views_1.default)(props, dispatch),
47
+ attributes: props.attributes,
48
+ transformPasted: paste_1.transformPasted,
49
+ });
50
+ const tr = view.state.tr.setMeta('INIT', true);
51
+ const nextState = view.state.apply(tr);
52
+ view.updateState(nextState);
53
+ return view;
54
+ };
49
55
  exports.createEditorView = createEditorView;
@@ -69,7 +69,7 @@ exports.default = (props, dispatch) => {
69
69
  footnote: (0, footnote_editable_1.default)(props),
70
70
  footnotes_element: (0, footnotes_element_1.default)(props),
71
71
  inline_equation: (0, inline_equation_editable_1.default)(props),
72
- inline_footnote: (0, inline_footnote_editable_1.default)(props),
72
+ inline_footnote: (0, inline_footnote_editable_1.default)(props, dispatch),
73
73
  keyword: (0, keyword_1.default)(props, dispatch),
74
74
  keyword_group: (0, keyword_group_1.default)(props, dispatch),
75
75
  link: (0, link_editable_1.default)(props, dispatch),
@@ -214,7 +214,10 @@ class ContextMenu {
214
214
  index: tablesFootnoteLabels.get(node.attrs.id),
215
215
  }));
216
216
  const targetDom = this.view.domAtPos(this.view.state.selection.from);
217
- if (targetDom.node instanceof Element && this.props) {
217
+ const targetNode = targetDom.node.nodeType === Node.TEXT_NODE
218
+ ? targetDom.node.parentNode
219
+ : targetDom.node;
220
+ if (targetNode instanceof Element && this.props) {
218
221
  const popperContainer = (0, ReactSubView_1.default)(Object.assign(Object.assign({}, this.props), { dispatch: this.view.dispatch }), style_guide_1.TableFootnotesSelector, {
219
222
  notes: footnotes,
220
223
  onAdd: () => {
@@ -251,7 +254,7 @@ class ContextMenu {
251
254
  (_a = this.props) === null || _a === void 0 ? void 0 : _a.popper.destroy();
252
255
  },
253
256
  }, this.node, this.getPos, this.view, 'table-footnote-editor');
254
- (_a = this.props) === null || _a === void 0 ? void 0 : _a.popper.show(targetDom.node, popperContainer, 'bottom-end');
257
+ (_a = this.props) === null || _a === void 0 ? void 0 : _a.popper.show(targetNode, popperContainer, 'bottom-end');
255
258
  }
256
259
  }
257
260
  }));
@@ -74,6 +74,9 @@ exports.default = () => {
74
74
  },
75
75
  appendTransaction(transactions, oldState, newState) {
76
76
  const { indexedAffiliationIds } = exports.affiliationsKey.getState(newState);
77
+ if (!transactions.find((tr) => tr.docChanged)) {
78
+ return;
79
+ }
77
80
  const oldPluginState = exports.affiliationsKey.getState(oldState);
78
81
  const { tr } = newState;
79
82
  const affiliations = [];
@@ -54,7 +54,7 @@ exports.default = (props) => {
54
54
  props: {
55
55
  decorations(state) {
56
56
  const bib = (0, exports.getBibliographyPluginState)(state);
57
- return prosemirror_view_1.DecorationSet.create(state.doc, (0, bibliography_utils_1.buildDecorations)(bib, state.doc));
57
+ return prosemirror_view_1.DecorationSet.create(state.doc, bib ? (0, bibliography_utils_1.buildDecorations)(bib, state.doc) : []);
58
58
  },
59
59
  },
60
60
  });
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.getInlineFootnotes = exports.updateTableInlineFootnoteLabels = exports.orderTableFootnotes = exports.buildTableFootnoteLabels = exports.getNewFootnotePos = exports.findTableInlineFootnoteIds = void 0;
18
+ exports.getAlphaOrderIndices = exports.getInlineFootnotes = exports.updateTableInlineFootnoteLabels = exports.orderTableFootnotes = exports.buildTableFootnoteLabels = exports.getNewFootnotePos = exports.findTableInlineFootnoteIds = void 0;
19
19
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
20
20
  const transform_1 = require("@manuscripts/transform");
21
21
  const prosemirror_model_1 = require("prosemirror-model");
@@ -113,3 +113,35 @@ const getInlineFootnotes = (id, targetNode) => {
113
113
  return inlineFootnotes;
114
114
  };
115
115
  exports.getInlineFootnotes = getInlineFootnotes;
116
+ function getAlphaOrderIndices(index) {
117
+ const unicodeInterval = [97, 123];
118
+ const places = unicodeInterval[1] - unicodeInterval[0];
119
+ function getClassCount(n, order) {
120
+ return n * Math.pow(places, order - 1);
121
+ }
122
+ let indices = null;
123
+ for (;;) {
124
+ let current = index;
125
+ let position = 1;
126
+ while (current >= places) {
127
+ current = current / places;
128
+ position++;
129
+ }
130
+ const newIndex = Math.floor(current);
131
+ indices = indices ? indices : new Array(position).fill(0);
132
+ indices.splice(indices.length - position, 1, newIndex);
133
+ index -= getClassCount(newIndex, position);
134
+ if (position === 1) {
135
+ break;
136
+ }
137
+ }
138
+ return (indices || [])
139
+ .map((v, i, array) => {
140
+ if (array.length > 1 && i !== array.length - 1) {
141
+ return String.fromCodePoint(v + unicodeInterval[0] - 1);
142
+ }
143
+ return String.fromCodePoint(v + unicodeInterval[0]);
144
+ })
145
+ .join('');
146
+ }
147
+ exports.getAlphaOrderIndices = getAlphaOrderIndices;
@@ -18,7 +18,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.uncitedFootnoteWidget = exports.buildPluginState = exports.footnotesKey = void 0;
21
+ exports.buildPluginState = exports.uncitedFootnoteWidget = exports.footnotesKey = void 0;
22
+ const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
22
23
  const transform_1 = require("@manuscripts/transform");
23
24
  const lodash_1 = require("lodash");
24
25
  const prosemirror_state_1 = require("prosemirror-state");
@@ -31,27 +32,10 @@ const ReactSubView_1 = __importDefault(require("../../views/ReactSubView"));
31
32
  const placeholder_1 = require("../placeholder");
32
33
  const footnotes_utils_1 = require("./footnotes-utils");
33
34
  exports.footnotesKey = new prosemirror_state_1.PluginKey('footnotes');
34
- const buildPluginState = (doc) => {
35
- const nodes = [];
36
- let index = 0;
37
- const labels = new Map();
38
- doc.descendants((node, pos, parentNode) => {
39
- if ((0, transform_1.isInlineFootnoteNode)(node) &&
40
- parentNode &&
41
- parentNode.type !== transform_1.schema.nodes.table_cell) {
42
- nodes.push([node, pos]);
43
- node.attrs.rids.forEach((rid) => {
44
- labels.set(rid, String(++index));
45
- });
46
- }
47
- });
48
- return { nodes, labels };
49
- };
50
- exports.buildPluginState = buildPluginState;
51
35
  const scrollToInlineFootnote = (rid, view) => {
52
36
  view.state.doc.descendants((node, pos) => {
53
37
  const footnote = node;
54
- if (footnote.attrs.rids.includes(rid)) {
38
+ if ((0, transform_1.isInlineFootnoteNode)(node) && footnote.attrs.rids.includes(rid)) {
55
39
  const selection = prosemirror_state_1.NodeSelection.create(view.state.doc, pos);
56
40
  view.dispatch(view.state.tr.setSelection(selection).scrollIntoView());
57
41
  }
@@ -61,7 +45,7 @@ const labelWidget = (label, id) => (view) => {
61
45
  const element = document.createElement('span');
62
46
  element.className = 'footnote-label';
63
47
  element.textContent = label;
64
- element.addEventListener('click', () => {
48
+ element.addEventListener('mousedown', () => {
65
49
  scrollToInlineFootnote(id, view);
66
50
  });
67
51
  return element;
@@ -136,6 +120,39 @@ const deleteFootnoteWidget = (node, props, id, tableElement) => (view, getPos) =
136
120
  });
137
121
  return deleteBtn;
138
122
  };
123
+ const buildPluginState = (doc) => {
124
+ const inlineFootnotes = [];
125
+ const footnotes = new Map();
126
+ let footnoteElement;
127
+ doc.descendants((node, pos, parentNode) => {
128
+ if ((0, transform_1.isFootnotesSectionNode)(node)) {
129
+ node.descendants((node, childPos) => {
130
+ if ((0, transform_1.isFootnotesElementNode)(node)) {
131
+ footnoteElement = [node, pos + childPos];
132
+ }
133
+ if ((0, transform_1.isFootnoteNode)(node)) {
134
+ footnotes.set(node.attrs.id, [node, pos + childPos]);
135
+ }
136
+ });
137
+ }
138
+ if ((0, transform_1.isInlineFootnoteNode)(node) &&
139
+ parentNode &&
140
+ parentNode.type !== transform_1.schema.nodes.table_cell &&
141
+ parentNode.type !== transform_1.schema.nodes.table_header) {
142
+ inlineFootnotes.push([node, pos]);
143
+ }
144
+ });
145
+ let index = 0;
146
+ const labels = new Map();
147
+ inlineFootnotes.sort((a, b) => a[1] - b[1]);
148
+ inlineFootnotes.forEach(([node]) => {
149
+ node.attrs.rids.forEach((rid) => {
150
+ labels.set(rid, (0, footnotes_utils_1.getAlphaOrderIndices)(index++));
151
+ });
152
+ });
153
+ return { inlineFootnotes, labels, footnotes, footnoteElement };
154
+ };
155
+ exports.buildPluginState = buildPluginState;
139
156
  exports.default = (props) => {
140
157
  return new prosemirror_state_1.Plugin({
141
158
  key: exports.footnotesKey,
@@ -144,25 +161,60 @@ exports.default = (props) => {
144
161
  return (0, exports.buildPluginState)(instance.doc);
145
162
  },
146
163
  apply(tr, value, oldState, newState) {
164
+ const prevState = exports.footnotesKey.getState(oldState);
165
+ if (!tr.docChanged && prevState) {
166
+ return prevState;
167
+ }
147
168
  return (0, exports.buildPluginState)(newState.doc);
148
169
  },
149
170
  },
150
171
  appendTransaction(transactions, oldState, newState) {
151
- const { nodes: oldInlineFootnoteNodes } = exports.footnotesKey.getState(oldState);
152
- const { nodes: inlineFootnoteNodes, labels } = exports.footnotesKey.getState(newState);
153
- if ((0, lodash_1.isEqual)(inlineFootnoteNodes, oldInlineFootnoteNodes)) {
172
+ const { inlineFootnotes: oldInlineFootnoteNodes } = exports.footnotesKey.getState(oldState);
173
+ const { inlineFootnotes: inlineFootnoteNodes, footnotes, labels, footnoteElement, } = exports.footnotesKey.getState(newState);
174
+ const prevIds = oldInlineFootnoteNodes.map(([node]) => node.attrs.rids);
175
+ const newIds = inlineFootnoteNodes.map(([node]) => node.attrs.rids);
176
+ const initTransaction = transactions.find((t) => t.getMeta('INIT'));
177
+ if (!footnoteElement || (!initTransaction && (0, lodash_1.isEqual)(prevIds, newIds))) {
154
178
  return null;
155
179
  }
156
180
  const { tr } = newState;
181
+ const footnotesReordered = [];
182
+ const footnotesRest = new Map(footnotes);
157
183
  inlineFootnoteNodes.forEach(([node, pos]) => {
158
184
  const footnote = node;
159
185
  const contents = footnote.attrs.rids
160
- .map((rid) => labels.get(rid))
186
+ .map((rid) => {
187
+ const currentfNode = footnotesRest.get(rid);
188
+ if (currentfNode) {
189
+ footnotesReordered.push(currentfNode[0]);
190
+ footnotesRest.delete(rid);
191
+ }
192
+ return labels.get(rid);
193
+ })
161
194
  .join('');
162
195
  if (footnote.attrs.contents !== contents) {
163
196
  tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, footnote.attrs), { rids: footnote.attrs.rids, contents }));
164
197
  }
165
198
  });
199
+ footnotesRest.forEach(([node]) => footnotesReordered.push(node));
200
+ const newFElement = transform_1.schema.nodes.footnotes_element.create(footnoteElement[0].attrs, footnotesReordered);
201
+ if (newFElement && footnotes.size > 0) {
202
+ tr.replaceWith(footnoteElement[1], footnoteElement[1] + footnoteElement[0].nodeSize, newFElement);
203
+ }
204
+ const prevSelection = newState.selection;
205
+ const selectedFootnote = (0, prosemirror_utils_1.findParentNodeClosestToPos)(prevSelection.$anchor, (node) => (0, transform_1.isFootnoteNode)(node));
206
+ if (selectedFootnote && footnotes.size > 0) {
207
+ let newFootnotePos = 0;
208
+ for (let i = 0; i < footnotesReordered.length; i++) {
209
+ const node = footnotesReordered[i];
210
+ newFootnotePos += node.nodeSize;
211
+ if (node.attrs.id === selectedFootnote.node.attrs.id) {
212
+ break;
213
+ }
214
+ }
215
+ tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, footnoteElement[1] + newFootnotePos));
216
+ }
217
+ (0, track_changes_plugin_1.skipTracking)(tr);
166
218
  return tr;
167
219
  },
168
220
  props: {
@@ -205,7 +257,7 @@ exports.default = (props) => {
205
257
  }
206
258
  }
207
259
  if (!((_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.textContent)) {
208
- decorations.push(prosemirror_view_1.Decoration.widget(pos + 2, (0, placeholder_1.placeholderWidget)('Add new note here')));
260
+ decorations.push(prosemirror_view_1.Decoration.widget(pos + 2, (0, placeholder_1.placeholderWidget)('Type new footnote here')));
209
261
  }
210
262
  if (tableInlineFootnoteIds &&
211
263
  !tableInlineFootnoteIds.has(node.attrs.id)) {
@@ -62,12 +62,13 @@ exports.default = (props) => {
62
62
  key: exports.highlightKey,
63
63
  state: {
64
64
  init: (tr, state) => buildPluginState(state.doc),
65
- apply: (tr) => {
65
+ apply: (tr, value) => {
66
66
  const meta = tr.getMeta(exports.highlightKey);
67
- if (meta) {
68
- if (exports.SET_COMMENT in meta) {
69
- props.setComment(meta[exports.SET_COMMENT]);
70
- }
67
+ if (meta && exports.SET_COMMENT in meta) {
68
+ props.setComment(meta[exports.SET_COMMENT]);
69
+ }
70
+ else if (!tr.docChanged || tr.step.length === 0) {
71
+ return value;
71
72
  }
72
73
  return buildPluginState(tr.doc);
73
74
  },
@@ -94,7 +94,6 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
94
94
  return buildSelectedSuggestionDecoration(suggestionId, state, props);
95
95
  }
96
96
  if (tr.getMeta(exports.CLEAR_SUGGESTION_ID)) {
97
- props.setEditorSelectedSuggestion(undefined);
98
97
  return prosemirror_view_1.DecorationSet.empty;
99
98
  }
100
99
  return value;
@@ -105,8 +104,11 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
105
104
  const nodeClicked = view.state.doc.nodeAt(pos);
106
105
  const trackChangesData = nodeClicked && getTrackChangesData(nodeClicked);
107
106
  if (!trackChangesData) {
108
- view.dispatch(view.state.tr.setMeta(exports.CLEAR_SUGGESTION_ID, true));
109
- props.setEditorSelectedSuggestion(undefined);
107
+ setTimeout(() => {
108
+ const newTr = view.state.tr.setMeta(exports.CLEAR_SUGGESTION_ID, true);
109
+ view.dispatch(newTr);
110
+ props.setEditorSelectedSuggestion(undefined);
111
+ });
110
112
  }
111
113
  },
112
114
  decorations: (state) => exports.selectedSuggestionKey.getState(state),
@@ -122,7 +124,9 @@ const buildSelectedSuggestionDecoration = (suggestionId, state, props) => {
122
124
  decorations.push(decoration(change.from, change.to, {
123
125
  class: 'selected-suggestion',
124
126
  }));
125
- props.setEditorSelectedSuggestion(change.id);
127
+ setTimeout(() => {
128
+ props.setEditorSelectedSuggestion(change.id);
129
+ }, 0);
126
130
  }
127
131
  return prosemirror_view_1.DecorationSet.create(state.doc, decorations);
128
132
  };
@@ -14,6 +14,9 @@ const isInlineFootnoteChange = (step, oldState, newState) => {
14
14
  exports.default = () => {
15
15
  return new prosemirror_state_1.Plugin({
16
16
  appendTransaction(transactions, oldState, newState) {
17
+ if (!transactions.find((tr) => tr.docChanged)) {
18
+ return null;
19
+ }
17
20
  const tableInlineFootnoteChange = transactions.find((tr) => tr.steps.find((s, i) => {
18
21
  var _a;
19
22
  if (s instanceof prosemirror_transform_1.ReplaceStep) {
@@ -62,7 +62,7 @@ class BaseNodeView {
62
62
  }
63
63
  };
64
64
  }
65
- setDomAttrs(node, element, omit = []) {
65
+ setDomAttrs(node, element, omit = ['contents']) {
66
66
  Object.keys(node.attrs || {}).forEach((attr) => {
67
67
  if (!omit.includes(attr)) {
68
68
  element.setAttribute(attr, node.attrs[attr]);
@@ -49,6 +49,9 @@ class BibliographyElementBlockView extends block_view_1.default {
49
49
  this.showPopper = (id) => {
50
50
  this.props.popper.destroy();
51
51
  const bib = (0, bibliography_1.getBibliographyPluginState)(this.view.state);
52
+ if (!bib) {
53
+ return;
54
+ }
52
55
  const componentProps = {
53
56
  items: Array.from(bib.bibliographyItems.values()),
54
57
  citationCounts: bib.citationCounts,
@@ -140,6 +143,9 @@ class BibliographyElementBlockView extends block_view_1.default {
140
143
  const can = this.props.getCapabilities();
141
144
  const wrapper = document.createElement('div');
142
145
  wrapper.classList.add('contents');
146
+ if (!bib) {
147
+ return;
148
+ }
143
149
  const [meta, bibliography] = bib.provider.makeBibliography();
144
150
  for (let i = 0; i < bibliography.length; i++) {
145
151
  const id = meta.entry_ids[i];
@@ -40,6 +40,9 @@ class CitationView extends base_node_view_1.BaseNodeView {
40
40
  };
41
41
  this.updateContents = () => {
42
42
  const bib = (0, bibliography_1.getBibliographyPluginState)(this.view.state);
43
+ if (!bib) {
44
+ return;
45
+ }
43
46
  const classes = [
44
47
  'citation',
45
48
  ...(0, track_changes_utils_1.getChangeClasses)(this.node.attrs.dataTracked),
@@ -90,6 +90,9 @@ class CitationEditableView extends citation_1.CitationView {
90
90
  this.showPopper = () => {
91
91
  this.props.popper.destroy();
92
92
  const bib = (0, bibliography_1.getBibliographyPluginState)(this.view.state);
93
+ if (!bib) {
94
+ return;
95
+ }
93
96
  const can = this.props.getCapabilities();
94
97
  const attrs = (0, track_changes_utils_1.getActualAttrs)(this.node);
95
98
  const rids = attrs.rids;
@@ -152,6 +155,9 @@ class CitationEditableView extends citation_1.CitationView {
152
155
  };
153
156
  this.handleCite = (items) => {
154
157
  const bib = (0, bibliography_1.getBibliographyPluginState)(this.view.state);
158
+ if (!bib) {
159
+ return;
160
+ }
155
161
  const attrs = (0, track_changes_utils_1.getActualAttrs)(this.node);
156
162
  const rids = [...attrs.rids];
157
163
  items = items.filter((i) => !rids.includes(i.id));
@@ -28,7 +28,9 @@ class FootnotesElementView extends block_view_1.default {
28
28
  this.elementType = 'div';
29
29
  this.checkEditability = () => {
30
30
  var _a, _b;
31
- const editable = this.node.childCount ? 'true' : 'false';
31
+ const editable = this.props.getCapabilities().editArticle && this.node.childCount
32
+ ? 'true'
33
+ : 'false';
32
34
  (_a = this.contentDOM) === null || _a === void 0 ? void 0 : _a.setAttribute('contenteditable', editable);
33
35
  (_b = this.dom) === null || _b === void 0 ? void 0 : _b.setAttribute('contenteditable', editable);
34
36
  };
@@ -21,6 +21,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.InlineFootnoteView = void 0;
22
22
  const style_guide_1 = require("@manuscripts/style-guide");
23
23
  const transform_1 = require("@manuscripts/transform");
24
+ const prosemirror_state_1 = require("prosemirror-state");
24
25
  const prosemirror_utils_1 = require("prosemirror-utils");
25
26
  const commands_1 = require("../commands");
26
27
  const track_changes_utils_1 = require("../lib/track-changes-utils");
@@ -33,6 +34,7 @@ class InlineFootnoteView extends base_node_view_1.BaseNodeView {
33
34
  super(...arguments);
34
35
  this.findParentTableElement = () => (0, prosemirror_utils_1.findParentNodeClosestToPos)(this.view.state.doc.resolve(this.getPos()), (node) => node.type === transform_1.schema.nodes.table_element);
35
36
  this.handleClick = () => {
37
+ var _a;
36
38
  if ((0, track_changes_utils_1.isDeleted)(this.node)) {
37
39
  return;
38
40
  }
@@ -49,11 +51,24 @@ class InlineFootnoteView extends base_node_view_1.BaseNodeView {
49
51
  this.props.popper.show(this.dom, this.popperContainer, 'bottom-end');
50
52
  }
51
53
  else {
52
- this.props.history.push(Object.assign(Object.assign({}, this.props.history.location), { hash: '#' + this.node.attrs.rid }));
54
+ if ((_a = this.node.attrs.rids) === null || _a === void 0 ? void 0 : _a.length) {
55
+ let nodePos = undefined;
56
+ this.view.state.doc.descendants((node, pos) => {
57
+ if (node.attrs.id === this.node.attrs.rids[0]) {
58
+ nodePos = pos;
59
+ }
60
+ });
61
+ if (nodePos && this.props.dispatch) {
62
+ const sel = prosemirror_state_1.TextSelection.near(this.view.state.doc.resolve(nodePos + 1));
63
+ this.props.dispatch(this.view.state.tr.setSelection(sel).scrollIntoView());
64
+ }
65
+ }
53
66
  }
54
67
  };
55
68
  this.updateContents = () => {
56
- this.setDomAttrs(this.node, this.dom);
69
+ const node = this.node;
70
+ this.dom.setAttribute('rids', node.attrs.rids.join(','));
71
+ this.dom.setAttribute('contents', node.attrs.contents);
57
72
  this.dom.className = [
58
73
  'footnote',
59
74
  ...(0, track_changes_utils_1.getChangeClasses)(this.node.attrs.dataTracked),
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { ObjectTypes } from '@manuscripts/json-schema';
17
17
  import { skipTracking } from '@manuscripts/track-changes-plugin';
18
- import { buildComment, generateID, isElementNodeType, isInBibliographySection, isListNode, isSectionNodeType, schema, } from '@manuscripts/transform';
18
+ import { buildComment, generateID, isElementNodeType, isFootnoteNode, isInBibliographySection, isListNode, isParagraphNode, isSectionNodeType, schema, } from '@manuscripts/transform';
19
19
  import { NodeRange } from 'prosemirror-model';
20
20
  import { wrapInList } from 'prosemirror-schema-list';
21
21
  import { NodeSelection, TextSelection, } from 'prosemirror-state';
@@ -53,7 +53,10 @@ export const blockActive = (type) => (state) => {
53
53
  return false;
54
54
  };
55
55
  export const canInsert = (type) => (state) => {
56
- const { $from } = state.selection;
56
+ const { $from, $to } = state.selection;
57
+ if ($from.node().type === schema.nodes.title && $from.pos === $to.pos) {
58
+ return false;
59
+ }
57
60
  for (let d = $from.depth; d >= 0; d--) {
58
61
  const index = $from.index(d);
59
62
  if ($from.node(d).canReplaceWith(index, index, type)) {
@@ -305,12 +308,24 @@ export const insertInlineFootnote = (kind) => (state, dispatch) => {
305
308
  let selectionPos;
306
309
  if (!footnotesSection) {
307
310
  const section = state.schema.nodes.footnotes_section.create({}, [
308
- state.schema.nodes.section_title.create({}, state.schema.text('Notes')),
311
+ state.schema.nodes.section_title.create({}, state.schema.text('Footnotes')),
309
312
  state.schema.nodes.footnotes_element.create({}, footnote),
310
313
  ]);
311
314
  const backmatter = findChildrenByType(tr.doc, schema.nodes.backmatter)[0];
312
- tr.insert(backmatter.pos + 1, section);
313
- selectionPos = backmatter.pos + section.nodeSize - 3;
315
+ const sectionPos = backmatter.pos + 1;
316
+ tr.insert(sectionPos, section);
317
+ let footnotePos = 0;
318
+ section.descendants((n, pos) => {
319
+ if (isFootnoteNode(n)) {
320
+ footnotePos = pos;
321
+ n.descendants((childNode, childPos) => {
322
+ if (isParagraphNode(childNode)) {
323
+ footnotePos += childPos;
324
+ }
325
+ });
326
+ }
327
+ });
328
+ selectionPos = sectionPos + footnotePos;
314
329
  }
315
330
  else {
316
331
  const footnoteElement = findChildrenByType(footnotesSection.node, schema.nodes.footnotes_element);
@@ -322,7 +337,7 @@ export const insertInlineFootnote = (kind) => (state, dispatch) => {
322
337
  selectionPos = pos + 2;
323
338
  }
324
339
  if (dispatch && selectionPos) {
325
- const selection = TextSelection.create(tr.doc, selectionPos);
340
+ const selection = TextSelection.near(tr.doc.resolve(selectionPos));
326
341
  dispatch(tr.setSelection(selection).scrollIntoView());
327
342
  }
328
343
  return true;
@@ -671,10 +686,13 @@ const addBlockComment = (node, state, dispatch) => {
671
686
  [SET_COMMENT]: comment,
672
687
  });
673
688
  tr.setMeta('addToHistory', false);
674
- if (dispatch && isAllowedType(type)) {
675
- dispatch(tr);
689
+ if (isAllowedType(type)) {
690
+ dispatch && dispatch(tr);
691
+ return true;
692
+ }
693
+ else {
694
+ return false;
676
695
  }
677
- return true;
678
696
  };
679
697
  const addHighlightComment = (node, state, dispatch) => {
680
698
  const { attrs: { id }, type, } = node;