feat: the index reads like the one a word processor generates
Its leader is real dots now, not a border, so it scales with the font and reaches the PDF as text. Title and entries follow the document's Heading 1 and default style, which is what the index styles of Word and LO are based on.
This commit is contained in:
1 parent
34c529e3c4
commit
5549d625f7
3 files changed
+14
-6
No files matched your search
@@ -16,6 +16,8 @@ const FALLBACK_PAGE_HEIGHT = 1123;
|
||||
// The heading above the entries. An imported TOC keeps the one its file used
|
||||
// ("Inhalt", "Sommaire", …); a freshly inserted one takes this.
|
||||
const TITLE = 'Table of Contents';
|
||||
// Enough leader dots to cross the widest gap a page can offer; the row clips the rest.
|
||||
const LEADER_DOTS = 200;
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
interface Commands<ReturnType> {
|
||||
@@ -183,6 +185,9 @@ class TocView {
|
||||
text.textContent = e.text;
|
||||
const leader = document.createElement('span');
|
||||
leader.className = 'toc-leader';
|
||||
// Real dots, as a word processor fills the gap: they scale with the font and
|
||||
// reach the PDF as text. The row clips whatever the gap has no room for.
|
||||
leader.textContent = '.'.repeat(LEADER_DOTS);
|
||||
const page = document.createElement('span');
|
||||
page.className = 'toc-page';
|
||||
page.textContent = String(e.page);
|
||||
|
||||
@@ -270,7 +270,10 @@ export function styleCss(sheet: StyleSheet): string {
|
||||
const attr = `[data-style="${style.name.replace(/"/g, '\\"')}"]`;
|
||||
const selectors = [`.paper .tiptap ${attr}`];
|
||||
if (style.outlineLevel) selectors.push(`.paper .tiptap h${style.outlineLevel}:not([data-style])`);
|
||||
if (style.name === DEFAULT_STYLE) selectors.push('.paper .tiptap p:not([data-style])');
|
||||
if (style.outlineLevel === 1) selectors.push('.paper .tiptap .toc-title'); // the index heads its list like any chapter
|
||||
// The generated index carries no style name, and a word processor bases its own
|
||||
// index styles on the default one — so it follows the document's body text.
|
||||
if (style.name === DEFAULT_STYLE) selectors.push('.paper .tiptap p:not([data-style])', '.paper .tiptap .toc');
|
||||
rules.push(`${selectors.join(',\n')} {\n ${decls.join(';\n ')};\n}`);
|
||||
|
||||
// A list marker inherits the item's own font, never its paragraph's, so the item
|
||||
|
||||
@@ -214,13 +214,13 @@
|
||||
text-overflow: ellipsis;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
/* Dotted leader filling the gap; nudged up to sit on the text baseline. */
|
||||
/* Leader dots filling the gap: the row grants the span the space that is left and
|
||||
clips the dots that do not fit, so the page number stays put. */
|
||||
.paper .tiptap .toc-leader {
|
||||
flex: 1 1 auto;
|
||||
flex: 1 1 0; /* basis 0: the dots are decoration, they must not size the row */
|
||||
min-width: 1em;
|
||||
margin: 0 4px;
|
||||
border-bottom: 1px dotted currentColor;
|
||||
transform: translateY(-0.25em);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.paper .tiptap .toc-page {
|
||||
flex: 0 0 auto;
|
||||
|
||||
Reference in new issue
Block a user