@manuscripts/body-editor 1.6.13 → 1.6.14-LEAN-3094

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 (70) hide show
  1. package/dist/cjs/citation-sources/crossref.js +27 -54
  2. package/dist/cjs/commands.js +5 -6
  3. package/dist/cjs/configs/editor-views.js +4 -4
  4. package/dist/cjs/lib/array-reducer.js +45 -0
  5. package/dist/cjs/lib/mathml-to-svg.js +70 -0
  6. package/dist/cjs/lib/tex-to-svg.js +60 -0
  7. package/dist/cjs/plugins/bibliography/index.js +11 -1
  8. package/dist/cjs/testing/default-editor-data.js +0 -22
  9. package/dist/cjs/views/CitationEditorWrapper.js +65 -0
  10. package/dist/cjs/views/ReferencesEditor.js +50 -0
  11. package/dist/cjs/views/base_node_view.js +1 -1
  12. package/dist/cjs/views/bibliography_element.js +20 -27
  13. package/dist/cjs/views/citation.js +1 -72
  14. package/dist/cjs/views/citation_editable.js +91 -106
  15. package/dist/cjs/views/cross_reference_editable.js +12 -10
  16. package/dist/cjs/views/equation.js +8 -3
  17. package/dist/cjs/views/equation_editable.js +3 -9
  18. package/dist/cjs/views/equation_element.js +6 -3
  19. package/dist/cjs/views/inline_equation.js +8 -3
  20. package/dist/cjs/views/inline_equation_editable.js +3 -9
  21. package/dist/cjs/views/link_editable.js +42 -34
  22. package/dist/es/citation-sources/crossref.js +27 -54
  23. package/dist/es/commands.js +6 -7
  24. package/dist/es/configs/editor-views.js +4 -4
  25. package/dist/es/lib/array-reducer.js +41 -0
  26. package/dist/es/lib/mathml-to-svg.js +66 -0
  27. package/dist/es/lib/tex-to-svg.js +56 -0
  28. package/dist/es/plugins/bibliography/index.js +11 -1
  29. package/dist/es/testing/default-editor-data.js +0 -22
  30. package/dist/es/views/CitationEditorWrapper.js +38 -0
  31. package/dist/es/views/ReferencesEditor.js +23 -0
  32. package/dist/es/views/base_node_view.js +1 -1
  33. package/dist/es/views/bibliography_element.js +21 -28
  34. package/dist/es/views/citation.js +1 -49
  35. package/dist/es/views/citation_editable.js +92 -107
  36. package/dist/es/views/cross_reference_editable.js +12 -10
  37. package/dist/es/views/editable_block.js +1 -1
  38. package/dist/es/views/equation.js +8 -3
  39. package/dist/es/views/equation_editable.js +3 -9
  40. package/dist/es/views/equation_element.js +6 -3
  41. package/dist/es/views/inline_equation.js +8 -3
  42. package/dist/es/views/inline_equation_editable.js +3 -9
  43. package/dist/es/views/link_editable.js +42 -34
  44. package/dist/types/citation-sources/crossref.d.ts +2 -11
  45. package/dist/types/commands.d.ts +3 -3
  46. package/dist/types/components/views/LinkForm.d.ts +2 -2
  47. package/dist/types/configs/ManuscriptsEditor.d.ts +1 -6
  48. package/dist/types/configs/editor-plugins.d.ts +1 -2
  49. package/dist/types/configs/editor-views.d.ts +1 -3
  50. package/dist/types/lib/array-reducer.d.ts +25 -0
  51. package/dist/types/lib/context-menu.d.ts +1 -1
  52. package/dist/types/{plugins/models.d.ts → lib/mathml-to-svg.d.ts} +2 -13
  53. package/dist/types/lib/tex-to-svg.d.ts +18 -0
  54. package/dist/types/plugins/bibliography/index.d.ts +1 -1
  55. package/dist/types/views/CitationEditorWrapper.d.ts +3 -0
  56. package/dist/types/views/ReferencesEditor.d.ts +4 -0
  57. package/dist/types/views/base_node_view.d.ts +0 -3
  58. package/dist/types/views/bibliography_element.d.ts +6 -5
  59. package/dist/types/views/citation.d.ts +2 -14
  60. package/dist/types/views/citation_editable.d.ts +12 -6
  61. package/dist/types/views/cross_reference.d.ts +0 -1
  62. package/dist/types/views/editable_block.d.ts +2 -4
  63. package/dist/types/views/keyword_group.d.ts +3 -15
  64. package/dist/types/views/link_editable.d.ts +3 -0
  65. package/package.json +6 -5
  66. package/dist/cjs/plugins/models.js +0 -48
  67. package/dist/cjs/views/ReactView.js +0 -94
  68. package/dist/es/plugins/models.js +0 -45
  69. package/dist/es/views/ReactView.js +0 -66
  70. package/dist/types/views/ReactView.d.ts +0 -33
@@ -13,66 +13,39 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
- return new (P || (P = Promise))(function (resolve, reject) {
19
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
20
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
- step((generator = generator.apply(thisArg, _arguments || [])).next());
23
- });
24
- };
25
16
  import { convertCSLToBibliographyItem } from '@manuscripts/library';
17
+ import { buildBibliographyItem } from '@manuscripts/transform';
26
18
  import axios from 'axios';
27
- const search = (query, rows, mailto, tokenSource) => __awaiter(void 0, void 0, void 0, function* () {
28
- if (query.trim().match(/^10\.\S+\/\S+$/)) {
29
- return searchByDOI(query.trim(), mailto);
30
- }
31
- const response = yield axios.get(`https://api.crossref.org/works?mailto=${mailto}`, {
19
+ const search = (query, limit) => {
20
+ const controller = new AbortController();
21
+ const response = axios
22
+ .get(`https://api.crossref.org/works`, {
32
23
  params: {
33
24
  filter: 'type:journal-article',
34
25
  query,
35
- rows,
26
+ rows: limit,
36
27
  },
37
- cancelToken: tokenSource,
28
+ signal: controller.signal,
29
+ })
30
+ .then((r) => {
31
+ if (r.status !== 200) {
32
+ throw new Error('There was a problem searching for this query.');
33
+ }
34
+ const items = r.data.message.items;
35
+ const total = r.data.message['total-results'];
36
+ return {
37
+ items: items.map((i) => buildBibliographyItem(convertCSLToBibliographyItem(i))),
38
+ total,
39
+ };
38
40
  });
39
- if (response.status !== 200) {
40
- throw new Error('There was a problem searching for this query.');
41
- }
42
- const { message: { items, 'total-results': total }, } = response.data;
43
- return {
44
- items: items.map(convertCSLToBibliographyItem),
45
- total,
46
- };
47
- });
48
- const searchByDOI = (doi, mailto) => __awaiter(void 0, void 0, void 0, function* () {
49
- const response = yield axios.get(`https://api.crossref.org/works/${encodeURIComponent(doi)}?mailto=${mailto}`);
50
- if (response.status === 404) {
51
- throw new Error('An item with this DOI could not be found.');
52
- }
53
- if (response.status !== 200) {
54
- throw new Error('There was a problem searching for this DOI.');
55
- }
56
- const { message } = response.data;
57
- const item = convertCSLToBibliographyItem(message);
58
41
  return {
59
- items: [item],
60
- total: 1,
42
+ response: response,
43
+ cancel: () => controller.abort(),
44
+ isCancelled: controller.signal.aborted,
61
45
  };
62
- });
63
- const fetch = (item) => __awaiter(void 0, void 0, void 0, function* () {
64
- if (!item.DOI) {
65
- throw new Error('The item does not have a DOI');
66
- }
67
- const response = yield axios.get(`https://api.crossref.org/works/${encodeURIComponent(item.DOI)}/transform/application/vnd.citationstyles.csl+json`, {
68
- headers: {},
69
- });
70
- if (response.status === 404) {
71
- throw new Error('An item with this DOI could not be found.');
72
- }
73
- if (response.status !== 200) {
74
- throw new Error('There was a problem fetching this DOI.');
75
- }
76
- return convertCSLToBibliographyItem(response.data);
77
- });
78
- export const crossref = { fetch, search };
46
+ };
47
+ export const crossref = {
48
+ id: 'crossref',
49
+ label: 'External sources',
50
+ search,
51
+ };
@@ -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, buildInlineMathFragment, generateID, isElementNodeType, isInBibliographySection, isListNode, isSectionNodeType, schema, } from '@manuscripts/transform';
18
+ import { buildComment, generateID, isElementNodeType, isInBibliographySection, isListNode, 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';
@@ -101,7 +101,6 @@ export const createBlock = (nodeType, position, state, dispatch) => {
101
101
  case state.schema.nodes.equation_element:
102
102
  node = state.schema.nodes.equation_element.create({}, [
103
103
  state.schema.nodes.equation.create(),
104
- createAndFillFigcaptionElement(state),
105
104
  ]);
106
105
  break;
107
106
  default:
@@ -219,7 +218,7 @@ export const insertLink = (state, dispatch) => {
219
218
  }
220
219
  return true;
221
220
  };
222
- export const insertInlineCitation = (state, dispatch, view) => {
221
+ export const insertInlineCitation = (state, dispatch) => {
223
222
  const node = state.schema.nodes.citation.create({
224
223
  id: generateID(ObjectTypes.Citation),
225
224
  rids: [],
@@ -247,10 +246,10 @@ export const insertCrossReference = (state, dispatch) => {
247
246
  return true;
248
247
  };
249
248
  export const insertInlineEquation = (state, dispatch) => {
250
- const inlineMathFragment = buildInlineMathFragment(state.selection.$anchor.parent.attrs.id, selectedText().replace(/^\$/, '').replace(/\$$/, ''));
251
249
  const sourcePos = state.selection.from - 1;
252
250
  const tr = state.tr.replaceSelectionWith(state.schema.nodes.inline_equation.create({
253
- id: inlineMathFragment._id,
251
+ format: 'tex',
252
+ contents: selectedText().replace(/^\$/, '').replace(/\$$/, ''),
254
253
  }));
255
254
  if (dispatch) {
256
255
  const selection = NodeSelection.create(tr.doc, tr.mapping.map(sourcePos) + 1);
@@ -374,10 +373,10 @@ export const insertList = (type, style) => (state, dispatch) => {
374
373
  return skipCommandTracking(command)(state, dispatch);
375
374
  }
376
375
  };
377
- export const insertBibliographySection = (state, dispatch) => {
376
+ export const insertBibliographySection = () => {
378
377
  return false;
379
378
  };
380
- export const insertTOCSection = (state, dispatch) => {
379
+ export const insertTOCSection = () => {
381
380
  return false;
382
381
  };
383
382
  export const ifInTableBody = (command) => (state) => {
@@ -47,11 +47,11 @@ import tocElement from '../views/toc_element_editable';
47
47
  export default (props, dispatch) => {
48
48
  return {
49
49
  title: title(props, dispatch),
50
- bibliography_element: bibliographyElement(props),
50
+ bibliography_element: bibliographyElement(props, dispatch),
51
51
  blockquote_element: blockquoteElement(props),
52
52
  bullet_list: bulletList(props),
53
- citation: citation(props),
54
- cross_reference: crossReference(props),
53
+ citation: citation(props, dispatch),
54
+ cross_reference: crossReference(props, dispatch),
55
55
  contributors: contributorsSection(props, dispatch),
56
56
  equation: equation(props),
57
57
  equation_element: equationElement(props),
@@ -63,7 +63,7 @@ export default (props, dispatch) => {
63
63
  inline_footnote: inlineFootnote(props),
64
64
  keyword: keyword(props, dispatch),
65
65
  keyword_group: keywordGroup(props, dispatch),
66
- link: link(props),
66
+ link: link(props, dispatch),
67
67
  listing: listing(props),
68
68
  listing_element: listingElement(props),
69
69
  ordered_list: orderedList(props),
@@ -0,0 +1,41 @@
1
+ /*!
2
+ * © 2024 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export const arrayReducer = (isEqual = (a, b) => a === b) => {
17
+ return (state, action) => {
18
+ const handleUpdate = (state, items) => {
19
+ const copy = [...state];
20
+ items.forEach((item) => {
21
+ const index = copy.findIndex((i) => isEqual(item, i));
22
+ if (index >= 0) {
23
+ copy[index] = item;
24
+ }
25
+ else {
26
+ copy.push(item);
27
+ }
28
+ });
29
+ return copy;
30
+ };
31
+ const handleDelete = (state, item) => {
32
+ return state.filter((i) => !isEqual(item, i));
33
+ };
34
+ switch (action.type) {
35
+ case 'update':
36
+ return handleUpdate(state, action.items);
37
+ case 'delete':
38
+ return handleDelete(state, action.item);
39
+ }
40
+ };
41
+ };
@@ -0,0 +1,66 @@
1
+ /*!
2
+ * © 2019 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import 'mathjax-full/js/util/entities/all';
17
+ import { xmlSerializer } from '@manuscripts/transform';
18
+ import { HTMLAdaptor } from 'mathjax-full/js/adaptors/HTMLAdaptor';
19
+ import { MmlFactory } from 'mathjax-full/js/core/MmlTree/MmlFactory';
20
+ import { HTMLDocument } from 'mathjax-full/js/handlers/html/HTMLDocument';
21
+ import { MathML } from 'mathjax-full/js/input/mathml';
22
+ import { SVG } from 'mathjax-full/js/output/svg';
23
+ class ManuscriptsMmlFactory extends MmlFactory {
24
+ constructor() {
25
+ super();
26
+ this.nodeMap.set('image', this.nodeMap.get('none'));
27
+ }
28
+ create(kind, properties = {}, children = []) {
29
+ if (kind === 'image') {
30
+ return this.node['none'](properties, children);
31
+ }
32
+ return this.node[kind](properties, children);
33
+ }
34
+ }
35
+ class ManuscriptsHTMLAdaptor extends HTMLAdaptor {
36
+ setAttribute(node, name, value, ns) {
37
+ if (name !== 'xmlns') {
38
+ ns ? node.setAttributeNS(ns, name, value) : node.setAttribute(name, value);
39
+ }
40
+ }
41
+ }
42
+ const InputJax = new MathML();
43
+ const OutputJax = new SVG({
44
+ fontCache: 'none',
45
+ });
46
+ const adaptor = new ManuscriptsHTMLAdaptor(window);
47
+ const doc = new HTMLDocument(document, adaptor, {
48
+ InputJax,
49
+ OutputJax,
50
+ MmlFactory: new ManuscriptsMmlFactory(),
51
+ });
52
+ doc.addStyleSheet();
53
+ export const convertMathMLToSVG = (mathml, display) => {
54
+ const item = doc.convert(mathml, {
55
+ display,
56
+ em: 16,
57
+ ex: 8,
58
+ containerWidth: 1000000,
59
+ lineWidth: 1000000,
60
+ scale: 1,
61
+ });
62
+ if (!item || !item.firstChild) {
63
+ return null;
64
+ }
65
+ return xmlSerializer.serializeToString(item.firstChild);
66
+ };
@@ -0,0 +1,56 @@
1
+ /*!
2
+ * © 2019 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import 'mathjax-full/js/util/entities/all';
17
+ import { xmlSerializer } from '@manuscripts/transform';
18
+ import { HTMLAdaptor } from 'mathjax-full/js/adaptors/HTMLAdaptor';
19
+ import { HTMLDocument } from 'mathjax-full/js/handlers/html/HTMLDocument';
20
+ import { TeX } from 'mathjax-full/js/input/tex';
21
+ import { AllPackages } from 'mathjax-full/js/input/tex/AllPackages';
22
+ import { SVG } from 'mathjax-full/js/output/svg';
23
+ export const packages = AllPackages.filter((name) => name !== 'html' && name !== 'bussproofs');
24
+ class ManuscriptsHTMLAdaptor extends HTMLAdaptor {
25
+ setAttribute(node, name, value, ns) {
26
+ if (name !== 'xmlns') {
27
+ ns ? node.setAttributeNS(ns, name, value) : node.setAttribute(name, value);
28
+ }
29
+ }
30
+ }
31
+ const InputJax = new TeX({
32
+ packages,
33
+ });
34
+ const OutputJax = new SVG({
35
+ fontCache: 'none',
36
+ });
37
+ const adaptor = new ManuscriptsHTMLAdaptor(window);
38
+ const doc = new HTMLDocument(document, adaptor, {
39
+ InputJax,
40
+ OutputJax,
41
+ });
42
+ doc.addStyleSheet();
43
+ export const convertTeXToSVG = (tex, display) => {
44
+ const item = doc.convert(tex, {
45
+ display,
46
+ em: 16,
47
+ ex: 8,
48
+ containerWidth: 1000000,
49
+ lineWidth: 1000000,
50
+ scale: 1,
51
+ });
52
+ if (!item || !item.firstChild) {
53
+ return null;
54
+ }
55
+ return xmlSerializer.serializeToString(item.firstChild);
56
+ };
@@ -60,17 +60,27 @@ const buildBibliographyPluginState = (doc, csl, $old) => {
60
60
  if (!csl.style) {
61
61
  return $new;
62
62
  }
63
- if ($old && isEqual(citations, $old.citations)) {
63
+ if ($old &&
64
+ isEqual(citations, $old.citations) &&
65
+ isEqual(modelMap, $old.bibliographyItems)) {
66
+ $new.citationCounts = $old.citationCounts;
64
67
  $new.provider = $old.provider;
65
68
  $new.renderedCitations = $old.renderedCitations;
66
69
  }
67
70
  else {
71
+ const citationCounts = new Map();
72
+ const rids = nodes.flatMap((e) => e[0].attrs.rids);
73
+ rids.forEach((rid) => {
74
+ const count = citationCounts.get(rid) || 0;
75
+ citationCounts.set(rid, count + 1);
76
+ });
68
77
  const provider = new CitationProvider({
69
78
  getLibraryItem: (id) => modelMap.get(id),
70
79
  citationStyle: csl.style || '',
71
80
  locale: csl.locale,
72
81
  });
73
82
  const citationTexts = provider.rebuildState(buildCitations(nodes));
83
+ $new.citationCounts = citationCounts;
74
84
  $new.provider = provider;
75
85
  $new.renderedCitations = new Map(citationTexts.map((i) => [i[0], i[2]]));
76
86
  }
@@ -16,8 +16,6 @@
16
16
  import { getAllPermitted } from '@manuscripts/style-guide';
17
17
  import { schema } from '@manuscripts/transform';
18
18
  import { createBrowserHistory } from 'history';
19
- import { uniqueId } from 'lodash';
20
- import ReactDOM from 'react-dom';
21
19
  import { PopperManager } from '../lib/popper';
22
20
  import emptyEditorDocJson from './empty-editor-doc.json';
23
21
  const theme = {};
@@ -64,10 +62,6 @@ export const defaultEditorProps = {
64
62
  projectID: 'test-project-id',
65
63
  getCurrentUser: () => TEST_DATA.USER,
66
64
  history: createBrowserHistory(),
67
- renderReactComponent: (child, container) => {
68
- ReactDOM.render(child, container);
69
- },
70
- unmountReactComponent: ReactDOM.unmountComponentAtNode,
71
65
  theme,
72
66
  getFiles: () => [],
73
67
  fileManagement: {
@@ -83,29 +77,13 @@ export const defaultEditorProps = {
83
77
  },
84
78
  getCitationProvider: () => undefined,
85
79
  plugins: [],
86
- saveModel: (model) => {
87
- var _a, _b;
88
- const id = (_a = model._id) !== null && _a !== void 0 ? _a : '';
89
- const oldModel = (_b = TEST_DATA.MODEL_MAP.get(id)) !== null && _b !== void 0 ? _b : {};
90
- const updatedModel = Object.assign(Object.assign({ createdAt: Date.now() / 1000, updatedAt: Date.now() / 1000, _id: uniqueId() }, oldModel), model);
91
- TEST_DATA.MODEL_MAP.set(id, updatedModel);
92
- return Promise.resolve(updatedModel);
93
- },
94
80
  deleteModel: (id) => {
95
81
  TEST_DATA.MODEL_MAP.delete(id);
96
82
  return Promise.resolve(id);
97
83
  },
98
- getLibraryItem: () => undefined,
99
- setLibraryItem: () => undefined,
100
- matchLibraryItemByIdentifier: () => undefined,
101
- filterLibraryItems: () => Promise.resolve([]),
102
- removeLibraryItem: () => undefined,
103
84
  retrySync: () => Promise.resolve(),
104
85
  setComment: () => undefined,
105
86
  setSelectedComment: () => undefined,
106
87
  setEditorSelectedSuggestion: () => undefined,
107
- components: {},
108
88
  environment: undefined,
109
- setCiteprocCitations: () => undefined,
110
- getCiteprocCitations: () => new Map(),
111
89
  };
@@ -0,0 +1,38 @@
1
+ import { CitationEditor } from '@manuscripts/style-guide';
2
+ import React, { useReducer } from 'react';
3
+ import { arrayReducer } from '../lib/array-reducer';
4
+ const itemsReducer = arrayReducer((a, b) => a._id === b._id);
5
+ const ridsReducer = arrayReducer();
6
+ export const CitationEditorWrapper = (props) => {
7
+ const [items, dispatchItems] = useReducer(itemsReducer, props.items);
8
+ const [rids, dispatchRids] = useReducer(ridsReducer, props.rids);
9
+ const handleSave = (item) => {
10
+ props.onSave(item);
11
+ dispatchItems({
12
+ type: 'update',
13
+ items: [item],
14
+ });
15
+ };
16
+ const handleDelete = (item) => {
17
+ props.onDelete(item);
18
+ dispatchItems({
19
+ type: 'delete',
20
+ item,
21
+ });
22
+ };
23
+ const handleCite = (items) => {
24
+ props.onCite(items);
25
+ dispatchRids({
26
+ type: 'update',
27
+ items: items.map((i) => i._id),
28
+ });
29
+ };
30
+ const handleUncite = (rid) => {
31
+ props.onUncite(rid);
32
+ dispatchRids({
33
+ type: 'delete',
34
+ item: rid,
35
+ });
36
+ };
37
+ return (React.createElement(CitationEditor, Object.assign({}, props, { rids: rids, items: items, onCite: handleCite, onUncite: handleUncite, onSave: handleSave, onDelete: handleDelete })));
38
+ };
@@ -0,0 +1,23 @@
1
+ import { ReferencesModal } from '@manuscripts/style-guide';
2
+ import React, { useReducer, useState } from 'react';
3
+ import { arrayReducer } from '../lib/array-reducer';
4
+ const itemsReducer = arrayReducer((a, b) => a._id === b._id);
5
+ export const ReferencesEditor = (props) => {
6
+ const [isOpen, setOpen] = useState(true);
7
+ const [items, dispatch] = useReducer(itemsReducer, props.items);
8
+ const handleSave = (item) => {
9
+ props.onSave(item);
10
+ dispatch({
11
+ type: 'update',
12
+ items: [item],
13
+ });
14
+ };
15
+ const handleDelete = (item) => {
16
+ props.onDelete(item);
17
+ dispatch({
18
+ type: 'delete',
19
+ item: item,
20
+ });
21
+ };
22
+ return (React.createElement(ReferencesModal, Object.assign({}, props, { isOpen: isOpen, onCancel: () => setOpen(false), items: items, onSave: handleSave, onDelete: handleDelete })));
23
+ };
@@ -72,7 +72,7 @@ export class BaseNodeView {
72
72
  };
73
73
  this.deleteNode = (id) => {
74
74
  this.view.state.doc.descendants((node, pos) => {
75
- if ((node.attrs.id || node.attrs.rid) === id) {
75
+ if (node.attrs.id === id) {
76
76
  this.view.dispatch(this.view.state.tr.delete(pos, pos + node.nodeSize));
77
77
  }
78
78
  });
@@ -22,20 +22,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
22
22
  step((generator = generator.apply(thisArg, _arguments || [])).next());
23
23
  });
24
24
  };
25
- var __rest = (this && this.__rest) || function (s, e) {
26
- var t = {};
27
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
28
- t[p] = s[p];
29
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
30
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
31
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
32
- t[p[i]] = s[p[i]];
33
- }
34
- return t;
35
- };
36
25
  import { CHANGE_OPERATION, CHANGE_STATUS, } from '@manuscripts/track-changes-plugin';
37
- import { buildComment } from '@manuscripts/transform';
38
- import React from 'react';
26
+ import { buildComment, Decoder, } from '@manuscripts/transform';
39
27
  import { commentIcon, editIcon } from '../assets';
40
28
  import { sanitize } from '../lib/dompurify';
41
29
  import { getBibliographyPluginState } from '../plugins/bibliography';
@@ -43,25 +31,24 @@ import { commentAnnotation } from '../plugins/comment_annotation';
43
31
  import { getAttrsTrackingButton, getMarkDecoration, } from '../plugins/tracking-mark';
44
32
  import BlockView from './block_view';
45
33
  import { createNodeView } from './creators';
34
+ import ReactSubView from './ReactSubView';
35
+ import { ReferencesEditor } from './ReferencesEditor';
46
36
  export class BibliographyElementBlockView extends BlockView {
47
37
  constructor() {
48
38
  super(...arguments);
39
+ this.decoder = new Decoder(new Map());
49
40
  this.gutterButtons = () => [];
50
- this.showPopper = (referenceID) => {
51
- const { renderReactComponent, components: { ReferencesEditor }, } = this.props;
52
- const handleSave = (data) => __awaiter(this, void 0, void 0, function* () {
53
- const _a = data, { _id: id, 'container-title': containerTitle, DOI: doi } = _a, rest = __rest(_a, ["_id", 'container-title', "DOI"]);
54
- this.updateNodeAttrs(Object.assign({ id,
55
- containerTitle,
56
- doi }, rest));
57
- });
58
- if (!this.popperContainer) {
59
- this.popperContainer = document.createElement('div');
60
- this.popperContainer.className = 'references';
61
- }
41
+ this.showPopper = (id) => {
62
42
  const bib = getBibliographyPluginState(this.view.state);
63
- renderReactComponent(React.createElement(ReferencesEditor, { saveModel: handleSave, deleteModel: this.deleteNode, modelMap: bib.bibliographyItems, referenceID: referenceID }), this.popperContainer);
64
- this.props.popper.show(this.dom, this.popperContainer, 'right');
43
+ const componentProps = {
44
+ items: Array.from(bib.bibliographyItems.values()),
45
+ citationCounts: bib.citationCounts,
46
+ item: bib.bibliographyItems.get(id),
47
+ onSave: this.handleSave,
48
+ onDelete: this.handleDelete,
49
+ };
50
+ this.editor = ReactSubView(this.props, ReferencesEditor, componentProps, this.node, this.getPos, this.view, 'references-modal');
51
+ this.props.popper.show(this.dom, this.editor, 'right');
65
52
  };
66
53
  this.stopEvent = () => true;
67
54
  this.ignoreMutation = () => true;
@@ -106,7 +93,6 @@ export class BibliographyElementBlockView extends BlockView {
106
93
  editButton.addEventListener('click', (e) => {
107
94
  e.preventDefault();
108
95
  this.showPopper(element.id);
109
- this.popperContainer = undefined;
110
96
  });
111
97
  editButton.innerHTML = editIcon;
112
98
  commentButton.innerHTML = commentIcon;
@@ -147,6 +133,13 @@ export class BibliographyElementBlockView extends BlockView {
147
133
  this.dom.setAttribute('contenteditable', 'false');
148
134
  this.dom.appendChild(this.container);
149
135
  };
136
+ this.handleSave = (item) => {
137
+ const node = this.decoder.decode(item);
138
+ this.updateNodeAttrs(node.attrs);
139
+ };
140
+ this.handleDelete = (item) => {
141
+ return this.deleteNode(item._id);
142
+ };
150
143
  }
151
144
  }
152
145
  export default createNodeView(BibliographyElementBlockView);
@@ -13,9 +13,8 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { ObjectTypes } from '@manuscripts/json-schema';
17
16
  import { DOMSerializer } from 'prosemirror-model';
18
- import React, { createElement } from 'react';
17
+ import { createElement } from 'react';
19
18
  import ReactDOM from 'react-dom';
20
19
  import { TrackChangesReview } from '../components/track-changes/TrackChangesReview';
21
20
  import { sanitize } from '../lib/dompurify';
@@ -27,38 +26,7 @@ import { createNodeView } from './creators';
27
26
  export class CitationView extends BaseNodeView {
28
27
  constructor() {
29
28
  super(...arguments);
30
- this.showPopper = () => {
31
- const { components: { CitationViewer }, projectID, renderReactComponent, } = this.props;
32
- const items = this.getBibliographyItems();
33
- if (!this.popperContainer) {
34
- this.popperContainer = document.createElement('div');
35
- this.popperContainer.className = 'citation-editor';
36
- }
37
- renderReactComponent(React.createElement(CitationViewer, { items: items, projectID: projectID, scheduleUpdate: this.props.popper.update }), this.popperContainer);
38
- this.props.popper.show(this.dom, this.popperContainer, 'right');
39
- };
40
29
  this.ignoreMutation = () => true;
41
- this.selectNode = () => {
42
- var _a;
43
- const isDeleted = !!((_a = this.node.attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.find(({ operation, status }) => operation === 'delete' && status !== 'rejected'));
44
- if (!isDeleted) {
45
- this.showPopper();
46
- this.dom.classList.add('ProseMirror-selectednode');
47
- }
48
- };
49
- this.deselectNode = () => {
50
- this.dom.classList.remove('ProseMirror-selectednode');
51
- this.props.popper.destroy();
52
- if (this.popperContainer) {
53
- this.props.unmountReactComponent(this.popperContainer);
54
- }
55
- };
56
- this.destroy = () => {
57
- this.props.popper.destroy();
58
- if (this.popperContainer) {
59
- this.props.unmountReactComponent(this.popperContainer);
60
- }
61
- };
62
30
  this.initialise = () => {
63
31
  if (!this.node.type.spec.toDOM) {
64
32
  throw Error(`Node view ${this.node.type} doesn't have toDOM method`);
@@ -109,22 +77,6 @@ export class CitationView extends BaseNodeView {
109
77
  }
110
78
  return citation;
111
79
  };
112
- this.getBibliographyItems = () => {
113
- const bib = getBibliographyPluginState(this.view.state);
114
- const citation = this.node;
115
- return citation.attrs.rids.map((rid) => {
116
- const item = bib.bibliographyItems.get(rid);
117
- if (!item) {
118
- const placeholder = {
119
- _id: rid,
120
- objectType: ObjectTypes.BibliographyItem,
121
- title: '[missing library item]',
122
- };
123
- return placeholder;
124
- }
125
- return item;
126
- });
127
- };
128
80
  }
129
81
  }
130
82
  export default createNodeView(CitationView);