@manuscripts/body-editor 1.9.6 → 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 (39) 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/plugins/affiliations.js +3 -0
  5. package/dist/cjs/plugins/bibliography/index.js +1 -1
  6. package/dist/cjs/plugins/footnotes/footnotes-utils.js +33 -1
  7. package/dist/cjs/plugins/footnotes/index.js +77 -26
  8. package/dist/cjs/plugins/highlight/index.js +6 -5
  9. package/dist/cjs/plugins/selected-suggestion-ui.js +8 -4
  10. package/dist/cjs/plugins/table-footnote.js +3 -0
  11. package/dist/cjs/views/base_node_view.js +1 -1
  12. package/dist/cjs/views/bibliography_element.js +6 -0
  13. package/dist/cjs/views/citation.js +3 -0
  14. package/dist/cjs/views/citation_editable.js +6 -0
  15. package/dist/cjs/views/footnotes_element.js +3 -1
  16. package/dist/cjs/views/inline_footnote.js +17 -2
  17. package/dist/es/commands.js +27 -9
  18. package/dist/es/configs/ManuscriptsEditor.js +20 -14
  19. package/dist/es/configs/editor-views.js +1 -1
  20. package/dist/es/plugins/affiliations.js +3 -0
  21. package/dist/es/plugins/bibliography/index.js +1 -1
  22. package/dist/es/plugins/footnotes/footnotes-utils.js +31 -0
  23. package/dist/es/plugins/footnotes/index.js +78 -27
  24. package/dist/es/plugins/highlight/index.js +6 -5
  25. package/dist/es/plugins/selected-suggestion-ui.js +8 -4
  26. package/dist/es/plugins/table-footnote.js +3 -0
  27. package/dist/es/views/base_node_view.js +1 -1
  28. package/dist/es/views/bibliography_element.js +6 -0
  29. package/dist/es/views/citation.js +3 -0
  30. package/dist/es/views/citation_editable.js +6 -0
  31. package/dist/es/views/footnotes_element.js +3 -1
  32. package/dist/es/views/inline_footnote.js +17 -2
  33. package/dist/types/plugins/bibliography/index.d.ts +1 -1
  34. package/dist/types/plugins/footnotes/footnotes-utils.d.ts +1 -0
  35. package/dist/types/plugins/footnotes/index.d.ts +5 -3
  36. package/dist/types/views/footnotes_element.d.ts +3 -3
  37. package/package.json +4 -4
  38. package/styles/AdvancedEditor.css +6 -8
  39. 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),
@@ -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,28 +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
- parentNode.type !== transform_1.schema.nodes.table_header) {
43
- nodes.push([node, pos]);
44
- node.attrs.rids.forEach((rid) => {
45
- labels.set(rid, String(++index));
46
- });
47
- }
48
- });
49
- return { nodes, labels };
50
- };
51
- exports.buildPluginState = buildPluginState;
52
35
  const scrollToInlineFootnote = (rid, view) => {
53
36
  view.state.doc.descendants((node, pos) => {
54
37
  const footnote = node;
55
- if (footnote.attrs.rids.includes(rid)) {
38
+ if ((0, transform_1.isInlineFootnoteNode)(node) && footnote.attrs.rids.includes(rid)) {
56
39
  const selection = prosemirror_state_1.NodeSelection.create(view.state.doc, pos);
57
40
  view.dispatch(view.state.tr.setSelection(selection).scrollIntoView());
58
41
  }
@@ -62,7 +45,7 @@ const labelWidget = (label, id) => (view) => {
62
45
  const element = document.createElement('span');
63
46
  element.className = 'footnote-label';
64
47
  element.textContent = label;
65
- element.addEventListener('click', () => {
48
+ element.addEventListener('mousedown', () => {
66
49
  scrollToInlineFootnote(id, view);
67
50
  });
68
51
  return element;
@@ -137,6 +120,39 @@ const deleteFootnoteWidget = (node, props, id, tableElement) => (view, getPos) =
137
120
  });
138
121
  return deleteBtn;
139
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;
140
156
  exports.default = (props) => {
141
157
  return new prosemirror_state_1.Plugin({
142
158
  key: exports.footnotesKey,
@@ -145,25 +161,60 @@ exports.default = (props) => {
145
161
  return (0, exports.buildPluginState)(instance.doc);
146
162
  },
147
163
  apply(tr, value, oldState, newState) {
164
+ const prevState = exports.footnotesKey.getState(oldState);
165
+ if (!tr.docChanged && prevState) {
166
+ return prevState;
167
+ }
148
168
  return (0, exports.buildPluginState)(newState.doc);
149
169
  },
150
170
  },
151
171
  appendTransaction(transactions, oldState, newState) {
152
- const { nodes: oldInlineFootnoteNodes } = exports.footnotesKey.getState(oldState);
153
- const { nodes: inlineFootnoteNodes, labels } = exports.footnotesKey.getState(newState);
154
- 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))) {
155
178
  return null;
156
179
  }
157
180
  const { tr } = newState;
181
+ const footnotesReordered = [];
182
+ const footnotesRest = new Map(footnotes);
158
183
  inlineFootnoteNodes.forEach(([node, pos]) => {
159
184
  const footnote = node;
160
185
  const contents = footnote.attrs.rids
161
- .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
+ })
162
194
  .join('');
163
195
  if (footnote.attrs.contents !== contents) {
164
196
  tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, footnote.attrs), { rids: footnote.attrs.rids, contents }));
165
197
  }
166
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);
167
218
  return tr;
168
219
  },
169
220
  props: {
@@ -206,7 +257,7 @@ exports.default = (props) => {
206
257
  }
207
258
  }
208
259
  if (!((_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.textContent)) {
209
- 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')));
210
261
  }
211
262
  if (tableInlineFootnoteIds &&
212
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;
@@ -25,17 +25,23 @@ export const createEditorState = (props) => EditorState.create({
25
25
  schema,
26
26
  plugins: plugins(props),
27
27
  });
28
- export const createEditorView = (props, root, state, dispatch) => new EditorView(root, {
29
- state,
30
- editable: () => props.getCapabilities().editArticle,
31
- scrollMargin: {
32
- top: 100,
33
- bottom: 100,
34
- left: 0,
35
- right: 0,
36
- },
37
- dispatchTransaction: dispatch,
38
- nodeViews: views(props, dispatch),
39
- attributes: props.attributes,
40
- transformPasted,
41
- });
28
+ export const createEditorView = (props, root, state, dispatch) => {
29
+ const view = new EditorView(root, {
30
+ state,
31
+ editable: () => props.getCapabilities().editArticle,
32
+ scrollMargin: {
33
+ top: 100,
34
+ bottom: 100,
35
+ left: 0,
36
+ right: 0,
37
+ },
38
+ dispatchTransaction: dispatch,
39
+ nodeViews: views(props, dispatch),
40
+ attributes: props.attributes,
41
+ transformPasted,
42
+ });
43
+ const tr = view.state.tr.setMeta('INIT', true);
44
+ const nextState = view.state.apply(tr);
45
+ view.updateState(nextState);
46
+ return view;
47
+ };
@@ -64,7 +64,7 @@ export default (props, dispatch) => {
64
64
  footnote: footnote(props),
65
65
  footnotes_element: footnotesElement(props),
66
66
  inline_equation: inlineEquation(props),
67
- inline_footnote: inlineFootnote(props),
67
+ inline_footnote: inlineFootnote(props, dispatch),
68
68
  keyword: keyword(props, dispatch),
69
69
  keyword_group: keywordGroup(props, dispatch),
70
70
  link: link(props, dispatch),
@@ -70,6 +70,9 @@ export default () => {
70
70
  },
71
71
  appendTransaction(transactions, oldState, newState) {
72
72
  const { indexedAffiliationIds } = affiliationsKey.getState(newState);
73
+ if (!transactions.find((tr) => tr.docChanged)) {
74
+ return;
75
+ }
73
76
  const oldPluginState = affiliationsKey.getState(oldState);
74
77
  const { tr } = newState;
75
78
  const affiliations = [];
@@ -51,7 +51,7 @@ export default (props) => {
51
51
  props: {
52
52
  decorations(state) {
53
53
  const bib = getBibliographyPluginState(state);
54
- return DecorationSet.create(state.doc, buildDecorations(bib, state.doc));
54
+ return DecorationSet.create(state.doc, bib ? buildDecorations(bib, state.doc) : []);
55
55
  },
56
56
  },
57
57
  });
@@ -104,3 +104,34 @@ export const getInlineFootnotes = (id, targetNode) => {
104
104
  });
105
105
  return inlineFootnotes;
106
106
  };
107
+ export function getAlphaOrderIndices(index) {
108
+ const unicodeInterval = [97, 123];
109
+ const places = unicodeInterval[1] - unicodeInterval[0];
110
+ function getClassCount(n, order) {
111
+ return n * Math.pow(places, order - 1);
112
+ }
113
+ let indices = null;
114
+ for (;;) {
115
+ let current = index;
116
+ let position = 1;
117
+ while (current >= places) {
118
+ current = current / places;
119
+ position++;
120
+ }
121
+ const newIndex = Math.floor(current);
122
+ indices = indices ? indices : new Array(position).fill(0);
123
+ indices.splice(indices.length - position, 1, newIndex);
124
+ index -= getClassCount(newIndex, position);
125
+ if (position === 1) {
126
+ break;
127
+ }
128
+ }
129
+ return (indices || [])
130
+ .map((v, i, array) => {
131
+ if (array.length > 1 && i !== array.length - 1) {
132
+ return String.fromCodePoint(v + unicodeInterval[0] - 1);
133
+ }
134
+ return String.fromCodePoint(v + unicodeInterval[0]);
135
+ })
136
+ .join('');
137
+ }
@@ -13,9 +13,10 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { isFootnoteNode, isInlineFootnoteNode, schema, } from '@manuscripts/transform';
16
+ import { skipTracking } from '@manuscripts/track-changes-plugin';
17
+ import { isFootnoteNode, isFootnotesElementNode, isFootnotesSectionNode, isInlineFootnoteNode, schema, } from '@manuscripts/transform';
17
18
  import { isEqual } from 'lodash';
18
- import { NodeSelection, Plugin, PluginKey } from 'prosemirror-state';
19
+ import { NodeSelection, Plugin, PluginKey, TextSelection, } from 'prosemirror-state';
19
20
  import { findParentNodeClosestToPos, findParentNodeOfType, } from 'prosemirror-utils';
20
21
  import { Decoration, DecorationSet } from 'prosemirror-view';
21
22
  import { alertIcon, deleteIcon } from '../../assets';
@@ -23,29 +24,12 @@ import { DeleteFootnoteDialog, } from '../../components/views/DeleteFootnoteDial
23
24
  import { findParentNodeWithIdValue, getChildOfType } from '../../lib/utils';
24
25
  import ReactSubView from '../../views/ReactSubView';
25
26
  import { placeholderWidget } from '../placeholder';
26
- import { findTableInlineFootnoteIds, getInlineFootnotes, } from './footnotes-utils';
27
+ import { findTableInlineFootnoteIds, getAlphaOrderIndices, getInlineFootnotes, } from './footnotes-utils';
27
28
  export const footnotesKey = new PluginKey('footnotes');
28
- export const buildPluginState = (doc) => {
29
- const nodes = [];
30
- let index = 0;
31
- const labels = new Map();
32
- doc.descendants((node, pos, parentNode) => {
33
- if (isInlineFootnoteNode(node) &&
34
- parentNode &&
35
- parentNode.type !== schema.nodes.table_cell &&
36
- parentNode.type !== schema.nodes.table_header) {
37
- nodes.push([node, pos]);
38
- node.attrs.rids.forEach((rid) => {
39
- labels.set(rid, String(++index));
40
- });
41
- }
42
- });
43
- return { nodes, labels };
44
- };
45
29
  const scrollToInlineFootnote = (rid, view) => {
46
30
  view.state.doc.descendants((node, pos) => {
47
31
  const footnote = node;
48
- if (footnote.attrs.rids.includes(rid)) {
32
+ if (isInlineFootnoteNode(node) && footnote.attrs.rids.includes(rid)) {
49
33
  const selection = NodeSelection.create(view.state.doc, pos);
50
34
  view.dispatch(view.state.tr.setSelection(selection).scrollIntoView());
51
35
  }
@@ -55,7 +39,7 @@ const labelWidget = (label, id) => (view) => {
55
39
  const element = document.createElement('span');
56
40
  element.className = 'footnote-label';
57
41
  element.textContent = label;
58
- element.addEventListener('click', () => {
42
+ element.addEventListener('mousedown', () => {
59
43
  scrollToInlineFootnote(id, view);
60
44
  });
61
45
  return element;
@@ -129,6 +113,38 @@ const deleteFootnoteWidget = (node, props, id, tableElement) => (view, getPos) =
129
113
  });
130
114
  return deleteBtn;
131
115
  };
116
+ export const buildPluginState = (doc) => {
117
+ const inlineFootnotes = [];
118
+ const footnotes = new Map();
119
+ let footnoteElement;
120
+ doc.descendants((node, pos, parentNode) => {
121
+ if (isFootnotesSectionNode(node)) {
122
+ node.descendants((node, childPos) => {
123
+ if (isFootnotesElementNode(node)) {
124
+ footnoteElement = [node, pos + childPos];
125
+ }
126
+ if (isFootnoteNode(node)) {
127
+ footnotes.set(node.attrs.id, [node, pos + childPos]);
128
+ }
129
+ });
130
+ }
131
+ if (isInlineFootnoteNode(node) &&
132
+ parentNode &&
133
+ parentNode.type !== schema.nodes.table_cell &&
134
+ parentNode.type !== schema.nodes.table_header) {
135
+ inlineFootnotes.push([node, pos]);
136
+ }
137
+ });
138
+ let index = 0;
139
+ const labels = new Map();
140
+ inlineFootnotes.sort((a, b) => a[1] - b[1]);
141
+ inlineFootnotes.forEach(([node]) => {
142
+ node.attrs.rids.forEach((rid) => {
143
+ labels.set(rid, getAlphaOrderIndices(index++));
144
+ });
145
+ });
146
+ return { inlineFootnotes, labels, footnotes, footnoteElement };
147
+ };
132
148
  export default (props) => {
133
149
  return new Plugin({
134
150
  key: footnotesKey,
@@ -137,25 +153,60 @@ export default (props) => {
137
153
  return buildPluginState(instance.doc);
138
154
  },
139
155
  apply(tr, value, oldState, newState) {
156
+ const prevState = footnotesKey.getState(oldState);
157
+ if (!tr.docChanged && prevState) {
158
+ return prevState;
159
+ }
140
160
  return buildPluginState(newState.doc);
141
161
  },
142
162
  },
143
163
  appendTransaction(transactions, oldState, newState) {
144
- const { nodes: oldInlineFootnoteNodes } = footnotesKey.getState(oldState);
145
- const { nodes: inlineFootnoteNodes, labels } = footnotesKey.getState(newState);
146
- if (isEqual(inlineFootnoteNodes, oldInlineFootnoteNodes)) {
164
+ const { inlineFootnotes: oldInlineFootnoteNodes } = footnotesKey.getState(oldState);
165
+ const { inlineFootnotes: inlineFootnoteNodes, footnotes, labels, footnoteElement, } = footnotesKey.getState(newState);
166
+ const prevIds = oldInlineFootnoteNodes.map(([node]) => node.attrs.rids);
167
+ const newIds = inlineFootnoteNodes.map(([node]) => node.attrs.rids);
168
+ const initTransaction = transactions.find((t) => t.getMeta('INIT'));
169
+ if (!footnoteElement || (!initTransaction && isEqual(prevIds, newIds))) {
147
170
  return null;
148
171
  }
149
172
  const { tr } = newState;
173
+ const footnotesReordered = [];
174
+ const footnotesRest = new Map(footnotes);
150
175
  inlineFootnoteNodes.forEach(([node, pos]) => {
151
176
  const footnote = node;
152
177
  const contents = footnote.attrs.rids
153
- .map((rid) => labels.get(rid))
178
+ .map((rid) => {
179
+ const currentfNode = footnotesRest.get(rid);
180
+ if (currentfNode) {
181
+ footnotesReordered.push(currentfNode[0]);
182
+ footnotesRest.delete(rid);
183
+ }
184
+ return labels.get(rid);
185
+ })
154
186
  .join('');
155
187
  if (footnote.attrs.contents !== contents) {
156
188
  tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, footnote.attrs), { rids: footnote.attrs.rids, contents }));
157
189
  }
158
190
  });
191
+ footnotesRest.forEach(([node]) => footnotesReordered.push(node));
192
+ const newFElement = schema.nodes.footnotes_element.create(footnoteElement[0].attrs, footnotesReordered);
193
+ if (newFElement && footnotes.size > 0) {
194
+ tr.replaceWith(footnoteElement[1], footnoteElement[1] + footnoteElement[0].nodeSize, newFElement);
195
+ }
196
+ const prevSelection = newState.selection;
197
+ const selectedFootnote = findParentNodeClosestToPos(prevSelection.$anchor, (node) => isFootnoteNode(node));
198
+ if (selectedFootnote && footnotes.size > 0) {
199
+ let newFootnotePos = 0;
200
+ for (let i = 0; i < footnotesReordered.length; i++) {
201
+ const node = footnotesReordered[i];
202
+ newFootnotePos += node.nodeSize;
203
+ if (node.attrs.id === selectedFootnote.node.attrs.id) {
204
+ break;
205
+ }
206
+ }
207
+ tr.setSelection(TextSelection.create(tr.doc, footnoteElement[1] + newFootnotePos));
208
+ }
209
+ skipTracking(tr);
159
210
  return tr;
160
211
  },
161
212
  props: {
@@ -198,7 +249,7 @@ export default (props) => {
198
249
  }
199
250
  }
200
251
  if (!((_a = node.firstChild) === null || _a === void 0 ? void 0 : _a.textContent)) {
201
- decorations.push(Decoration.widget(pos + 2, placeholderWidget('Add new note here')));
252
+ decorations.push(Decoration.widget(pos + 2, placeholderWidget('Type new footnote here')));
202
253
  }
203
254
  if (tableInlineFootnoteIds &&
204
255
  !tableInlineFootnoteIds.has(node.attrs.id)) {
@@ -56,12 +56,13 @@ export default (props) => {
56
56
  key: highlightKey,
57
57
  state: {
58
58
  init: (tr, state) => buildPluginState(state.doc),
59
- apply: (tr) => {
59
+ apply: (tr, value) => {
60
60
  const meta = tr.getMeta(highlightKey);
61
- if (meta) {
62
- if (SET_COMMENT in meta) {
63
- props.setComment(meta[SET_COMMENT]);
64
- }
61
+ if (meta && SET_COMMENT in meta) {
62
+ props.setComment(meta[SET_COMMENT]);
63
+ }
64
+ else if (!tr.docChanged || tr.step.length === 0) {
65
+ return value;
65
66
  }
66
67
  return buildPluginState(tr.doc);
67
68
  },
@@ -91,7 +91,6 @@ export default (props) => new Plugin({
91
91
  return buildSelectedSuggestionDecoration(suggestionId, state, props);
92
92
  }
93
93
  if (tr.getMeta(CLEAR_SUGGESTION_ID)) {
94
- props.setEditorSelectedSuggestion(undefined);
95
94
  return DecorationSet.empty;
96
95
  }
97
96
  return value;
@@ -102,8 +101,11 @@ export default (props) => new Plugin({
102
101
  const nodeClicked = view.state.doc.nodeAt(pos);
103
102
  const trackChangesData = nodeClicked && getTrackChangesData(nodeClicked);
104
103
  if (!trackChangesData) {
105
- view.dispatch(view.state.tr.setMeta(CLEAR_SUGGESTION_ID, true));
106
- props.setEditorSelectedSuggestion(undefined);
104
+ setTimeout(() => {
105
+ const newTr = view.state.tr.setMeta(CLEAR_SUGGESTION_ID, true);
106
+ view.dispatch(newTr);
107
+ props.setEditorSelectedSuggestion(undefined);
108
+ });
107
109
  }
108
110
  },
109
111
  decorations: (state) => selectedSuggestionKey.getState(state),
@@ -119,7 +121,9 @@ const buildSelectedSuggestionDecoration = (suggestionId, state, props) => {
119
121
  decorations.push(decoration(change.from, change.to, {
120
122
  class: 'selected-suggestion',
121
123
  }));
122
- props.setEditorSelectedSuggestion(change.id);
124
+ setTimeout(() => {
125
+ props.setEditorSelectedSuggestion(change.id);
126
+ }, 0);
123
127
  }
124
128
  return DecorationSet.create(state.doc, decorations);
125
129
  };
@@ -12,6 +12,9 @@ const isInlineFootnoteChange = (step, oldState, newState) => {
12
12
  export default () => {
13
13
  return new Plugin({
14
14
  appendTransaction(transactions, oldState, newState) {
15
+ if (!transactions.find((tr) => tr.docChanged)) {
16
+ return null;
17
+ }
15
18
  const tableInlineFootnoteChange = transactions.find((tr) => tr.steps.find((s, i) => {
16
19
  var _a;
17
20
  if (s instanceof ReplaceStep) {
@@ -59,7 +59,7 @@ export class BaseNodeView {
59
59
  }
60
60
  };
61
61
  }
62
- setDomAttrs(node, element, omit = []) {
62
+ setDomAttrs(node, element, omit = ['contents']) {
63
63
  Object.keys(node.attrs || {}).forEach((attr) => {
64
64
  if (!omit.includes(attr)) {
65
65
  element.setAttribute(attr, node.attrs[attr]);
@@ -43,6 +43,9 @@ export class BibliographyElementBlockView extends BlockView {
43
43
  this.showPopper = (id) => {
44
44
  this.props.popper.destroy();
45
45
  const bib = getBibliographyPluginState(this.view.state);
46
+ if (!bib) {
47
+ return;
48
+ }
46
49
  const componentProps = {
47
50
  items: Array.from(bib.bibliographyItems.values()),
48
51
  citationCounts: bib.citationCounts,
@@ -134,6 +137,9 @@ export class BibliographyElementBlockView extends BlockView {
134
137
  const can = this.props.getCapabilities();
135
138
  const wrapper = document.createElement('div');
136
139
  wrapper.classList.add('contents');
140
+ if (!bib) {
141
+ return;
142
+ }
137
143
  const [meta, bibliography] = bib.provider.makeBibliography();
138
144
  for (let i = 0; i < bibliography.length; i++) {
139
145
  const id = meta.entry_ids[i];
@@ -37,6 +37,9 @@ export class CitationView extends BaseNodeView {
37
37
  };
38
38
  this.updateContents = () => {
39
39
  const bib = getBibliographyPluginState(this.view.state);
40
+ if (!bib) {
41
+ return;
42
+ }
40
43
  const classes = [
41
44
  'citation',
42
45
  ...getChangeClasses(this.node.attrs.dataTracked),
@@ -84,6 +84,9 @@ export class CitationEditableView extends CitationView {
84
84
  this.showPopper = () => {
85
85
  this.props.popper.destroy();
86
86
  const bib = getBibliographyPluginState(this.view.state);
87
+ if (!bib) {
88
+ return;
89
+ }
87
90
  const can = this.props.getCapabilities();
88
91
  const attrs = getActualAttrs(this.node);
89
92
  const rids = attrs.rids;
@@ -146,6 +149,9 @@ export class CitationEditableView extends CitationView {
146
149
  };
147
150
  this.handleCite = (items) => {
148
151
  const bib = getBibliographyPluginState(this.view.state);
152
+ if (!bib) {
153
+ return;
154
+ }
149
155
  const attrs = getActualAttrs(this.node);
150
156
  const rids = [...attrs.rids];
151
157
  items = items.filter((i) => !rids.includes(i.id));
@@ -22,7 +22,9 @@ export class FootnotesElementView extends BlockView {
22
22
  this.elementType = 'div';
23
23
  this.checkEditability = () => {
24
24
  var _a, _b;
25
- const editable = this.node.childCount ? 'true' : 'false';
25
+ const editable = this.props.getCapabilities().editArticle && this.node.childCount
26
+ ? 'true'
27
+ : 'false';
26
28
  (_a = this.contentDOM) === null || _a === void 0 ? void 0 : _a.setAttribute('contenteditable', editable);
27
29
  (_b = this.dom) === null || _b === void 0 ? void 0 : _b.setAttribute('contenteditable', editable);
28
30
  };
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import { TableFootnotesSelector, } from '@manuscripts/style-guide';
17
17
  import { schema, } from '@manuscripts/transform';
18
+ import { TextSelection } from 'prosemirror-state';
18
19
  import { findChildrenByType, findParentNodeClosestToPos, } from 'prosemirror-utils';
19
20
  import { insertTableFootnote } from '../commands';
20
21
  import { getChangeClasses, isDeleted, isRejectedInsert, } from '../lib/track-changes-utils';
@@ -27,6 +28,7 @@ export class InlineFootnoteView extends BaseNodeView {
27
28
  super(...arguments);
28
29
  this.findParentTableElement = () => findParentNodeClosestToPos(this.view.state.doc.resolve(this.getPos()), (node) => node.type === schema.nodes.table_element);
29
30
  this.handleClick = () => {
31
+ var _a;
30
32
  if (isDeleted(this.node)) {
31
33
  return;
32
34
  }
@@ -43,11 +45,24 @@ export class InlineFootnoteView extends BaseNodeView {
43
45
  this.props.popper.show(this.dom, this.popperContainer, 'bottom-end');
44
46
  }
45
47
  else {
46
- this.props.history.push(Object.assign(Object.assign({}, this.props.history.location), { hash: '#' + this.node.attrs.rid }));
48
+ if ((_a = this.node.attrs.rids) === null || _a === void 0 ? void 0 : _a.length) {
49
+ let nodePos = undefined;
50
+ this.view.state.doc.descendants((node, pos) => {
51
+ if (node.attrs.id === this.node.attrs.rids[0]) {
52
+ nodePos = pos;
53
+ }
54
+ });
55
+ if (nodePos && this.props.dispatch) {
56
+ const sel = TextSelection.near(this.view.state.doc.resolve(nodePos + 1));
57
+ this.props.dispatch(this.view.state.tr.setSelection(sel).scrollIntoView());
58
+ }
59
+ }
47
60
  }
48
61
  };
49
62
  this.updateContents = () => {
50
- this.setDomAttrs(this.node, this.dom);
63
+ const node = this.node;
64
+ this.dom.setAttribute('rids', node.attrs.rids.join(','));
65
+ this.dom.setAttribute('contents', node.attrs.contents);
51
66
  this.dom.className = [
52
67
  'footnote',
53
68
  ...getChangeClasses(this.node.attrs.dataTracked),
@@ -36,4 +36,4 @@ export interface BibliographyProps {
36
36
  }
37
37
  declare const _default: (props: BibliographyProps) => Plugin<PluginState>;
38
38
  export default _default;
39
- export declare const getBibliographyPluginState: (state: EditorState) => PluginState;
39
+ export declare const getBibliographyPluginState: (state: EditorState) => PluginState | undefined;
@@ -27,4 +27,5 @@ interface InlineFootnote {
27
27
  pos: number;
28
28
  }
29
29
  export declare const getInlineFootnotes: (id: string, targetNode: ManuscriptNode) => InlineFootnote[];
30
+ export declare function getAlphaOrderIndices(index: number): string;
30
31
  export {};
@@ -13,15 +13,17 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { InlineFootnoteNode, ManuscriptNode } from '@manuscripts/transform';
16
+ import { FootnoteNode, FootnotesElementNode, InlineFootnoteNode, ManuscriptNode } from '@manuscripts/transform';
17
17
  import { Plugin, PluginKey } from 'prosemirror-state';
18
18
  import { PluginProps } from '../../configs/editor-plugins';
19
19
  interface PluginState {
20
- nodes: [InlineFootnoteNode, number][];
20
+ inlineFootnotes: [InlineFootnoteNode, number][];
21
21
  labels: Map<string, string>;
22
+ footnotes: Map<string, [FootnoteNode, number]>;
23
+ footnoteElement?: [FootnotesElementNode, number];
22
24
  }
23
25
  export declare const footnotesKey: PluginKey<PluginState>;
24
- export declare const buildPluginState: (doc: ManuscriptNode) => PluginState;
25
26
  export declare const uncitedFootnoteWidget: () => () => HTMLSpanElement;
27
+ export declare const buildPluginState: (doc: ManuscriptNode) => PluginState;
26
28
  declare const _default: (props: PluginProps) => Plugin<PluginState>;
27
29
  export default _default;
@@ -13,12 +13,12 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { BaseNodeProps } from './base_node_view';
17
16
  import BlockView from './block_view';
18
- export declare class FootnotesElementView<PropsType extends BaseNodeProps> extends BlockView<PropsType> {
17
+ import { EditableBlockProps } from './editable_block';
18
+ export declare class FootnotesElementView<Props extends EditableBlockProps> extends BlockView<Props> {
19
19
  elementType: string;
20
20
  onUpdateContent(): void;
21
21
  checkEditability: () => void;
22
22
  }
23
- declare const _default: (props: BaseNodeProps) => import("../types").NodeViewCreator<FootnotesElementView<any>>;
23
+ declare const _default: (props: import("./base_node_view").BaseNodeProps) => import("../types").NodeViewCreator<FootnotesElementView<any>>;
24
24
  export default _default;
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.9.6",
4
+ "version": "1.9.7-LEAN-3136",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -31,8 +31,8 @@
31
31
  "@manuscripts/assets": "^0.6.4",
32
32
  "@manuscripts/json-schema": "^2.2.7",
33
33
  "@manuscripts/library": "^1.3.6",
34
- "@manuscripts/style-guide": "1.12.3",
35
- "@manuscripts/track-changes-plugin": "1.7.10",
34
+ "@manuscripts/style-guide": "1.12.4",
35
+ "@manuscripts/track-changes-plugin": "1.7.10-LEAN-3136-2MB-3",
36
36
  "@manuscripts/transform": "2.3.3",
37
37
  "astrocite-eutils": "^0.16.4",
38
38
  "mathjax-full": "^3.2.2",
@@ -111,4 +111,4 @@
111
111
  "@types/react": "^17.0.2",
112
112
  "prosemirror-tables": "^1.3.5"
113
113
  }
114
- }
114
+ }
@@ -686,12 +686,12 @@ Next levels are shifted 'up' by 1
686
686
  }
687
687
 
688
688
  .selected-suggestion {
689
- background: #BCE7F6 !important;
689
+ background: #bce7f6 !important;
690
690
  }
691
691
 
692
692
  .selected-suggestion {
693
693
  border-width: 2px 0 2px 0 !important;
694
- border-color: #20AEDF !important;
694
+ border-color: #20aedf !important;
695
695
  border-radius: 3px !important;
696
696
  border-style: solid !important;
697
697
  }
@@ -795,14 +795,14 @@ Next levels are shifted 'up' by 1
795
795
  display: flex;
796
796
  justify-content: space-between;
797
797
  align-items: flex-start;
798
- gap: 0 .5em;
798
+ gap: 0 0.5em;
799
799
  }
800
800
  .contributors-list {
801
801
  display: flex;
802
802
  max-width: 100%;
803
803
  flex: 0 1 auto;
804
804
  flex-wrap: wrap;
805
- gap: 0 .25em;
805
+ gap: 0 0.25em;
806
806
  }
807
807
  .contributors .tools-panel {
808
808
  position: initial;
@@ -825,7 +825,7 @@ Next levels are shifted 'up' by 1
825
825
  left: 0;
826
826
  top: -8px;
827
827
  width: auto;
828
- height: auto;
828
+ height: auto;
829
829
  }
830
830
  .contributor {
831
831
  position: relative;
@@ -864,8 +864,6 @@ Next levels are shifted 'up' by 1
864
864
  vertical-align: top;
865
865
  }
866
866
 
867
-
868
-
869
867
  .contributor-note {
870
868
  display: inline-block;
871
869
  font-size: 0.75em;
@@ -893,4 +891,4 @@ Next levels are shifted 'up' by 1
893
891
 
894
892
  * {
895
893
  scroll-behavior: smooth;
896
- }
894
+ }
package/styles/Editor.css CHANGED
@@ -937,13 +937,14 @@
937
937
 
938
938
  .ProseMirror .footnote::before {
939
939
  content: attr(contents);
940
- display: inline-block;
941
940
  position: relative;
942
941
  cursor: pointer;
943
942
  vertical-align: super;
943
+ z-index: 1;
944
944
  font-size: 75%;
945
945
  color: #0d79d0;
946
946
  }
947
+
947
948
  .ProseMirror .table-footer {
948
949
  font-size: 14px;
949
950
  padding-top: 8px;
@@ -951,7 +952,7 @@
951
952
 
952
953
  .ProseMirror .table-footnotes-element:has(> div):not(:first-child)::before {
953
954
  content: '';
954
- border-bottom: 1px dashed #C9C9C9;
955
+ border-bottom: 1px dashed #c9c9c9;
955
956
  display: block;
956
957
  margin-bottom: 8px;
957
958
  }
@@ -975,7 +976,10 @@
975
976
  position: relative;
976
977
  }
977
978
 
978
- .ProseMirror .table-footnotes-element > div:not(:has(.unctied-table-footnote)) p::before {
979
+ .ProseMirror
980
+ .table-footnotes-element
981
+ > div:not(:has(.unctied-table-footnote))
982
+ p::before {
979
983
  counter-increment: table_footnote;
980
984
  content: counter(table_footnote);
981
985
  display: inline-block;