@manuscripts/body-editor 2.8.30 → 2.8.32

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.
@@ -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 affiliations_1 = __importDefault(require("../plugins/affiliations"));
30
+ const alt_titles_1 = __importDefault(require("../plugins/alt-titles"));
30
31
  const bibliography_1 = __importDefault(require("../plugins/bibliography"));
31
32
  const comments_1 = __importDefault(require("../plugins/comments"));
32
33
  const cross_references_1 = __importDefault(require("../plugins/cross-references"));
@@ -75,6 +76,7 @@ exports.default = (props) => {
75
76
  (0, section_category_1.default)(props),
76
77
  (0, cross_references_1.default)(),
77
78
  (0, search_replace_1.default)(),
79
+ (0, alt_titles_1.default)(),
78
80
  ];
79
81
  if (props.collabProvider) {
80
82
  allPlugins.push((0, prosemirror_collab_1.collab)({ version: props.collabProvider.currentVersion }));
@@ -1,24 +1,11 @@
1
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
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
18
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
4
  };
20
5
  Object.defineProperty(exports, "__esModule", { value: true });
21
6
  const affiliations_1 = __importDefault(require("../views/affiliations"));
7
+ const alt_title_1 = __importDefault(require("../views/alt_title"));
8
+ const alt_titles_section_1 = __importDefault(require("../views/alt_titles_section"));
22
9
  const author_notes_1 = __importDefault(require("../views/author_notes"));
23
10
  const award_1 = __importDefault(require("../views/award"));
24
11
  const awards_1 = __importDefault(require("../views/awards"));
@@ -58,7 +45,8 @@ const title_editable_1 = __importDefault(require("../views/title_editable"));
58
45
  exports.default = (props, dispatch) => {
59
46
  return {
60
47
  title: (0, title_editable_1.default)(props, dispatch),
61
- alt_title: (0, empty_1.default)('alt_title'),
48
+ alt_title: (0, alt_title_1.default)(props),
49
+ alt_titles: (0, alt_titles_section_1.default)(props),
62
50
  bibliography_element: (0, bibliography_element_1.default)(props, dispatch),
63
51
  blockquote_element: (0, blockquote_element_editable_1.default)(props),
64
52
  box_element: (0, box_element_1.default)(props),
package/dist/cjs/icons.js CHANGED
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.scrollIcon = exports.sectionCategoryIcon = exports.editIcon = exports.deleteIcon = exports.alertIcon = void 0;
3
+ exports.scrollIcon = exports.sectionCategoryIcon = exports.editIcon = exports.deleteIcon = exports.alertIcon = exports.arrowDown = 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.arrowDown = renderIcon(style_guide_1.ArrowDownCircleIcon);
8
9
  exports.alertIcon = renderIcon(style_guide_1.AlertIcon);
9
10
  exports.deleteIcon = renderIcon(style_guide_1.DeleteIcon);
10
11
  exports.editIcon = (0, server_1.renderToStaticMarkup)((0, react_1.createElement)(style_guide_1.EditIcon));
@@ -28,8 +28,8 @@ const title_1 = __importDefault(require("./title"));
28
28
  exports.default = [
29
29
  (0, prosemirror_keymap_1.keymap)(keyword_1.default),
30
30
  (0, prosemirror_keymap_1.keymap)(list_1.default),
31
- (0, prosemirror_keymap_1.keymap)(misc_1.default),
32
31
  (0, prosemirror_keymap_1.keymap)(title_1.default),
32
+ (0, prosemirror_keymap_1.keymap)(misc_1.default),
33
33
  (0, prosemirror_keymap_1.keymap)(prosemirror_commands_1.baseKeymap),
34
34
  (0, prosemirror_keymap_1.keymap)(highlight_1.default),
35
35
  ];
@@ -70,7 +70,7 @@ const exitBlock = (direction) => (state, dispatch) => {
70
70
  }
71
71
  return true;
72
72
  };
73
- const leaveSectionTitle = (state, dispatch, view) => {
73
+ const leaveTitle = (state, dispatch, view) => {
74
74
  const { selection } = state;
75
75
  if (!(0, commands_1.isTextSelection)(selection)) {
76
76
  return false;
@@ -79,9 +79,17 @@ const leaveSectionTitle = (state, dispatch, view) => {
79
79
  if (!$cursor) {
80
80
  return false;
81
81
  }
82
- if ($cursor.parent.type !== $cursor.parent.type.schema.nodes.section_title) {
82
+ const titleTypes = [
83
+ transform_1.schema.nodes.alt_title,
84
+ transform_1.schema.nodes.section_title,
85
+ transform_1.schema.nodes.title,
86
+ ];
87
+ if (!titleTypes.includes($cursor.parent.type)) {
83
88
  return false;
84
89
  }
90
+ if ($cursor.parent.type === transform_1.schema.nodes.alt_title) {
91
+ return true;
92
+ }
85
93
  if ((0, transform_1.isInGraphicalAbstractSection)($cursor)) {
86
94
  return false;
87
95
  }
@@ -97,7 +105,7 @@ const leaveFigcaption = (state) => {
97
105
  const { selection: { $anchor }, } = state;
98
106
  return $anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title;
99
107
  };
100
- const protectSectionTitle = (state, dispatch, view) => {
108
+ const protectTitles = (state, dispatch, view) => {
101
109
  const { selection } = state;
102
110
  if (!(0, commands_1.isTextSelection)(selection)) {
103
111
  return false;
@@ -106,6 +114,10 @@ const protectSectionTitle = (state, dispatch, view) => {
106
114
  if (!$cursor) {
107
115
  return false;
108
116
  }
117
+ if ($cursor.parent.type === transform_1.schema.nodes.alt_title &&
118
+ $cursor.pos === $cursor.before() + 1) {
119
+ return true;
120
+ }
109
121
  return ($cursor.parent.type === $cursor.parent.type.schema.nodes.section_title &&
110
122
  (0, commands_1.isAtStartOfTextBlock)(state, $cursor, view));
111
123
  };
@@ -139,8 +151,8 @@ const keepCaption = (state) => {
139
151
  $anchor.parent.content.size === 0);
140
152
  };
141
153
  const titleKeymap = {
142
- Backspace: (0, prosemirror_commands_1.chainCommands)(protectSectionTitle, exports.protectReferencesTitle, protectCaption),
143
- Enter: (0, prosemirror_commands_1.chainCommands)(leaveSectionTitle, leaveFigcaption),
154
+ Backspace: (0, prosemirror_commands_1.chainCommands)(protectTitles, exports.protectReferencesTitle, protectCaption),
155
+ Enter: (0, prosemirror_commands_1.chainCommands)(leaveTitle, leaveFigcaption),
144
156
  Tab: exitBlock(1),
145
157
  Delete: (0, prosemirror_commands_1.chainCommands)(keepCaption, exports.protectReferencesTitle),
146
158
  'Shift-Tab': exitBlock(-1),
@@ -72,7 +72,7 @@ const handleScrollToSelectedTarget = (view) => {
72
72
  }
73
73
  target = node;
74
74
  }
75
- if (!target) {
75
+ if (!target || !(target instanceof HTMLElement)) {
76
76
  return false;
77
77
  }
78
78
  const blockAlignment = node.type === transform_1.schema.nodes.bibliography_item ? 'center' : 'start';
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.altTitlesKey = void 0;
4
+ const transform_1 = require("@manuscripts/transform");
5
+ const prosemirror_state_1 = require("prosemirror-state");
6
+ const prosemirror_view_1 = require("prosemirror-view");
7
+ const icons_1 = require("../icons");
8
+ const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
9
+ function getTitlesData(doc) {
10
+ let title;
11
+ let runningTitle;
12
+ let shortTitle;
13
+ let altTitlesSection;
14
+ doc.descendants((node, pos) => {
15
+ if (title && runningTitle && shortTitle && altTitlesSection) {
16
+ return false;
17
+ }
18
+ if (node.type === transform_1.schema.nodes.title) {
19
+ title = [node, pos];
20
+ }
21
+ if (node.type === transform_1.schema.nodes.alt_titles) {
22
+ altTitlesSection = [node, pos];
23
+ }
24
+ if (node.type === transform_1.schema.nodes.alt_title) {
25
+ if (node.attrs.type === 'running') {
26
+ runningTitle = [node, pos];
27
+ }
28
+ if (node.attrs.type === 'short') {
29
+ shortTitle = [node, pos];
30
+ }
31
+ }
32
+ });
33
+ return { title, runningTitle, shortTitle, altTitlesSection };
34
+ }
35
+ function createAltTitlesButton(listener) {
36
+ const altTitlesButton = document.createElement('button');
37
+ altTitlesButton.classList.add('alt-titles-open', 'button-reset');
38
+ altTitlesButton.innerHTML = icons_1.arrowDown;
39
+ altTitlesButton.addEventListener('click', (e) => {
40
+ e.preventDefault();
41
+ listener();
42
+ });
43
+ return altTitlesButton;
44
+ }
45
+ function selectionInAltTitles(from, to, state) {
46
+ if (state.runningTitle && state.shortTitle) {
47
+ const range = {
48
+ from: Math.min(state.runningTitle[1], state.shortTitle[1]),
49
+ to: Math.max(state.runningTitle[1] + state.runningTitle[0].nodeSize, state.shortTitle[1] + state.shortTitle[0].nodeSize),
50
+ };
51
+ return Math.max(from, range.from) <= Math.min(to, range.to);
52
+ }
53
+ return false;
54
+ }
55
+ exports.altTitlesKey = new prosemirror_state_1.PluginKey('altTitles');
56
+ exports.default = () => {
57
+ return new prosemirror_state_1.Plugin({
58
+ key: exports.altTitlesKey,
59
+ state: {
60
+ init: (_, state) => {
61
+ return Object.assign({ collapsed: true }, getTitlesData(state.doc));
62
+ },
63
+ apply: (tr, value) => {
64
+ let newState = value;
65
+ if (tr.docChanged) {
66
+ newState = Object.assign(Object.assign({}, newState), getTitlesData(tr.doc));
67
+ }
68
+ if (tr.selectionSet &&
69
+ selectionInAltTitles(tr.selection.from, tr.selection.to, newState)) {
70
+ newState = Object.assign(Object.assign({}, newState), { collapsed: false });
71
+ }
72
+ if (tr.getMeta(exports.altTitlesKey)) {
73
+ newState = Object.assign(Object.assign(Object.assign({}, newState), tr.getMeta(exports.altTitlesKey)), getTitlesData(tr.doc));
74
+ }
75
+ return newState;
76
+ },
77
+ },
78
+ appendTransaction: (transactions, _, newState) => {
79
+ let tr = newState.tr;
80
+ if (!transactions.some((tr) => tr.getMeta(exports.altTitlesKey)) ||
81
+ !exports.altTitlesKey.getState(newState)) {
82
+ return null;
83
+ }
84
+ const { title, runningTitle, shortTitle, altTitlesSection } = exports.altTitlesKey.getState(newState);
85
+ const schema = newState.schema;
86
+ if (!title) {
87
+ return null;
88
+ }
89
+ if (!altTitlesSection) {
90
+ const titleEnd = title[0].nodeSize + title[1];
91
+ const section = schema.nodes.alt_titles.create({}, [
92
+ schema.nodes.alt_title.create({
93
+ type: 'running',
94
+ }),
95
+ schema.nodes.alt_title.create({ type: 'short' }),
96
+ ]);
97
+ tr.insert(titleEnd, section);
98
+ }
99
+ else {
100
+ const endPos = altTitlesSection[1] + altTitlesSection[0].nodeSize - 1;
101
+ if (!runningTitle) {
102
+ const title = schema.nodes.alt_title.create({
103
+ type: 'running',
104
+ });
105
+ tr.insert(endPos, title);
106
+ }
107
+ if (!shortTitle) {
108
+ const title = schema.nodes.alt_title.create({ type: 'short' });
109
+ const newPos = tr.mapping.map(endPos);
110
+ tr.insert(newPos, title);
111
+ }
112
+ }
113
+ if (tr.docChanged) {
114
+ return tr.setMeta(exports.altTitlesKey, 'created-missing-titles');
115
+ }
116
+ else {
117
+ return null;
118
+ }
119
+ },
120
+ props: {
121
+ decorations: (state) => {
122
+ const decorations = [];
123
+ const pState = exports.altTitlesKey.getState(state);
124
+ if (!pState || !pState.title) {
125
+ return prosemirror_view_1.DecorationSet.empty;
126
+ }
127
+ if (!pState.collapsed) {
128
+ state.doc.descendants((node, pos) => {
129
+ if (node.type === state.schema.nodes.alt_titles) {
130
+ decorations.push(prosemirror_view_1.Decoration.node(pos, pos + node.nodeSize, {
131
+ class: 'alt-titles-section-open',
132
+ }));
133
+ }
134
+ });
135
+ }
136
+ else if (pState.title[0].textContent.length) {
137
+ const titleEnd = pState.title[0].nodeSize + pState.title[1];
138
+ decorations.push(prosemirror_view_1.Decoration.widget(titleEnd - 1, (view) => {
139
+ return createAltTitlesButton(() => {
140
+ const tr = view.state.tr.setMeta(exports.altTitlesKey, {
141
+ collapsed: false,
142
+ });
143
+ view.dispatch((0, track_changes_plugin_1.skipTracking)(tr));
144
+ });
145
+ }, {
146
+ side: -1,
147
+ key: 'title-' + titleEnd,
148
+ }));
149
+ }
150
+ return prosemirror_view_1.DecorationSet.create(state.doc, decorations);
151
+ },
152
+ },
153
+ });
154
+ };
@@ -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.8.30';
4
+ exports.VERSION = '2.8.32';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -0,0 +1,44 @@
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.AltTitleView = void 0;
19
+ const base_node_view_1 = require("./base_node_view");
20
+ const creators_1 = require("./creators");
21
+ class AltTitleView 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-alt-title');
30
+ const label = document.createElement('div');
31
+ label.classList.add('alt-title-label');
32
+ label.innerHTML = this.node.attrs.type + ' title';
33
+ label.contentEditable = 'false';
34
+ this.dom.setAttribute('data-type', this.node.attrs.type);
35
+ this.contentDOM = document.createElement('div');
36
+ this.contentDOM.classList.add('alt-title-text');
37
+ this.dom.appendChild(label);
38
+ this.dom.appendChild(this.contentDOM);
39
+ this.updateContents();
40
+ };
41
+ }
42
+ }
43
+ exports.AltTitleView = AltTitleView;
44
+ exports.default = (0, creators_1.createNodeView)(AltTitleView);
@@ -0,0 +1,58 @@
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
+ 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.AltTitleSectionView = void 0;
22
+ const icons_1 = require("../icons");
23
+ const alt_titles_1 = require("../plugins/alt-titles");
24
+ const block_view_1 = __importDefault(require("./block_view"));
25
+ const creators_1 = require("./creators");
26
+ class AltTitleSectionView extends block_view_1.default {
27
+ constructor() {
28
+ super(...arguments);
29
+ this.ignoreMutation = () => true;
30
+ this.createElement = () => {
31
+ this.container = document.createElement('div');
32
+ this.container.classList.add('block');
33
+ this.dom.appendChild(this.container);
34
+ this.contentDOM = document.createElement('div');
35
+ this.contentDOM.classList.add('alt-titles-section');
36
+ this.contentDOM.setAttribute('id', this.node.attrs.id);
37
+ this.container.appendChild(this.contentDOM);
38
+ this.container.appendChild(this.createClosingPanel());
39
+ };
40
+ }
41
+ createClosingPanel() {
42
+ const closingPanel = document.createElement('div');
43
+ closingPanel.classList.add('alt-titles-closing-panel');
44
+ const button = document.createElement('button');
45
+ button.classList.add('alt-titles-closing-button', 'button-reset');
46
+ button.innerHTML = icons_1.arrowDown;
47
+ button.addEventListener('click', () => {
48
+ const tr = this.view.state.tr.setMeta(alt_titles_1.altTitlesKey, {
49
+ collapsed: true,
50
+ });
51
+ this.view.dispatch(tr);
52
+ });
53
+ closingPanel.appendChild(button);
54
+ return closingPanel;
55
+ }
56
+ }
57
+ exports.AltTitleSectionView = AltTitleSectionView;
58
+ exports.default = (0, creators_1.createNodeView)(AltTitleSectionView);
@@ -34,6 +34,7 @@ class TitleView extends base_node_view_1.BaseNodeView {
34
34
  this.contentDOM.setAttribute('data-placeholder', attrs.placeholder);
35
35
  }
36
36
  this.dom.appendChild(this.contentDOM);
37
+ this.updateContents();
37
38
  };
38
39
  }
39
40
  }
@@ -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 affiliations from '../plugins/affiliations';
25
+ import alt_titles from '../plugins/alt-titles';
25
26
  import bibliography from '../plugins/bibliography';
26
27
  import comments from '../plugins/comments';
27
28
  import cross_references from '../plugins/cross-references';
@@ -70,6 +71,7 @@ export default (props) => {
70
71
  section_category(props),
71
72
  cross_references(),
72
73
  search_replace(),
74
+ alt_titles(),
73
75
  ];
74
76
  if (props.collabProvider) {
75
77
  allPlugins.push(collab({ version: props.collabProvider.currentVersion }));
@@ -1,19 +1,6 @@
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
1
  import affiliations from '../views/affiliations';
2
+ import alt_title from '../views/alt_title';
3
+ import alt_titles_section from '../views/alt_titles_section';
17
4
  import authorNotes from '../views/author_notes';
18
5
  import award from '../views/award';
19
6
  import awards from '../views/awards';
@@ -53,7 +40,8 @@ import title from '../views/title_editable';
53
40
  export default (props, dispatch) => {
54
41
  return {
55
42
  title: title(props, dispatch),
56
- alt_title: empty('alt_title'),
43
+ alt_title: alt_title(props),
44
+ alt_titles: alt_titles_section(props),
57
45
  bibliography_element: bibliographyElement(props, dispatch),
58
46
  blockquote_element: blockquoteElement(props),
59
47
  box_element: boxElement(props),
package/dist/es/icons.js CHANGED
@@ -1,7 +1,8 @@
1
- import { AlertIcon, DeleteIcon, EditIcon, ScrollIcon, SectionCategoryIcon, } from '@manuscripts/style-guide';
1
+ import { AlertIcon, ArrowDownCircleIcon, DeleteIcon, EditIcon, ScrollIcon, SectionCategoryIcon, } 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 arrowDown = renderIcon(ArrowDownCircleIcon);
5
6
  export const alertIcon = renderIcon(AlertIcon);
6
7
  export const deleteIcon = renderIcon(DeleteIcon);
7
8
  export const editIcon = renderToStaticMarkup(createElement(EditIcon));
@@ -23,8 +23,8 @@ import titleKeymap from './title';
23
23
  export default [
24
24
  keymap(keywordKeymap),
25
25
  keymap(listKeymap),
26
- keymap(miscKeymap),
27
26
  keymap(titleKeymap),
27
+ keymap(miscKeymap),
28
28
  keymap(baseKeymap),
29
29
  keymap(highlightKeymap),
30
30
  ];
@@ -67,7 +67,7 @@ const exitBlock = (direction) => (state, dispatch) => {
67
67
  }
68
68
  return true;
69
69
  };
70
- const leaveSectionTitle = (state, dispatch, view) => {
70
+ const leaveTitle = (state, dispatch, view) => {
71
71
  const { selection } = state;
72
72
  if (!isTextSelection(selection)) {
73
73
  return false;
@@ -76,9 +76,17 @@ const leaveSectionTitle = (state, dispatch, view) => {
76
76
  if (!$cursor) {
77
77
  return false;
78
78
  }
79
- if ($cursor.parent.type !== $cursor.parent.type.schema.nodes.section_title) {
79
+ const titleTypes = [
80
+ schema.nodes.alt_title,
81
+ schema.nodes.section_title,
82
+ schema.nodes.title,
83
+ ];
84
+ if (!titleTypes.includes($cursor.parent.type)) {
80
85
  return false;
81
86
  }
87
+ if ($cursor.parent.type === schema.nodes.alt_title) {
88
+ return true;
89
+ }
82
90
  if (isInGraphicalAbstractSection($cursor)) {
83
91
  return false;
84
92
  }
@@ -94,7 +102,7 @@ const leaveFigcaption = (state) => {
94
102
  const { selection: { $anchor }, } = state;
95
103
  return $anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title;
96
104
  };
97
- const protectSectionTitle = (state, dispatch, view) => {
105
+ const protectTitles = (state, dispatch, view) => {
98
106
  const { selection } = state;
99
107
  if (!isTextSelection(selection)) {
100
108
  return false;
@@ -103,6 +111,10 @@ const protectSectionTitle = (state, dispatch, view) => {
103
111
  if (!$cursor) {
104
112
  return false;
105
113
  }
114
+ if ($cursor.parent.type === schema.nodes.alt_title &&
115
+ $cursor.pos === $cursor.before() + 1) {
116
+ return true;
117
+ }
106
118
  return ($cursor.parent.type === $cursor.parent.type.schema.nodes.section_title &&
107
119
  isAtStartOfTextBlock(state, $cursor, view));
108
120
  };
@@ -135,8 +147,8 @@ const keepCaption = (state) => {
135
147
  $anchor.parent.content.size === 0);
136
148
  };
137
149
  const titleKeymap = {
138
- Backspace: chainCommands(protectSectionTitle, protectReferencesTitle, protectCaption),
139
- Enter: chainCommands(leaveSectionTitle, leaveFigcaption),
150
+ Backspace: chainCommands(protectTitles, protectReferencesTitle, protectCaption),
151
+ Enter: chainCommands(leaveTitle, leaveFigcaption),
140
152
  Tab: exitBlock(1),
141
153
  Delete: chainCommands(keepCaption, protectReferencesTitle),
142
154
  'Shift-Tab': exitBlock(-1),
@@ -66,7 +66,7 @@ export const handleScrollToSelectedTarget = (view) => {
66
66
  }
67
67
  target = node;
68
68
  }
69
- if (!target) {
69
+ if (!target || !(target instanceof HTMLElement)) {
70
70
  return false;
71
71
  }
72
72
  const blockAlignment = node.type === schema.nodes.bibliography_item ? 'center' : 'start';