@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.
- package/dist/cjs/citation-sources/crossref.js +27 -54
- package/dist/cjs/commands.js +5 -6
- package/dist/cjs/configs/editor-views.js +4 -4
- package/dist/cjs/lib/array-reducer.js +45 -0
- package/dist/cjs/lib/mathml-to-svg.js +70 -0
- package/dist/cjs/lib/tex-to-svg.js +60 -0
- package/dist/cjs/plugins/bibliography/index.js +11 -1
- package/dist/cjs/testing/default-editor-data.js +0 -22
- package/dist/cjs/views/CitationEditorWrapper.js +65 -0
- package/dist/cjs/views/ReferencesEditor.js +50 -0
- package/dist/cjs/views/base_node_view.js +1 -1
- package/dist/cjs/views/bibliography_element.js +20 -27
- package/dist/cjs/views/citation.js +1 -72
- package/dist/cjs/views/citation_editable.js +91 -106
- package/dist/cjs/views/cross_reference_editable.js +12 -10
- package/dist/cjs/views/equation.js +8 -3
- package/dist/cjs/views/equation_editable.js +3 -9
- package/dist/cjs/views/equation_element.js +6 -3
- package/dist/cjs/views/inline_equation.js +8 -3
- package/dist/cjs/views/inline_equation_editable.js +3 -9
- package/dist/cjs/views/link_editable.js +42 -34
- package/dist/es/citation-sources/crossref.js +27 -54
- package/dist/es/commands.js +6 -7
- package/dist/es/configs/editor-views.js +4 -4
- package/dist/es/lib/array-reducer.js +41 -0
- package/dist/es/lib/mathml-to-svg.js +66 -0
- package/dist/es/lib/tex-to-svg.js +56 -0
- package/dist/es/plugins/bibliography/index.js +11 -1
- package/dist/es/testing/default-editor-data.js +0 -22
- package/dist/es/views/CitationEditorWrapper.js +38 -0
- package/dist/es/views/ReferencesEditor.js +23 -0
- package/dist/es/views/base_node_view.js +1 -1
- package/dist/es/views/bibliography_element.js +21 -28
- package/dist/es/views/citation.js +1 -49
- package/dist/es/views/citation_editable.js +92 -107
- package/dist/es/views/cross_reference_editable.js +12 -10
- package/dist/es/views/editable_block.js +1 -1
- package/dist/es/views/equation.js +8 -3
- package/dist/es/views/equation_editable.js +3 -9
- package/dist/es/views/equation_element.js +6 -3
- package/dist/es/views/inline_equation.js +8 -3
- package/dist/es/views/inline_equation_editable.js +3 -9
- package/dist/es/views/link_editable.js +42 -34
- package/dist/types/citation-sources/crossref.d.ts +2 -11
- package/dist/types/commands.d.ts +3 -3
- package/dist/types/components/views/LinkForm.d.ts +2 -2
- package/dist/types/configs/ManuscriptsEditor.d.ts +1 -6
- package/dist/types/configs/editor-plugins.d.ts +1 -2
- package/dist/types/configs/editor-views.d.ts +1 -3
- package/dist/types/lib/array-reducer.d.ts +25 -0
- package/dist/types/lib/context-menu.d.ts +1 -1
- package/dist/types/{plugins/models.d.ts → lib/mathml-to-svg.d.ts} +2 -13
- package/dist/types/lib/tex-to-svg.d.ts +18 -0
- package/dist/types/plugins/bibliography/index.d.ts +1 -1
- package/dist/types/views/CitationEditorWrapper.d.ts +3 -0
- package/dist/types/views/ReferencesEditor.d.ts +4 -0
- package/dist/types/views/base_node_view.d.ts +0 -3
- package/dist/types/views/bibliography_element.d.ts +6 -5
- package/dist/types/views/citation.d.ts +2 -14
- package/dist/types/views/citation_editable.d.ts +12 -6
- package/dist/types/views/cross_reference.d.ts +0 -1
- package/dist/types/views/editable_block.d.ts +2 -4
- package/dist/types/views/keyword_group.d.ts +3 -15
- package/dist/types/views/link_editable.d.ts +3 -0
- package/package.json +6 -5
- package/dist/cjs/plugins/models.js +0 -48
- package/dist/cjs/views/ReactView.js +0 -94
- package/dist/es/plugins/models.js +0 -45
- package/dist/es/views/ReactView.js +0 -66
- 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,
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
42
|
+
response: response,
|
|
43
|
+
cancel: () => controller.abort(),
|
|
44
|
+
isCancelled: controller.signal.aborted,
|
|
61
45
|
};
|
|
62
|
-
}
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
+
};
|
package/dist/es/commands.js
CHANGED
|
@@ -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,
|
|
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
|
|
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
|
-
|
|
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 = (
|
|
376
|
+
export const insertBibliographySection = () => {
|
|
378
377
|
return false;
|
|
379
378
|
};
|
|
380
|
-
export const insertTOCSection = (
|
|
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 &&
|
|
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 (
|
|
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 = (
|
|
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
|
-
|
|
64
|
-
|
|
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
|
|
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);
|