4,456
edits
No edit summary |
No edit summary |
||
Line 1,370: | Line 1,370: | ||
// Remove “empty” optional sections so they don’t leave gaps in print. | // Remove “empty” optional sections so they don’t leave gaps in print. | ||
// | // --- PRUNE EMPTY PRINT SECTIONS (ES5-safe) --- | ||
var | (function () { | ||
var content = doc.getElementById("article-content"); | |||
if (!content) return; | |||
// Remove pure-whitespace text nodes so :empty checks can work | |||
function stripWhitespaceTextNodes(node) { | |||
var i, child; | |||
for (i = node.childNodes.length - 1; i >= 0; i--) { | |||
child = node.childNodes[i]; | |||
if ( | |||
child.nodeType === 3 && | |||
(!child.nodeValue || | |||
child.nodeValue.replace(/\u00a0/g, " ").trim() === "") | |||
) { | |||
" | node.removeChild(child); | ||
} else if (child.nodeType === 1) { | |||
" | stripWhitespaceTextNodes(child); | ||
} | |||
} | |||
" | } | ||
stripWhitespaceTextNodes(content); | |||
function isEffectivelyEmpty(el) { | |||
if (!el) return true; | |||
// images make it non-empty | |||
if (el.getElementsByTagName("img").length) return false; | |||
// ignore <br> | |||
var brs = el.getElementsByTagName("br"); | |||
while (brs.length) brs[0].parentNode.removeChild(brs[0]); | |||
var txt = (el.textContent || "").replace(/\u00a0/g, " ").trim(); | |||
return txt.length === 0; | |||
} | |||
function rm(el) { | |||
if (el && el.parentNode) el.parentNode.removeChild(el); | |||
} | |||
// Label/content pairs to prune together | |||
var PAIRS = [ | |||
["article-label-description", "article-description"], | |||
["article-label-reflection", "article-reflection"], | |||
["article-label-external-reference", "article-external-reference"], | |||
["article-label-quote", "article-quote"], | |||
["article-label-modification-date", "article-modification-date"], | |||
]; | |||
// Remove empty metadata columns, then whole metadata if all empty | |||
(function pruneMetadata() { | |||
var meta = content.querySelector(".article-metadata"); | |||
if (!meta) return; | |||
var cols = meta.querySelectorAll(".article-metadata-column"); | |||
var nonEmptyCols = 0; | |||
for (var i = 0; i < cols.length; i++) { | |||
var val = cols[i].querySelector(".article-metadata-value"); | |||
if (isEffectivelyEmpty(val)) { | |||
rm(cols[i]); | |||
} else { | |||
nonEmptyCols++; | |||
} | |||
} | |||
if (!nonEmptyCols) rm(meta); | |||
})(); | |||
// Prune each label/content pair if content is empty (or missing) | |||
for (var i = 0; i < PAIRS.length; i++) { | |||
var label = content.querySelector("." + PAIRS[i][0]); | |||
var body = content.querySelector("." + PAIRS[i][1]); | |||
if (!body || isEffectivelyEmpty(body)) { | |||
rm(label); | |||
rm(body); | |||
} | |||
} | |||
// If images wrapper has no <img>, remove it | |||
var imagesWrap = content.querySelector(".article-images"); | |||
if (imagesWrap && !imagesWrap.getElementsByTagName("img").length) { | |||
rm(imagesWrap); | |||
} | |||
// After pruning, strip whitespace again so first/last-child calcs are clean | |||
stripWhitespaceTextNodes(content); | |||
// Mark the LAST visible block so we can remove its hairline/padding | |||
var kids = content.children; | |||
if (kids && kids.length) { | |||
// Remove any previous marker | |||
var old = content.querySelector(".no-rule-last"); | |||
if (old) | |||
old.className = old.className | |||
.replace(/\bno-rule-last\b/g, "") | |||
.trim(); | |||
kids[kids.length - 1].className += " no-rule-last"; | |||
} | |||
// Tiny CSS to kill rule & padding on the last element and tighten rhythm | |||
var tidy = doc.createElement("style"); | |||
tidy.type = "text/css"; | |||
tidy.appendChild( | |||
doc.createTextNode( | |||
"@media print {" + | |||
" #article-content > * { margin-top:0 !important; margin-bottom:0 !important; }" + | |||
" #article-content > * + * { margin-top:2mm !important; }" + | |||
" /* kill hairline/padding on last visible block */" + | |||
" #article-content > .no-rule-last { padding-bottom:0 !important; }" + | |||
" #article-content > .no-rule-last::after { content:none !important; display:none !important; }" + | |||
" /* paragraphs inside rich text */" + | |||
" .article-description p, .article-reflection p { margin:0 0 1.2mm 0 !important; }" + | |||
" .article-description p:last-child, .article-reflection p:last-child { margin-bottom:0 !important; }" + | |||
"}" | |||
) | |||
); | |||
doc.head.appendChild(tidy); | |||
})(); | |||
// --- PDF-friendly links for Chrome on macOS --- | // --- PDF-friendly links for Chrome on macOS --- |