MediaWiki:Common.js: Difference between revisions

Jump to navigation Jump to search
no edit summary
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.
         (function pruneEmptySections(doc) {
        // --- Collapse empty sections & their labels, and tidy any leftover spacing ---
           function isEffectivelyEmpty(el) {
         (function tidyPrint(doc) {
             // Text with whitespace-only (incl. NBSP/zero-width) & no images/links
          // 1) Utility: detect “visually empty” blocks
             var txt = (el.textContent || "")
           function isVisuallyEmpty(el) {
            if (!el) return true;
 
             // If it contains any real content, bail
            if (
              el.querySelector("img, video, audio, iframe, svg, object, embed")
            )
              return false;
            if (el.querySelector("a[href]")) return false;
 
            // Remove <br> & empty <p> shells before checking text
            // (work on a shallow clone so we don't touch the live node yet)
            var clone = el.cloneNode(true);
            var i,
              brs = clone.getElementsByTagName("br");
            for (i = brs.length - 1; i >= 0; i--)
              brs[i].parentNode.removeChild(brs[i]);
 
            // Remove <p> that are empty/whitespace only
            var ps = clone.getElementsByTagName("p");
            for (i = ps.length - 1; i >= 0; i--) {
              var t = (ps[i].textContent || "")
                .replace(/\u00A0/g, " ")
                .replace(/\u200B/g, "")
                .replace(/\s+/g, " ")
                .trim();
              if (!t) ps[i].parentNode.removeChild(ps[i]);
            }
 
            // Now inspect text
             var txt = (clone.textContent || "")
               .replace(/\u00A0/g, " ") // NBSP
               .replace(/\u00A0/g, " ") // NBSP
               .replace(/\u200B/g, "") // zero-width space
               .replace(/\u200B/g, "") // zero-width space
               .replace(/\s+/g, " ") // compress whitespace
               .replace(/\s+/g, " ") // collapse spaces
               .trim();
               .trim();
            var hasImg = el.getElementsByTagName("img").length > 0;
 
            var hasLink = el.getElementsByTagName("a").length > 0;
             return !txt;
             return !txt && !hasImg && !hasLink;
           }
           }


           function removeIfEmpty(selector, labelSelector) {
          // 2) Remove block + its label if empty
             var node = doc.querySelector(selector);
           function removePair(blockSel, labelSel) {
             if (node && isEffectivelyEmpty(node)) {
             var block = doc.querySelector(blockSel);
               // remove paired label just before the node, if present
             if (block && isVisuallyEmpty(block)) {
               if (labelSelector) {
               // Remove preceding label if it matches
                 var prev = node.previousElementSibling;
               if (labelSel) {
                 if (prev && prev.matches && prev.matches(labelSelector)) {
                 var prev = block.previousElementSibling;
                   if (prev.parentNode) prev.parentNode.removeChild(prev);
                 if (
                  prev &&
                  prev.matches &&
                  prev.matches(labelSel) &&
                   prev.parentNode
                ) {
                  prev.parentNode.removeChild(prev);
                 }
                 }
               }
               }
               if (node.parentNode) node.parentNode.removeChild(node);
               if (block.parentNode) block.parentNode.removeChild(block);
             }
             }
           }
           }


           // Image block: kill if there is no <img src> inside
           // 3) Images wrapper: only keep if it actually has a usable <img src>
           (function () {
           (function () {
             var imgWrap = doc.querySelector(".article-images");
             var wrap = doc.querySelector(".article-images");
             if (!imgWrap) return;
             if (!wrap) return;
             var imgs = imgWrap.getElementsByTagName("img");
             var imgs = wrap.getElementsByTagName("img");
             var hasRealImg = false;
             var hasSrc = false,
             for (var i = 0; i < imgs.length; i++) {
              i;
               if (imgs[i].getAttribute("src")) {
             for (i = 0; i < imgs.length; i++) {
                 hasRealImg = true;
               var s = imgs[i].getAttribute("src");
              if (s && /\S/.test(s)) {
                 hasSrc = true;
                 break;
                 break;
               }
               }
             }
             }
             if (!hasRealImg && imgWrap.parentNode) {
             if (!hasSrc && wrap.parentNode) wrap.parentNode.removeChild(wrap);
              imgWrap.parentNode.removeChild(imgWrap);
            }
           })();
           })();


           // Description / Reflection / External reference / Quote
           // 4) Optional sections
           removeIfEmpty(".article-description", ".article-label-description");
           removePair(".article-description", ".article-label-description");
           removeIfEmpty(".article-reflection", ".article-label-reflection");
           removePair(".article-reflection", ".article-label-reflection");
           removeIfEmpty(
           removePair(
             ".article-external-reference",
             ".article-external-reference",
             ".article-label-external-reference"
             ".article-label-external-reference"
           );
           );
           removeIfEmpty(".article-quote", ".article-label-quote");
           removePair(".article-quote", ".article-label-quote");


           // Metadata: if all values are empty, remove the whole grid
           // 5) Metadata grid: drop if all values are empty
           (function () {
           (function () {
             var meta = doc.querySelector(".article-metadata");
             var meta = doc.querySelector(".article-metadata");
             if (!meta) return;
             if (!meta) return;
             var values = meta.querySelectorAll(".article-metadata-value");
             var vals = meta.querySelectorAll(".article-metadata-value");
             var allEmpty = true;
             var allEmpty = true,
             for (var i = 0; i < values.length; i++) {
              i;
               if (!isEffectivelyEmpty(values[i])) {
             for (i = 0; i < vals.length; i++) {
               if (!isVisuallyEmpty(vals[i])) {
                 allEmpty = false;
                 allEmpty = false;
                 break;
                 break;
               }
               }
             }
             }
             if (allEmpty && meta.parentNode) {
             if (allEmpty && meta.parentNode) meta.parentNode.removeChild(meta);
               meta.parentNode.removeChild(meta);
          })();
 
          // 6) Title link row: remove the link bar if it ended up empty (no anchors)
          (function () {
            var bar = doc.querySelector(".link-pdf");
            if (!bar) return;
            if (!bar.querySelector("a[href]") && bar.parentNode)
              bar.parentNode.removeChild(bar);
          })();
 
          // 7) Remove any now-empty label that wasn’t paired (defensive)
          var strayLabels = doc.querySelectorAll(
            ".article-label-description, .article-label-reflection, " +
              ".article-label-external-reference, .article-label-quote"
          );
          for (var i = 0; i < strayLabels.length; i++) {
            if (strayLabels[i].parentNode)
               strayLabels[i].parentNode.removeChild(strayLabels[i]);
          }
 
          // 8) Kill truly empty paragraphs that may still add height
          var empties = doc.querySelectorAll("#article-content p");
          for (var j = 0; j < empties.length; j++) {
            var text = (empties[j].textContent || "")
              .replace(/\u00A0/g, " ")
              .replace(/\u200B/g, "")
              .trim();
            if (
              !text &&
              empties[j].children.length === 0 &&
              empties[j].parentNode
            ) {
              empties[j].parentNode.removeChild(empties[j]);
             }
             }
           })();
           }
 
          // 9) Hide the hairline on the very last block to avoid a “phantom gap”
          var css = doc.createElement("style");
          css.textContent =
            "@media print{#article-content>:last-child{padding-bottom:0!important;}" +
            "#article-content>:last-child::after{content:none!important;}}";
          doc.head.appendChild(css);
         })(doc);
         })(doc);


Navigation menu