Changes for page Alder Support Center scripts
Last modified by wiki admin on 2026/08/26 01:04
From version 8.1
edited by wiki admin
on 2026/08/24 22:49
on 2026/08/24 22:49
Change comment:
There is no comment for this version
To version 9.1
edited by wiki admin
on 2026/08/24 23:09
on 2026/08/24 23:09
Change comment:
There is no comment for this version
Summary
-
Objects (1 modified, 0 added, 0 removed)
Details
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -38,6 +38,23 @@ 38 38 return svg; 39 39 } 40 40 41 + function sectionRoot(content) { 42 + // Content is sometimes wrapped in one container (an {{html}} macro's div, 43 + // for instance). Descend through single-child wrappers so the section 44 + // blocks are found, but only a couple of levels -- deeper than that and we 45 + // are guessing. 46 + var el = content; 47 + for (var depth = 0; depth < 3; depth++) { 48 + var kids = el.children; 49 + if (kids.length === 1 && kids[0].tagName === 'DIV' && kids[0].children.length > 1) { 50 + el = kids[0]; 51 + } else { 52 + break; 53 + } 54 + } 55 + return el; 56 + } 57 + 41 41 function isWikiHome() { 42 42 // The employees home page has several H2s (departments, article status, 43 43 // publishing workflow). Collapsing a landing page into rows hides the ... ... @@ -71,13 +71,21 @@ 71 71 // (each heading has its OWN panel, so every group had one item and the 72 72 // script bailed silently). Both looked fine on a hand-written preview page. 73 73 var made = []; 74 - var panels = content.querySelectorAll('.f-accordion-panel'); 75 75 92 + // Helpjuice exported three different widget wrappers -- f-accordion-panel 93 + // (25 articles), helpjuice-tab (71) and helpjuice-accordion (68) -- and the 94 + // migration carried all of them across as raw HTML. Rather than hardcode 95 + // class names that would miss the next variant, look for the shape they 96 + // share: a wrapper element whose FIRST element is a heading. That is a 97 + // section container regardless of what it is called. 98 + var root = sectionRoot(content); 76 76 var eligible = []; 77 - for (var p = 0; p < panels.length; p++) { 78 - var first = panels[p].firstElementChild; 79 - if (first && /^H[1-4]$/.test(first.tagName)) { 80 - eligible.push({ panel: panels[p], heading: first }); 100 + var kids = root.children; 101 + for (var p = 0; p < kids.length; p++) { 102 + var first = kids[p].firstElementChild; 103 + if (first && /^H[1-4]$/.test(first.tagName) && 104 + (first.textContent || '').trim()) { 105 + eligible.push({ panel: kids[p], heading: first }); 81 81 } 82 82 } 83 83 ... ... @@ -114,28 +114,46 @@ 114 114 made.push(details); 115 115 }); 116 116 } else { 117 - // Fallback for content without those panels -- hand-written wiki markup, 118 - // and any XWiki version that renders sections differently. 119 - var found = content.querySelectorAll('h2'); 120 - if (found.length < MIN_SECTIONS) { return; } 142 + // No Helpjuice panels: build sections from headings. Do NOT assume h2. 143 + // Across the migrated corpus the section level varies -- 304 articles use 144 + // h2, 67 use h3, 13 use h1 -- because Helpjuice authors picked levels by 145 + // appearance rather than structure. Assuming h2 left 99 articles with no 146 + // rows at all. 147 + // 148 + // Rule: use the SHALLOWEST level that appears at least twice among 149 + // headings sharing a parent. That is the level acting as "section" in 150 + // this particular article; anything deeper is a subsection and travels 151 + // inside. 152 + var chosen = null; 153 + for (var level = 1; level <= 4 && !chosen; level++) { 154 + // A heading with no text (Helpjuice left a few) would become a row 155 + // with a blank title, which is worse than no row at all. 156 + var all = content.querySelectorAll('h' + level); 157 + var atLevel = []; 158 + for (var t = 0; t < all.length; t++) { 159 + if ((all[t].textContent || '').trim()) { atLevel.push(all[t]); } 160 + } 161 + if (atLevel.length < MIN_SECTIONS) { continue; } 121 121 122 - var byParent = []; 123 - for (var f = 0; f < found.length; f++) { 124 - var parent = found[f].parentNode; 125 - var slot = null; 126 - for (var b = 0; b < byParent.length; b++) { 127 - if (byParent[b].parent === parent) { slot = byParent[b]; break; } 163 + var groups = []; 164 + for (var i = 0; i < atLevel.length; i++) { 165 + var parent = atLevel[i].parentNode; 166 + var slot = null; 167 + for (var g = 0; g < groups.length; g++) { 168 + if (groups[g].parent === parent) { slot = groups[g]; break; } 169 + } 170 + if (!slot) { slot = { parent: parent, items: [] }; groups.push(slot); } 171 + slot.items.push(atLevel[i]); 128 128 } 129 - if (!slot) { slot = { parent: parent, items: [] }; byParent.push(slot); } 130 - slot.items.push(found[f]); 173 + groups.sort(function (a, b) { return b.items.length - a.items.length; }); 174 + if (groups[0].items.length >= MIN_SECTIONS) { 175 + chosen = { level: level, container: groups[0].parent, items: groups[0].items }; 176 + } 131 131 } 132 - byParent.sort(function(a, b) { returnb.items.length - a.items.length; });178 + if (!chosen) { return; } 133 133 134 - var container = byParent[0].parent; 135 - var headings = byParent[0].items; 136 - if (headings.length < MIN_SECTIONS) { return; } 137 - 138 - headings.forEach(function (h2, index) { 180 + var container = chosen.container; 181 + chosen.items.forEach(function (heading, index) { 139 139 var details = document.createElement('details'); 140 140 details.className = 'alder-sec'; 141 141 if (index === 0) { details.open = true; } ... ... @@ -143,7 +143,7 @@ 143 143 var summary = document.createElement('summary'); 144 144 var title = document.createElement('span'); 145 145 title.className = 'alder-sec-title'; 146 - title.textContent = (h 2.textContent || '').trim();189 + title.textContent = (heading.textContent || '').trim(); 147 147 summary.appendChild(title); 148 148 summary.appendChild(chevron()); 149 149 details.appendChild(summary); ... ... @@ -152,15 +152,20 @@ 152 152 wrap.className = 'alder-sec-body'; 153 153 details.appendChild(wrap); 154 154 155 - if (h 2.id) { details.id = h2.id; h2.removeAttribute('id'); }156 - container.insertBefore(details, h 2);198 + if (heading.id) { details.id = heading.id; heading.removeAttribute('id'); } 199 + container.insertBefore(details, heading); 157 157 158 - var node = h2; 159 - while (node && !(node !== h2 && node.tagName === 'H2')) { 201 + // Absorb everything up to the next heading at this level or shallower. 202 + // Stopping only at the same tag would let a shallower heading (a real 203 + // structural break) get swallowed into the section above it. 204 + var node = heading; 205 + while (node) { 160 160 var next = node.nextSibling; 161 161 wrap.appendChild(node); 162 162 node = next; 163 - if (node && node.nodeType === 1 && node.tagName === 'H2') { break; } 209 + if (node && node.nodeType === 1 && /^H([1-6])$/.test(node.tagName)) { 210 + if (parseInt(node.tagName.slice(1), 10) <= chosen.level) { break; } 211 + } 164 164 } 165 165 made.push(details); 166 166 });