diff --git a/src/lib/editor/extensions/tableOfContents.ts b/src/lib/editor/extensions/tableOfContents.ts
index 8e6c794..046aa79 100644
--- a/src/lib/editor/extensions/tableOfContents.ts
+++ b/src/lib/editor/extensions/tableOfContents.ts
@@ -156,7 +156,11 @@ class TocView {
const out: HeadingRef[] = [];
this.editor.state.doc.descendants((node, pos) => {
if (node.type.name === 'heading') {
- const text = node.textContent.trim();
+ // A hard break inside the heading is a line of the entry too — a book's
+ // "Chapter 1" / title pair is two lines in LibreOffice's own index.
+ let raw = '';
+ node.forEach((child) => { raw += child.type.name === 'hardBreak' ? '\n' : child.textContent; });
+ const text = raw.trim();
const level = Math.min(MAX_HEADING_LEVEL, (node.attrs.level as number) ?? 1);
if (text && level <= max) out.push({ text, level, pos });
}
@@ -246,7 +250,10 @@ class TocView {
if (levelStyle) row.dataset.style = levelStyle;
const text = document.createElement('span');
text.className = 'toc-text';
- text.textContent = e.text;
+ e.text.split('\n').forEach((part, li) => {
+ if (li) text.appendChild(document.createElement('br'));
+ text.appendChild(document.createTextNode(part));
+ });
const leader = document.createElement('span');
leader.className = 'toc-leader';
// Real fill characters, as a word processor draws them: they scale with the font
diff --git a/src/lib/export/odt.ts b/src/lib/export/odt.ts
index e6f1f51..8a00299 100644
--- a/src/lib/export/odt.ts
+++ b/src/lib/export/odt.ts
@@ -3268,7 +3268,7 @@ function tocXml(toc: TocExport, index: number): string {
``
: '') +
toc.entries
- .map(e => `${escapeXml(e.text)}${e.page}`)
+ .map(e => `${escapeXml(e.text).replace(/\n/g, '')}${e.page}`)
.join('') +
``;
return `${source}${body}`;
diff --git a/src/styles/editor.css b/src/styles/editor.css
index 8597464..062f211 100644
--- a/src/styles/editor.css
+++ b/src/styles/editor.css
@@ -225,7 +225,9 @@
}
.paper .tiptap .toc-entry {
display: flex;
- align-items: baseline;
+ /* The last one: an entry whose heading carries a hard break is several lines, and the
+ leader and page number belong beside the last of them. */
+ align-items: last baseline;
cursor: pointer;
}
.paper .tiptap .toc-entry:hover .toc-text {