walter-boente_book-collection/js/beforeAll.js
2026-04-22 10:43:53 +02:00

263 lines
No EOL
9.8 KiB
JavaScript

import { Handler } from '/csspageweaver/lib/paged.esm.js';
export default class beforeAll extends Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
}
beforeParsed(content){
listAbbr(content);
numParagraph(content);
thesis(content);
wrapChapterAndIntro(content);
}
afterPageLayout(pageElement, page, breakToken){
let intro = pageElement.querySelector('.intro');
let pageContent = pageElement.querySelector('.pagedjs_page_content');
if(intro && pageContent){
let introBottom = intro.getBoundingClientRect().bottom;
let pageContentBottom = pageContent.getBoundingClientRect().bottom;
let gap = pageContentBottom - introBottom;
gap = gap - 4; // snap on baseline
intro.style.paddingTop = gap + "px";
}
let thesisList = pageElement.querySelectorAll('.thesis');
if(thesisList.length > 0 && pageContent){
let lastThesis = thesisList[thesisList.length - 1];
let firstThesis = thesisList[0];
let lastThesisBottom = lastThesis.getBoundingClientRect().bottom;
let pageContentBottom = pageContent.getBoundingClientRect().bottom;
let gap = pageContentBottom - lastThesisBottom;
gap = gap - 4; // snap on baseline
firstThesis.style.marginTop = gap + "px";
}
}
}
function listAbbr(content){
const h1s = content.querySelectorAll('h1');
let abbrH1 = null;
h1s.forEach(h1 => {
if (h1.textContent.trim().includes('Abkürzungsverzeichnis')) {
abbrH1 = h1;
}
});
if (!abbrH1) return;
const sectionContent = content.querySelector('#section__content');
if (!sectionContent || !sectionContent.contains(abbrH1)) return;
// Collect h1 and all following siblings until next h1
const elements = [abbrH1];
let next = abbrH1.nextElementSibling;
while (next && next.tagName.toLowerCase() !== 'h1') {
elements.push(next);
next = next.nextElementSibling;
}
// Create section and move elements into it
const section = document.createElement('section');
section.id = 'list-of-abbr';
elements.forEach(el => section.appendChild(el));
// content is the DocumentFragment; insert #list-of-abbr before #section__content
content.insertBefore(section, sectionContent);
}
function numParagraph(content){
let numParagraphs = content.querySelectorAll('ol[type="1"]');
numParagraphs.forEach(function (num, index) {
let start = num.getAttribute('start');
num.querySelector('li').innerHTML = start;
});
}
function wrapChapterAndIntro(content){
// Wrap h1 and following content in .chapter sections
const sectionContent = content.querySelector('#section__content');
if (sectionContent) {
const h1s = sectionContent.querySelectorAll(':scope > h1');
h1s.forEach(h1 => {
// Create chapter section
const chapter = document.createElement('section');
chapter.classList.add('chapter');
// Insert chapter before h1
h1.parentNode.insertBefore(chapter, h1);
// Move h1 into chapter
chapter.appendChild(h1);
// Move following siblings until next h1 or end
let nextElement = chapter.nextElementSibling;
while (nextElement && nextElement.tagName.toLowerCase() !== 'h1') {
const current = nextElement;
nextElement = nextElement.nextElementSibling;
chapter.appendChild(current);
}
let divEnd = document.createElement('div');
divEnd.classList.add("chapter-end"); // need to avoid to add new page
chapter.appendChild(divEnd);
});
// Wrap content between h1 and h2 in .intro if chapter doesn't contain .thesis
const chapters = sectionContent.querySelectorAll('.chapter');
chapters.forEach(chapter => {
if (chapter.querySelector('.thesis')) {
// Case 1: Chapter has thesis
chapter.classList.add('has-thesis');
} else {
const h1 = chapter.querySelector('h1');
if (h1) {
// Calculate chapter content length excluding notes
const chapterClone = chapter.cloneNode(true);
// Remove notes (common note selectors)
chapterClone.querySelectorAll('.note, .footnote, .sidenote, aside, [role="note"]').forEach(note => note.remove());
const contentLength = chapterClone.textContent.trim().length;
const intro = document.createElement('div');
intro.classList.add('intro');
if (contentLength < 5000) {
// Case 2: Short chapter, wrap all content after h1
h1.parentNode.insertBefore(intro, h1.nextSibling);
let current = intro.nextSibling;
while (current) {
const next = current.nextSibling;
intro.appendChild(current);
current = next;
}
chapter.classList.add('has-only-intro');
} else {
const nextHeading = chapter.querySelector('h2, h3, h4, h5, h6');
if (nextHeading) {
// Case 3: Has heading, wrap all content between h1 and that heading
h1.parentNode.insertBefore(intro, h1.nextSibling);
let current = intro.nextSibling;
while (current && current !== nextHeading) {
const next = current.nextSibling;
intro.appendChild(current);
current = next;
}
chapter.classList.add('has-intro');
} else {
// Case 4: No heading, wrap first ol[type="1"] and first p after h1
h1.parentNode.insertBefore(intro, h1.nextSibling);
let foundOl = false;
let foundP = false;
let current = intro.nextSibling;
while (current && (!foundOl || !foundP)) {
const next = current.nextSibling;
// Skip text nodes (whitespace)
if (current.nodeType !== 1) {
current = next;
continue;
}
const isOlType1 = current.tagName.toLowerCase() === 'ol' && current.getAttribute('type') === '1';
const isP = current.tagName.toLowerCase() === 'p';
if (isOlType1 && !foundOl) {
intro.appendChild(current);
foundOl = true;
current = next;
} else if (isP && !foundP) {
intro.appendChild(current);
foundP = true;
current = next;
} else if (!isOlType1 && !isP) {
break;
} else {
current = next;
}
}
if (intro.children.length > 0) {
chapter.classList.add('has-intro-1-paragraph');
}
}
}
}
}
});
}
}
function thesis(content){
const strongs = content.querySelectorAll('strong');
const thesisElements = [];
strongs.forEach(strong => {
if (/^these\s+\d+/i.test(strong.textContent.trim())) {
const parent = strong.closest('p');
if (parent) {
// Create thesis wrapper
const thesisWrapper = document.createElement('div');
thesisWrapper.classList.add('thesis');
// Find preceding ol if it exists
let prev = parent.previousElementSibling;
let olElement = null;
if (prev && prev.tagName.toLowerCase() === 'ol') {
olElement = prev;
}
// Insert thesis wrapper before ol or before p
if (olElement) {
olElement.parentNode.insertBefore(thesisWrapper, olElement);
thesisWrapper.appendChild(olElement);
} else {
parent.parentNode.insertBefore(thesisWrapper, parent);
}
// Create thesis-title
const thesisTitleDiv = document.createElement('div');
thesisTitleDiv.classList.add('thesis-title');
const thesisP = document.createElement('p');
thesisP.textContent = strong.textContent;
var line = document.createElement('div');
line.classList.add('thesis-line');
thesisTitleDiv.appendChild(thesisP);
thesisTitleDiv.appendChild(line)
thesisWrapper.appendChild(thesisTitleDiv);
// Transform parent p into thesis-content
strong.remove();
parent.classList.add('thesis-content');
thesisWrapper.appendChild(parent);
thesisElements.push(thesisWrapper);
}
}
});
// Mark first and last thesis
if (thesisElements.length > 0) {
thesisElements[0].classList.add('thesis-first');
thesisElements[thesisElements.length - 1].classList.add('thesis-last');
}
}