263 lines
No EOL
9.8 KiB
JavaScript
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');
|
|
}
|
|
} |