@manuscripts/body-editor 2.5.6-date-fix.0 → 2.5.7
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/commands.js +121 -211
- package/dist/cjs/components/views/DeleteFootnoteDialog.js +2 -2
- package/dist/cjs/components/views/FootnotesSelector.js +18 -19
- package/dist/cjs/configs/ManuscriptsEditor.js +2 -1
- package/dist/cjs/configs/editor-plugins.js +0 -2
- package/dist/cjs/configs/editor-views.js +6 -4
- package/dist/cjs/icons.js +8 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/lib/comments.js +5 -1
- package/dist/cjs/lib/context-menu.js +21 -101
- package/dist/cjs/lib/doc.js +27 -4
- package/dist/cjs/lib/footnotes.js +31 -122
- package/dist/cjs/lib/plugins.js +8 -0
- package/dist/cjs/menus.js +1 -1
- package/dist/cjs/plugins/affiliations.js +2 -1
- package/dist/cjs/plugins/comments.js +10 -8
- package/dist/cjs/plugins/footnotes.js +188 -0
- package/dist/cjs/plugins/persist.js +4 -4
- package/dist/cjs/plugins/placeholder.js +19 -12
- package/dist/cjs/testing/default-editor-data.js +1 -1
- package/dist/cjs/testing/setup-editor.js +1 -0
- package/dist/cjs/versions.js +1 -1
- package/dist/cjs/views/editable_block.js +1 -1
- package/dist/cjs/views/footnote.js +117 -13
- package/dist/cjs/views/footnotes_element.js +10 -2
- package/dist/cjs/views/general_table_footnote.js +83 -0
- package/dist/cjs/views/inline_footnote.js +74 -124
- package/dist/cjs/views/table_element_footer.js +2 -5
- package/dist/es/commands.js +118 -207
- package/dist/es/components/views/DeleteFootnoteDialog.js +2 -2
- package/dist/es/components/views/FootnotesSelector.js +18 -19
- package/dist/es/configs/ManuscriptsEditor.js +2 -1
- package/dist/es/configs/editor-plugins.js +0 -2
- package/dist/es/configs/editor-views.js +4 -2
- package/dist/es/icons.js +5 -0
- package/dist/es/index.js +1 -0
- package/dist/es/lib/comments.js +3 -0
- package/dist/es/lib/context-menu.js +24 -101
- package/dist/es/lib/doc.js +25 -4
- package/dist/es/lib/footnotes.js +28 -116
- package/dist/es/lib/plugins.js +4 -0
- package/dist/es/menus.js +1 -1
- package/dist/es/plugins/affiliations.js +2 -1
- package/dist/es/plugins/comments.js +11 -9
- package/dist/es/plugins/footnotes.js +185 -0
- package/dist/es/plugins/persist.js +4 -4
- package/dist/es/plugins/placeholder.js +20 -11
- package/dist/es/testing/default-editor-data.js +1 -1
- package/dist/es/testing/setup-editor.js +1 -0
- package/dist/es/versions.js +1 -1
- package/dist/es/views/editable_block.js +1 -1
- package/dist/es/views/footnote.js +118 -13
- package/dist/es/views/footnotes_element.js +10 -2
- package/dist/es/views/general_table_footnote.js +76 -0
- package/dist/es/views/inline_footnote.js +78 -128
- package/dist/es/views/table_element_footer.js +4 -5
- package/dist/types/commands.d.ts +10 -14
- package/dist/types/components/views/DeleteFootnoteDialog.d.ts +2 -2
- package/dist/types/components/views/FootnotesSelector.d.ts +7 -7
- package/dist/types/configs/editor-views.d.ts +22 -35
- package/dist/types/icons.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lib/comments.d.ts +1 -0
- package/dist/types/lib/context-menu.d.ts +1 -3
- package/dist/types/lib/doc.d.ts +2 -0
- package/dist/types/lib/footnotes.d.ts +8 -19
- package/dist/types/lib/plugins.d.ts +3 -0
- package/dist/types/plugins/{footnotes/index.d.ts → footnotes.d.ts} +14 -11
- package/dist/types/plugins/placeholder.d.ts +0 -2
- package/dist/types/versions.d.ts +1 -1
- package/dist/types/views/footnote.d.ts +14 -6
- package/dist/types/views/footnotes_element.d.ts +1 -0
- package/dist/types/views/{table_element_footer_editable.d.ts → general_table_footnote.d.ts} +11 -2
- package/dist/types/views/inline_footnote.d.ts +8 -14
- package/dist/types/views/table_element_footer.d.ts +2 -2
- package/package.json +3 -3
- package/styles/Editor.css +35 -64
- package/dist/cjs/plugins/footnotes/index.js +0 -215
- package/dist/cjs/plugins/footnotes/widgets.js +0 -136
- package/dist/cjs/plugins/table-footnote.js +0 -46
- package/dist/cjs/views/footnote_editable.js +0 -21
- package/dist/cjs/views/footnotes_element_editable.js +0 -22
- package/dist/cjs/views/table_element_footer_editable.js +0 -20
- package/dist/es/plugins/footnotes/index.js +0 -211
- package/dist/es/plugins/footnotes/widgets.js +0 -127
- package/dist/es/plugins/table-footnote.js +0 -44
- package/dist/es/views/footnote_editable.js +0 -19
- package/dist/es/views/footnotes_element_editable.js +0 -20
- package/dist/es/views/table_element_footer_editable.js +0 -18
- package/dist/types/plugins/footnotes/widgets.d.ts +0 -22
- package/dist/types/plugins/table-footnote.d.ts +0 -3
- package/dist/types/views/footnote_editable.d.ts +0 -51
- package/dist/types/views/footnotes_element_editable.d.ts +0 -51
|
@@ -13,30 +13,40 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { isFootnoteNode, isGeneralTableFootnoteNode, } from '@manuscripts/transform';
|
|
16
17
|
import { Plugin, TextSelection } from 'prosemirror-state';
|
|
17
18
|
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
18
|
-
|
|
19
|
+
const placeholderWidget = (placeholder) => (view, getPos) => {
|
|
19
20
|
const element = document.createElement('span');
|
|
20
21
|
element.className = 'placeholder-text';
|
|
21
22
|
element.textContent = placeholder;
|
|
22
23
|
element.addEventListener('click', (event) => {
|
|
23
24
|
event.preventDefault();
|
|
24
|
-
|
|
25
|
+
const pos = getPos();
|
|
26
|
+
const selection = TextSelection.create(view.state.tr.doc, pos);
|
|
27
|
+
view.dispatch(view.state.tr.setSelection(selection));
|
|
25
28
|
});
|
|
26
29
|
return element;
|
|
27
30
|
};
|
|
31
|
+
const getParagraphPlaceholderText = (parent) => {
|
|
32
|
+
if (!parent || parent.textContent.length) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (isFootnoteNode(parent) || isGeneralTableFootnoteNode(parent)) {
|
|
36
|
+
return 'Type new footnote here';
|
|
37
|
+
}
|
|
38
|
+
};
|
|
28
39
|
export default () => new Plugin({
|
|
29
40
|
props: {
|
|
30
41
|
decorations: (state) => {
|
|
31
42
|
const decorations = [];
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (placeholder &&
|
|
35
|
-
!node.isAtom &&
|
|
36
|
-
node.type.isBlock &&
|
|
37
|
-
node.childCount === 0) {
|
|
43
|
+
state.doc.descendants((node, pos, parent) => {
|
|
44
|
+
if (!node.isAtom && node.type.isBlock && node.childCount === 0) {
|
|
38
45
|
if (node.type === node.type.schema.nodes.paragraph) {
|
|
39
|
-
|
|
46
|
+
const text = getParagraphPlaceholderText(parent);
|
|
47
|
+
if (text) {
|
|
48
|
+
decorations.push(Decoration.widget(pos + 1, placeholderWidget(text)));
|
|
49
|
+
}
|
|
40
50
|
}
|
|
41
51
|
else {
|
|
42
52
|
decorations.push(Decoration.node(pos, pos + node.nodeSize, {
|
|
@@ -44,8 +54,7 @@ export default () => new Plugin({
|
|
|
44
54
|
}));
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
|
-
};
|
|
48
|
-
state.doc.descendants(decorate);
|
|
57
|
+
});
|
|
49
58
|
return DecorationSet.create(state.doc, decorations);
|
|
50
59
|
},
|
|
51
60
|
},
|
|
@@ -68,7 +68,7 @@ export const defaultEditorProps = {
|
|
|
68
68
|
upload: () => { },
|
|
69
69
|
download: () => { },
|
|
70
70
|
},
|
|
71
|
-
getCapabilities: () => getAllPermitted(),
|
|
71
|
+
getCapabilities: () => (Object.assign(Object.assign({}, getAllPermitted()), { editWithoutTracking: true })),
|
|
72
72
|
cslProps: {
|
|
73
73
|
style: '',
|
|
74
74
|
locale: '',
|
package/dist/es/versions.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = '2.5.
|
|
1
|
+
export const VERSION = '2.5.7';
|
|
2
2
|
export const MATHJAX_VERSION = '3.2.2';
|
|
@@ -13,22 +13,127 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
19
|
-
|
|
16
|
+
import { schema } from '@manuscripts/transform';
|
|
17
|
+
import { isEqual } from 'lodash';
|
|
18
|
+
import { NodeSelection } from 'prosemirror-state';
|
|
19
|
+
import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils';
|
|
20
|
+
import { DeleteFootnoteDialog, } from '../components/views/DeleteFootnoteDialog';
|
|
21
|
+
import { alertIcon, deleteIcon } from '../icons';
|
|
22
|
+
import { getFootnotesElementState } from '../lib/footnotes';
|
|
23
|
+
import { getChangeClasses, isDeleted } from '../lib/track-changes-utils';
|
|
24
|
+
import { BaseNodeView } from './base_node_view';
|
|
25
|
+
import { createNodeView } from './creators';
|
|
26
|
+
import ReactSubView from './ReactSubView';
|
|
27
|
+
export class FootnoteView extends BaseNodeView {
|
|
20
28
|
constructor() {
|
|
21
29
|
super(...arguments);
|
|
22
|
-
this.
|
|
30
|
+
this.initialise = () => {
|
|
31
|
+
this.dom = document.createElement('div');
|
|
32
|
+
this.contentDOM = document.createElement('div');
|
|
33
|
+
this.contentDOM.classList.add('footnote-text');
|
|
34
|
+
this.updateContents();
|
|
35
|
+
};
|
|
36
|
+
this.updateContents = () => {
|
|
37
|
+
const id = this.node.attrs.id;
|
|
38
|
+
const fn = getFootnotesElementState(this.view.state, id);
|
|
39
|
+
if (!fn) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const marker = document.createElement('span');
|
|
43
|
+
if (!isDeleted(this.node) && fn.unusedFootnoteIDs.has(id)) {
|
|
44
|
+
marker.classList.add('uncited-footnote');
|
|
45
|
+
marker.innerHTML = alertIcon;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
marker.classList.add('footnote-marker');
|
|
49
|
+
marker.innerText = fn.labels.get(id) || '';
|
|
50
|
+
marker.addEventListener('mousedown', (e) => this.handleMarkerClick(e));
|
|
51
|
+
}
|
|
52
|
+
const deleteBtn = document.createElement('span');
|
|
53
|
+
deleteBtn.classList.add('delete-icon');
|
|
54
|
+
deleteBtn.innerHTML = deleteIcon;
|
|
55
|
+
deleteBtn.addEventListener('mousedown', (e) => this.handleDeleteClick(e));
|
|
56
|
+
this.dom.innerHTML = '';
|
|
57
|
+
this.dom.classList.value = '';
|
|
58
|
+
this.dom.classList.add('footnote');
|
|
59
|
+
this.dom.classList.add(...getChangeClasses(this.node.attrs.dataTracked));
|
|
60
|
+
this.dom.appendChild(marker);
|
|
61
|
+
this.contentDOM && this.dom.appendChild(this.contentDOM);
|
|
62
|
+
this.dom.appendChild(deleteBtn);
|
|
63
|
+
};
|
|
64
|
+
this.handleMarkerClick = (e) => {
|
|
65
|
+
e.preventDefault();
|
|
66
|
+
e.stopPropagation();
|
|
67
|
+
const id = this.node.attrs.id;
|
|
68
|
+
const fn = getFootnotesElementState(this.view.state, id);
|
|
69
|
+
if (!fn) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
for (const [node, pos] of fn.inlineFootnotes) {
|
|
73
|
+
if (node.attrs.rids.includes(id)) {
|
|
74
|
+
const tr = this.view.state.tr;
|
|
75
|
+
const selection = NodeSelection.create(this.view.state.doc, pos);
|
|
76
|
+
tr.setSelection(selection);
|
|
77
|
+
tr.scrollIntoView();
|
|
78
|
+
this.view.dispatch(tr);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
this.handleDeleteClick = (e) => {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
e.stopPropagation();
|
|
85
|
+
const componentProps = {
|
|
86
|
+
header: 'Delete footnote',
|
|
87
|
+
message: 'This action will entirely remove the footnote from the list because it will no longer be used.',
|
|
88
|
+
handleDelete: this.handleDelete,
|
|
89
|
+
};
|
|
90
|
+
this.dialog = ReactSubView(this.props, DeleteFootnoteDialog, componentProps, this.node, this.getPos, this.view);
|
|
91
|
+
this.props.popper.show(this.dom, this.dialog, 'auto', false);
|
|
92
|
+
};
|
|
93
|
+
this.handleDelete = () => {
|
|
94
|
+
const tr = this.view.state.tr;
|
|
95
|
+
this.deleteInlineFootnotes(tr);
|
|
96
|
+
this.deleteFootnote(tr);
|
|
97
|
+
this.view.dispatch(tr);
|
|
98
|
+
};
|
|
99
|
+
this.deleteInlineFootnotes = (tr) => {
|
|
100
|
+
const id = this.node.attrs.id;
|
|
101
|
+
const fns = getFootnotesElementState(this.view.state, this.node.attrs.id);
|
|
102
|
+
fns === null || fns === void 0 ? void 0 : fns.inlineFootnotes.forEach(([node, pos]) => {
|
|
103
|
+
pos = tr.mapping.map(pos);
|
|
104
|
+
const rids = node.attrs.rids.filter((rid) => rid !== id);
|
|
105
|
+
if (isEqual(rids, node.attrs.rids)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (!rids.length) {
|
|
109
|
+
tr.delete(pos, pos + node.nodeSize);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
tr.setNodeAttribute(pos, 'rids', rids);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
this.deleteFootnote = (tr) => {
|
|
117
|
+
const pos = tr.mapping.map(this.getPos());
|
|
118
|
+
const $pos = tr.doc.resolve(pos);
|
|
119
|
+
const element = findParentNodeOfTypeClosestToPos($pos, schema.nodes.footnotes_element);
|
|
120
|
+
if (element && getEffectiveChildCount(element.node) <= 1) {
|
|
121
|
+
tr.delete(element.pos, element.pos + element.node.nodeSize);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
tr.delete(pos, pos + this.node.nodeSize);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
23
127
|
}
|
|
24
128
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
129
|
+
const getEffectiveChildCount = (node) => {
|
|
130
|
+
let count = 0;
|
|
131
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
132
|
+
const child = node.child(i);
|
|
133
|
+
if (!isDeleted(child)) {
|
|
134
|
+
count++;
|
|
135
|
+
}
|
|
31
136
|
}
|
|
32
|
-
|
|
137
|
+
return count;
|
|
33
138
|
};
|
|
34
|
-
export default
|
|
139
|
+
export default createNodeView(FootnoteView);
|
|
@@ -13,13 +13,16 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { getChangeClasses } from '../lib/track-changes-utils';
|
|
16
17
|
import BlockView from './block_view';
|
|
17
18
|
import { createNodeOrElementView } from './creators';
|
|
18
|
-
import { setTCClasses } from './footnote';
|
|
19
19
|
export class FootnotesElementView extends BlockView {
|
|
20
20
|
constructor() {
|
|
21
21
|
super(...arguments);
|
|
22
22
|
this.elementType = 'div';
|
|
23
|
+
this.updateClasses = () => {
|
|
24
|
+
updateClasses(this.node, this.dom);
|
|
25
|
+
};
|
|
23
26
|
this.checkEditability = () => {
|
|
24
27
|
var _a, _b;
|
|
25
28
|
const editable = this.props.getCapabilities().editArticle && this.node.childCount
|
|
@@ -33,4 +36,9 @@ export class FootnotesElementView extends BlockView {
|
|
|
33
36
|
this.checkEditability();
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
|
-
|
|
39
|
+
const updateClasses = (node, dom) => {
|
|
40
|
+
!node.childCount && dom.classList.add('empty-node');
|
|
41
|
+
dom.classList.add('footnotes-element');
|
|
42
|
+
dom.classList.add(...getChangeClasses(node.attrs.dataTracked));
|
|
43
|
+
};
|
|
44
|
+
export default createNodeOrElementView(FootnotesElementView, 'div', updateClasses);
|
|
@@ -0,0 +1,76 @@
|
|
|
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 { schema } from '@manuscripts/transform';
|
|
17
|
+
import { findChildrenByType, findParentNodeOfTypeClosestToPos, } from 'prosemirror-utils';
|
|
18
|
+
import { DeleteFootnoteDialog, } from '../components/views/DeleteFootnoteDialog';
|
|
19
|
+
import { deleteIcon } from '../icons';
|
|
20
|
+
import { getChangeClasses, isDeleted } from '../lib/track-changes-utils';
|
|
21
|
+
import { BaseNodeView } from './base_node_view';
|
|
22
|
+
import { createNodeView } from './creators';
|
|
23
|
+
import ReactSubView from './ReactSubView';
|
|
24
|
+
export class GeneralTableFootnoteView extends BaseNodeView {
|
|
25
|
+
constructor() {
|
|
26
|
+
super(...arguments);
|
|
27
|
+
this.initialise = () => {
|
|
28
|
+
this.dom = document.createElement('div');
|
|
29
|
+
this.contentDOM = document.createElement('div');
|
|
30
|
+
this.contentDOM.classList.add('footnote-text');
|
|
31
|
+
this.updateContents();
|
|
32
|
+
};
|
|
33
|
+
this.updateContents = () => {
|
|
34
|
+
const deleteBtn = document.createElement('span');
|
|
35
|
+
deleteBtn.classList.add('delete-icon');
|
|
36
|
+
deleteBtn.innerHTML = deleteIcon;
|
|
37
|
+
deleteBtn.addEventListener('mousedown', (e) => this.handleClick(e));
|
|
38
|
+
this.dom.innerHTML = '';
|
|
39
|
+
this.dom.classList.value = '';
|
|
40
|
+
this.dom.classList.add('footnote', 'general-table-footnote');
|
|
41
|
+
this.dom.classList.add(...getChangeClasses(this.node.attrs.dataTracked));
|
|
42
|
+
this.contentDOM && this.dom.appendChild(this.contentDOM);
|
|
43
|
+
this.dom.appendChild(deleteBtn);
|
|
44
|
+
};
|
|
45
|
+
this.handleClick = (e) => {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
e.stopPropagation();
|
|
48
|
+
const componentProps = {
|
|
49
|
+
header: 'Delete table general note',
|
|
50
|
+
message: 'This action will entirely remove the table general note.',
|
|
51
|
+
handleDelete: this.handleDelete,
|
|
52
|
+
};
|
|
53
|
+
this.dialog = ReactSubView(this.props, DeleteFootnoteDialog, componentProps, this.node, this.getPos, this.view);
|
|
54
|
+
this.props.popper.show(this.dom, this.dialog, 'auto', false);
|
|
55
|
+
};
|
|
56
|
+
this.handleDelete = () => {
|
|
57
|
+
const tr = this.view.state.tr;
|
|
58
|
+
const pos = this.getPos();
|
|
59
|
+
const $pos = this.view.state.doc.resolve(pos);
|
|
60
|
+
const footer = findParentNodeOfTypeClosestToPos($pos, schema.nodes.table_element_footer);
|
|
61
|
+
const element = findChildrenByType(footer.node, schema.nodes.footnotes_element)[0];
|
|
62
|
+
if (element && !isDeleted(element.node)) {
|
|
63
|
+
const from = pos;
|
|
64
|
+
const to = from + this.node.nodeSize;
|
|
65
|
+
tr.delete(from, to);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const from = footer.pos;
|
|
69
|
+
const to = from + footer.node.nodeSize;
|
|
70
|
+
tr.delete(from, to);
|
|
71
|
+
}
|
|
72
|
+
this.view.dispatch(tr);
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export default createNodeView(GeneralTableFootnoteView);
|
|
@@ -14,21 +14,17 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { ContextMenu } from '@manuscripts/style-guide';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { createFootnote,
|
|
21
|
-
import { FootnotesSelector } from '../components/views/FootnotesSelector';
|
|
22
|
-
import { buildTableFootnoteLabels } from '../lib/footnotes';
|
|
17
|
+
import { isTableElementNode, } from '@manuscripts/transform';
|
|
18
|
+
import { TextSelection } from 'prosemirror-state';
|
|
19
|
+
import { FootnotesSelector, } from '../components/views/FootnotesSelector';
|
|
20
|
+
import { createFootnote, findFootnotesContainerNode, getFootnotesElementState, } from '../lib/footnotes';
|
|
23
21
|
import { getChangeClasses, isDeleted, isPendingInsert, } from '../lib/track-changes-utils';
|
|
24
|
-
import { footnotesKey } from '../plugins/footnotes';
|
|
25
22
|
import { BaseNodeView } from './base_node_view';
|
|
26
23
|
import { createNodeView } from './creators';
|
|
27
24
|
import ReactSubView from './ReactSubView';
|
|
28
25
|
export class InlineFootnoteView extends BaseNodeView {
|
|
29
26
|
constructor() {
|
|
30
27
|
super(...arguments);
|
|
31
|
-
this.findParentTableElement = () => findParentNodeClosestToPos(this.view.state.doc.resolve(this.getPos()), (node) => node.type === schema.nodes.table_element);
|
|
32
28
|
this.showContextMenu = () => {
|
|
33
29
|
this.props.popper.destroy();
|
|
34
30
|
const componentProps = {
|
|
@@ -37,7 +33,7 @@ export class InlineFootnoteView extends BaseNodeView {
|
|
|
37
33
|
label: 'Edit',
|
|
38
34
|
action: () => {
|
|
39
35
|
this.props.popper.destroy();
|
|
40
|
-
this.
|
|
36
|
+
this.showFootnotesSelector();
|
|
41
37
|
},
|
|
42
38
|
icon: 'Edit',
|
|
43
39
|
},
|
|
@@ -46,93 +42,66 @@ export class InlineFootnoteView extends BaseNodeView {
|
|
|
46
42
|
this.props.popper.show(this.dom, ReactSubView(this.props, ContextMenu, componentProps, this.node, this.getPos, this.view, 'context-menu'), 'right-start', false);
|
|
47
43
|
};
|
|
48
44
|
this.handleClick = () => {
|
|
49
|
-
if (isDeleted(this.node)) {
|
|
45
|
+
if (isDeleted(this.node) || !this.props.getCapabilities().editArticle) {
|
|
50
46
|
return;
|
|
51
47
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.activateModal({
|
|
55
|
-
notes: this.getNotes(tableElement),
|
|
56
|
-
onAdd: this.onAdd,
|
|
57
|
-
});
|
|
48
|
+
if (this.isTableFootnote) {
|
|
49
|
+
this.showFootnotesSelector();
|
|
58
50
|
}
|
|
59
51
|
else {
|
|
60
52
|
this.showContextMenu();
|
|
61
53
|
}
|
|
62
54
|
};
|
|
63
|
-
this.
|
|
64
|
-
var _a;
|
|
65
|
-
if ((_a = this.node.attrs.rids) === null || _a === void 0 ? void 0 : _a.length) {
|
|
66
|
-
let nodePos = undefined;
|
|
67
|
-
this.view.state.doc.descendants((node, pos) => {
|
|
68
|
-
if (node.attrs.id === this.node.attrs.rids[0]) {
|
|
69
|
-
nodePos = pos;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
if (nodePos && this.props.dispatch) {
|
|
73
|
-
const sel = TextSelection.near(this.view.state.doc.resolve(nodePos + 1));
|
|
74
|
-
this.props.dispatch(this.view.state.tr.setSelection(sel).scrollIntoView());
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
this.activateGenericFnModal = () => {
|
|
55
|
+
this.showFootnotesSelector = () => {
|
|
79
56
|
if (!this.props.getCapabilities().editArticle) {
|
|
80
57
|
return;
|
|
81
58
|
}
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
acc.push({
|
|
89
|
-
node,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
return acc;
|
|
93
|
-
}, []),
|
|
94
|
-
onCancel: () => {
|
|
95
|
-
const { tr } = this.view.state;
|
|
96
|
-
if (this.node.attrs.rids.length) {
|
|
97
|
-
this.view.dispatch(tr.delete(this.getPos(), this.getPos() + this.node.nodeSize));
|
|
98
|
-
}
|
|
99
|
-
this.destroy();
|
|
100
|
-
},
|
|
101
|
-
onAdd: () => {
|
|
102
|
-
const footnote = createFootnote(this.view.state, 'footnote');
|
|
103
|
-
const tr = insertFootnote(this.view.state, this.view.state.tr, footnote);
|
|
104
|
-
tr.setNodeAttribute(tr.mapping.map(this.getPos()), 'rids', [
|
|
105
|
-
footnote.attrs.id,
|
|
106
|
-
]);
|
|
107
|
-
this.view.dispatch(tr);
|
|
108
|
-
this.view.focus();
|
|
109
|
-
this.destroy();
|
|
110
|
-
},
|
|
111
|
-
addNewLabel: 'Replace with new footnote',
|
|
112
|
-
});
|
|
113
|
-
return true;
|
|
59
|
+
const state = this.view.state;
|
|
60
|
+
const pos = this.getPos();
|
|
61
|
+
const container = findFootnotesContainerNode(state.doc, pos);
|
|
62
|
+
const fn = getFootnotesElementState(state, container.node.attrs.id);
|
|
63
|
+
if (!fn) {
|
|
64
|
+
return [];
|
|
114
65
|
}
|
|
115
|
-
|
|
66
|
+
const rids = this.node.attrs.rids;
|
|
67
|
+
const footnotes = fn.footnotes
|
|
68
|
+
.map((n) => n[0])
|
|
69
|
+
.filter((n) => fn.unusedFootnoteIDs.has(n.attrs.id) || rids.includes(n.attrs.id));
|
|
70
|
+
const props = {
|
|
71
|
+
footnotes,
|
|
72
|
+
inlineFootnote: this.node,
|
|
73
|
+
labels: fn.labels,
|
|
74
|
+
onCancel: this.handleCancel,
|
|
75
|
+
onAdd: this.handleAdd,
|
|
76
|
+
onInsert: this.handleInsert,
|
|
77
|
+
};
|
|
78
|
+
this.popperContainer = ReactSubView(this.props, FootnotesSelector, props, this.node, this.getPos, this.view, 'footnote-editor');
|
|
79
|
+
this.props.popper.show(this.dom, this.popperContainer, 'auto', false);
|
|
116
80
|
};
|
|
117
81
|
this.updateContents = () => {
|
|
118
|
-
const attrs = this.node.attrs;
|
|
119
|
-
this.dom.setAttribute('rids', attrs.rids.join(','));
|
|
120
|
-
this.dom.setAttribute('contents', attrs.contents);
|
|
121
82
|
this.dom.className = [
|
|
122
|
-
'footnote',
|
|
83
|
+
'footnote-marker',
|
|
123
84
|
...getChangeClasses(this.node.attrs.dataTracked),
|
|
124
85
|
].join(' ');
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
86
|
+
const state = this.view.state;
|
|
87
|
+
const fn = getFootnotesElementState(state, this.node.attrs.id);
|
|
88
|
+
if (!fn) {
|
|
89
|
+
return;
|
|
129
90
|
}
|
|
91
|
+
this.dom.innerText = fn.labels.get(this.node.attrs.id) || '';
|
|
130
92
|
};
|
|
131
93
|
this.initialise = () => {
|
|
132
94
|
this.dom = this.createDOM();
|
|
133
|
-
this.dom.classList.add('footnote');
|
|
95
|
+
this.dom.classList.add('footnote-marker');
|
|
134
96
|
this.dom.addEventListener('click', this.handleClick);
|
|
135
97
|
this.updateContents();
|
|
98
|
+
const container = findFootnotesContainerNode(this.view.state.doc, this.getPos());
|
|
99
|
+
this.isTableFootnote = isTableElementNode(container.node);
|
|
100
|
+
};
|
|
101
|
+
this.selectNode = () => {
|
|
102
|
+
if (!this.node.attrs.rids.length) {
|
|
103
|
+
this.showFootnotesSelector();
|
|
104
|
+
}
|
|
136
105
|
};
|
|
137
106
|
this.ignoreMutation = () => true;
|
|
138
107
|
this.createDOM = () => {
|
|
@@ -143,71 +112,52 @@ export class InlineFootnoteView extends BaseNodeView {
|
|
|
143
112
|
this.props.popper.destroy();
|
|
144
113
|
(_a = this.popperContainer) === null || _a === void 0 ? void 0 : _a.remove();
|
|
145
114
|
};
|
|
146
|
-
this.
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
.filter(({ node }) => !isDeleted(node))
|
|
154
|
-
.map(({ node }) => ({
|
|
155
|
-
node: node,
|
|
156
|
-
index: tablesFootnoteLabels.get(node.attrs.id),
|
|
157
|
-
}));
|
|
115
|
+
this.handleCancel = () => {
|
|
116
|
+
const tr = this.view.state.tr;
|
|
117
|
+
const rids = this.node.attrs.rids;
|
|
118
|
+
if (!rids.length) {
|
|
119
|
+
const pos = this.getPos();
|
|
120
|
+
tr.delete(pos, pos + this.node.nodeSize);
|
|
121
|
+
this.view.dispatch(tr);
|
|
158
122
|
}
|
|
159
|
-
|
|
123
|
+
this.destroy();
|
|
160
124
|
};
|
|
161
|
-
this.
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
this.destroy();
|
|
125
|
+
this.handleAdd = () => {
|
|
126
|
+
const state = this.view.state;
|
|
127
|
+
const pos = this.getPos();
|
|
128
|
+
const container = findFootnotesContainerNode(state.doc, pos);
|
|
129
|
+
const fn = getFootnotesElementState(state, container.node.attrs.id);
|
|
130
|
+
if (!fn) {
|
|
131
|
+
return;
|
|
169
132
|
}
|
|
133
|
+
const tr = this.view.state.tr;
|
|
134
|
+
const footnote = createFootnote();
|
|
135
|
+
const rids = this.node.attrs.rids;
|
|
136
|
+
tr.setNodeAttribute(pos, 'rids', [...rids, footnote.attrs.id]);
|
|
137
|
+
const fnPos = fn.element[1] + fn.element[0].nodeSize - 1;
|
|
138
|
+
tr.insert(fnPos, footnote);
|
|
139
|
+
const selection = TextSelection.create(tr.doc, fnPos + 2);
|
|
140
|
+
tr.setSelection(selection).scrollIntoView();
|
|
141
|
+
this.view.dispatch(tr);
|
|
142
|
+
this.view.focus();
|
|
143
|
+
this.destroy();
|
|
170
144
|
};
|
|
171
|
-
this.
|
|
172
|
-
if (
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const rids = notes.map((note) => note.node.attrs.id);
|
|
177
|
-
const { tr } = this.view.state;
|
|
145
|
+
this.handleInsert = (footnotes) => {
|
|
146
|
+
if (footnotes.length) {
|
|
147
|
+
const pos = this.getPos();
|
|
148
|
+
const rids = footnotes.map((note) => note.attrs.id);
|
|
149
|
+
const tr = this.view.state.tr;
|
|
178
150
|
if (rids.length) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
contents: notes
|
|
182
|
-
.map(({ index }) => (index ? index : Math.max(...contents) + 1))
|
|
183
|
-
.join(),
|
|
184
|
-
}));
|
|
151
|
+
tr.setNodeAttribute(pos, 'rids', rids);
|
|
152
|
+
this.view.dispatch(tr);
|
|
185
153
|
}
|
|
186
154
|
else if (isPendingInsert(this.node)) {
|
|
187
|
-
|
|
155
|
+
tr.delete(pos, pos + this.node.nodeSize);
|
|
156
|
+
this.view.dispatch(tr);
|
|
188
157
|
}
|
|
189
158
|
}
|
|
190
159
|
this.destroy();
|
|
191
160
|
};
|
|
192
161
|
}
|
|
193
|
-
isSelected() {
|
|
194
|
-
const sel = this.view.state.selection;
|
|
195
|
-
const juxtaposed = sel.$head.pos === sel.$anchor.pos &&
|
|
196
|
-
sel.$head.pos === this.getPos() + this.node.nodeSize;
|
|
197
|
-
if ((sel instanceof NodeSelection && sel.node == this.node) || juxtaposed) {
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
activateModal(modalProps) {
|
|
203
|
-
const defaultModal = {
|
|
204
|
-
notes: [],
|
|
205
|
-
onInsert: this.onInsert,
|
|
206
|
-
onCancel: this.destroy,
|
|
207
|
-
inlineFootnote: this.node,
|
|
208
|
-
};
|
|
209
|
-
this.popperContainer = ReactSubView(Object.assign(Object.assign({}, this.props), { dispatch: this.view.dispatch }), FootnotesSelector, Object.assign(Object.assign({}, defaultModal), modalProps), this.node, this.getPos, this.view, 'footnote-editor');
|
|
210
|
-
this.props.popper.show(this.dom, this.popperContainer, 'auto', false);
|
|
211
|
-
}
|
|
212
162
|
}
|
|
213
163
|
export default createNodeView(InlineFootnoteView);
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { BaseNodeView } from './base_node_view';
|
|
17
|
-
import {
|
|
18
|
-
|
|
17
|
+
import { createEditableNodeView } from './creators';
|
|
18
|
+
class TableElementFooterView extends BaseNodeView {
|
|
19
19
|
constructor() {
|
|
20
20
|
super(...arguments);
|
|
21
21
|
this.initialise = () => {
|
|
@@ -25,9 +25,8 @@ export class TableElementFooterView extends BaseNodeView {
|
|
|
25
25
|
this.dom = document.createElement('div');
|
|
26
26
|
this.dom.classList.add('table-footer');
|
|
27
27
|
this.dom.setAttribute('id', this.node.attrs.id);
|
|
28
|
-
this.contentDOM =
|
|
29
|
-
this.dom.appendChild(this.contentDOM);
|
|
28
|
+
this.contentDOM = this.dom;
|
|
30
29
|
};
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
|
-
export default
|
|
32
|
+
export default createEditableNodeView(TableElementFooterView);
|