@manuscripts/body-editor 2.0.43 → 2.0.44-LEAN-3883.3

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.
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.mergeCellsWithSpace = exports.addColumns = exports.addRows = exports.insertTableFootnote = exports.addInlineComment = exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = exports.ignoreAtomBlockNodeForward = exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertKeywords = exports.insertContributors = exports.insertAbstract = exports.insertBackMatterSection = exports.insertSection = exports.insertGraphicalAbstract = exports.insertInlineFootnote = exports.insertFootnote = exports.createFootnote = exports.insertInlineEquation = exports.insertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.findPosBeforeFirstSubsection = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertSupplement = exports.insertTable = exports.insertFigure = exports.insertGeneralFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = void 0;
18
+ exports.autoComplete = exports.mergeCellsWithSpace = exports.addColumns = exports.addRows = exports.insertTableFootnote = exports.addInlineComment = exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = exports.ignoreAtomBlockNodeForward = exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertKeywords = exports.insertContributors = exports.insertAbstract = exports.insertBackMatterSection = exports.insertSection = exports.insertGraphicalAbstract = exports.insertInlineFootnote = exports.insertFootnote = exports.createFootnote = exports.insertInlineEquation = exports.insertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.findPosBeforeFirstSubsection = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertSupplement = exports.insertTable = exports.insertFigure = exports.insertGeneralFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = void 0;
19
19
  const json_schema_1 = require("@manuscripts/json-schema");
20
20
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
21
21
  const transform_1 = require("@manuscripts/transform");
@@ -29,11 +29,13 @@ const comments_1 = require("./lib/comments");
29
29
  const doc_1 = require("./lib/doc");
30
30
  const footnotes_1 = require("./lib/footnotes");
31
31
  const helpers_1 = require("./lib/helpers");
32
+ const section_titles_1 = require("./lib/section-titles");
32
33
  const track_changes_utils_1 = require("./lib/track-changes-utils");
33
34
  const utils_1 = require("./lib/utils");
34
35
  const comments_2 = require("./plugins/comments");
35
36
  const editor_props_1 = require("./plugins/editor-props");
36
37
  const footnotes_2 = require("./plugins/footnotes");
38
+ const autocompletion_1 = require("./plugins/section_title/autocompletion");
37
39
  const markActive = (type) => (state) => {
38
40
  const { from, $from, to, empty } = state.selection;
39
41
  return empty
@@ -196,7 +198,7 @@ const insertTable = (config, state, dispatch) => {
196
198
  };
197
199
  exports.insertTable = insertTable;
198
200
  const insertSupplement = (file, state, dispatch) => {
199
- const supplement = transform_1.schema.nodes.supplement.create({
201
+ const supplement = transform_1.schema.nodes.supplement.createAndFill({
200
202
  id: (0, transform_1.generateNodeID)(transform_1.schema.nodes.supplement),
201
203
  href: file.id,
202
204
  });
@@ -481,16 +483,6 @@ const insertSection = (subsection = false) => (state, dispatch, view) => {
481
483
  return true;
482
484
  };
483
485
  exports.insertSection = insertSection;
484
- const sectionTitles = new Map([
485
- ['MPSectionCategory:acknowledgement', 'Acknowledgments'],
486
- ['MPSectionCategory:availability', 'Availability'],
487
- ['MPSectionCategory:competing-interests', 'COI Statement'],
488
- ['MPSectionCategory:con', 'Contributed-by information'],
489
- ['MPSectionCategory:ethics-statement', 'Ethics Statement'],
490
- ['MPSectionCategory:financial-disclosure', 'Financial Disclosure'],
491
- ['MPSectionCategory:supplementary-material', 'Supplementary Material'],
492
- ['MPSectionCategory:supported-by', 'Supported By'],
493
- ]);
494
486
  const insertBackMatterSection = (category) => (state, dispatch, view) => {
495
487
  const backmatter = (0, doc_1.findBackmatter)(state.doc);
496
488
  const sections = (0, prosemirror_utils_1.findChildrenByType)(backmatter.node, transform_1.schema.nodes.section);
@@ -508,7 +500,7 @@ const insertBackMatterSection = (category) => (state, dispatch, view) => {
508
500
  const node = transform_1.schema.nodes.section.createAndFill({
509
501
  category,
510
502
  }, [
511
- transform_1.schema.nodes.section_title.create({}, transform_1.schema.text(sectionTitles.get(category) || '')),
503
+ transform_1.schema.nodes.section_title.create({}, transform_1.schema.text(section_titles_1.sectionTitles.get(category) || '')),
512
504
  ]);
513
505
  const tr = state.tr.insert(pos, node);
514
506
  if (dispatch) {
@@ -1139,3 +1131,13 @@ function mergeCellsWithSpace(state, dispatch) {
1139
1131
  return true;
1140
1132
  }
1141
1133
  exports.mergeCellsWithSpace = mergeCellsWithSpace;
1134
+ const autoComplete = (state, dispatch) => {
1135
+ const autocompleteText = (0, autocompletion_1.checkForCompletion)(state);
1136
+ if (autocompleteText) {
1137
+ const tr = state.tr.insertText(autocompleteText, state.selection.from);
1138
+ dispatch && dispatch(tr);
1139
+ return true;
1140
+ }
1141
+ return false;
1142
+ };
1143
+ exports.autoComplete = autoComplete;
@@ -39,6 +39,7 @@ const customKeymap = {
39
39
  'Mod-Alt-=': (0, prosemirror_commands_1.toggleMark)(transform_1.schema.marks.superscript),
40
40
  'Mod-Alt--': (0, prosemirror_commands_1.toggleMark)(transform_1.schema.marks.subscript),
41
41
  'Ctrl->': (0, prosemirror_commands_1.wrapIn)(transform_1.schema.nodes.blockquote),
42
+ Enter: (0, prosemirror_commands_1.chainCommands)(commands_1.autoComplete, prosemirror_commands_1.newlineInCode, prosemirror_commands_1.createParagraphNear, prosemirror_commands_1.liftEmptyBlock, prosemirror_commands_1.splitBlock),
42
43
  'Shift-Mod-Enter': (0, commands_1.insertSection)(true),
43
44
  'Mod-Enter': (0, prosemirror_commands_1.chainCommands)(prosemirror_commands_1.exitCode, (0, commands_1.insertSection)()),
44
45
  'Shift-Enter': (0, prosemirror_commands_1.chainCommands)(prosemirror_commands_1.exitCode, commands_1.insertBreak),
@@ -11,9 +11,10 @@ const insertSupplementsNode = (tr) => {
11
11
  }
12
12
  const abstracts = (0, exports.findAbstractsNode)(doc);
13
13
  const pos = abstracts.pos - 1;
14
- tr.insert(pos, transform_1.schema.nodes.supplements.create());
14
+ const supplementsNode = transform_1.schema.nodes.supplements.createAndFill();
15
+ tr.insert(pos, supplementsNode);
15
16
  return {
16
- node: supplements,
17
+ node: supplementsNode,
17
18
  pos,
18
19
  };
19
20
  };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2019 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.sectionTitles = void 0;
19
+ exports.sectionTitles = new Map([
20
+ ['MPSectionCategory:abstract', 'Abstract'],
21
+ ['MPSectionCategory:abstract-graphical', 'Graphical Abstract'],
22
+ ['MPSectionCategory:introduction', 'Introduction'],
23
+ ['MPSectionCategory:materials-method', 'Materials & Methods'],
24
+ ['MPSectionCategory:results', 'Results'],
25
+ ['MPSectionCategory:discussion', 'Discussion'],
26
+ ['MPSectionCategory:conclusions', 'Conclusions'],
27
+ ['MPSectionCategory:acknowledgement', 'Acknowledgments'],
28
+ ['MPSectionCategory:availability', 'Availability'],
29
+ ['MPSectionCategory:competing-interests', 'COI Statement'],
30
+ ['MPSectionCategory:con', 'Contributed-by information'],
31
+ ['MPSectionCategory:ethics-statement', 'Ethics Statement'],
32
+ ['MPSectionCategory:financial-disclosure', 'Financial Disclosure'],
33
+ ['MPSectionCategory:supplementary-material', 'Supplementary Material'],
34
+ ['MPSectionCategory:supported-by', 'Supported By'],
35
+ ]);
@@ -15,8 +15,9 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.sanitizeAttrsChange = exports.isHidden = exports.getAttrsTrackingButton = exports.getActualAttrs = exports.isTracked = exports.getChangeClasses = exports.isPendingSetAttrs = exports.isPending = exports.isPendingInsert = exports.isDeleted = exports.isRejectedInsert = void 0;
18
+ exports.sanitizeAttrsChange = exports.getActualTextContent = exports.isRejectedText = exports.isDeletedText = exports.isHidden = exports.getAttrsTrackingButton = exports.getActualAttrs = exports.isTracked = exports.getChangeClasses = exports.isPendingSetAttrs = exports.isPending = exports.isPendingInsert = exports.isDeleted = exports.isRejectedInsert = void 0;
19
19
  const style_guide_1 = require("@manuscripts/style-guide");
20
+ const transform_1 = require("@manuscripts/transform");
20
21
  const react_1 = require("react");
21
22
  const server_1 = require("react-dom/server");
22
23
  function isRejectedInsert(node) {
@@ -105,6 +106,46 @@ function isHidden(node) {
105
106
  return isDeleted(node) || isRejectedInsert(node);
106
107
  }
107
108
  exports.isHidden = isHidden;
109
+ function isDeletedText(node) {
110
+ var _a, _b, _c, _d;
111
+ if (node.type === transform_1.schema.nodes.text && node.marks.length) {
112
+ const deleteMark = node.marks.find((mark) => mark.type === transform_1.schema.marks.tracked_delete);
113
+ if (deleteMark &&
114
+ ((_b = (_a = deleteMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked) === null || _b === void 0 ? void 0 : _b.status) &&
115
+ ['pending', 'approved'].includes((_d = (_c = deleteMark.attrs) === null || _c === void 0 ? void 0 : _c.dataTracked) === null || _d === void 0 ? void 0 : _d.status)) {
116
+ return true;
117
+ }
118
+ }
119
+ return false;
120
+ }
121
+ exports.isDeletedText = isDeletedText;
122
+ function isRejectedText(node) {
123
+ var _a, _b;
124
+ if (node.type === transform_1.schema.nodes.text) {
125
+ const insertMark = node.marks.find((mark) => mark.type === transform_1.schema.marks.tracked_insert);
126
+ if (insertMark && ((_b = (_a = insertMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked) === null || _b === void 0 ? void 0 : _b.status) === 'rejected') {
127
+ return true;
128
+ }
129
+ }
130
+ return false;
131
+ }
132
+ exports.isRejectedText = isRejectedText;
133
+ function getActualTextContent(fragment) {
134
+ let finalContent = '';
135
+ function getContent(fragment) {
136
+ fragment.forEach((node) => {
137
+ if (node.type !== transform_1.schema.nodes.text) {
138
+ finalContent += getContent(node.content);
139
+ }
140
+ if (!isDeletedText(node) && !isRejectedText(node)) {
141
+ finalContent += node.textContent;
142
+ }
143
+ });
144
+ }
145
+ getContent(fragment);
146
+ return finalContent;
147
+ }
148
+ exports.getActualTextContent = getActualTextContent;
108
149
  function sanitizeAttrsChange(newAttr, currentAttrs) {
109
150
  return Object.keys(newAttr).reduce((acc, attr) => {
110
151
  const key = attr;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkForCompletion = exports.hasAutoCompletionSlack = void 0;
4
+ const transform_1 = require("@manuscripts/transform");
5
+ const prosemirror_utils_1 = require("prosemirror-utils");
6
+ const section_titles_1 = require("../../lib/section-titles");
7
+ const track_changes_utils_1 = require("../../lib/track-changes-utils");
8
+ function cursorAtTheEndOfText(state, nodeSize, nodePos) {
9
+ const { from, to } = state.selection;
10
+ return from === to && to === nodePos + nodeSize - 1;
11
+ }
12
+ const isUpperCase = (test) => test === test.toUpperCase() && test.length > 1;
13
+ function hasAutoCompletionSlack(parentSection, titleSection) {
14
+ const category = (0, track_changes_utils_1.getActualAttrs)(parentSection).category;
15
+ const title = section_titles_1.sectionTitles.get(category);
16
+ if (category &&
17
+ title &&
18
+ titleSection.textContent) {
19
+ const actualTextContent = (0, track_changes_utils_1.getActualTextContent)(titleSection.content);
20
+ console.log('actualTextContent');
21
+ console.log(actualTextContent);
22
+ if (title.toLowerCase().startsWith(actualTextContent.toLowerCase())) {
23
+ const suggestionText = title.slice(actualTextContent.length);
24
+ return isUpperCase(actualTextContent)
25
+ ? suggestionText.toUpperCase()
26
+ : suggestionText;
27
+ }
28
+ }
29
+ return '';
30
+ }
31
+ exports.hasAutoCompletionSlack = hasAutoCompletionSlack;
32
+ function checkForCompletion(state) {
33
+ const section = (0, prosemirror_utils_1.findParentNodeOfTypeClosestToPos)(state.selection.$from, transform_1.schema.nodes.section);
34
+ const title = (0, prosemirror_utils_1.findParentNodeOfTypeClosestToPos)(state.selection.$from, transform_1.schema.nodes.section_title);
35
+ if (section &&
36
+ title &&
37
+ cursorAtTheEndOfText(state, title.node.nodeSize, title.pos)) {
38
+ const text = hasAutoCompletionSlack(section.node, title.node);
39
+ console.log('returnable text');
40
+ console.log(text);
41
+ return text;
42
+ }
43
+ return '';
44
+ }
45
+ exports.checkForCompletion = checkForCompletion;
@@ -4,7 +4,9 @@ exports.sectionTitleKey = void 0;
4
4
  const transform_1 = require("@manuscripts/transform");
5
5
  const prosemirror_state_1 = require("prosemirror-state");
6
6
  const prosemirror_utils_1 = require("prosemirror-utils");
7
- const track_changes_utils_1 = require("../lib/track-changes-utils");
7
+ const prosemirror_view_1 = require("prosemirror-view");
8
+ const track_changes_utils_1 = require("../../lib/track-changes-utils");
9
+ const autocompletion_1 = require("./autocompletion");
8
10
  exports.sectionTitleKey = new prosemirror_state_1.PluginKey('sectionNumbering');
9
11
  const calculateSectionLevels = (node, startPos, sectionNumberMap, numbering = [0]) => {
10
12
  node.forEach((childNode, offset) => {
@@ -35,6 +37,21 @@ const getPluginState = (doc) => {
35
37
  exports.default = () => {
36
38
  return new prosemirror_state_1.Plugin({
37
39
  key: exports.sectionTitleKey,
40
+ props: {
41
+ decorations(state) {
42
+ const text = (0, autocompletion_1.checkForCompletion)(state);
43
+ if (text) {
44
+ const decoration = prosemirror_view_1.Decoration.widget(state.selection.from, () => {
45
+ const node = document.createElement('span');
46
+ node.classList.add('completion-bearer');
47
+ node.dataset.suggest = text;
48
+ return node;
49
+ });
50
+ return prosemirror_view_1.DecorationSet.create(state.doc, [decoration]);
51
+ }
52
+ return prosemirror_view_1.DecorationSet.empty;
53
+ },
54
+ },
38
55
  state: {
39
56
  init: (_, state) => {
40
57
  return getPluginState(state.doc);
@@ -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 = '2.0.43';
4
+ exports.VERSION = '2.0.44-LEAN-3883.3';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -30,6 +30,7 @@ class SectionTitleView extends block_view_1.default {
30
30
  super(...arguments);
31
31
  this.elementType = 'h1';
32
32
  this.onUpdateContent = () => {
33
+ console.log(this.node);
33
34
  const $pos = this.view.state.doc.resolve(this.getPos());
34
35
  const sectionTitleState = section_title_1.sectionTitleKey.getState(this.view.state);
35
36
  const parentSection = (0, prosemirror_utils_1.findParentNodeOfTypeClosestToPos)($pos, transform_1.schema.nodes.section);
@@ -26,11 +26,13 @@ import { getCommentKey, getCommentRange } from './lib/comments';
26
26
  import { findBackmatter, findBibliographySection, findBody, insertSupplementsNode, } from './lib/doc';
27
27
  import { getNewFootnotePos } from './lib/footnotes';
28
28
  import { findWordBoundaries, isNodeOfType, nearestAncestor, } from './lib/helpers';
29
+ import { sectionTitles } from './lib/section-titles';
29
30
  import { isDeleted, isRejectedInsert } from './lib/track-changes-utils';
30
31
  import { findParentNodeWithId, getChildOfType, getMatchingChild, } from './lib/utils';
31
32
  import { setCommentSelection } from './plugins/comments';
32
33
  import { getEditorProps } from './plugins/editor-props';
33
34
  import { footnotesKey } from './plugins/footnotes';
35
+ import { checkForCompletion } from './plugins/section_title/autocompletion';
34
36
  export const markActive = (type) => (state) => {
35
37
  const { from, $from, to, empty } = state.selection;
36
38
  return empty
@@ -184,7 +186,7 @@ export const insertTable = (config, state, dispatch) => {
184
186
  return true;
185
187
  };
186
188
  export const insertSupplement = (file, state, dispatch) => {
187
- const supplement = schema.nodes.supplement.create({
189
+ const supplement = schema.nodes.supplement.createAndFill({
188
190
  id: generateNodeID(schema.nodes.supplement),
189
191
  href: file.id,
190
192
  });
@@ -454,16 +456,6 @@ export const insertSection = (subsection = false) => (state, dispatch, view) =>
454
456
  }
455
457
  return true;
456
458
  };
457
- const sectionTitles = new Map([
458
- ['MPSectionCategory:acknowledgement', 'Acknowledgments'],
459
- ['MPSectionCategory:availability', 'Availability'],
460
- ['MPSectionCategory:competing-interests', 'COI Statement'],
461
- ['MPSectionCategory:con', 'Contributed-by information'],
462
- ['MPSectionCategory:ethics-statement', 'Ethics Statement'],
463
- ['MPSectionCategory:financial-disclosure', 'Financial Disclosure'],
464
- ['MPSectionCategory:supplementary-material', 'Supplementary Material'],
465
- ['MPSectionCategory:supported-by', 'Supported By'],
466
- ]);
467
459
  export const insertBackMatterSection = (category) => (state, dispatch, view) => {
468
460
  const backmatter = findBackmatter(state.doc);
469
461
  const sections = findChildrenByType(backmatter.node, schema.nodes.section);
@@ -1091,3 +1083,12 @@ export function mergeCellsWithSpace(state, dispatch) {
1091
1083
  }
1092
1084
  return true;
1093
1085
  }
1086
+ export const autoComplete = (state, dispatch) => {
1087
+ const autocompleteText = checkForCompletion(state);
1088
+ if (autocompleteText) {
1089
+ const tr = state.tr.insertText(autocompleteText, state.selection.from);
1090
+ dispatch && dispatch(tr);
1091
+ return true;
1092
+ }
1093
+ return false;
1094
+ };
@@ -14,11 +14,11 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { schema } from '@manuscripts/transform';
17
- import { chainCommands, exitCode, joinDown, joinUp, lift, toggleMark, wrapIn, } from 'prosemirror-commands';
17
+ import { chainCommands, createParagraphNear, exitCode, joinDown, joinUp, lift, liftEmptyBlock, newlineInCode, splitBlock, toggleMark, wrapIn, } from 'prosemirror-commands';
18
18
  import { redo, undo } from 'prosemirror-history';
19
19
  import { undoInputRule } from 'prosemirror-inputrules';
20
20
  import { goToNextCell } from 'prosemirror-tables';
21
- import { ignoreAtomBlockNodeBackward, ignoreAtomBlockNodeForward, ignoreMetaNodeBackspaceCommand, insertBlock, insertBreak, insertCrossReference, insertInlineCitation, insertInlineEquation, insertSection, selectAllIsolating, } from '../commands';
21
+ import { autoComplete, ignoreAtomBlockNodeBackward, ignoreAtomBlockNodeForward, ignoreMetaNodeBackspaceCommand, insertBlock, insertBreak, insertCrossReference, insertInlineCitation, insertInlineEquation, insertSection, selectAllIsolating, } from '../commands';
22
22
  const customKeymap = {
23
23
  Backspace: chainCommands(undoInputRule, ignoreAtomBlockNodeBackward, ignoreMetaNodeBackspaceCommand),
24
24
  Delete: ignoreAtomBlockNodeForward,
@@ -37,6 +37,7 @@ const customKeymap = {
37
37
  'Mod-Alt-=': toggleMark(schema.marks.superscript),
38
38
  'Mod-Alt--': toggleMark(schema.marks.subscript),
39
39
  'Ctrl->': wrapIn(schema.nodes.blockquote),
40
+ Enter: chainCommands(autoComplete, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock),
40
41
  'Shift-Mod-Enter': insertSection(true),
41
42
  'Mod-Enter': chainCommands(exitCode, insertSection()),
42
43
  'Shift-Enter': chainCommands(exitCode, insertBreak),
@@ -8,9 +8,10 @@ export const insertSupplementsNode = (tr) => {
8
8
  }
9
9
  const abstracts = findAbstractsNode(doc);
10
10
  const pos = abstracts.pos - 1;
11
- tr.insert(pos, schema.nodes.supplements.create());
11
+ const supplementsNode = schema.nodes.supplements.createAndFill();
12
+ tr.insert(pos, supplementsNode);
12
13
  return {
13
- node: supplements,
14
+ node: supplementsNode,
14
15
  pos,
15
16
  };
16
17
  };
@@ -0,0 +1,32 @@
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
+ export const sectionTitles = new Map([
17
+ ['MPSectionCategory:abstract', 'Abstract'],
18
+ ['MPSectionCategory:abstract-graphical', 'Graphical Abstract'],
19
+ ['MPSectionCategory:introduction', 'Introduction'],
20
+ ['MPSectionCategory:materials-method', 'Materials & Methods'],
21
+ ['MPSectionCategory:results', 'Results'],
22
+ ['MPSectionCategory:discussion', 'Discussion'],
23
+ ['MPSectionCategory:conclusions', 'Conclusions'],
24
+ ['MPSectionCategory:acknowledgement', 'Acknowledgments'],
25
+ ['MPSectionCategory:availability', 'Availability'],
26
+ ['MPSectionCategory:competing-interests', 'COI Statement'],
27
+ ['MPSectionCategory:con', 'Contributed-by information'],
28
+ ['MPSectionCategory:ethics-statement', 'Ethics Statement'],
29
+ ['MPSectionCategory:financial-disclosure', 'Financial Disclosure'],
30
+ ['MPSectionCategory:supplementary-material', 'Supplementary Material'],
31
+ ['MPSectionCategory:supported-by', 'Supported By'],
32
+ ]);
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { EditAttrsTrackingIcon } from '@manuscripts/style-guide';
17
+ import { schema } from '@manuscripts/transform';
17
18
  import { createElement } from 'react';
18
19
  import { renderToStaticMarkup } from 'react-dom/server';
19
20
  export function isRejectedInsert(node) {
@@ -92,6 +93,43 @@ export const getAttrsTrackingButton = (changeID) => {
92
93
  export function isHidden(node) {
93
94
  return isDeleted(node) || isRejectedInsert(node);
94
95
  }
96
+ export function isDeletedText(node) {
97
+ var _a, _b, _c, _d;
98
+ if (node.type === schema.nodes.text && node.marks.length) {
99
+ const deleteMark = node.marks.find((mark) => mark.type === schema.marks.tracked_delete);
100
+ if (deleteMark &&
101
+ ((_b = (_a = deleteMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked) === null || _b === void 0 ? void 0 : _b.status) &&
102
+ ['pending', 'approved'].includes((_d = (_c = deleteMark.attrs) === null || _c === void 0 ? void 0 : _c.dataTracked) === null || _d === void 0 ? void 0 : _d.status)) {
103
+ return true;
104
+ }
105
+ }
106
+ return false;
107
+ }
108
+ export function isRejectedText(node) {
109
+ var _a, _b;
110
+ if (node.type === schema.nodes.text) {
111
+ const insertMark = node.marks.find((mark) => mark.type === schema.marks.tracked_insert);
112
+ if (insertMark && ((_b = (_a = insertMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked) === null || _b === void 0 ? void 0 : _b.status) === 'rejected') {
113
+ return true;
114
+ }
115
+ }
116
+ return false;
117
+ }
118
+ export function getActualTextContent(fragment) {
119
+ let finalContent = '';
120
+ function getContent(fragment) {
121
+ fragment.forEach((node) => {
122
+ if (node.type !== schema.nodes.text) {
123
+ finalContent += getContent(node.content);
124
+ }
125
+ if (!isDeletedText(node) && !isRejectedText(node)) {
126
+ finalContent += node.textContent;
127
+ }
128
+ });
129
+ }
130
+ getContent(fragment);
131
+ return finalContent;
132
+ }
95
133
  export function sanitizeAttrsChange(newAttr, currentAttrs) {
96
134
  return Object.keys(newAttr).reduce((acc, attr) => {
97
135
  const key = attr;
@@ -0,0 +1,40 @@
1
+ import { schema, } from '@manuscripts/transform';
2
+ import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils';
3
+ import { sectionTitles } from '../../lib/section-titles';
4
+ import { getActualAttrs, getActualTextContent, } from '../../lib/track-changes-utils';
5
+ function cursorAtTheEndOfText(state, nodeSize, nodePos) {
6
+ const { from, to } = state.selection;
7
+ return from === to && to === nodePos + nodeSize - 1;
8
+ }
9
+ const isUpperCase = (test) => test === test.toUpperCase() && test.length > 1;
10
+ export function hasAutoCompletionSlack(parentSection, titleSection) {
11
+ const category = getActualAttrs(parentSection).category;
12
+ const title = sectionTitles.get(category);
13
+ if (category &&
14
+ title &&
15
+ titleSection.textContent) {
16
+ const actualTextContent = getActualTextContent(titleSection.content);
17
+ console.log('actualTextContent');
18
+ console.log(actualTextContent);
19
+ if (title.toLowerCase().startsWith(actualTextContent.toLowerCase())) {
20
+ const suggestionText = title.slice(actualTextContent.length);
21
+ return isUpperCase(actualTextContent)
22
+ ? suggestionText.toUpperCase()
23
+ : suggestionText;
24
+ }
25
+ }
26
+ return '';
27
+ }
28
+ export function checkForCompletion(state) {
29
+ const section = findParentNodeOfTypeClosestToPos(state.selection.$from, schema.nodes.section);
30
+ const title = findParentNodeOfTypeClosestToPos(state.selection.$from, schema.nodes.section_title);
31
+ if (section &&
32
+ title &&
33
+ cursorAtTheEndOfText(state, title.node.nodeSize, title.pos)) {
34
+ const text = hasAutoCompletionSlack(section.node, title.node);
35
+ console.log('returnable text');
36
+ console.log(text);
37
+ return text;
38
+ }
39
+ return '';
40
+ }
@@ -1,7 +1,9 @@
1
1
  import { schema } from '@manuscripts/transform';
2
2
  import { Plugin, PluginKey } from 'prosemirror-state';
3
3
  import { findChildrenByType } from 'prosemirror-utils';
4
- import { isRejectedInsert } from '../lib/track-changes-utils';
4
+ import { Decoration, DecorationSet } from 'prosemirror-view';
5
+ import { isRejectedInsert } from '../../lib/track-changes-utils';
6
+ import { checkForCompletion } from './autocompletion';
5
7
  export const sectionTitleKey = new PluginKey('sectionNumbering');
6
8
  const calculateSectionLevels = (node, startPos, sectionNumberMap, numbering = [0]) => {
7
9
  node.forEach((childNode, offset) => {
@@ -32,6 +34,21 @@ const getPluginState = (doc) => {
32
34
  export default () => {
33
35
  return new Plugin({
34
36
  key: sectionTitleKey,
37
+ props: {
38
+ decorations(state) {
39
+ const text = checkForCompletion(state);
40
+ if (text) {
41
+ const decoration = Decoration.widget(state.selection.from, () => {
42
+ const node = document.createElement('span');
43
+ node.classList.add('completion-bearer');
44
+ node.dataset.suggest = text;
45
+ return node;
46
+ });
47
+ return DecorationSet.create(state.doc, [decoration]);
48
+ }
49
+ return DecorationSet.empty;
50
+ },
51
+ },
35
52
  state: {
36
53
  init: (_, state) => {
37
54
  return getPluginState(state.doc);
@@ -1,2 +1,2 @@
1
- export const VERSION = '2.0.43';
1
+ export const VERSION = '2.0.44-LEAN-3883.3';
2
2
  export const MATHJAX_VERSION = '3.2.2';
@@ -24,6 +24,7 @@ export class SectionTitleView extends BlockView {
24
24
  super(...arguments);
25
25
  this.elementType = 'h1';
26
26
  this.onUpdateContent = () => {
27
+ console.log(this.node);
27
28
  const $pos = this.view.state.doc.resolve(this.getPos());
28
29
  const sectionTitleState = sectionTitleKey.getState(this.view.state);
29
30
  const parentSection = findParentNodeOfTypeClosestToPos($pos, schema.nodes.section);
@@ -75,4 +75,5 @@ export declare const insertTableFootnote: (tableElementNode: ManuscriptNode, pos
75
75
  export declare const addRows: (direction: 'top' | 'bottom') => (state: EditorState, dispatch?: ((tr: Transaction) => void) | undefined) => boolean;
76
76
  export declare const addColumns: (direction: 'right' | 'left') => (state: EditorState, dispatch?: ((tr: Transaction) => void) | undefined) => boolean;
77
77
  export declare function mergeCellsWithSpace(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
78
+ export declare const autoComplete: (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
78
79
  export {};
@@ -0,0 +1,17 @@
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 { SectionCategory } from '@manuscripts/transform';
17
+ export declare const sectionTitles: Map<SectionCategory, string>;
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { TrackedAttrs } from '@manuscripts/track-changes-plugin';
17
17
  import { ManuscriptNode } from '@manuscripts/transform';
18
- import { Node as ProsemirrorNode } from 'prosemirror-model';
18
+ import { Fragment, Node as ProsemirrorNode } from 'prosemirror-model';
19
19
  export declare function isRejectedInsert(node: ProsemirrorNode): boolean;
20
20
  export declare function isDeleted(node: ProsemirrorNode): boolean;
21
21
  export declare function isPendingInsert(node: ProsemirrorNode): boolean;
@@ -26,4 +26,7 @@ export declare function isTracked(node: ProsemirrorNode): boolean;
26
26
  export declare function getActualAttrs<T extends ManuscriptNode>(node: T): T["attrs"];
27
27
  export declare const getAttrsTrackingButton: (changeID: string) => HTMLButtonElement;
28
28
  export declare function isHidden(node: ProsemirrorNode): boolean;
29
+ export declare function isDeletedText(node: ProsemirrorNode): boolean;
30
+ export declare function isRejectedText(node: ProsemirrorNode): boolean;
31
+ export declare function getActualTextContent(fragment: Fragment): string;
29
32
  export declare function sanitizeAttrsChange<T extends ProsemirrorNode>(newAttr: T['attrs'], currentAttrs: T['attrs']): T["attrs"];
@@ -0,0 +1,4 @@
1
+ import { SectionNode, SectionTitleNode } from '@manuscripts/transform';
2
+ import { EditorState } from 'prosemirror-state';
3
+ export declare function hasAutoCompletionSlack(parentSection: SectionNode, titleSection: SectionTitleNode): string;
4
+ export declare function checkForCompletion(state: EditorState): string;
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "2.0.43";
1
+ export declare const VERSION = "2.0.44-LEAN-3883.3";
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": "2.0.43",
4
+ "version": "2.0.44-LEAN-3883.3",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -32,7 +32,7 @@
32
32
  "@iarna/word-count": "^1.1.2",
33
33
  "@manuscripts/json-schema": "2.2.11",
34
34
  "@manuscripts/library": "1.3.11",
35
- "@manuscripts/style-guide": "2.0.19",
35
+ "@manuscripts/style-guide": "2.0.20-LEAN-3883.0",
36
36
  "@manuscripts/track-changes-plugin": "1.7.17",
37
37
  "@manuscripts/transform": "2.3.31",
38
38
  "@popperjs/core": "^2.11.8",
@@ -1,20 +1,15 @@
1
1
  .ProseMirror
2
2
  > div.body
3
- section:not(.toc)
4
- .block-section_title
3
+ section:not(.toc)
4
+ .block-section_title
5
5
  h1.empty-node[data-placeholder]::before {
6
6
  content: attr(data-section-number) '. ' attr(data-placeholder);
7
7
  }
8
8
 
9
- .ProseMirror
10
- > div.body
11
- section:not(.toc)
12
- .block-section_title
13
- h1::before {
9
+ .ProseMirror > div.body section:not(.toc) .block-section_title h1::before {
14
10
  content: attr(data-section-number) '. ';
15
11
  }
16
12
 
17
-
18
13
  .ProseMirror > div .block-section_title > h1 {
19
14
  font-size: 16pt !important;
20
15
  font-style: normal !important;
@@ -39,8 +34,6 @@
39
34
  font-size: 13.5pt !important;
40
35
  }
41
36
 
42
-
43
-
44
37
  .ProseMirror div.backmatter::before {
45
38
  content: '';
46
39
  border-bottom: 1px dashed #c9c9c9;
@@ -51,6 +44,15 @@
51
44
  font-size: 13.5pt !important;
52
45
  color: #6e6e6e !important;
53
46
  }
47
+ .completion-bearer {
48
+ pointer-events: none;
49
+ }
50
+ .block-section_title .completion-bearer:after {
51
+ content: attr(data-suggest);
52
+ opacity: 0.5;
53
+ pointer-events: none;
54
+ font-style: italic;
55
+ }
54
56
 
55
57
  .ProseMirror p.block {
56
58
  font-size: 12pt !important;
@@ -154,8 +156,8 @@
154
156
  position: static;
155
157
  }
156
158
 
157
-
158
- .comment-marker.selected-comment > svg > path, .comment-marker:active > svg > path {
159
+ .comment-marker.selected-comment > svg > path,
160
+ .comment-marker:active > svg > path {
159
161
  stroke: #f7b314;
160
162
  fill: #ffe0b2;
161
163
  }
@@ -170,7 +172,8 @@
170
172
  position: relative;
171
173
  }
172
174
 
173
- .block > div.comment-marker, .figure-block > div.comment-marker {
175
+ .block > div.comment-marker,
176
+ .figure-block > div.comment-marker {
174
177
  top: -25px;
175
178
  left: 100%;
176
179
  }
@@ -209,7 +212,7 @@ span.comment-marker {
209
212
  top: 12px;
210
213
  }
211
214
 
212
- .comment-marker[data-count="0"] {
215
+ .comment-marker[data-count='0'] {
213
216
  display: none;
214
217
  }
215
218
 
@@ -221,7 +224,7 @@ span.comment-marker {
221
224
  content: attr(data-count);
222
225
  top: 8px;
223
226
  left: 8px;
224
- background-color: #F7B314;
227
+ background-color: #f7b314;
225
228
  border-radius: 50%;
226
229
  width: 12px;
227
230
  height: 12px;
@@ -287,7 +290,7 @@ span.comment-marker {
287
290
  font-size: 16px !important;
288
291
  font-weight: 700 !important;
289
292
  line-height: 24px !important;
290
- margin: 0 !important
293
+ margin: 0 !important;
291
294
  }
292
295
 
293
296
  .ProseMirror .author-notes-container > div {
@@ -309,7 +312,7 @@ span.comment-marker {
309
312
  position: relative;
310
313
  cursor: default;
311
314
  padding: 4px 8px;
312
- border: 1px solid #C9C9C9;
315
+ border: 1px solid #c9c9c9;
313
316
  margin-top: 10px;
314
317
  margin-bottom: 4px;
315
318
  }
@@ -375,7 +378,7 @@ span.comment-marker {
375
378
 
376
379
  .keywords .keyword-group-container {
377
380
  position: relative;
378
- margin: 0 0 36px !important;
381
+ margin: 0 0 36px !important;
379
382
  }
380
383
 
381
384
  .keywords .keyword-group {
@@ -449,8 +452,8 @@ span.comment-marker {
449
452
  --inserted-pending-bg-color: #e6ffdb;
450
453
  --inserted-pending-color: #01872e;
451
454
  --accepted-bg-color: #e2e2e2;
452
- --deleted-color: #F35143;
453
- --deleted-pending-bg-color: #FFF1F0;
455
+ --deleted-color: #f35143;
456
+ --deleted-pending-bg-color: #fff1f0;
454
457
  --highlight-bg-color: #ffeebf;
455
458
  --common-color: #353535;
456
459
  --selected-pending-background-color: #ddf3fa;
@@ -479,22 +482,28 @@ span.selected-suggestion,
479
482
  span.accepted .selected-suggestion,
480
483
  .accepted .selected-suggestion > .block-container .block,
481
484
  .accepted .selected-suggestion:not(:has(> .block-container)),
482
- .selected-suggestion[data-track-status="accepted"],
483
- .selected-suggestion > .block-container .block.accepted,
484
- .selected-suggestion > .block-container .block:has([data-track-status='accepted']),
485
- .selected-suggestion:not(:has(> .block-container)):has([data-track-status='accepted']) {
485
+ .selected-suggestion[data-track-status='accepted'],
486
+ .selected-suggestion > .block-container .block.accepted,
487
+ .selected-suggestion
488
+ > .block-container
489
+ .block:has([data-track-status='accepted']),
490
+ .selected-suggestion:not(:has(> .block-container)):has(
491
+ [data-track-status='accepted']
492
+ ) {
486
493
  background-color: var(--selected-accepted-background-color) !important;
487
494
  border-width: 2px 0 2px 0 !important;
488
- border-color: #C9C9C9 !important;
495
+ border-color: #c9c9c9 !important;
489
496
  border-radius: 3px !important;
490
497
  border-style: solid !important;
491
498
  }
492
499
 
493
- .block-bullet_list .selected-suggestion p, .block-ordered_list .selected-suggestion p {
500
+ .block-bullet_list .selected-suggestion p,
501
+ .block-ordered_list .selected-suggestion p {
494
502
  margin: 0;
495
503
  }
496
504
 
497
- .block-bullet_list .selected-suggestion, .block-ordered_list .selected-suggestion {
505
+ .block-bullet_list .selected-suggestion,
506
+ .block-ordered_list .selected-suggestion {
498
507
  margin: 16px 0;
499
508
  }
500
509
 
@@ -506,7 +515,10 @@ span.accepted .selected-suggestion,
506
515
  }
507
516
 
508
517
  .ProseMirror .selected-suggestion .inserted.pending,
509
- .ProseMirror .selected-suggestion [data-track-op='insert'][data-track-status='pending'] .block,
518
+ .ProseMirror
519
+ .selected-suggestion
520
+ [data-track-op='insert'][data-track-status='pending']
521
+ .block,
510
522
  .ProseMirror .selected-suggestion .deleted.pending {
511
523
  background-color: var(--selected-pending-background-color) !important;
512
524
  color: var(--common-color) !important;
@@ -549,7 +561,11 @@ span.accepted .selected-suggestion,
549
561
  .ProseMirror .inserted.pending:has(.selected-suggestion),
550
562
  .ProseMirror .deleted.pending:has(.selected-suggestion),
551
563
  .ProseMirror .selected-suggestion .highlight,
552
- .ProseMirror .selected-suggestion .graphical-abstract:has([data-track-status='pending'][data-track-op='insert']) {
564
+ .ProseMirror
565
+ .selected-suggestion
566
+ .graphical-abstract:has(
567
+ [data-track-status='pending'][data-track-op='insert']
568
+ ) {
553
569
  background: transparent !important;
554
570
  color: var(--common-color);
555
571
  text-decoration: none;
@@ -588,7 +604,7 @@ span.accepted .selected-suggestion,
588
604
  .affiliation[data-track-status='pending'][data-track-op='delete'] {
589
605
  text-decoration: line-through;
590
606
  color: var(--deleted-color);
591
- background-color: var(--deleted-pending-bg-color)
607
+ background-color: var(--deleted-pending-bg-color);
592
608
  }
593
609
 
594
610
  .contributor[data-track-op='delete']:not([data-track-status='rejected']),
@@ -602,7 +618,9 @@ span.accepted .selected-suggestion,
602
618
  color: var(--inserted-pending-color);
603
619
  text-decoration: underline;
604
620
  }
605
- .block-contributors, .block-affiliations, .keywords {
621
+ .block-contributors,
622
+ .block-affiliations,
623
+ .keywords {
606
624
  margin: 15px 0px;
607
625
  }
608
626
  .contributors {
@@ -703,7 +721,6 @@ span.accepted .selected-suggestion,
703
721
  margin: 1rem 64px 0;
704
722
  font-size: 12px;
705
723
  color: #6e6e6e;
706
-
707
724
  }
708
725
 
709
726
  * {
@@ -741,7 +758,9 @@ span.accepted .selected-suggestion,
741
758
  z-index: 10;
742
759
  }
743
760
 
744
- .ProseMirror td:hover > .table-context-menu-button, th:hover > .table-context-menu-button, .open-context-menu {
761
+ .ProseMirror td:hover > .table-context-menu-button,
762
+ th:hover > .table-context-menu-button,
763
+ .open-context-menu {
745
764
  visibility: visible !important;
746
765
  }
747
766
 
@@ -766,7 +785,7 @@ span.accepted .selected-suggestion,
766
785
  }
767
786
 
768
787
  .section-category-button:not(.assigned) path {
769
- fill: #FFE0B2;
788
+ fill: #ffe0b2;
770
789
  }
771
790
 
772
791
  .section-category-button.assigned:after {
@@ -776,8 +795,8 @@ span.accepted .selected-suggestion,
776
795
  content: '';
777
796
  height: 8px;
778
797
  width: 4px;
779
- border-bottom: 2px solid #36B260;
780
- border-right: 2px solid #36B260;
798
+ border-bottom: 2px solid #36b260;
799
+ border-right: 2px solid #36b260;
781
800
  transform: rotate(45deg);
782
801
  }
783
802
 
@@ -786,8 +805,8 @@ span.accepted .selected-suggestion,
786
805
  }
787
806
  .section-category.menu {
788
807
  border-radius: 8px;
789
- border: 1px solid #E2E2E2;
790
- box-shadow: 0px 4px 9px 0px rgba(0, 0, 0, 0.30);
808
+ border: 1px solid #e2e2e2;
809
+ box-shadow: 0px 4px 9px 0px rgba(0, 0, 0, 0.3);
791
810
  }
792
811
 
793
812
  .section-category.menu .menu-item {
@@ -814,8 +833,8 @@ span.accepted .selected-suggestion,
814
833
  content: '';
815
834
  height: 10px;
816
835
  width: 5px;
817
- border-bottom: 2px solid #36B260;
818
- border-right: 2px solid #36B260;
836
+ border-bottom: 2px solid #36b260;
837
+ border-right: 2px solid #36b260;
819
838
  transform: rotate(45deg);
820
839
  }
821
840
 
@@ -831,16 +850,16 @@ span.accepted .selected-suggestion,
831
850
  display: flex;
832
851
  align-items: center;
833
852
  border-radius: 6px;
834
- background: #E2E2E2;
853
+ background: #e2e2e2;
835
854
  font-size: 12px;
836
855
  font-style: normal;
837
856
  font-weight: 400;
838
- color: #353535;
857
+ color: #353535;
839
858
  line-height: 16px;
840
859
  }
841
860
 
842
861
  .section-category.tooltip span {
843
- color: #353535;
862
+ color: #353535;
844
863
  font-size: 12px;
845
864
  font-style: normal;
846
865
  font-weight: 700;