@manuscripts/body-editor 3.5.6 → 3.5.8

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.
Files changed (46) hide show
  1. package/dist/cjs/commands.js +15 -1
  2. package/dist/cjs/configs/editor-plugins.js +2 -0
  3. package/dist/cjs/configs/editor-views.js +4 -2
  4. package/dist/cjs/icons.js +2 -1
  5. package/dist/cjs/keys/misc.js +1 -1
  6. package/dist/cjs/keys/title.js +2 -1
  7. package/dist/cjs/lib/context-menu.js +11 -0
  8. package/dist/cjs/plugins/add-subtitle.js +70 -0
  9. package/dist/cjs/plugins/alt-titles.js +8 -3
  10. package/dist/cjs/plugins/placeholder.js +5 -0
  11. package/dist/cjs/versions.js +1 -1
  12. package/dist/cjs/views/alt_titles_section.js +9 -0
  13. package/dist/cjs/views/editable_block.js +1 -0
  14. package/dist/cjs/views/subtitle.js +37 -0
  15. package/dist/cjs/views/subtitle_editable.js +20 -0
  16. package/dist/cjs/views/subtitles.js +35 -0
  17. package/dist/cjs/views/subtitles_editable.js +21 -0
  18. package/dist/es/commands.js +13 -0
  19. package/dist/es/configs/editor-plugins.js +2 -0
  20. package/dist/es/configs/editor-views.js +4 -2
  21. package/dist/es/icons.js +2 -1
  22. package/dist/es/keys/misc.js +2 -2
  23. package/dist/es/keys/title.js +2 -1
  24. package/dist/es/lib/context-menu.js +11 -0
  25. package/dist/es/plugins/add-subtitle.js +68 -0
  26. package/dist/es/plugins/alt-titles.js +8 -3
  27. package/dist/es/plugins/placeholder.js +5 -0
  28. package/dist/es/versions.js +1 -1
  29. package/dist/es/views/alt_titles_section.js +9 -0
  30. package/dist/es/views/editable_block.js +1 -0
  31. package/dist/es/views/subtitle.js +33 -0
  32. package/dist/es/views/subtitle_editable.js +18 -0
  33. package/dist/es/views/subtitles.js +28 -0
  34. package/dist/es/views/subtitles_editable.js +19 -0
  35. package/dist/types/commands.d.ts +1 -0
  36. package/dist/types/icons.d.ts +1 -0
  37. package/dist/types/plugins/add-subtitle.d.ts +18 -0
  38. package/dist/types/plugins/alt-titles.d.ts +2 -1
  39. package/dist/types/versions.d.ts +1 -1
  40. package/dist/types/views/subtitle.d.ts +24 -0
  41. package/dist/types/views/subtitle_editable.d.ts +18 -0
  42. package/dist/types/views/subtitles.d.ts +23 -0
  43. package/dist/types/views/subtitles_editable.d.ts +44 -0
  44. package/package.json +2 -2
  45. package/styles/AdvancedEditor.css +7 -0
  46. package/styles/Editor.css +30 -0
@@ -16,7 +16,7 @@
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.addRows = exports.addInlineComment = exports.addNodeComment = exports.isCommentingAllowed = 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.insertAward = exports.insertAffiliation = exports.insertContributors = exports.insertGraphicalAbstract = exports.insertBackmatterSection = exports.insertAbstractSection = exports.insertSection = exports.insertBoxElement = exports.insertInlineFootnote = exports.insertFootnotesElement = exports.insertTableElementFooter = exports.insertInlineEquation = exports.insertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.findPosBeforeFirstSubsection = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertAttachment = exports.insertSupplement = exports.insertTable = exports.insertEmbed = exports.insertFigure = exports.insertGeneralTableFootnote = exports.insertInlineTableFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = exports.addToStart = void 0;
19
- exports.insertHeroImage = exports.activateSearchReplace = exports.activateSearch = exports.autoComplete = exports.addColumns = exports.addHeaderRow = void 0;
19
+ exports.ignoreEnterInSubtitles = exports.insertHeroImage = exports.activateSearchReplace = exports.activateSearch = exports.autoComplete = exports.addColumns = exports.addHeaderRow = void 0;
20
20
  const json_schema_1 = require("@manuscripts/json-schema");
21
21
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
22
22
  const transform_1 = require("@manuscripts/transform");
@@ -1101,6 +1101,7 @@ const getParentNode = (selection) => {
1101
1101
  return node;
1102
1102
  };
1103
1103
  const isCommentingAllowed = (type) => type === transform_1.schema.nodes.title ||
1104
+ type === transform_1.schema.nodes.subtitles ||
1104
1105
  type === transform_1.schema.nodes.section ||
1105
1106
  type === transform_1.schema.nodes.citation ||
1106
1107
  type === transform_1.schema.nodes.bibliography_item ||
@@ -1296,3 +1297,16 @@ const insertHeroImage = () => (state, dispatch, view) => {
1296
1297
  return true;
1297
1298
  };
1298
1299
  exports.insertHeroImage = insertHeroImage;
1300
+ const ignoreEnterInSubtitles = (state) => {
1301
+ const { selection } = state;
1302
+ if (!(0, exports.isTextSelection)(selection)) {
1303
+ return false;
1304
+ }
1305
+ const cursorParent = selection.$from.node();
1306
+ if (cursorParent.type === state.schema.nodes.subtitle ||
1307
+ cursorParent.type === state.schema.nodes.subtitles) {
1308
+ return true;
1309
+ }
1310
+ return false;
1311
+ };
1312
+ exports.ignoreEnterInSubtitles = ignoreEnterInSubtitles;
@@ -27,6 +27,7 @@ const prosemirror_history_1 = require("prosemirror-history");
27
27
  const prosemirror_tables_1 = require("prosemirror-tables");
28
28
  const keys_1 = __importDefault(require("../keys"));
29
29
  const accessibility_element_1 = __importDefault(require("../plugins/accessibility_element"));
30
+ const add_subtitle_1 = __importDefault(require("../plugins/add-subtitle"));
30
31
  const affiliations_1 = __importDefault(require("../plugins/affiliations"));
31
32
  const alt_titles_1 = __importDefault(require("../plugins/alt-titles"));
32
33
  const bibliography_1 = __importDefault(require("../plugins/bibliography"));
@@ -75,6 +76,7 @@ exports.default = (props) => {
75
76
  (0, comments_1.default)(),
76
77
  (0, paragraphs_1.default)(),
77
78
  (0, placeholder_1.default)(),
79
+ (0, add_subtitle_1.default)(),
78
80
  (0, prosemirror_tables_1.tableEditing)(),
79
81
  (0, selected_suggestion_1.default)(),
80
82
  (0, footnotes_1.default)(props),
@@ -43,6 +43,8 @@ const quote_image_editable_1 = __importDefault(require("../views/quote_image_edi
43
43
  const section_1 = __importDefault(require("../views/section"));
44
44
  const section_label_1 = __importDefault(require("../views/section_label"));
45
45
  const section_title_editable_1 = __importDefault(require("../views/section_title_editable"));
46
+ const subtitle_editable_1 = __importDefault(require("../views/subtitle_editable"));
47
+ const subtitles_editable_1 = __importDefault(require("../views/subtitles_editable"));
46
48
  const table_cell_1 = __importDefault(require("../views/table_cell"));
47
49
  const table_element_editable_1 = __importDefault(require("../views/table_element_editable"));
48
50
  const table_element_footer_1 = __importDefault(require("../views/table_element_footer"));
@@ -51,8 +53,8 @@ const translated_abstract_editable_1 = __importDefault(require("../views/transla
51
53
  exports.default = (props, dispatch) => {
52
54
  return {
53
55
  title: (0, title_editable_1.default)(props, dispatch),
54
- subtitle: (0, empty_1.default)('subtitle'),
55
- subtitles: (0, empty_1.default)('subtitles'),
56
+ subtitles: (0, subtitles_editable_1.default)(props, dispatch),
57
+ subtitle: (0, subtitle_editable_1.default)(props, dispatch),
56
58
  alt_title: (0, alt_title_1.default)(props),
57
59
  alt_titles: (0, alt_titles_section_1.default)(props),
58
60
  bibliography_element: (0, bibliography_element_1.default)(props, dispatch),
package/dist/cjs/icons.js CHANGED
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.translateIcon = exports.draggableIcon = exports.fileCorruptedIcon = exports.imageDefaultIcon = exports.imageLeftIcon = exports.imageRightIcon = exports.addBtnIcon = exports.plusIcon = exports.lockIcon = exports.scrollIcon = exports.sectionCategoryIcon = exports.editIcon = exports.deleteIcon = exports.alertIcon = exports.arrowUp = exports.arrowDown = void 0;
3
+ exports.translateIcon = exports.draggableIcon = exports.fileCorruptedIcon = exports.imageDefaultIcon = exports.imageLeftIcon = exports.imageRightIcon = exports.addBtnIcon = exports.plusIcon = exports.lockIcon = exports.scrollIcon = exports.sectionCategoryIcon = exports.editIcon = exports.deleteIcon = exports.alertIcon = exports.arrowUp = exports.arrowDown = exports.addAuthorIcon = void 0;
4
4
  const style_guide_1 = require("@manuscripts/style-guide");
5
5
  const react_1 = require("react");
6
6
  const server_1 = require("react-dom/server");
7
7
  const renderIcon = (c) => (0, server_1.renderToStaticMarkup)((0, react_1.createElement)(c));
8
+ exports.addAuthorIcon = renderIcon(style_guide_1.AddAuthorIcon);
8
9
  exports.arrowDown = renderIcon(style_guide_1.ArrowDownCircleIcon);
9
10
  exports.arrowUp = renderIcon(style_guide_1.ArrowUpIcon);
10
11
  exports.alertIcon = renderIcon(style_guide_1.AlertIcon);
@@ -40,7 +40,7 @@ const customKeymap = {
40
40
  'Mod-Alt-=': (0, prosemirror_commands_1.toggleMark)(transform_1.schema.marks.superscript),
41
41
  'Mod-Alt--': (0, prosemirror_commands_1.toggleMark)(transform_1.schema.marks.subscript),
42
42
  'Ctrl->': (0, prosemirror_commands_1.wrapIn)(transform_1.schema.nodes.blockquote),
43
- Enter: (0, prosemirror_commands_1.chainCommands)(commands_1.autoComplete, commands_1.addToStart, prosemirror_commands_1.newlineInCode, prosemirror_commands_1.createParagraphNear, prosemirror_commands_1.liftEmptyBlock, prosemirror_commands_1.splitBlock),
43
+ Enter: (0, prosemirror_commands_1.chainCommands)(commands_1.ignoreEnterInSubtitles, commands_1.autoComplete, commands_1.addToStart, prosemirror_commands_1.newlineInCode, prosemirror_commands_1.createParagraphNear, prosemirror_commands_1.liftEmptyBlock, prosemirror_commands_1.splitBlock),
44
44
  'Shift-Mod-Enter': (0, commands_1.insertSection)(true),
45
45
  'Mod-Enter': (0, prosemirror_commands_1.chainCommands)(prosemirror_commands_1.exitCode, (0, commands_1.insertSection)()),
46
46
  'Shift-Enter': (0, prosemirror_commands_1.chainCommands)(prosemirror_commands_1.exitCode, commands_1.insertBreak),
@@ -114,7 +114,8 @@ const protectTitles = (state, dispatch, view) => {
114
114
  if (!$cursor) {
115
115
  return false;
116
116
  }
117
- if ($cursor.parent.type === transform_1.schema.nodes.alt_title &&
117
+ if (($cursor.parent.type === transform_1.schema.nodes.alt_title ||
118
+ $cursor.parent.type === transform_1.schema.nodes.subtitle) &&
118
119
  $cursor.pos === $cursor.before() + 1) {
119
120
  return true;
120
121
  }
@@ -18,6 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.ContextMenu = exports.contextMenuBtnClass = exports.sectionLevel = void 0;
19
19
  const style_guide_1 = require("@manuscripts/style-guide");
20
20
  const transform_1 = require("@manuscripts/transform");
21
+ const prosemirror_state_1 = require("prosemirror-state");
21
22
  const prosemirror_utils_1 = require("prosemirror-utils");
22
23
  const react_1 = require("react");
23
24
  const server_1 = require("react-dom/server");
@@ -370,6 +371,16 @@ class ContextMenu {
370
371
  this.view.dispatch(this.view.state.tr.delete($pos.before($pos.depth - 1), $pos.after($pos.depth - 1)));
371
372
  break;
372
373
  }
374
+ case 'subtitles': {
375
+ const pos = this.getPos();
376
+ const tr = this.view.state.tr;
377
+ tr.delete(pos, pos + this.node.nodeSize);
378
+ const titleNode = (0, prosemirror_utils_1.findChildrenByType)(tr.doc, transform_1.schema.nodes.title)[0];
379
+ const titleEndPos = titleNode.pos + titleNode.node.nodeSize - 1;
380
+ tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, titleEndPos));
381
+ this.view.dispatch(tr);
382
+ break;
383
+ }
373
384
  default: {
374
385
  const pos = this.getPos();
375
386
  this.view.dispatch(this.view.state.tr.delete(pos, pos + this.node.nodeSize));
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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
+ const transform_1 = require("@manuscripts/transform");
19
+ const prosemirror_state_1 = require("prosemirror-state");
20
+ const prosemirror_view_1 = require("prosemirror-view");
21
+ const uuid_1 = require("uuid");
22
+ const icons_1 = require("../icons");
23
+ const createAddSubtitleButton = (handler) => {
24
+ const button = document.createElement('span');
25
+ button.className = 'add-subtitle';
26
+ button.innerHTML = `${icons_1.addAuthorIcon} <span class="add-subtitle-text">Add subtitle</span>`;
27
+ button.addEventListener('mousedown', (e) => {
28
+ e.preventDefault();
29
+ handler();
30
+ });
31
+ return button;
32
+ };
33
+ exports.default = () => new prosemirror_state_1.Plugin({
34
+ props: {
35
+ decorations: (state) => {
36
+ let titleHasContent = false;
37
+ let titlePos = -1;
38
+ let hasSubtitles = false;
39
+ state.doc.descendants((node, pos) => {
40
+ if (node.type === transform_1.schema.nodes.title && node.textContent.trim()) {
41
+ titleHasContent = true;
42
+ titlePos = pos;
43
+ }
44
+ else if (node.type === transform_1.schema.nodes.subtitles) {
45
+ hasSubtitles = true;
46
+ return false;
47
+ }
48
+ });
49
+ if (titleHasContent && !hasSubtitles) {
50
+ const titleNode = state.doc.nodeAt(titlePos);
51
+ if (titleNode) {
52
+ const titleEndPos = titlePos + titleNode.nodeSize;
53
+ return prosemirror_view_1.DecorationSet.create(state.doc, [
54
+ prosemirror_view_1.Decoration.widget(titleEndPos, (view) => {
55
+ return createAddSubtitleButton(() => {
56
+ const subtitlesNode = transform_1.schema.nodes.subtitles.create({ id: (0, uuid_1.v4)() }, [transform_1.schema.nodes.subtitle.create({ id: (0, uuid_1.v4)() })]);
57
+ const tr = view.state.tr.insert(titleEndPos, subtitlesNode);
58
+ const subtitlePos = titleEndPos + 1;
59
+ tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, subtitlePos));
60
+ view.dispatch(tr);
61
+ view.focus();
62
+ });
63
+ }),
64
+ ]);
65
+ }
66
+ }
67
+ return prosemirror_view_1.DecorationSet.empty;
68
+ },
69
+ },
70
+ });
@@ -8,6 +8,7 @@ const prosemirror_view_1 = require("prosemirror-view");
8
8
  const utils_1 = require("../lib/utils");
9
9
  function getTitlesData(doc) {
10
10
  let title;
11
+ let subtitles;
11
12
  let runningTitle;
12
13
  let shortTitle;
13
14
  let altTitlesSection;
@@ -18,6 +19,9 @@ function getTitlesData(doc) {
18
19
  if (node.type === transform_1.schema.nodes.title) {
19
20
  title = [node, pos];
20
21
  }
22
+ if (node.type === transform_1.schema.nodes.subtitles) {
23
+ subtitles = [node, pos];
24
+ }
21
25
  if (node.type === transform_1.schema.nodes.alt_titles) {
22
26
  altTitlesSection = [node, pos];
23
27
  }
@@ -30,7 +34,7 @@ function getTitlesData(doc) {
30
34
  }
31
35
  }
32
36
  });
33
- return { title, runningTitle, shortTitle, altTitlesSection };
37
+ return { title, subtitles, runningTitle, shortTitle, altTitlesSection };
34
38
  }
35
39
  function selectionInAltTitles(from, to, state) {
36
40
  if (state.runningTitle && state.shortTitle) {
@@ -75,13 +79,14 @@ exports.default = () => {
75
79
  !exports.altTitlesKey.getState(newState)) {
76
80
  return null;
77
81
  }
78
- const { title, runningTitle, shortTitle, altTitlesSection } = exports.altTitlesKey.getState(newState);
82
+ const { title, subtitles, runningTitle, shortTitle, altTitlesSection } = exports.altTitlesKey.getState(newState);
79
83
  const schema = newState.schema;
80
84
  if (!title) {
81
85
  return null;
82
86
  }
83
87
  if (!altTitlesSection) {
84
- const titleEnd = title[0].nodeSize + title[1];
88
+ const prev = subtitles || title;
89
+ const titleEnd = prev[0].nodeSize + prev[1];
85
90
  const section = schema.nodes.alt_titles.create({}, [
86
91
  schema.nodes.alt_title.create({
87
92
  type: 'running',
@@ -19,6 +19,9 @@ const transform_1 = require("@manuscripts/transform");
19
19
  const prosemirror_state_1 = require("prosemirror-state");
20
20
  const prosemirror_utils_1 = require("prosemirror-utils");
21
21
  const prosemirror_view_1 = require("prosemirror-view");
22
+ const placeholderMap = {
23
+ subtitle: 'Type subtitle here...',
24
+ };
22
25
  const placeholderWidget = (placeholder) => (view, getPos) => {
23
26
  const element = document.createElement('span');
24
27
  element.className = 'placeholder-text';
@@ -87,8 +90,10 @@ exports.default = () => new prosemirror_state_1.Plugin({
87
90
  decorations.push(prosemirror_view_1.Decoration.widget(pos + 1, placeholderWidget('Type new abstract title here')));
88
91
  }
89
92
  else {
93
+ const placeholder = placeholderMap[node.type.name];
90
94
  decorations.push(prosemirror_view_1.Decoration.node(pos, pos + node.nodeSize, {
91
95
  class: 'empty-node',
96
+ ...(placeholder && { 'data-placeholder': placeholder }),
92
97
  }));
93
98
  }
94
99
  }
@@ -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.6';
4
+ exports.VERSION = '3.5.8';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -19,6 +19,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.AltTitleSectionView = void 0;
22
+ const prosemirror_state_1 = require("prosemirror-state");
23
+ const prosemirror_utils_1 = require("prosemirror-utils");
22
24
  const icons_1 = require("../icons");
23
25
  const alt_titles_1 = require("../plugins/alt-titles");
24
26
  const block_view_1 = __importDefault(require("./block_view"));
@@ -48,6 +50,13 @@ class AltTitleSectionView extends block_view_1.default {
48
50
  const tr = this.view.state.tr.setMeta(alt_titles_1.altTitlesKey, {
49
51
  collapsed: true,
50
52
  });
53
+ const titleNode = (0, prosemirror_utils_1.findChildrenByType)(this.view.state.doc, this.view.state.schema.nodes.title)[0];
54
+ const subtitleNode = (0, prosemirror_utils_1.findChildrenByType)(this.view.state.doc, this.view.state.schema.nodes.subtitle)[0];
55
+ const prev = subtitleNode || titleNode;
56
+ if (prev) {
57
+ const titleEndPos = prev.pos + prev.node.nodeSize;
58
+ tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, titleEndPos));
59
+ }
51
60
  this.view.dispatch(tr);
52
61
  });
53
62
  closingPanel.appendChild(button);
@@ -41,6 +41,7 @@ const EditableBlock = (Base) => {
41
41
  const $pos = this.view.state.doc.resolve(this.getPos());
42
42
  const nodeType = this.node.type;
43
43
  if (nodeType === transform_1.schema.nodes.hero_image ||
44
+ nodeType === transform_1.schema.nodes.subtitles ||
44
45
  (0, utils_1.hasParent)($pos, [
45
46
  transform_1.schema.nodes.keywords,
46
47
  transform_1.schema.nodes.bibliography_section,
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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.SubtitleView = void 0;
19
+ const base_node_view_1 = require("./base_node_view");
20
+ const creators_1 = require("./creators");
21
+ class SubtitleView extends base_node_view_1.BaseNodeView {
22
+ constructor() {
23
+ super(...arguments);
24
+ this.initialise = () => {
25
+ this.createDOM();
26
+ };
27
+ this.createDOM = () => {
28
+ this.dom = document.createElement('div');
29
+ this.dom.classList.add('manuscript-subtitle');
30
+ this.contentDOM = document.createElement('span');
31
+ this.dom.appendChild(this.contentDOM);
32
+ this.updateContents();
33
+ };
34
+ }
35
+ }
36
+ exports.SubtitleView = SubtitleView;
37
+ exports.default = (0, creators_1.createNodeView)(SubtitleView);
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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
+ const creators_1 = require("./creators");
19
+ const subtitle_1 = require("./subtitle");
20
+ exports.default = (0, creators_1.createEditableNodeView)(subtitle_1.SubtitleView);
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.SubtitlesView = void 0;
22
+ const block_view_1 = __importDefault(require("./block_view"));
23
+ const creators_1 = require("./creators");
24
+ class SubtitlesView extends block_view_1.default {
25
+ constructor() {
26
+ super(...arguments);
27
+ this.createElement = () => {
28
+ this.contentDOM = document.createElement('div');
29
+ this.contentDOM.classList.add('block');
30
+ this.dom.appendChild(this.contentDOM);
31
+ };
32
+ }
33
+ }
34
+ exports.SubtitlesView = SubtitlesView;
35
+ exports.default = (0, creators_1.createNodeView)(SubtitlesView);
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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
+ const creators_1 = require("./creators");
19
+ const editable_block_1 = require("./editable_block");
20
+ const subtitles_1 = require("./subtitles");
21
+ exports.default = (0, creators_1.createEditableNodeView)((0, editable_block_1.EditableBlock)(subtitles_1.SubtitlesView));
@@ -1051,6 +1051,7 @@ const getParentNode = (selection) => {
1051
1051
  return node;
1052
1052
  };
1053
1053
  export const isCommentingAllowed = (type) => type === schema.nodes.title ||
1054
+ type === schema.nodes.subtitles ||
1054
1055
  type === schema.nodes.section ||
1055
1056
  type === schema.nodes.citation ||
1056
1057
  type === schema.nodes.bibliography_item ||
@@ -1236,3 +1237,15 @@ export const insertHeroImage = () => (state, dispatch, view) => {
1236
1237
  createBlock(schema.nodes.hero_image, position, state, dispatch);
1237
1238
  return true;
1238
1239
  };
1240
+ export const ignoreEnterInSubtitles = (state) => {
1241
+ const { selection } = state;
1242
+ if (!isTextSelection(selection)) {
1243
+ return false;
1244
+ }
1245
+ const cursorParent = selection.$from.node();
1246
+ if (cursorParent.type === state.schema.nodes.subtitle ||
1247
+ cursorParent.type === state.schema.nodes.subtitles) {
1248
+ return true;
1249
+ }
1250
+ return false;
1251
+ };
@@ -22,6 +22,7 @@ import { history } from 'prosemirror-history';
22
22
  import { tableEditing } from 'prosemirror-tables';
23
23
  import keys from '../keys';
24
24
  import accessibility_element from '../plugins/accessibility_element';
25
+ import add_subtitle from '../plugins/add-subtitle';
25
26
  import affiliations from '../plugins/affiliations';
26
27
  import alt_titles from '../plugins/alt-titles';
27
28
  import bibliography from '../plugins/bibliography';
@@ -70,6 +71,7 @@ export default (props) => {
70
71
  comments(),
71
72
  paragraphs(),
72
73
  placeholder(),
74
+ add_subtitle(),
73
75
  tableEditing(),
74
76
  selected_suggestion(),
75
77
  footnotes(props),
@@ -38,6 +38,8 @@ import quoteImage from '../views/quote_image_editable';
38
38
  import section from '../views/section';
39
39
  import sectionLabel from '../views/section_label';
40
40
  import sectionTitle from '../views/section_title_editable';
41
+ import subtitle from '../views/subtitle_editable';
42
+ import subtitles from '../views/subtitles_editable';
41
43
  import tableCell from '../views/table_cell';
42
44
  import tableElement from '../views/table_element_editable';
43
45
  import tableElementFooter from '../views/table_element_footer';
@@ -46,8 +48,8 @@ import transAbstract from '../views/translated_abstract_editable';
46
48
  export default (props, dispatch) => {
47
49
  return {
48
50
  title: title(props, dispatch),
49
- subtitle: empty('subtitle'),
50
- subtitles: empty('subtitles'),
51
+ subtitles: subtitles(props, dispatch),
52
+ subtitle: subtitle(props, dispatch),
51
53
  alt_title: alt_title(props),
52
54
  alt_titles: alt_titles_section(props),
53
55
  bibliography_element: bibliographyElement(props, dispatch),
package/dist/es/icons.js CHANGED
@@ -1,7 +1,8 @@
1
- import { AlertIcon, ArrowDownCircleIcon, ArrowUpIcon, DeleteIcon, DraggableIcon, EditIcon, FileCorruptedIcon, ImageDefaultIcon, ImageLeftIcon, ImageRightIcon, LockIcon, PlusIcon, ScrollIcon, SectionCategoryIcon, TranslateIcon, } from '@manuscripts/style-guide';
1
+ import { AddAuthorIcon, AlertIcon, ArrowDownCircleIcon, ArrowUpIcon, DeleteIcon, DraggableIcon, EditIcon, FileCorruptedIcon, ImageDefaultIcon, ImageLeftIcon, ImageRightIcon, LockIcon, PlusIcon, ScrollIcon, SectionCategoryIcon, TranslateIcon, } from '@manuscripts/style-guide';
2
2
  import { createElement } from 'react';
3
3
  import { renderToStaticMarkup } from 'react-dom/server';
4
4
  const renderIcon = (c) => renderToStaticMarkup(createElement(c));
5
+ export const addAuthorIcon = renderIcon(AddAuthorIcon);
5
6
  export const arrowDown = renderIcon(ArrowDownCircleIcon);
6
7
  export const arrowUp = renderIcon(ArrowUpIcon);
7
8
  export const alertIcon = renderIcon(AlertIcon);
@@ -18,7 +18,7 @@ import { chainCommands, createParagraphNear, exitCode, joinBackward, joinDown, j
18
18
  import { redo, undo } from 'prosemirror-history';
19
19
  import { undoInputRule } from 'prosemirror-inputrules';
20
20
  import { goToNextCell } from 'prosemirror-tables';
21
- import { activateSearch, activateSearchReplace, addToStart, autoComplete, ignoreAtomBlockNodeBackward, ignoreAtomBlockNodeForward, ignoreMetaNodeBackspaceCommand, insertBlock, insertBreak, insertCrossReference, insertInlineCitation, insertInlineEquation, insertSection, selectAllIsolating, } from '../commands';
21
+ import { activateSearch, activateSearchReplace, addToStart, autoComplete, ignoreAtomBlockNodeBackward, ignoreAtomBlockNodeForward, ignoreEnterInSubtitles, ignoreMetaNodeBackspaceCommand, insertBlock, insertBreak, insertCrossReference, insertInlineCitation, insertInlineEquation, insertSection, selectAllIsolating, } from '../commands';
22
22
  import { skipCommandTracking } from './list';
23
23
  const customKeymap = {
24
24
  Backspace: chainCommands(undoInputRule, ignoreAtomBlockNodeBackward, ignoreMetaNodeBackspaceCommand, skipCommandTracking(joinBackward)),
@@ -38,7 +38,7 @@ const customKeymap = {
38
38
  'Mod-Alt-=': toggleMark(schema.marks.superscript),
39
39
  'Mod-Alt--': toggleMark(schema.marks.subscript),
40
40
  'Ctrl->': wrapIn(schema.nodes.blockquote),
41
- Enter: chainCommands(autoComplete, addToStart, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock),
41
+ Enter: chainCommands(ignoreEnterInSubtitles, autoComplete, addToStart, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock),
42
42
  'Shift-Mod-Enter': insertSection(true),
43
43
  'Mod-Enter': chainCommands(exitCode, insertSection()),
44
44
  'Shift-Enter': chainCommands(exitCode, insertBreak),
@@ -111,7 +111,8 @@ const protectTitles = (state, dispatch, view) => {
111
111
  if (!$cursor) {
112
112
  return false;
113
113
  }
114
- if ($cursor.parent.type === schema.nodes.alt_title &&
114
+ if (($cursor.parent.type === schema.nodes.alt_title ||
115
+ $cursor.parent.type === schema.nodes.subtitle) &&
115
116
  $cursor.pos === $cursor.before() + 1) {
116
117
  return true;
117
118
  }
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import { TriangleCollapsedIcon } from '@manuscripts/style-guide';
17
17
  import { isInGraphicalAbstractSection, isSectionTitleNode, nodeNames, schema, } from '@manuscripts/transform';
18
+ import { TextSelection } from 'prosemirror-state';
18
19
  import { findChildrenByType } from 'prosemirror-utils';
19
20
  import { createElement } from 'react';
20
21
  import { renderToStaticMarkup } from 'react-dom/server';
@@ -366,6 +367,16 @@ export class ContextMenu {
366
367
  this.view.dispatch(this.view.state.tr.delete($pos.before($pos.depth - 1), $pos.after($pos.depth - 1)));
367
368
  break;
368
369
  }
370
+ case 'subtitles': {
371
+ const pos = this.getPos();
372
+ const tr = this.view.state.tr;
373
+ tr.delete(pos, pos + this.node.nodeSize);
374
+ const titleNode = findChildrenByType(tr.doc, schema.nodes.title)[0];
375
+ const titleEndPos = titleNode.pos + titleNode.node.nodeSize - 1;
376
+ tr.setSelection(TextSelection.create(tr.doc, titleEndPos));
377
+ this.view.dispatch(tr);
378
+ break;
379
+ }
369
380
  default: {
370
381
  const pos = this.getPos();
371
382
  this.view.dispatch(this.view.state.tr.delete(pos, pos + this.node.nodeSize));
@@ -0,0 +1,68 @@
1
+ /*!
2
+ * © 2025 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 { Plugin, TextSelection } from 'prosemirror-state';
18
+ import { Decoration, DecorationSet } from 'prosemirror-view';
19
+ import { v4 as uuidv4 } from 'uuid';
20
+ import { addAuthorIcon } from '../icons';
21
+ const createAddSubtitleButton = (handler) => {
22
+ const button = document.createElement('span');
23
+ button.className = 'add-subtitle';
24
+ button.innerHTML = `${addAuthorIcon} <span class="add-subtitle-text">Add subtitle</span>`;
25
+ button.addEventListener('mousedown', (e) => {
26
+ e.preventDefault();
27
+ handler();
28
+ });
29
+ return button;
30
+ };
31
+ export default () => new Plugin({
32
+ props: {
33
+ decorations: (state) => {
34
+ let titleHasContent = false;
35
+ let titlePos = -1;
36
+ let hasSubtitles = false;
37
+ state.doc.descendants((node, pos) => {
38
+ if (node.type === schema.nodes.title && node.textContent.trim()) {
39
+ titleHasContent = true;
40
+ titlePos = pos;
41
+ }
42
+ else if (node.type === schema.nodes.subtitles) {
43
+ hasSubtitles = true;
44
+ return false;
45
+ }
46
+ });
47
+ if (titleHasContent && !hasSubtitles) {
48
+ const titleNode = state.doc.nodeAt(titlePos);
49
+ if (titleNode) {
50
+ const titleEndPos = titlePos + titleNode.nodeSize;
51
+ return DecorationSet.create(state.doc, [
52
+ Decoration.widget(titleEndPos, (view) => {
53
+ return createAddSubtitleButton(() => {
54
+ const subtitlesNode = schema.nodes.subtitles.create({ id: uuidv4() }, [schema.nodes.subtitle.create({ id: uuidv4() })]);
55
+ const tr = view.state.tr.insert(titleEndPos, subtitlesNode);
56
+ const subtitlePos = titleEndPos + 1;
57
+ tr.setSelection(TextSelection.create(tr.doc, subtitlePos));
58
+ view.dispatch(tr);
59
+ view.focus();
60
+ });
61
+ }),
62
+ ]);
63
+ }
64
+ }
65
+ return DecorationSet.empty;
66
+ },
67
+ },
68
+ });
@@ -5,6 +5,7 @@ import { Decoration, DecorationSet } from 'prosemirror-view';
5
5
  import { createToggleButton } from '../lib/utils';
6
6
  function getTitlesData(doc) {
7
7
  let title;
8
+ let subtitles;
8
9
  let runningTitle;
9
10
  let shortTitle;
10
11
  let altTitlesSection;
@@ -15,6 +16,9 @@ function getTitlesData(doc) {
15
16
  if (node.type === schema.nodes.title) {
16
17
  title = [node, pos];
17
18
  }
19
+ if (node.type === schema.nodes.subtitles) {
20
+ subtitles = [node, pos];
21
+ }
18
22
  if (node.type === schema.nodes.alt_titles) {
19
23
  altTitlesSection = [node, pos];
20
24
  }
@@ -27,7 +31,7 @@ function getTitlesData(doc) {
27
31
  }
28
32
  }
29
33
  });
30
- return { title, runningTitle, shortTitle, altTitlesSection };
34
+ return { title, subtitles, runningTitle, shortTitle, altTitlesSection };
31
35
  }
32
36
  function selectionInAltTitles(from, to, state) {
33
37
  if (state.runningTitle && state.shortTitle) {
@@ -72,13 +76,14 @@ export default () => {
72
76
  !altTitlesKey.getState(newState)) {
73
77
  return null;
74
78
  }
75
- const { title, runningTitle, shortTitle, altTitlesSection } = altTitlesKey.getState(newState);
79
+ const { title, subtitles, runningTitle, shortTitle, altTitlesSection } = altTitlesKey.getState(newState);
76
80
  const schema = newState.schema;
77
81
  if (!title) {
78
82
  return null;
79
83
  }
80
84
  if (!altTitlesSection) {
81
- const titleEnd = title[0].nodeSize + title[1];
85
+ const prev = subtitles || title;
86
+ const titleEnd = prev[0].nodeSize + prev[1];
82
87
  const section = schema.nodes.alt_titles.create({}, [
83
88
  schema.nodes.alt_title.create({
84
89
  type: 'running',
@@ -17,6 +17,9 @@ import { isFootnoteNode, isGeneralTableFootnoteNode, isPullquoteElement, schema,
17
17
  import { Plugin, TextSelection } from 'prosemirror-state';
18
18
  import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils';
19
19
  import { Decoration, DecorationSet } from 'prosemirror-view';
20
+ const placeholderMap = {
21
+ subtitle: 'Type subtitle here...',
22
+ };
20
23
  const placeholderWidget = (placeholder) => (view, getPos) => {
21
24
  const element = document.createElement('span');
22
25
  element.className = 'placeholder-text';
@@ -85,8 +88,10 @@ export default () => new Plugin({
85
88
  decorations.push(Decoration.widget(pos + 1, placeholderWidget('Type new abstract title here')));
86
89
  }
87
90
  else {
91
+ const placeholder = placeholderMap[node.type.name];
88
92
  decorations.push(Decoration.node(pos, pos + node.nodeSize, {
89
93
  class: 'empty-node',
94
+ ...(placeholder && { 'data-placeholder': placeholder }),
90
95
  }));
91
96
  }
92
97
  }
@@ -1,2 +1,2 @@
1
- export const VERSION = '3.5.6';
1
+ export const VERSION = '3.5.8';
2
2
  export const MATHJAX_VERSION = '3.2.2';
@@ -13,6 +13,8 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { TextSelection } from 'prosemirror-state';
17
+ import { findChildrenByType } from 'prosemirror-utils';
16
18
  import { arrowDown } from '../icons';
17
19
  import { altTitlesKey } from '../plugins/alt-titles';
18
20
  import BlockView from './block_view';
@@ -42,6 +44,13 @@ export class AltTitleSectionView extends BlockView {
42
44
  const tr = this.view.state.tr.setMeta(altTitlesKey, {
43
45
  collapsed: true,
44
46
  });
47
+ const titleNode = findChildrenByType(this.view.state.doc, this.view.state.schema.nodes.title)[0];
48
+ const subtitleNode = findChildrenByType(this.view.state.doc, this.view.state.schema.nodes.subtitle)[0];
49
+ const prev = subtitleNode || titleNode;
50
+ if (prev) {
51
+ const titleEndPos = prev.pos + prev.node.nodeSize;
52
+ tr.setSelection(TextSelection.create(tr.doc, titleEndPos));
53
+ }
45
54
  this.view.dispatch(tr);
46
55
  });
47
56
  closingPanel.appendChild(button);
@@ -38,6 +38,7 @@ export const EditableBlock = (Base) => {
38
38
  const $pos = this.view.state.doc.resolve(this.getPos());
39
39
  const nodeType = this.node.type;
40
40
  if (nodeType === schema.nodes.hero_image ||
41
+ nodeType === schema.nodes.subtitles ||
41
42
  hasParent($pos, [
42
43
  schema.nodes.keywords,
43
44
  schema.nodes.bibliography_section,
@@ -0,0 +1,33 @@
1
+ /*!
2
+ * © 2025 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 { BaseNodeView } from './base_node_view';
17
+ import { createNodeView } from './creators';
18
+ export class SubtitleView extends BaseNodeView {
19
+ constructor() {
20
+ super(...arguments);
21
+ this.initialise = () => {
22
+ this.createDOM();
23
+ };
24
+ this.createDOM = () => {
25
+ this.dom = document.createElement('div');
26
+ this.dom.classList.add('manuscript-subtitle');
27
+ this.contentDOM = document.createElement('span');
28
+ this.dom.appendChild(this.contentDOM);
29
+ this.updateContents();
30
+ };
31
+ }
32
+ }
33
+ export default createNodeView(SubtitleView);
@@ -0,0 +1,18 @@
1
+ /*!
2
+ * © 2025 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 { createEditableNodeView } from './creators';
17
+ import { SubtitleView } from './subtitle';
18
+ export default createEditableNodeView(SubtitleView);
@@ -0,0 +1,28 @@
1
+ /*!
2
+ * © 2025 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 BlockView from './block_view';
17
+ import { createNodeView } from './creators';
18
+ export class SubtitlesView extends BlockView {
19
+ constructor() {
20
+ super(...arguments);
21
+ this.createElement = () => {
22
+ this.contentDOM = document.createElement('div');
23
+ this.contentDOM.classList.add('block');
24
+ this.dom.appendChild(this.contentDOM);
25
+ };
26
+ }
27
+ }
28
+ export default createNodeView(SubtitlesView);
@@ -0,0 +1,19 @@
1
+ /*!
2
+ * © 2025 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 { createEditableNodeView } from './creators';
17
+ import { EditableBlock } from './editable_block';
18
+ import { SubtitlesView } from './subtitles';
19
+ export default createEditableNodeView(EditableBlock(SubtitlesView));
@@ -84,3 +84,4 @@ export declare const autoComplete: (state: ManuscriptEditorState, dispatch?: Dis
84
84
  export declare const activateSearch: (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
85
85
  export declare const activateSearchReplace: (state: ManuscriptEditorState, dispatch?: Dispatch) => boolean;
86
86
  export declare const insertHeroImage: () => (state: ManuscriptEditorState, dispatch?: Dispatch, view?: EditorView) => boolean;
87
+ export declare const ignoreEnterInSubtitles: (state: ManuscriptEditorState) => boolean;
@@ -1,3 +1,4 @@
1
+ export declare const addAuthorIcon: string;
1
2
  export declare const arrowDown: string;
2
3
  export declare const arrowUp: string;
3
4
  export declare const alertIcon: string;
@@ -0,0 +1,18 @@
1
+ /*!
2
+ * © 2025 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 { Plugin } from 'prosemirror-state';
17
+ declare const _default: () => Plugin<null>;
18
+ export default _default;
@@ -1,8 +1,9 @@
1
- import { AltTitleNode, AltTitlesSectionNode, TitleNode } from '@manuscripts/transform';
1
+ import { AltTitleNode, AltTitlesSectionNode, SubtitlesNode, TitleNode } from '@manuscripts/transform';
2
2
  import { Plugin, PluginKey } from 'prosemirror-state';
3
3
  export interface PluginState {
4
4
  collapsed: boolean;
5
5
  title: [TitleNode, number] | undefined;
6
+ subtitles: [SubtitlesNode, number] | undefined;
6
7
  runningTitle: [AltTitleNode, number] | undefined;
7
8
  shortTitle: [AltTitleNode, number] | undefined;
8
9
  altTitlesSection: [AltTitlesSectionNode, number] | undefined;
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "3.5.6";
1
+ export declare const VERSION = "3.5.8";
2
2
  export declare const MATHJAX_VERSION = "3.2.2";
@@ -0,0 +1,24 @@
1
+ /*!
2
+ * © 2025 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 { ManuscriptNodeView, SubtitleNode } from '@manuscripts/transform';
17
+ import { BaseNodeView } from './base_node_view';
18
+ export declare class SubtitleView extends BaseNodeView<SubtitleNode> implements ManuscriptNodeView {
19
+ contentDOM: HTMLElement;
20
+ initialise: () => void;
21
+ protected createDOM: () => void;
22
+ }
23
+ declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<SubtitleView>;
24
+ export default _default;
@@ -0,0 +1,18 @@
1
+ /*!
2
+ * © 2025 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 { SubtitleView } from './subtitle';
17
+ declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<SubtitleView>;
18
+ export default _default;
@@ -0,0 +1,23 @@
1
+ /*!
2
+ * © 2025 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 { ManuscriptNodeView, SubtitlesNode } from '@manuscripts/transform';
17
+ import { Trackable } from '../types';
18
+ import BlockView from './block_view';
19
+ export declare class SubtitlesView extends BlockView<Trackable<SubtitlesNode>> implements ManuscriptNodeView {
20
+ createElement: () => void;
21
+ }
22
+ declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<SubtitlesView>;
23
+ export default _default;
@@ -0,0 +1,44 @@
1
+ /*!
2
+ * © 2025 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 { SubtitlesView } from './subtitles';
17
+ declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<{
18
+ gutterButtons(): HTMLElement[];
19
+ actionGutterButtons(): never[];
20
+ createAddButton(): HTMLAnchorElement | null;
21
+ createEditButton(): HTMLElement | null;
22
+ createMenu: () => import("../lib/context-menu").ContextMenu;
23
+ initialise(): void;
24
+ updateContents(): void;
25
+ handleTrackChanges(): void;
26
+ updateClasses(): void;
27
+ updatePlaceholder(): void;
28
+ createElement(): void;
29
+ createDOM(): void;
30
+ gutter: Record<string, HTMLElement>;
31
+ createGutter(className: string, buttons: HTMLElement[]): void;
32
+ dom: HTMLElement;
33
+ contentDOM?: HTMLElement;
34
+ elementType: string;
35
+ readonly props: import("../configs/ManuscriptsEditor").EditorProps;
36
+ node: import("prosemirror-model").Node;
37
+ readonly view: import("@manuscripts/transform").ManuscriptEditorView;
38
+ readonly getPos: () => number;
39
+ update(newNode: import("@manuscripts/transform").ManuscriptNode): boolean;
40
+ selectNode(): void;
41
+ deselectNode(): void;
42
+ destroy(): void;
43
+ } & SubtitlesView>;
44
+ export default _default;
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.6",
4
+ "version": "3.5.8",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -41,7 +41,7 @@
41
41
  "@manuscripts/json-schema": "2.2.12",
42
42
  "@manuscripts/style-guide": "3.3.0",
43
43
  "@manuscripts/track-changes-plugin": "2.0.12",
44
- "@manuscripts/transform": "4.2.15",
44
+ "@manuscripts/transform": "4.2.17",
45
45
  "@popperjs/core": "2.11.8",
46
46
  "citeproc": "2.4.63",
47
47
  "codemirror": "5.65.19",
@@ -520,6 +520,13 @@ ProseMirror .block-embed .position-menu {
520
520
  display: block;
521
521
  }
522
522
 
523
+ .block-subtitles .comment-marker {
524
+ top: 0;
525
+ left: -10px;
526
+ float: right;
527
+ position: relative;
528
+ }
529
+
523
530
  .block > div.comment-marker,
524
531
  .figure-block > div.comment-marker {
525
532
  top: -25px;
package/styles/Editor.css CHANGED
@@ -566,6 +566,22 @@
566
566
  color: #c9c9c9;
567
567
  margin: 0;
568
568
  }
569
+
570
+ .ProseMirror .add-subtitle {
571
+ display: inline-flex;
572
+ align-items: center;
573
+ cursor: pointer;
574
+ padding-left: var(--body-side-margin);
575
+ }
576
+
577
+ .ProseMirror .add-subtitle-text {
578
+ margin-left: 8px;
579
+ }
580
+
581
+ .ProseMirror .add-subtitle svg rect {
582
+ fill: #6E6E6E !important;
583
+ }
584
+
569
585
  .ProseMirror .empty-node:hover::before {
570
586
  color: #6e6e6e;
571
587
  }
@@ -589,6 +605,9 @@
589
605
 
590
606
  .ProseMirror .empty-node[data-placeholder]::before {
591
607
  content: attr(data-placeholder); /* TODO: innerHTML? */
608
+ color: #c9c9c9;
609
+ position: absolute;
610
+ pointer-events: none;
592
611
  }
593
612
 
594
613
  .ProseMirror table {
@@ -698,6 +717,9 @@
698
717
  .ProseMirror .block-paragraph .block-gutter {
699
718
  margin-top: 16px;
700
719
  }
720
+ .ProseMirror .block-subtitles .block-gutter {
721
+ margin-top: 4px;
722
+ }
701
723
 
702
724
  .ProseMirror
703
725
  .block-container:not(
@@ -1101,6 +1123,14 @@
1101
1123
  padding-left: var(--body-side-margin);
1102
1124
  padding-right: var(--body-side-margin);
1103
1125
  }
1126
+ .manuscript-subtitle {
1127
+ font-family: Lato;
1128
+ font-size: 24px;
1129
+ font-style: normal;
1130
+ font-weight: 400;
1131
+ line-height: 32px;
1132
+ align-items: center;
1133
+ }
1104
1134
  .highlight {
1105
1135
  background-color: #ffeebf !important;
1106
1136
  }