@manuscripts/body-editor 3.5.13 → 3.5.14

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.
@@ -63,6 +63,9 @@ const findParentElement = (selection, validIds) => (0, prosemirror_utils_1.findP
63
63
  })(selection);
64
64
  exports.findParentElement = findParentElement;
65
65
  const isChildOfNodeTypes = (doc, pos, parentNodeTypes) => {
66
+ if (pos > doc.content.size) {
67
+ return false;
68
+ }
66
69
  const resolvedPos = doc.resolve(pos);
67
70
  for (let depth = resolvedPos.depth; depth >= 0; depth--) {
68
71
  if (parentNodeTypes.includes(resolvedPos.node(depth).type)) {
@@ -18,6 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.buildPluginState = exports.createDecoration = void 0;
19
19
  const prosemirror_state_1 = require("prosemirror-state");
20
20
  const prosemirror_view_1 = require("prosemirror-view");
21
+ const affiliations_1 = require("../affiliations");
21
22
  const bibliography_1 = require("../bibliography");
22
23
  const footnotes_1 = require("../footnotes");
23
24
  const objects_1 = require("../objects");
@@ -43,9 +44,11 @@ const buildPluginState = (state, props, showDecorations) => {
43
44
  }
44
45
  const context = {
45
46
  pluginStates: {
47
+ affiliations: affiliations_1.affiliationsKey.getState(state)?.indexedAffiliationIds,
46
48
  bibliography: (0, bibliography_1.getBibliographyPluginState)(state)?.bibliographyItems,
47
49
  objects: objects_1.objectsKey.getState(state),
48
50
  footnotes: footnotes_1.footnotesKey.getState(state)?.footnotesElementIDs,
51
+ footnotesElements: footnotes_1.footnotesKey.getState(state)?.footnotesElements,
49
52
  },
50
53
  showDecorations,
51
54
  selectedPos,
@@ -18,12 +18,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.validators = void 0;
19
19
  const transform_1 = require("@manuscripts/transform");
20
20
  const url_1 = require("../../lib/url");
21
+ const utils_1 = require("../../lib/utils");
21
22
  const detect_inconsistency_utils_1 = require("./detect-inconsistency-utils");
22
23
  const getNodeDescription = (node) => {
23
24
  return transform_1.nodeNames.get(node.type) || node.type?.name || 'node';
24
25
  };
25
- const createWarning = (node, pos, category, severity) => {
26
- const nodeDescription = getNodeDescription(node);
26
+ const createWarning = (node, pos, category, severity, customNodeDescription) => {
27
+ const nodeDescription = customNodeDescription || getNodeDescription(node);
27
28
  const message = (() => {
28
29
  switch (node.type) {
29
30
  case transform_1.schema.nodes.figure_element:
@@ -33,10 +34,14 @@ const createWarning = (node, pos, category, severity) => {
33
34
  return 'Has no link or uploaded file';
34
35
  case transform_1.schema.nodes.link:
35
36
  return 'Url is empty';
37
+ case transform_1.schema.nodes.footnote:
38
+ return 'Is not used';
39
+ case transform_1.schema.nodes.affiliation:
40
+ return 'Is not corresponding to any Author';
36
41
  default:
37
42
  return category === 'empty-content'
38
- ? `Is empty`
39
- : `Has no linked reference`;
43
+ ? 'Is empty'
44
+ : 'Has no linked reference';
40
45
  }
41
46
  })();
42
47
  return {
@@ -128,6 +133,33 @@ const validateLink = (node, pos) => {
128
133
  }
129
134
  return inconsistencies;
130
135
  };
136
+ const validateFootnote = (node, pos, context) => {
137
+ const inconsistencies = [];
138
+ const id = context.pluginStates.footnotes?.get(node.attrs.id);
139
+ const footnoteState = id
140
+ ? context.pluginStates.footnotesElements?.get(id)
141
+ : undefined;
142
+ const unused = footnoteState?.unusedFootnoteIDs?.has(node.attrs.id);
143
+ if (unused) {
144
+ const isTableFootnote = (0, utils_1.isChildOfNodeTypes)(context.props.doc, pos, [
145
+ transform_1.schema.nodes.table_element,
146
+ ]);
147
+ const inconsistency = createWarning(node, pos, 'not-used', 'warning', isTableFootnote ? 'table_footnote' : undefined);
148
+ inconsistencies.push(inconsistency);
149
+ }
150
+ return inconsistencies;
151
+ };
152
+ const validateAffiliation = (node, pos, context) => {
153
+ const inconsistencies = [];
154
+ const unused = !context.pluginStates.affiliations?.get(node.attrs.id);
155
+ if (unused) {
156
+ const $pos = context.props.doc.resolve(pos);
157
+ const affiliationsNodePos = $pos.before($pos.depth);
158
+ const inconsistency = createWarning(node, affiliationsNodePos, 'not-used', 'warning');
159
+ inconsistencies.push(inconsistency);
160
+ }
161
+ return inconsistencies;
162
+ };
131
163
  exports.validators = {
132
164
  [transform_1.schema.nodes.title.name]: validateTitle,
133
165
  [transform_1.schema.nodes.cross_reference.name]: validateCrossReference,
@@ -136,4 +168,6 @@ exports.validators = {
136
168
  [transform_1.schema.nodes.figure.name]: validateFigure,
137
169
  [transform_1.schema.nodes.embed.name]: validateMedia,
138
170
  [transform_1.schema.nodes.link.name]: validateLink,
171
+ [transform_1.schema.nodes.footnote.name]: validateFootnote,
172
+ [transform_1.schema.nodes.affiliation.name]: validateAffiliation,
139
173
  };
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MATHJAX_VERSION = exports.VERSION = void 0;
4
- exports.VERSION = '3.5.13';
4
+ exports.VERSION = '3.5.14';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -23,6 +23,7 @@ const style_guide_1 = require("@manuscripts/style-guide");
23
23
  const transform_1 = require("@manuscripts/transform");
24
24
  const prosemirror_state_1 = require("prosemirror-state");
25
25
  const AffiliationsModal_1 = require("../components/affiliations/AffiliationsModal");
26
+ const icons_1 = require("../icons");
26
27
  const authors_1 = require("../lib/authors");
27
28
  const comments_1 = require("../lib/comments");
28
29
  const track_changes_utils_1 = require("../lib/track-changes-utils");
@@ -136,11 +137,7 @@ class AffiliationsView extends block_view_1.default {
136
137
  return contextMenu ? [contextMenu] : [];
137
138
  };
138
139
  this.selectNode = () => {
139
- const selectedMarker = document.querySelector('.comment-marker.selected-comment');
140
140
  this.dom.classList.add('ProseMirror-selectednode');
141
- if (!(0, track_changes_utils_1.isDeleted)(this.node) && !selectedMarker) {
142
- this.handleEdit('', true);
143
- }
144
141
  };
145
142
  this.handleUpdateAuthors = (authors) => {
146
143
  authors.forEach((author) => {
@@ -189,12 +186,15 @@ class AffiliationsView extends block_view_1.default {
189
186
  element.classList.add('affiliation');
190
187
  element.id = attrs.id;
191
188
  (0, track_changes_utils_1.addTrackChangesAttributes)(attrs, element);
189
+ const marker = document.createElement('span');
192
190
  if (index) {
193
- const label = document.createElement('span');
194
- label.classList.add('affiliation-label');
195
- label.innerHTML = String(index);
196
- element.appendChild(label);
191
+ marker.classList.add('affiliation-label');
192
+ marker.innerText = String(index);
193
+ }
194
+ else {
195
+ marker.innerHTML = icons_1.alertIcon;
197
196
  }
197
+ element.appendChild(marker);
198
198
  const name = document.createElement('span');
199
199
  name.classList.add('affiliation-name');
200
200
  name.innerHTML = (0, authors_1.affiliationName)(attrs);
@@ -55,6 +55,9 @@ export const findParentElement = (selection, validIds) => findParentNode((node)
55
55
  return isElementNodeType(node.type) && node.attrs.id;
56
56
  })(selection);
57
57
  export const isChildOfNodeTypes = (doc, pos, parentNodeTypes) => {
58
+ if (pos > doc.content.size) {
59
+ return false;
60
+ }
58
61
  const resolvedPos = doc.resolve(pos);
59
62
  for (let depth = resolvedPos.depth; depth >= 0; depth--) {
60
63
  if (parentNodeTypes.includes(resolvedPos.node(depth).type)) {
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import { NodeSelection } from 'prosemirror-state';
17
17
  import { Decoration, DecorationSet } from 'prosemirror-view';
18
+ import { affiliationsKey } from '../affiliations';
18
19
  import { getBibliographyPluginState } from '../bibliography';
19
20
  import { footnotesKey } from '../footnotes';
20
21
  import { objectsKey } from '../objects';
@@ -39,9 +40,11 @@ export const buildPluginState = (state, props, showDecorations) => {
39
40
  }
40
41
  const context = {
41
42
  pluginStates: {
43
+ affiliations: affiliationsKey.getState(state)?.indexedAffiliationIds,
42
44
  bibliography: getBibliographyPluginState(state)?.bibliographyItems,
43
45
  objects: objectsKey.getState(state),
44
46
  footnotes: footnotesKey.getState(state)?.footnotesElementIDs,
47
+ footnotesElements: footnotesKey.getState(state)?.footnotesElements,
45
48
  },
46
49
  showDecorations,
47
50
  selectedPos,
@@ -15,12 +15,13 @@
15
15
  */
16
16
  import { nodeNames, schema, } from '@manuscripts/transform';
17
17
  import { allowedHref } from '../../lib/url';
18
+ import { isChildOfNodeTypes } from '../../lib/utils';
18
19
  import { createDecoration } from './detect-inconsistency-utils';
19
20
  const getNodeDescription = (node) => {
20
21
  return nodeNames.get(node.type) || node.type?.name || 'node';
21
22
  };
22
- const createWarning = (node, pos, category, severity) => {
23
- const nodeDescription = getNodeDescription(node);
23
+ const createWarning = (node, pos, category, severity, customNodeDescription) => {
24
+ const nodeDescription = customNodeDescription || getNodeDescription(node);
24
25
  const message = (() => {
25
26
  switch (node.type) {
26
27
  case schema.nodes.figure_element:
@@ -30,10 +31,14 @@ const createWarning = (node, pos, category, severity) => {
30
31
  return 'Has no link or uploaded file';
31
32
  case schema.nodes.link:
32
33
  return 'Url is empty';
34
+ case schema.nodes.footnote:
35
+ return 'Is not used';
36
+ case schema.nodes.affiliation:
37
+ return 'Is not corresponding to any Author';
33
38
  default:
34
39
  return category === 'empty-content'
35
- ? `Is empty`
36
- : `Has no linked reference`;
40
+ ? 'Is empty'
41
+ : 'Has no linked reference';
37
42
  }
38
43
  })();
39
44
  return {
@@ -125,6 +130,33 @@ const validateLink = (node, pos) => {
125
130
  }
126
131
  return inconsistencies;
127
132
  };
133
+ const validateFootnote = (node, pos, context) => {
134
+ const inconsistencies = [];
135
+ const id = context.pluginStates.footnotes?.get(node.attrs.id);
136
+ const footnoteState = id
137
+ ? context.pluginStates.footnotesElements?.get(id)
138
+ : undefined;
139
+ const unused = footnoteState?.unusedFootnoteIDs?.has(node.attrs.id);
140
+ if (unused) {
141
+ const isTableFootnote = isChildOfNodeTypes(context.props.doc, pos, [
142
+ schema.nodes.table_element,
143
+ ]);
144
+ const inconsistency = createWarning(node, pos, 'not-used', 'warning', isTableFootnote ? 'table_footnote' : undefined);
145
+ inconsistencies.push(inconsistency);
146
+ }
147
+ return inconsistencies;
148
+ };
149
+ const validateAffiliation = (node, pos, context) => {
150
+ const inconsistencies = [];
151
+ const unused = !context.pluginStates.affiliations?.get(node.attrs.id);
152
+ if (unused) {
153
+ const $pos = context.props.doc.resolve(pos);
154
+ const affiliationsNodePos = $pos.before($pos.depth);
155
+ const inconsistency = createWarning(node, affiliationsNodePos, 'not-used', 'warning');
156
+ inconsistencies.push(inconsistency);
157
+ }
158
+ return inconsistencies;
159
+ };
128
160
  export const validators = {
129
161
  [schema.nodes.title.name]: validateTitle,
130
162
  [schema.nodes.cross_reference.name]: validateCrossReference,
@@ -133,4 +165,6 @@ export const validators = {
133
165
  [schema.nodes.figure.name]: validateFigure,
134
166
  [schema.nodes.embed.name]: validateMedia,
135
167
  [schema.nodes.link.name]: validateLink,
168
+ [schema.nodes.footnote.name]: validateFootnote,
169
+ [schema.nodes.affiliation.name]: validateAffiliation,
136
170
  };
@@ -1,2 +1,2 @@
1
- export const VERSION = '3.5.13';
1
+ export const VERSION = '3.5.14';
2
2
  export const MATHJAX_VERSION = '3.2.2';
@@ -17,6 +17,7 @@ import { ContextMenu } from '@manuscripts/style-guide';
17
17
  import { schema } from '@manuscripts/transform';
18
18
  import { NodeSelection } from 'prosemirror-state';
19
19
  import { AffiliationsModal, } from '../components/affiliations/AffiliationsModal';
20
+ import { alertIcon } from '../icons';
20
21
  import { affiliationName, } from '../lib/authors';
21
22
  import { handleComment } from '../lib/comments';
22
23
  import { addTrackChangesAttributes, isDeleted, } from '../lib/track-changes-utils';
@@ -130,11 +131,7 @@ export class AffiliationsView extends BlockView {
130
131
  return contextMenu ? [contextMenu] : [];
131
132
  };
132
133
  this.selectNode = () => {
133
- const selectedMarker = document.querySelector('.comment-marker.selected-comment');
134
134
  this.dom.classList.add('ProseMirror-selectednode');
135
- if (!isDeleted(this.node) && !selectedMarker) {
136
- this.handleEdit('', true);
137
- }
138
135
  };
139
136
  this.handleUpdateAuthors = (authors) => {
140
137
  authors.forEach((author) => {
@@ -183,12 +180,15 @@ export class AffiliationsView extends BlockView {
183
180
  element.classList.add('affiliation');
184
181
  element.id = attrs.id;
185
182
  addTrackChangesAttributes(attrs, element);
183
+ const marker = document.createElement('span');
186
184
  if (index) {
187
- const label = document.createElement('span');
188
- label.classList.add('affiliation-label');
189
- label.innerHTML = String(index);
190
- element.appendChild(label);
185
+ marker.classList.add('affiliation-label');
186
+ marker.innerText = String(index);
187
+ }
188
+ else {
189
+ marker.innerHTML = alertIcon;
191
190
  }
191
+ element.appendChild(marker);
192
192
  const name = document.createElement('span');
193
193
  name.classList.add('affiliation-name');
194
194
  name.innerHTML = affiliationName(attrs);
@@ -18,7 +18,7 @@ import { Decoration, DecorationSet } from 'prosemirror-view';
18
18
  import { EditorProps } from '../../configs/ManuscriptsEditor';
19
19
  export type Inconsistency = {
20
20
  type: 'warning';
21
- category: 'missing-reference' | 'empty-content';
21
+ category: 'missing-reference' | 'not-used' | 'empty-content';
22
22
  severity: 'error' | 'warning';
23
23
  message: string;
24
24
  nodeDescription: string;
@@ -16,12 +16,15 @@
16
16
  import { BibliographyItemAttrs, ManuscriptNode, Target } from '@manuscripts/transform';
17
17
  import { Decoration } from 'prosemirror-view';
18
18
  import { EditorProps } from '../../configs/ManuscriptsEditor';
19
+ import { FootnotesElementState } from '../footnotes';
19
20
  import { Inconsistency } from './detect-inconsistency-utils';
20
21
  export type ValidatorContext = {
21
22
  pluginStates: {
23
+ affiliations: Map<string, number> | undefined;
22
24
  bibliography: Map<string, BibliographyItemAttrs> | undefined;
23
25
  objects: Map<string, Target> | undefined;
24
26
  footnotes: Map<string, string> | undefined;
27
+ footnotesElements: Map<string, FootnotesElementState> | undefined;
25
28
  };
26
29
  showDecorations: boolean;
27
30
  selectedPos: number | null;
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "3.5.13";
1
+ export declare const VERSION = "3.5.14";
2
2
  export declare const MATHJAX_VERSION = "3.2.2";
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": "3.5.13",
4
+ "version": "3.5.14",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -39,7 +39,7 @@
39
39
  "@cospired/i18n-iso-languages": "^4.2.0",
40
40
  "@iarna/word-count": "1.1.2",
41
41
  "@manuscripts/json-schema": "2.2.12",
42
- "@manuscripts/style-guide": "3.3.0",
42
+ "@manuscripts/style-guide": "3.3.1",
43
43
  "@manuscripts/track-changes-plugin": "2.0.13",
44
44
  "@manuscripts/transform": "4.2.17",
45
45
  "@popperjs/core": "2.11.8",
@@ -1262,11 +1262,13 @@ figure.block:has(.equation.selected-suggestion) {
1262
1262
  line-height: 1.2;
1263
1263
  cursor: default;
1264
1264
  user-select: none;
1265
+ display: flex;
1266
+ justify-content: flex-start;
1267
+ gap: 4px;
1265
1268
  }
1266
1269
 
1267
1270
  .affiliation .affiliation-label {
1268
1271
  font-weight: bold;
1269
- margin-right: 4px;
1270
1272
  }
1271
1273
 
1272
1274
  .ProseMirror .doi-container {