From: Thomas Walker Lynch Date: Fri, 13 Mar 2026 15:14:38 +0000 (+0000) Subject: improved paginator X-Git-Url: https://git.reasoningtechnology.com/%5B%5E?a=commitdiff_plain;h=99d450ca8b31e830565bae32a02979b3335eb32d;p=RT-style-JS_public improved paginator --- diff --git a/consumer/release/RT/layout/article_tech_ref.js b/consumer/release/RT/layout/article_tech_ref.js index 67fba92..8280bae 100644 --- a/consumer/release/RT/layout/article_tech_ref.js +++ b/consumer/release/RT/layout/article_tech_ref.js @@ -48,20 +48,39 @@ } // CSS injection for headers, lists, and layout mapped from theme variables -// CSS injection for headers, lists, and layout mapped from theme variables + // 1. Adjust paginator capacity to fit the physical page minus padding + window.StyleRT = window.StyleRT || {}; + window.StyleRT.config = window.StyleRT.config || {}; + window.StyleRT.config.page = window.StyleRT.config.page || {}; + // 1056px - 96px (padding) = 960px usable. 920px leaves room for the footer. + window.StyleRT.config.page.height_limit = 920; + + // 2. CSS injection for headers, lists, and layout mapped from theme variables const style_node = document.createElement("style"); style_node.innerHTML = ` rt-article { font-family: 'Noto Sans JP', Arial, sans-serif; background-color: var(--rt-surface-0); color: var(--rt-content-main); - padding: 2rem; + /* Force width so inline JS doesn't widen the measurement area */ + max-width: 46.875rem !important; + box-sizing: border-box !important; + } + + /* PRE-PAGINATION: Mimic page padding so text line-wraps accurately during measurement */ + rt-article:not(:has(rt-page)) { + padding: 3rem !important; } + + /* POST-PAGINATION: Remove article padding so we don't double-pad the generated pages */ + rt-article:has(rt-page) { + padding: 0 !important; + } + rt-article rt-page { display: block; padding: 3rem; margin: 1.25rem auto; - max-width: 46.875rem; background-color: var(--rt-surface-0); box-shadow: 0 0 0.625rem var(--rt-brand-primary); } @@ -71,7 +90,7 @@ font-size: 1.5rem; text-align: center; color: var(--rt-brand-primary); - font-weight: 500; /* Softened from the default heavy bold */ + font-weight: 500; margin-top: 1.5rem; line-height: 1.15; } @@ -87,7 +106,7 @@ color: var(--rt-brand-tertiary); text-align: left; margin-top: 1.5rem; - margin-left: 4ch; /* Indented 4 characters */ + margin-left: 4ch; } rt-article h4 { font-size: 1.05rem; @@ -95,7 +114,7 @@ font-weight: 600; text-align: left; margin-top: 1.25rem; - margin-left: 8ch; /* Indented 8 characters */ + margin-left: 8ch; } /* --- BODY TEXT (Flush Left) --- */ diff --git a/consumer/release/RT/layout/paginate_by_element.js b/consumer/release/RT/layout/paginate_by_element.js index e085148..89595ca 100644 --- a/consumer/release/RT/layout/paginate_by_element.js +++ b/consumer/release/RT/layout/paginate_by_element.js @@ -3,70 +3,106 @@ */ window.StyleRT = window.StyleRT || {}; -window.StyleRT.paginate_by_element = function() { +window.StyleRT.paginate_by_element = function(){ const RT = window.StyleRT; - - // Fix: Read safely without overwriting the config namespace const page_conf = (RT.config && RT.config.page) ? RT.config.page : {}; const page_height_limit = page_conf.height_limit || 1000; const article_seq = document.querySelectorAll("RT-article"); - - // HURDLE: Error if no articles found to paginate - if(article_seq.length === 0) { - RT.debug.error('pagination', 'No elements found. Pagination aborted.'); + if(article_seq.length === 0){ + RT.debug.error('pagination' ,'No elements found. Pagination aborted.'); return; } - article_seq.forEach( (article) => { - const raw_elements = Array.from(article.children).filter(el => - !['SCRIPT', 'STYLE', 'RT-PAGE'].includes(el.tagName) + let article_index = 0; + while(true){ + if(article_index === article_seq.length) break; + const article = article_seq[article_index]; + + const raw_element_seq = Array.from(article.children).filter( el => + !['SCRIPT' ,'STYLE' ,'RT-PAGE'].includes(el.tagName) ); - if(raw_elements.length === 0) return; + if(raw_element_seq.length > 0){ + const page_seq = []; + let current_batch_seq = []; + let current_h = 0; - const pages = []; - let current_batch = []; - let current_h = 0; + const get_el_height = (el) => { + const rect = el.getBoundingClientRect(); + const style = window.getComputedStyle(el); + const margin = parseFloat(style.marginTop) + parseFloat(style.marginBottom); + return (rect.height || 0) + (margin || 0); + }; - const get_el_height = (el) => { - const rect = el.getBoundingClientRect(); - const style = window.getComputedStyle(el); - const margin = parseFloat(style.marginTop) + parseFloat(style.marginBottom); - return (rect.height || 0) + (margin || 0); - }; + let i = 0; + while(true){ + if(i === raw_element_seq.length) break; + const el = raw_element_seq[i]; + const h = get_el_height(el); - for (let i = 0; i < raw_elements.length; i++) { - const el = raw_elements[i]; - const h = get_el_height(el); - const is_heading = /^H[1-6]/.test(el.tagName); + if(current_h + h > page_height_limit && current_batch_seq.length > 0){ + let backtrack_seq = []; + let backtrack_h = 0; - let total_required_h = h; - if (is_heading && i + 1 < raw_elements.length) { - total_required_h += get_el_height(raw_elements[i + 1]); - } + // Backtrack to rescue any widowed headings at the end of the batch + while(true){ + if(current_batch_seq.length === 0) break; + const last_el = current_batch_seq[current_batch_seq.length - 1]; + if(!/^H[1-6]/.test(last_el.tagName)) break; + + const popped_el = current_batch_seq.pop(); + backtrack_seq.unshift(popped_el); + backtrack_h += get_el_height(popped_el); + } + + if(current_batch_seq.length > 0){ + page_seq.push(current_batch_seq); + current_batch_seq = backtrack_seq; + current_h = backtrack_h; + }else{ + // Fallback for an extreme case where the entire page was a cascade of headings + page_seq.push(backtrack_seq); + current_batch_seq = []; + current_h = 0; + } + } - if (current_h + total_required_h > page_height_limit && current_batch.length > 0) { - pages.push(current_batch); - current_batch = []; - current_h = 0; + current_batch_seq.push(el); + current_h += h; + + i++; } - current_batch.push(el); - current_h += h; - } + if(current_batch_seq.length > 0){ + page_seq.push(current_batch_seq); + } - if (current_batch.length > 0) pages.push(current_batch); + article.innerHTML = ''; + + let p = 0; + while(true){ + if(p === page_seq.length) break; + const batch_seq = page_seq[p]; + const page_el = document.createElement('rt-page'); + page_el.id = `page-${p + 1}`; + + let item_idx = 0; + while(true){ + if(item_idx === batch_seq.length) break; + page_el.appendChild(batch_seq[item_idx]); + item_idx++; + } + + article.appendChild(page_el); + p++; + } - article.innerHTML = ''; - - pages.forEach( (list, index) => { - const page_el = document.createElement('rt-page'); - page_el.id = `page-${index+1}`; - list.forEach(item => page_el.appendChild(item)); - article.appendChild(page_el); - }); + if(RT.debug){ + RT.debug.log('pagination' ,`Article paginated into ${page_seq.length} pages.`); + } + } - if (RT.debug) RT.debug.log('pagination', `Article paginated into ${pages.length} pages.`); - }); + article_index++; + } }; diff --git a/developer/authored/RT/layout/article_tech_ref.js b/developer/authored/RT/layout/article_tech_ref.js index 67fba92..8280bae 100644 --- a/developer/authored/RT/layout/article_tech_ref.js +++ b/developer/authored/RT/layout/article_tech_ref.js @@ -48,20 +48,39 @@ } // CSS injection for headers, lists, and layout mapped from theme variables -// CSS injection for headers, lists, and layout mapped from theme variables + // 1. Adjust paginator capacity to fit the physical page minus padding + window.StyleRT = window.StyleRT || {}; + window.StyleRT.config = window.StyleRT.config || {}; + window.StyleRT.config.page = window.StyleRT.config.page || {}; + // 1056px - 96px (padding) = 960px usable. 920px leaves room for the footer. + window.StyleRT.config.page.height_limit = 920; + + // 2. CSS injection for headers, lists, and layout mapped from theme variables const style_node = document.createElement("style"); style_node.innerHTML = ` rt-article { font-family: 'Noto Sans JP', Arial, sans-serif; background-color: var(--rt-surface-0); color: var(--rt-content-main); - padding: 2rem; + /* Force width so inline JS doesn't widen the measurement area */ + max-width: 46.875rem !important; + box-sizing: border-box !important; + } + + /* PRE-PAGINATION: Mimic page padding so text line-wraps accurately during measurement */ + rt-article:not(:has(rt-page)) { + padding: 3rem !important; } + + /* POST-PAGINATION: Remove article padding so we don't double-pad the generated pages */ + rt-article:has(rt-page) { + padding: 0 !important; + } + rt-article rt-page { display: block; padding: 3rem; margin: 1.25rem auto; - max-width: 46.875rem; background-color: var(--rt-surface-0); box-shadow: 0 0 0.625rem var(--rt-brand-primary); } @@ -71,7 +90,7 @@ font-size: 1.5rem; text-align: center; color: var(--rt-brand-primary); - font-weight: 500; /* Softened from the default heavy bold */ + font-weight: 500; margin-top: 1.5rem; line-height: 1.15; } @@ -87,7 +106,7 @@ color: var(--rt-brand-tertiary); text-align: left; margin-top: 1.5rem; - margin-left: 4ch; /* Indented 4 characters */ + margin-left: 4ch; } rt-article h4 { font-size: 1.05rem; @@ -95,7 +114,7 @@ font-weight: 600; text-align: left; margin-top: 1.25rem; - margin-left: 8ch; /* Indented 8 characters */ + margin-left: 8ch; } /* --- BODY TEXT (Flush Left) --- */ diff --git a/developer/authored/RT/layout/paginate_by_element.js b/developer/authored/RT/layout/paginate_by_element.js index e085148..89595ca 100644 --- a/developer/authored/RT/layout/paginate_by_element.js +++ b/developer/authored/RT/layout/paginate_by_element.js @@ -3,70 +3,106 @@ */ window.StyleRT = window.StyleRT || {}; -window.StyleRT.paginate_by_element = function() { +window.StyleRT.paginate_by_element = function(){ const RT = window.StyleRT; - - // Fix: Read safely without overwriting the config namespace const page_conf = (RT.config && RT.config.page) ? RT.config.page : {}; const page_height_limit = page_conf.height_limit || 1000; const article_seq = document.querySelectorAll("RT-article"); - - // HURDLE: Error if no articles found to paginate - if(article_seq.length === 0) { - RT.debug.error('pagination', 'No elements found. Pagination aborted.'); + if(article_seq.length === 0){ + RT.debug.error('pagination' ,'No elements found. Pagination aborted.'); return; } - article_seq.forEach( (article) => { - const raw_elements = Array.from(article.children).filter(el => - !['SCRIPT', 'STYLE', 'RT-PAGE'].includes(el.tagName) + let article_index = 0; + while(true){ + if(article_index === article_seq.length) break; + const article = article_seq[article_index]; + + const raw_element_seq = Array.from(article.children).filter( el => + !['SCRIPT' ,'STYLE' ,'RT-PAGE'].includes(el.tagName) ); - if(raw_elements.length === 0) return; + if(raw_element_seq.length > 0){ + const page_seq = []; + let current_batch_seq = []; + let current_h = 0; - const pages = []; - let current_batch = []; - let current_h = 0; + const get_el_height = (el) => { + const rect = el.getBoundingClientRect(); + const style = window.getComputedStyle(el); + const margin = parseFloat(style.marginTop) + parseFloat(style.marginBottom); + return (rect.height || 0) + (margin || 0); + }; - const get_el_height = (el) => { - const rect = el.getBoundingClientRect(); - const style = window.getComputedStyle(el); - const margin = parseFloat(style.marginTop) + parseFloat(style.marginBottom); - return (rect.height || 0) + (margin || 0); - }; + let i = 0; + while(true){ + if(i === raw_element_seq.length) break; + const el = raw_element_seq[i]; + const h = get_el_height(el); - for (let i = 0; i < raw_elements.length; i++) { - const el = raw_elements[i]; - const h = get_el_height(el); - const is_heading = /^H[1-6]/.test(el.tagName); + if(current_h + h > page_height_limit && current_batch_seq.length > 0){ + let backtrack_seq = []; + let backtrack_h = 0; - let total_required_h = h; - if (is_heading && i + 1 < raw_elements.length) { - total_required_h += get_el_height(raw_elements[i + 1]); - } + // Backtrack to rescue any widowed headings at the end of the batch + while(true){ + if(current_batch_seq.length === 0) break; + const last_el = current_batch_seq[current_batch_seq.length - 1]; + if(!/^H[1-6]/.test(last_el.tagName)) break; + + const popped_el = current_batch_seq.pop(); + backtrack_seq.unshift(popped_el); + backtrack_h += get_el_height(popped_el); + } + + if(current_batch_seq.length > 0){ + page_seq.push(current_batch_seq); + current_batch_seq = backtrack_seq; + current_h = backtrack_h; + }else{ + // Fallback for an extreme case where the entire page was a cascade of headings + page_seq.push(backtrack_seq); + current_batch_seq = []; + current_h = 0; + } + } - if (current_h + total_required_h > page_height_limit && current_batch.length > 0) { - pages.push(current_batch); - current_batch = []; - current_h = 0; + current_batch_seq.push(el); + current_h += h; + + i++; } - current_batch.push(el); - current_h += h; - } + if(current_batch_seq.length > 0){ + page_seq.push(current_batch_seq); + } - if (current_batch.length > 0) pages.push(current_batch); + article.innerHTML = ''; + + let p = 0; + while(true){ + if(p === page_seq.length) break; + const batch_seq = page_seq[p]; + const page_el = document.createElement('rt-page'); + page_el.id = `page-${p + 1}`; + + let item_idx = 0; + while(true){ + if(item_idx === batch_seq.length) break; + page_el.appendChild(batch_seq[item_idx]); + item_idx++; + } + + article.appendChild(page_el); + p++; + } - article.innerHTML = ''; - - pages.forEach( (list, index) => { - const page_el = document.createElement('rt-page'); - page_el.id = `page-${index+1}`; - list.forEach(item => page_el.appendChild(item)); - article.appendChild(page_el); - }); + if(RT.debug){ + RT.debug.log('pagination' ,`Article paginated into ${page_seq.length} pages.`); + } + } - if (RT.debug) RT.debug.log('pagination', `Article paginated into ${pages.length} pages.`); - }); + article_index++; + } };