@manuscripts/body-editor 1.5.10 → 1.5.11
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/plugins/bibliography/bibliography-utils.js +10 -1
- package/dist/cjs/plugins/bibliography/index.js +15 -6
- package/dist/cjs/plugins/tracking-mark.js +3 -3
- package/dist/cjs/views/bibliography_element.js +139 -2
- package/dist/cjs/views/citation.js +1 -1
- package/dist/es/plugins/bibliography/bibliography-utils.js +10 -1
- package/dist/es/plugins/bibliography/index.js +15 -6
- package/dist/es/plugins/tracking-mark.js +3 -3
- package/dist/es/views/bibliography_element.js +139 -2
- package/dist/es/views/citation.js +1 -1
- package/dist/types/plugins/bibliography/bibliography-utils.d.ts +1 -1
- package/dist/types/plugins/bibliography/types.d.ts +1 -0
- package/dist/types/plugins/tracking-mark.d.ts +2 -2
- package/dist/types/views/bibliography_element.d.ts +12 -1
- package/package.json +1 -1
- package/styles/Editor.css +1 -9
|
@@ -34,7 +34,7 @@ const lodash_es_1 = require("lodash-es");
|
|
|
34
34
|
const prosemirror_view_1 = require("prosemirror-view");
|
|
35
35
|
const isBibliographyElement = (node) => node.type === node.type.schema.nodes.bibliography_element;
|
|
36
36
|
exports.isBibliographyElement = isBibliographyElement;
|
|
37
|
-
const buildDecorations = (doc, citationNodes, popper, referencesModelMap) => {
|
|
37
|
+
const buildDecorations = (doc, citationNodes, popper, referencesModelMap, triggerUpdate) => {
|
|
38
38
|
const decorations = [];
|
|
39
39
|
let hasMissingItems = false;
|
|
40
40
|
for (const [node, pos, citation] of citationNodes) {
|
|
@@ -72,6 +72,15 @@ const buildDecorations = (doc, citationNodes, popper, referencesModelMap) => {
|
|
|
72
72
|
}
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
+
if (triggerUpdate) {
|
|
76
|
+
doc.descendants((node, pos) => {
|
|
77
|
+
if ((0, exports.isBibliographyElement)(node)) {
|
|
78
|
+
decorations.push(prosemirror_view_1.Decoration.node(pos, pos + node.nodeSize, {}, {
|
|
79
|
+
triggerUpdate: true,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
75
84
|
return decorations;
|
|
76
85
|
};
|
|
77
86
|
exports.buildDecorations = buildDecorations;
|
|
@@ -20,6 +20,7 @@ const library_1 = require("@manuscripts/library");
|
|
|
20
20
|
const lodash_es_1 = require("lodash-es");
|
|
21
21
|
const prosemirror_state_1 = require("prosemirror-state");
|
|
22
22
|
const prosemirror_view_1 = require("prosemirror-view");
|
|
23
|
+
const track_changes_utils_1 = require("../../lib/track-changes-utils");
|
|
23
24
|
const bibliography_utils_1 = require("./bibliography-utils");
|
|
24
25
|
exports.bibliographyKey = new prosemirror_state_1.PluginKey('bibliography');
|
|
25
26
|
exports.default = (props) => {
|
|
@@ -30,8 +31,9 @@ exports.default = (props) => {
|
|
|
30
31
|
init(config, instance) {
|
|
31
32
|
const referencesModelMap = (0, bibliography_utils_1.getReferencesModelMap)(instance.doc);
|
|
32
33
|
const citationNodes = (0, library_1.buildCitationNodes)(instance.doc, referencesModelMap);
|
|
33
|
-
const
|
|
34
|
-
const
|
|
34
|
+
const filteredCitationNodes = citationNodes.filter((node) => !(0, track_changes_utils_1.isRejectedInsert)(node[0]));
|
|
35
|
+
const citations = (0, library_1.buildCitations)(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
36
|
+
const bibliographyItems = (0, library_1.buildBibliographyItems)(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
35
37
|
return {
|
|
36
38
|
citationNodes,
|
|
37
39
|
citations,
|
|
@@ -41,12 +43,16 @@ exports.default = (props) => {
|
|
|
41
43
|
apply(tr, value, oldState, newState) {
|
|
42
44
|
const referencesModelMap = (0, bibliography_utils_1.getReferencesModelMap)(newState.doc);
|
|
43
45
|
const citationNodes = (0, library_1.buildCitationNodes)(newState.doc, referencesModelMap);
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
+
const filteredCitationNodes = citationNodes.filter((node) => !(0, track_changes_utils_1.isRejectedInsert)(node[0]));
|
|
47
|
+
const citations = (0, library_1.buildCitations)(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
48
|
+
const bibliographyItems = (0, library_1.buildBibliographyItems)(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
49
|
+
const meta = tr.getMeta(exports.bibliographyKey);
|
|
50
|
+
const triggerUpdate = meta && meta.triggerUpdate;
|
|
46
51
|
return {
|
|
47
52
|
citationNodes,
|
|
48
53
|
citations,
|
|
49
54
|
bibliographyItems,
|
|
55
|
+
triggerUpdate,
|
|
50
56
|
};
|
|
51
57
|
},
|
|
52
58
|
},
|
|
@@ -74,6 +80,9 @@ exports.default = (props) => {
|
|
|
74
80
|
if (selection instanceof prosemirror_state_1.NodeSelection) {
|
|
75
81
|
tr.setSelection(prosemirror_state_1.NodeSelection.create(tr.doc, selection.from));
|
|
76
82
|
}
|
|
83
|
+
tr.setMeta(exports.bibliographyKey, {
|
|
84
|
+
triggerUpdate: true,
|
|
85
|
+
});
|
|
77
86
|
tr.setMeta('origin', exports.bibliographyKey);
|
|
78
87
|
return tr;
|
|
79
88
|
}
|
|
@@ -83,8 +92,8 @@ exports.default = (props) => {
|
|
|
83
92
|
},
|
|
84
93
|
props: {
|
|
85
94
|
decorations(state) {
|
|
86
|
-
const { citationNodes } = exports.bibliographyKey.getState(state);
|
|
87
|
-
return prosemirror_view_1.DecorationSet.create(state.doc, (0, bibliography_utils_1.buildDecorations)(state.doc, citationNodes, props.popper, (0, bibliography_utils_1.getReferencesModelMap)(state.doc)));
|
|
95
|
+
const { citationNodes, triggerUpdate } = exports.bibliographyKey.getState(state);
|
|
96
|
+
return prosemirror_view_1.DecorationSet.create(state.doc, (0, bibliography_utils_1.buildDecorations)(state.doc, citationNodes, props.popper, (0, bibliography_utils_1.getReferencesModelMap)(state.doc), triggerUpdate));
|
|
88
97
|
},
|
|
89
98
|
},
|
|
90
99
|
});
|
|
@@ -41,17 +41,17 @@ const buildDecorations = (state) => {
|
|
|
41
41
|
if (change.type === 'node-attr-change' &&
|
|
42
42
|
change.dataTracked.status === track_changes_plugin_1.CHANGE_STATUS.pending &&
|
|
43
43
|
change.dataTracked.operation === track_changes_plugin_1.CHANGE_OPERATION.set_node_attributes) {
|
|
44
|
-
decorations.push(prosemirror_view_1.Decoration.widget(change.from + 1, (0, exports.getAttrsTrackingButton)(change), {
|
|
44
|
+
decorations.push(prosemirror_view_1.Decoration.widget(change.from + 1, (0, exports.getAttrsTrackingButton)(change.id), {
|
|
45
45
|
key: change.id,
|
|
46
46
|
}));
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
49
|
return decorations;
|
|
50
50
|
};
|
|
51
|
-
const getAttrsTrackingButton = (
|
|
51
|
+
const getAttrsTrackingButton = (changeID) => {
|
|
52
52
|
const el = document.createElement('button');
|
|
53
53
|
el.className = 'attrs-popper-button';
|
|
54
|
-
el.value =
|
|
54
|
+
el.value = changeID;
|
|
55
55
|
el.innerHTML = editIcon;
|
|
56
56
|
return el;
|
|
57
57
|
};
|
|
@@ -14,25 +14,162 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
27
|
+
var t = {};
|
|
28
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
29
|
+
t[p] = s[p];
|
|
30
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
31
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
32
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
33
|
+
t[p[i]] = s[p[i]];
|
|
34
|
+
}
|
|
35
|
+
return t;
|
|
36
|
+
};
|
|
17
37
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
38
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
39
|
};
|
|
20
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
41
|
exports.BibliographyElementBlockView = void 0;
|
|
42
|
+
const library_1 = require("@manuscripts/library");
|
|
43
|
+
const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
|
|
44
|
+
const transform_1 = require("@manuscripts/transform");
|
|
45
|
+
const react_1 = __importDefault(require("react"));
|
|
46
|
+
const assets_1 = require("../assets");
|
|
47
|
+
const dompurify_1 = require("../lib/dompurify");
|
|
48
|
+
const bibliography_1 = require("../plugins/bibliography");
|
|
49
|
+
const bibliography_utils_1 = require("../plugins/bibliography/bibliography-utils");
|
|
50
|
+
const comment_annotation_1 = require("../plugins/comment_annotation");
|
|
51
|
+
const tracking_mark_1 = require("../plugins/tracking-mark");
|
|
22
52
|
const block_view_1 = __importDefault(require("./block_view"));
|
|
23
53
|
const creators_1 = require("./creators");
|
|
54
|
+
const createBibliography = (bibliographyItems, cslProps) => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
+
const bibliographyItemsMap = new Map(bibliographyItems.map((item) => [item._id, item]));
|
|
56
|
+
const getLibraryItem = (id) => bibliographyItemsMap.get(id);
|
|
57
|
+
const { style = '', locale } = cslProps;
|
|
58
|
+
const provider = new library_1.CitationProvider({
|
|
59
|
+
getLibraryItem,
|
|
60
|
+
citationStyle: style,
|
|
61
|
+
locale,
|
|
62
|
+
});
|
|
63
|
+
const [bibmeta, generatedBibliographyItems] = provider.makeBibliography(bibliographyItems);
|
|
64
|
+
if (bibmeta.bibliography_errors.length) {
|
|
65
|
+
console.error(bibmeta.bibliography_errors);
|
|
66
|
+
}
|
|
67
|
+
const bibliographyFragment = generatedBibliographyItems
|
|
68
|
+
.map((item, i) => `<div id=${bibmeta.entry_ids[i]} class="bib-item"><div><div class="csl-bib-body">${item}</div></div></div>`)
|
|
69
|
+
.join('');
|
|
70
|
+
return (0, dompurify_1.sanitize)(`<div class="contents">${bibliographyFragment}</div>`);
|
|
71
|
+
});
|
|
24
72
|
class BibliographyElementBlockView extends block_view_1.default {
|
|
25
73
|
constructor() {
|
|
26
74
|
super(...arguments);
|
|
75
|
+
this.showPopper = (referenceID) => {
|
|
76
|
+
const { renderReactComponent, components: { ReferencesEditor }, } = this.props;
|
|
77
|
+
const handleSave = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
const _a = data, { _id: id, 'container-title': containerTitle, DOI: doi } = _a, rest = __rest(_a, ["_id", 'container-title', "DOI"]);
|
|
79
|
+
this.updateNodeAttrs(Object.assign({ id,
|
|
80
|
+
containerTitle,
|
|
81
|
+
doi }, rest));
|
|
82
|
+
});
|
|
83
|
+
if (!this.popperContainer) {
|
|
84
|
+
this.popperContainer = document.createElement('div');
|
|
85
|
+
this.popperContainer.className = 'references';
|
|
86
|
+
}
|
|
87
|
+
renderReactComponent(react_1.default.createElement(ReferencesEditor, { saveModel: handleSave, deleteModel: this.deleteNode, modelMap: (0, bibliography_utils_1.getReferencesModelMap)(this.view.state.doc, true), referenceID: referenceID }), this.popperContainer);
|
|
88
|
+
this.props.popper.show(this.dom, this.popperContainer, 'right');
|
|
89
|
+
};
|
|
27
90
|
this.stopEvent = () => true;
|
|
28
91
|
this.ignoreMutation = () => true;
|
|
92
|
+
this.updateContents = () => __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const bibliographyItems = bibliography_1.bibliographyKey.getState(this.view.state).bibliographyItems;
|
|
94
|
+
const commentsDecorationSet = comment_annotation_1.commentAnnotation.getState(this.view.state);
|
|
95
|
+
const commentElementMap = new Map();
|
|
96
|
+
const dataTrackedMap = new Map();
|
|
97
|
+
this.node.descendants((node, pos) => {
|
|
98
|
+
if (commentsDecorationSet) {
|
|
99
|
+
const nodePosition = this.getPos() + pos + 2;
|
|
100
|
+
const commentWidget = commentsDecorationSet.find(nodePosition, nodePosition);
|
|
101
|
+
if (commentWidget.length) {
|
|
102
|
+
const commentElement = commentWidget[0].type.toDOM();
|
|
103
|
+
commentElementMap.set(commentElement.id, commentElement);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const dataTracked = node.attrs.dataTracked;
|
|
107
|
+
if (dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.length) {
|
|
108
|
+
const lastChange = dataTracked[dataTracked.length - 1];
|
|
109
|
+
dataTrackedMap.set(node.attrs.id, lastChange);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
const bibliographyFragment = yield createBibliography(bibliographyItems, this.props.cslProps);
|
|
113
|
+
const bibItems = bibliographyFragment.querySelectorAll('.bib-item');
|
|
114
|
+
bibItems.forEach((element) => {
|
|
115
|
+
const doubleButton = document.createElement('div');
|
|
116
|
+
const editButton = document.createElement('button');
|
|
117
|
+
const commentButton = document.createElement('button');
|
|
118
|
+
doubleButton.className = 'bibliography-double-button';
|
|
119
|
+
editButton.className = 'bibliography-edit-button';
|
|
120
|
+
commentButton.className = 'bibliography-comment-button';
|
|
121
|
+
commentButton.addEventListener('click', (e) => {
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
this.props.setComment((0, transform_1.buildComment)(element.id));
|
|
124
|
+
});
|
|
125
|
+
editButton.addEventListener('click', (e) => {
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
this.showPopper(element.id);
|
|
128
|
+
this.popperContainer = undefined;
|
|
129
|
+
});
|
|
130
|
+
editButton.innerHTML = assets_1.editIcon;
|
|
131
|
+
commentButton.innerHTML = assets_1.commentIcon;
|
|
132
|
+
doubleButton.append(editButton, commentButton);
|
|
133
|
+
if (this.props.getCapabilities().seeReferencesButtons &&
|
|
134
|
+
!element.querySelector('.bibliography-double-button')) {
|
|
135
|
+
element.appendChild(doubleButton);
|
|
136
|
+
}
|
|
137
|
+
editButton.disabled = !this.props.getCapabilities().editCitationsAndRefs;
|
|
138
|
+
const commentElement = commentElementMap.get(element.id);
|
|
139
|
+
if (commentElement) {
|
|
140
|
+
element.childNodes[0].appendChild(commentElement);
|
|
141
|
+
}
|
|
142
|
+
const dataTracked = dataTrackedMap.get(element.id);
|
|
143
|
+
if (dataTracked) {
|
|
144
|
+
element.classList.add('attrs-track-mark');
|
|
145
|
+
const decoration = (0, tracking_mark_1.getMarkDecoration)(dataTracked);
|
|
146
|
+
decoration.style && element.setAttribute('style', decoration.style);
|
|
147
|
+
if (dataTracked.status === track_changes_plugin_1.CHANGE_STATUS.pending &&
|
|
148
|
+
dataTracked.operation === track_changes_plugin_1.CHANGE_OPERATION.set_node_attributes) {
|
|
149
|
+
element.childNodes[0].appendChild((0, tracking_mark_1.getAttrsTrackingButton)(dataTracked.id));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
const oldContent = this.container.querySelector('.contents');
|
|
154
|
+
if (oldContent) {
|
|
155
|
+
this.container.replaceChild(bibliographyFragment, oldContent);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
this.container.appendChild(bibliographyFragment);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
29
161
|
this.createElement = () => {
|
|
162
|
+
this.container = document.createElement('div');
|
|
163
|
+
this.container.classList.add('block');
|
|
164
|
+
this.container.contentEditable = 'false';
|
|
165
|
+
this.dom.setAttribute('contenteditable', 'false');
|
|
166
|
+
this.dom.appendChild(this.container);
|
|
30
167
|
this.contentDOM = document.createElement('div');
|
|
31
168
|
this.contentDOM.classList.add('block');
|
|
32
169
|
this.contentDOM.setAttribute('id', this.node.attrs.id);
|
|
33
170
|
this.contentDOM.setAttribute('contenteditable', 'false');
|
|
34
|
-
this.
|
|
35
|
-
this.
|
|
171
|
+
this.contentDOM.hidden = true;
|
|
172
|
+
this.container.appendChild(this.contentDOM);
|
|
36
173
|
};
|
|
37
174
|
}
|
|
38
175
|
}
|
|
@@ -119,7 +119,7 @@ class CitationView extends base_node_view_1.BaseNodeView {
|
|
|
119
119
|
const citeprocContent = citeprocCitations === null || citeprocCitations === void 0 ? void 0 : citeprocCitations.get(this.node.attrs.rid);
|
|
120
120
|
const fragment = (0, dompurify_1.sanitize)(citeprocContent && citeprocContent !== '[NO_PRINTED_FORM]'
|
|
121
121
|
? citeprocContent
|
|
122
|
-
:
|
|
122
|
+
: ' ', {
|
|
123
123
|
ALLOWED_TAGS: ['i', 'b', 'span', 'sup', 'sub', '#text'],
|
|
124
124
|
});
|
|
125
125
|
citationElement.appendChild(fragment);
|
|
@@ -30,7 +30,7 @@ import { schema } from '@manuscripts/transform';
|
|
|
30
30
|
import { pickBy } from 'lodash-es';
|
|
31
31
|
import { Decoration } from 'prosemirror-view';
|
|
32
32
|
export const isBibliographyElement = (node) => node.type === node.type.schema.nodes.bibliography_element;
|
|
33
|
-
export const buildDecorations = (doc, citationNodes, popper, referencesModelMap) => {
|
|
33
|
+
export const buildDecorations = (doc, citationNodes, popper, referencesModelMap, triggerUpdate) => {
|
|
34
34
|
const decorations = [];
|
|
35
35
|
let hasMissingItems = false;
|
|
36
36
|
for (const [node, pos, citation] of citationNodes) {
|
|
@@ -68,6 +68,15 @@ export const buildDecorations = (doc, citationNodes, popper, referencesModelMap)
|
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
|
+
if (triggerUpdate) {
|
|
72
|
+
doc.descendants((node, pos) => {
|
|
73
|
+
if (isBibliographyElement(node)) {
|
|
74
|
+
decorations.push(Decoration.node(pos, pos + node.nodeSize, {}, {
|
|
75
|
+
triggerUpdate: true,
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
71
80
|
return decorations;
|
|
72
81
|
};
|
|
73
82
|
const cleanData = (model) => pickBy(model, (value) => value !== undefined);
|
|
@@ -17,6 +17,7 @@ import { buildBibliographyItems, buildCitationNodes, buildCitations, CitationPro
|
|
|
17
17
|
import { isEqual } from 'lodash-es';
|
|
18
18
|
import { NodeSelection, Plugin, PluginKey } from 'prosemirror-state';
|
|
19
19
|
import { DecorationSet } from 'prosemirror-view';
|
|
20
|
+
import { isRejectedInsert } from '../../lib/track-changes-utils';
|
|
20
21
|
import { buildDecorations, getReferencesModelMap } from './bibliography-utils';
|
|
21
22
|
export const bibliographyKey = new PluginKey('bibliography');
|
|
22
23
|
export default (props) => {
|
|
@@ -27,8 +28,9 @@ export default (props) => {
|
|
|
27
28
|
init(config, instance) {
|
|
28
29
|
const referencesModelMap = getReferencesModelMap(instance.doc);
|
|
29
30
|
const citationNodes = buildCitationNodes(instance.doc, referencesModelMap);
|
|
30
|
-
const
|
|
31
|
-
const
|
|
31
|
+
const filteredCitationNodes = citationNodes.filter((node) => !isRejectedInsert(node[0]));
|
|
32
|
+
const citations = buildCitations(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
33
|
+
const bibliographyItems = buildBibliographyItems(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
32
34
|
return {
|
|
33
35
|
citationNodes,
|
|
34
36
|
citations,
|
|
@@ -38,12 +40,16 @@ export default (props) => {
|
|
|
38
40
|
apply(tr, value, oldState, newState) {
|
|
39
41
|
const referencesModelMap = getReferencesModelMap(newState.doc);
|
|
40
42
|
const citationNodes = buildCitationNodes(newState.doc, referencesModelMap);
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
+
const filteredCitationNodes = citationNodes.filter((node) => !isRejectedInsert(node[0]));
|
|
44
|
+
const citations = buildCitations(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
45
|
+
const bibliographyItems = buildBibliographyItems(filteredCitationNodes, (id) => referencesModelMap.get(id));
|
|
46
|
+
const meta = tr.getMeta(bibliographyKey);
|
|
47
|
+
const triggerUpdate = meta && meta.triggerUpdate;
|
|
43
48
|
return {
|
|
44
49
|
citationNodes,
|
|
45
50
|
citations,
|
|
46
51
|
bibliographyItems,
|
|
52
|
+
triggerUpdate,
|
|
47
53
|
};
|
|
48
54
|
},
|
|
49
55
|
},
|
|
@@ -71,6 +77,9 @@ export default (props) => {
|
|
|
71
77
|
if (selection instanceof NodeSelection) {
|
|
72
78
|
tr.setSelection(NodeSelection.create(tr.doc, selection.from));
|
|
73
79
|
}
|
|
80
|
+
tr.setMeta(bibliographyKey, {
|
|
81
|
+
triggerUpdate: true,
|
|
82
|
+
});
|
|
74
83
|
tr.setMeta('origin', bibliographyKey);
|
|
75
84
|
return tr;
|
|
76
85
|
}
|
|
@@ -80,8 +89,8 @@ export default (props) => {
|
|
|
80
89
|
},
|
|
81
90
|
props: {
|
|
82
91
|
decorations(state) {
|
|
83
|
-
const { citationNodes } = bibliographyKey.getState(state);
|
|
84
|
-
return DecorationSet.create(state.doc, buildDecorations(state.doc, citationNodes, props.popper, getReferencesModelMap(state.doc)));
|
|
92
|
+
const { citationNodes, triggerUpdate } = bibliographyKey.getState(state);
|
|
93
|
+
return DecorationSet.create(state.doc, buildDecorations(state.doc, citationNodes, props.popper, getReferencesModelMap(state.doc), triggerUpdate));
|
|
85
94
|
},
|
|
86
95
|
},
|
|
87
96
|
});
|
|
@@ -38,17 +38,17 @@ const buildDecorations = (state) => {
|
|
|
38
38
|
if (change.type === 'node-attr-change' &&
|
|
39
39
|
change.dataTracked.status === CHANGE_STATUS.pending &&
|
|
40
40
|
change.dataTracked.operation === CHANGE_OPERATION.set_node_attributes) {
|
|
41
|
-
decorations.push(Decoration.widget(change.from + 1, getAttrsTrackingButton(change), {
|
|
41
|
+
decorations.push(Decoration.widget(change.from + 1, getAttrsTrackingButton(change.id), {
|
|
42
42
|
key: change.id,
|
|
43
43
|
}));
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
return decorations;
|
|
47
47
|
};
|
|
48
|
-
export const getAttrsTrackingButton = (
|
|
48
|
+
export const getAttrsTrackingButton = (changeID) => {
|
|
49
49
|
const el = document.createElement('button');
|
|
50
50
|
el.className = 'attrs-popper-button';
|
|
51
|
-
el.value =
|
|
51
|
+
el.value = changeID;
|
|
52
52
|
el.innerHTML = editIcon;
|
|
53
53
|
return el;
|
|
54
54
|
};
|
|
@@ -13,20 +13,157 @@
|
|
|
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
|
+
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
|
+
import { CitationProvider } from '@manuscripts/library';
|
|
37
|
+
import { CHANGE_OPERATION, CHANGE_STATUS, } from '@manuscripts/track-changes-plugin';
|
|
38
|
+
import { buildComment } from '@manuscripts/transform';
|
|
39
|
+
import React from 'react';
|
|
40
|
+
import { commentIcon, editIcon } from '../assets';
|
|
41
|
+
import { sanitize } from '../lib/dompurify';
|
|
42
|
+
import { bibliographyKey } from '../plugins/bibliography';
|
|
43
|
+
import { getReferencesModelMap } from '../plugins/bibliography/bibliography-utils';
|
|
44
|
+
import { commentAnnotation } from '../plugins/comment_annotation';
|
|
45
|
+
import { getAttrsTrackingButton, getMarkDecoration, } from '../plugins/tracking-mark';
|
|
16
46
|
import BlockView from './block_view';
|
|
17
47
|
import { createNodeView } from './creators';
|
|
48
|
+
const createBibliography = (bibliographyItems, cslProps) => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
+
const bibliographyItemsMap = new Map(bibliographyItems.map((item) => [item._id, item]));
|
|
50
|
+
const getLibraryItem = (id) => bibliographyItemsMap.get(id);
|
|
51
|
+
const { style = '', locale } = cslProps;
|
|
52
|
+
const provider = new CitationProvider({
|
|
53
|
+
getLibraryItem,
|
|
54
|
+
citationStyle: style,
|
|
55
|
+
locale,
|
|
56
|
+
});
|
|
57
|
+
const [bibmeta, generatedBibliographyItems] = provider.makeBibliography(bibliographyItems);
|
|
58
|
+
if (bibmeta.bibliography_errors.length) {
|
|
59
|
+
console.error(bibmeta.bibliography_errors);
|
|
60
|
+
}
|
|
61
|
+
const bibliographyFragment = generatedBibliographyItems
|
|
62
|
+
.map((item, i) => `<div id=${bibmeta.entry_ids[i]} class="bib-item"><div><div class="csl-bib-body">${item}</div></div></div>`)
|
|
63
|
+
.join('');
|
|
64
|
+
return sanitize(`<div class="contents">${bibliographyFragment}</div>`);
|
|
65
|
+
});
|
|
18
66
|
export class BibliographyElementBlockView extends BlockView {
|
|
19
67
|
constructor() {
|
|
20
68
|
super(...arguments);
|
|
69
|
+
this.showPopper = (referenceID) => {
|
|
70
|
+
const { renderReactComponent, components: { ReferencesEditor }, } = this.props;
|
|
71
|
+
const handleSave = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
const _a = data, { _id: id, 'container-title': containerTitle, DOI: doi } = _a, rest = __rest(_a, ["_id", 'container-title', "DOI"]);
|
|
73
|
+
this.updateNodeAttrs(Object.assign({ id,
|
|
74
|
+
containerTitle,
|
|
75
|
+
doi }, rest));
|
|
76
|
+
});
|
|
77
|
+
if (!this.popperContainer) {
|
|
78
|
+
this.popperContainer = document.createElement('div');
|
|
79
|
+
this.popperContainer.className = 'references';
|
|
80
|
+
}
|
|
81
|
+
renderReactComponent(React.createElement(ReferencesEditor, { saveModel: handleSave, deleteModel: this.deleteNode, modelMap: getReferencesModelMap(this.view.state.doc, true), referenceID: referenceID }), this.popperContainer);
|
|
82
|
+
this.props.popper.show(this.dom, this.popperContainer, 'right');
|
|
83
|
+
};
|
|
21
84
|
this.stopEvent = () => true;
|
|
22
85
|
this.ignoreMutation = () => true;
|
|
86
|
+
this.updateContents = () => __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
const bibliographyItems = bibliographyKey.getState(this.view.state).bibliographyItems;
|
|
88
|
+
const commentsDecorationSet = commentAnnotation.getState(this.view.state);
|
|
89
|
+
const commentElementMap = new Map();
|
|
90
|
+
const dataTrackedMap = new Map();
|
|
91
|
+
this.node.descendants((node, pos) => {
|
|
92
|
+
if (commentsDecorationSet) {
|
|
93
|
+
const nodePosition = this.getPos() + pos + 2;
|
|
94
|
+
const commentWidget = commentsDecorationSet.find(nodePosition, nodePosition);
|
|
95
|
+
if (commentWidget.length) {
|
|
96
|
+
const commentElement = commentWidget[0].type.toDOM();
|
|
97
|
+
commentElementMap.set(commentElement.id, commentElement);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const dataTracked = node.attrs.dataTracked;
|
|
101
|
+
if (dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.length) {
|
|
102
|
+
const lastChange = dataTracked[dataTracked.length - 1];
|
|
103
|
+
dataTrackedMap.set(node.attrs.id, lastChange);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const bibliographyFragment = yield createBibliography(bibliographyItems, this.props.cslProps);
|
|
107
|
+
const bibItems = bibliographyFragment.querySelectorAll('.bib-item');
|
|
108
|
+
bibItems.forEach((element) => {
|
|
109
|
+
const doubleButton = document.createElement('div');
|
|
110
|
+
const editButton = document.createElement('button');
|
|
111
|
+
const commentButton = document.createElement('button');
|
|
112
|
+
doubleButton.className = 'bibliography-double-button';
|
|
113
|
+
editButton.className = 'bibliography-edit-button';
|
|
114
|
+
commentButton.className = 'bibliography-comment-button';
|
|
115
|
+
commentButton.addEventListener('click', (e) => {
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
this.props.setComment(buildComment(element.id));
|
|
118
|
+
});
|
|
119
|
+
editButton.addEventListener('click', (e) => {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
this.showPopper(element.id);
|
|
122
|
+
this.popperContainer = undefined;
|
|
123
|
+
});
|
|
124
|
+
editButton.innerHTML = editIcon;
|
|
125
|
+
commentButton.innerHTML = commentIcon;
|
|
126
|
+
doubleButton.append(editButton, commentButton);
|
|
127
|
+
if (this.props.getCapabilities().seeReferencesButtons &&
|
|
128
|
+
!element.querySelector('.bibliography-double-button')) {
|
|
129
|
+
element.appendChild(doubleButton);
|
|
130
|
+
}
|
|
131
|
+
editButton.disabled = !this.props.getCapabilities().editCitationsAndRefs;
|
|
132
|
+
const commentElement = commentElementMap.get(element.id);
|
|
133
|
+
if (commentElement) {
|
|
134
|
+
element.childNodes[0].appendChild(commentElement);
|
|
135
|
+
}
|
|
136
|
+
const dataTracked = dataTrackedMap.get(element.id);
|
|
137
|
+
if (dataTracked) {
|
|
138
|
+
element.classList.add('attrs-track-mark');
|
|
139
|
+
const decoration = getMarkDecoration(dataTracked);
|
|
140
|
+
decoration.style && element.setAttribute('style', decoration.style);
|
|
141
|
+
if (dataTracked.status === CHANGE_STATUS.pending &&
|
|
142
|
+
dataTracked.operation === CHANGE_OPERATION.set_node_attributes) {
|
|
143
|
+
element.childNodes[0].appendChild(getAttrsTrackingButton(dataTracked.id));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
const oldContent = this.container.querySelector('.contents');
|
|
148
|
+
if (oldContent) {
|
|
149
|
+
this.container.replaceChild(bibliographyFragment, oldContent);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
this.container.appendChild(bibliographyFragment);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
23
155
|
this.createElement = () => {
|
|
156
|
+
this.container = document.createElement('div');
|
|
157
|
+
this.container.classList.add('block');
|
|
158
|
+
this.container.contentEditable = 'false';
|
|
159
|
+
this.dom.setAttribute('contenteditable', 'false');
|
|
160
|
+
this.dom.appendChild(this.container);
|
|
24
161
|
this.contentDOM = document.createElement('div');
|
|
25
162
|
this.contentDOM.classList.add('block');
|
|
26
163
|
this.contentDOM.setAttribute('id', this.node.attrs.id);
|
|
27
164
|
this.contentDOM.setAttribute('contenteditable', 'false');
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
165
|
+
this.contentDOM.hidden = true;
|
|
166
|
+
this.container.appendChild(this.contentDOM);
|
|
30
167
|
};
|
|
31
168
|
}
|
|
32
169
|
}
|
|
@@ -90,7 +90,7 @@ export class CitationView extends BaseNodeView {
|
|
|
90
90
|
const citeprocContent = citeprocCitations === null || citeprocCitations === void 0 ? void 0 : citeprocCitations.get(this.node.attrs.rid);
|
|
91
91
|
const fragment = sanitize(citeprocContent && citeprocContent !== '[NO_PRINTED_FORM]'
|
|
92
92
|
? citeprocContent
|
|
93
|
-
:
|
|
93
|
+
: ' ', {
|
|
94
94
|
ALLOWED_TAGS: ['i', 'b', 'span', 'sup', 'sub', '#text'],
|
|
95
95
|
});
|
|
96
96
|
citationElement.appendChild(fragment);
|
|
@@ -19,6 +19,6 @@ import { ManuscriptNode } from '@manuscripts/transform';
|
|
|
19
19
|
import { Decoration } from 'prosemirror-view';
|
|
20
20
|
import { PopperManager } from '../../lib/popper';
|
|
21
21
|
export declare const isBibliographyElement: (node: ManuscriptNode) => boolean;
|
|
22
|
-
export declare const buildDecorations: (doc: ManuscriptNode, citationNodes: CitationNodes, popper: PopperManager, referencesModelMap: Map<string, Model
|
|
22
|
+
export declare const buildDecorations: (doc: ManuscriptNode, citationNodes: CitationNodes, popper: PopperManager, referencesModelMap: Map<string, Model>, triggerUpdate?: boolean) => Decoration[];
|
|
23
23
|
export declare const getNodeModel: <T extends Model>(node: ManuscriptNode, excludeDeletedNode?: boolean) => T | undefined;
|
|
24
24
|
export declare const getReferencesModelMap: (doc: ManuscriptNode, excludeDeletedNode?: boolean) => Map<string, Model>;
|
|
@@ -29,6 +29,7 @@ export interface PluginState {
|
|
|
29
29
|
citationNodes: CitationNodes;
|
|
30
30
|
citations: CiteProcCitation[];
|
|
31
31
|
bibliographyItems: BibliographyItem[];
|
|
32
|
+
triggerUpdate?: boolean;
|
|
32
33
|
}
|
|
33
34
|
export interface BibliographyProps {
|
|
34
35
|
getCitationProvider: () => CitationProvider | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TrackedAttrs } from '@manuscripts/track-changes-plugin';
|
|
2
2
|
import { Plugin } from 'prosemirror-state';
|
|
3
3
|
import { DecorationAttrs, DecorationSet } from 'prosemirror-view';
|
|
4
4
|
declare const _default: () => Plugin<DecorationSet>;
|
|
5
5
|
export default _default;
|
|
6
|
-
export declare const getAttrsTrackingButton: (
|
|
6
|
+
export declare const getAttrsTrackingButton: (changeID: string) => HTMLButtonElement;
|
|
7
7
|
export declare const getMarkDecoration: (dataTracked: TrackedAttrs, htmlNode?: HTMLElement) => DecorationAttrs;
|
|
@@ -13,11 +13,22 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { CommentAnnotation } from '@manuscripts/json-schema';
|
|
17
|
+
import React from 'react';
|
|
16
18
|
import { BaseNodeProps } from './base_node_view';
|
|
17
19
|
import BlockView from './block_view';
|
|
18
|
-
|
|
20
|
+
import { EditableBlockProps } from './editable_block';
|
|
21
|
+
interface BibliographyElementViewProps extends BaseNodeProps {
|
|
22
|
+
setComment: (comment?: CommentAnnotation) => void;
|
|
23
|
+
components: Record<string, React.ComponentType<any>>;
|
|
24
|
+
}
|
|
25
|
+
export declare class BibliographyElementBlockView<PropsType extends BibliographyElementViewProps & EditableBlockProps> extends BlockView<PropsType> {
|
|
26
|
+
container: HTMLElement;
|
|
27
|
+
popperContainer?: HTMLDivElement;
|
|
28
|
+
showPopper: (referenceID: string) => void;
|
|
19
29
|
stopEvent: () => boolean;
|
|
20
30
|
ignoreMutation: () => boolean;
|
|
31
|
+
updateContents: () => Promise<void>;
|
|
21
32
|
createElement: () => void;
|
|
22
33
|
}
|
|
23
34
|
declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<BibliographyElementBlockView<any>>;
|
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.5.
|
|
4
|
+
"version": "1.5.11",
|
|
5
5
|
"repository": "github:Atypon-OpenSource/manuscripts-body-editor",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"main": "dist/cjs",
|
package/styles/Editor.css
CHANGED
|
@@ -731,12 +731,8 @@
|
|
|
731
731
|
text-align: center;
|
|
732
732
|
}
|
|
733
733
|
|
|
734
|
-
.ProseMirror .block {
|
|
735
|
-
counter-reset: bib_item;
|
|
736
|
-
}
|
|
737
734
|
|
|
738
735
|
.ProseMirror .bib-item {
|
|
739
|
-
counter-increment: bib_item;
|
|
740
736
|
position: relative;
|
|
741
737
|
margin-right: 40px;
|
|
742
738
|
}
|
|
@@ -751,11 +747,7 @@
|
|
|
751
747
|
|
|
752
748
|
.ProseMirror .csl-left-margin {
|
|
753
749
|
padding-right: 1ch;
|
|
754
|
-
display:
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
.ProseMirror .csl-right-inline::before {
|
|
758
|
-
content: counter(bib_item) '. ';
|
|
750
|
+
display: table-cell;
|
|
759
751
|
}
|
|
760
752
|
|
|
761
753
|
.ProseMirror .csl-entry a {
|