From: Thomas Walker Lynch Date: Mon, 12 Jan 2026 17:53:35 +0000 (+0000) Subject: . X-Git-Url: https://git.reasoningtechnology.com/style/RT_code.js?a=commitdiff_plain;h=6826b70e0112419b93ddae7c851f2805b2320cd2;p=Epimetheus%2F.git . --- diff --git a/developer/document/style/RT_TOC.js b/developer/document/style/RT_TOC.js new file mode 100644 index 0000000..dc1c5f5 --- /dev/null +++ b/developer/document/style/RT_TOC.js @@ -0,0 +1,84 @@ +/* + Processes existing tags. + Populates each with headings found below it that are exactly one level deeper. + Stops scanning if a heading of the same or higher level is encountered. +*/ +window.StyleRT = window.StyleRT || {}; + +window.StyleRT.RT_TOC = function() { + const debug = window.StyleRT.debug; + const toc_tags = document.querySelectorAll('rt-toc'); + + toc_tags.forEach((container, toc_index) => { + container.style.display = 'block'; + + // 1. Determine the context level of this TOC + // We look backward to find the most recent heading (H1-H6) + let context_level = 0; // Default to 0 (looking for H1s) + let prev = container.previousElementSibling; + + while (prev) { + const match = prev.tagName.match(/^H([1-6])$/); + if (match) { + context_level = parseInt(match[1]); + break; + } + prev = prev.previousElementSibling; + } + + const target_level = context_level + 1; + const stop_at_or_above = context_level; + + if (debug) debug.log('RT_TOC', `TOC #${toc_index} context: H${context_level}. Targeting: H${target_level}`); + + // 2. Setup Internal Structure + container.innerHTML = ''; // Clear any placeholder content + const title = document.createElement('h1'); + title.textContent = context_level === 0 ? 'Table of Contents' : 'Section Contents'; + title.style.textAlign = 'center'; + container.appendChild(title); + + const list = document.createElement('ul'); + list.style.listStyle = 'none'; + list.style.paddingLeft = '0'; + container.appendChild(list); + + // 3. Scan Forward for headings + let next_el = container.nextElementSibling; + while (next_el) { + const match = next_el.tagName.match(/^H([1-6])$/); + if (match) { + const found_level = parseInt(match[1]); + + // STOP condition: We hit a heading at our level or higher + // (e.g., if we are under an H1 looking for H2s, we stop at the next H1) + if (context_level !== 0 && found_level <= stop_at_or_above) { + break; + } + + // COLLECT condition: Heading is exactly one level deeper + if (found_level === target_level) { + if (!next_el.id) next_el.id = `toc-ref-${toc_index}-${found_level}-${list.children.length}`; + + const li = document.createElement('li'); + li.style.marginBottom = '0.5rem'; + + const a = document.createElement('a'); + a.href = `#${next_el.id}`; + a.textContent = next_el.textContent; + a.style.textDecoration = 'none'; + a.style.color = 'inherit'; + a.style.display = 'block'; + + // Hover effects + a.onmouseover = () => a.style.color = 'hsl(42, 100%, 50%)'; + a.onmouseout = () => a.style.color = 'inherit'; + + li.appendChild(a); + list.appendChild(li); + } + } + next_el = next_el.nextElementSibling; + } + }); +}; diff --git a/developer/document/style/article_generic.js b/developer/document/style/article_generic.js index f49feda..93000aa 100644 --- a/developer/document/style/article_generic.js +++ b/developer/document/style/article_generic.js @@ -1,6 +1,6 @@ /* - Sets basic document theme colors. - No layout enforcement (leaves flow to default HTML block behavior). + Sets basic document theme colors and dimensions. + Sets width immediately so layout-based pagination is accurate. */ window.StyleRT = window.StyleRT || {}; @@ -10,12 +10,23 @@ window.StyleRT.article_generic = function() { const body = document.body; - // Basic Theme Colors (Required for RT_code physics) - body.style.backgroundColor = theme.background || '#000'; - body.style.color = theme.foreground || '#ddd'; + // 1. Basic Theme Colors + body.style.backgroundColor = theme.background || 'hsl(0, 0%, 0%)'; + body.style.color = theme.foreground || 'hsl(42, 100%, 80%)'; body.style.fontFamily = '"Noto Sans JP", sans-serif'; - // Reset margins to prevent browser defaults from interfering with your page.js + // 2. Global Flow Reset + body.style.display = 'block'; body.style.margin = '0'; body.style.padding = '0'; + + // 3. Dimensions + // We apply the width to the body now so that getBoundingClientRect() + // in the paginator reflects the final text wrapping. + body.style.maxWidth = '50rem'; + body.style.margin = '0 auto'; // Center the content area + + // We store the target page height on the RT object for the paginator to find. + // This avoids assigning a height to the body itself (which would clip content). + RT.page_height = 1056; }; diff --git a/developer/document/style/do_style.js b/developer/document/style/do_style.js index ffd2da7..9fce950 100644 --- a/developer/document/style/do_style.js +++ b/developer/document/style/do_style.js @@ -1,89 +1,90 @@ /* Master Loader & Orchestrator for StyleRT. - - PIPELINE DEPENDENCY CHAIN: - 1. PHYSICS (Utility, Theme) -> Required by everything. - 2. GLOBAL (Article) -> Sets background for contrast checks. - 3. SEMANTICS (Code, Math) -> Expands text size; must run before pagination. - 4. STRUCTURE (H1, TOC) -> Creates .page containers. - 5. STYLING (Page) -> Applies borders/margins to .page containers. - 6. REVEAL -> Shows the result. + Loads utility.js first to ensure infrastructure (RT.debug) exists. */ window.StyleRT = window.StyleRT || {}; window.StyleRT.do_style = function() { + const RT = window.StyleRT; - // 1. Manifest const modules = [ - 'style/utility.js', 'style/theme_RT.js', 'style/RT_term.js', 'style/RT_math.js', 'style/RT_code.js', 'style/article_generic.js', - 'style/page_each_H1.js', - 'style/toc.js', - 'style/page.js', + 'style/RT_TOC.js', + 'style/paginate_by_element.js', + // 'style/page.js', + 'style/page_css.js', 'style/body_visibility_visible.js' ]; - // 2. Loader + // 1. Bootloader: Get the utility/logger in place first + const utility = document.createElement('script'); + utility.src = 'style/utility.js'; + + utility.onload = () => { + // Infrastructure ready; begin module sequence + load_next(0); + }; + + utility.onerror = () => { + console.error("StyleRT: Critical failure - utility.js missing."); + }; + + document.head.appendChild(utility); + + // 2. The Chain Loader const load_next = (index) => { if (index >= modules.length) { - run_pipeline(); + run_style(); return; } + const src = modules[index]; + + // Accessing the property live so it doesn't matter if it was set late + if (RT.debug) RT.debug.log('style', `Loading: ${src}`); + const script = document.createElement('script'); script.src = src; script.onload = () => load_next(index + 1); - script.onerror = () => { console.error(`StyleRT: Failed ${src}`); load_next(index + 1); }; + script.onerror = () => { + console.error(`StyleRT: Failed load on ${src}`); + load_next(index + 1); + }; document.head.appendChild(script); }; - // 3. Execution Pipeline - const run_pipeline = () => { - const RT = window.StyleRT; - const debug = RT.debug; + // 3. Phase 1: Semantics + const run_style = () => { + RT.debug.log('style', 'Starting Phase 1: Setup & Semantics'); - debug.log('pipeline', 'Starting execution...'); - - // PHASE 1: GLOBAL SETUP - if(RT.article_generic) { - debug.log('pipeline', 'Phase 1: Global Setup (article_generic)'); - RT.article_generic(); - } - - // PHASE 2: SEMANTICS (In-place modification) - debug.log('pipeline', 'Phase 2: Semantics (Term, Math, Code)'); + if(RT.article_generic) RT.article_generic(); if(RT.RT_term) RT.RT_term(); if(RT.RT_math) RT.RT_math(); if(RT.RT_code) RT.RT_code(); - // PHASE 3: STRUCTURE (DOM Surgery) - debug.log('pipeline', 'Phase 3: Structure (Pagination & TOC)'); - - // A. Content Pagination (Breaks body into pages) - if(RT.page_each_H1) RT.page_each_H1(); - - // B. TOC Generation (Creates the TOC Page) - // Must run AFTER H1s are processed (or scan them), but definitely creates a .page - if(RT.toc) RT.toc(); - - // PHASE 4: STYLING (The Frame) - // Must run LAST, after all .page elements (Content + TOC) exist. - if(RT.page) { - debug.log('pipeline', 'Phase 4: Styling (Applying Page Borders)'); - RT.page(); + // Hand off to MathJax task queue + if (window.MathJax && MathJax.Hub && MathJax.Hub.Queue) { + RT.debug.log('style', 'MathJax detected. Queueing layout tasks...'); + MathJax.Hub.Queue(["Typeset", MathJax.Hub], continue_style); + } else { + continue_style(); } + }; - // PHASE 5: REVEAL - debug.log('pipeline', 'Phase 5: Reveal'); + // 4. Phase 2: Layout + const continue_style = () => { + RT.debug.log('style', 'Starting Phase 2: Layout & Reveal'); + + if(RT.RT_TOC) RT.RT_TOC(); + if(RT.paginate_by_element) RT.paginate_by_element(); + if(RT.page) RT.page(); if(RT.body_visibility_visible) RT.body_visibility_visible(); - debug.log('pipeline', 'Execution complete.'); + RT.debug.log('style', 'Style execution complete.'); }; - - load_next(0); }; diff --git a/developer/document/style/page.js b/developer/document/style/page.js index 6eb5e61..91f6ff1 100644 --- a/developer/document/style/page.js +++ b/developer/document/style/page.js @@ -1,40 +1,49 @@ /* - Defines the appearance of a "Page" container. - Restores the Original "Gold Glow" Scheme. + Defines the appearance of the container via a CSS block. + Uses high-contrast offsets to ensure the drop shadow is visible. */ window.StyleRT = window.StyleRT || {}; window.StyleRT.page = function() { const RT = window.StyleRT; + const style_id = 'rt-page-styles'; - // Fetch Theme - const theme = RT.active_theme ? RT.active_theme() : {}; - // Use the bright accent for the glow - const glowColor = theme.accent || 'gold'; + if (!document.getElementById(style_id)) { + const style_el = document.createElement('style'); + style_el.id = style_id; + style_el.textContent = ` + html, body { + background-color: #1a1a1a !important; + margin: 0; + padding: 0; + } - document.querySelectorAll('.page').forEach(el => { - // A. Dimensions (The "Web" Look) - el.style.width = '1200px'; - el.style.maxWidth = '95vw'; // Responsive safety - el.style.height = 'auto'; // Hug content - el.style.minHeight = '200px'; // Minimum sanity check - el.style.boxSizing = 'border-box'; - - // B. The "Original" Visuals - // 1. Background: Likely darker/transparent to let the theme breathe - el.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; - - // 2. Border: Thin accent line - el.style.border = `1px solid ${glowColor}`; - - // 3. Shadow: The "Gold Drop Shadow" you missed - // Format: offset-x | offset-y | blur-radius | color - el.style.boxShadow = `0 0 15px ${glowColor}`; - - el.style.margin = '0 auto'; - - // C. Typography Base - el.style.padding = '2rem 4rem'; // Standard comfortable web reading padding - el.style.lineHeight = '1.6'; - }); + rt-page { + display: block; + max-width: 50rem; + width: 100%; + + /* Increased vertical margin to prevent shadow clipping */ + margin: 4rem auto 6rem auto; + padding: 3rem; + box-sizing: border-box; + background-color: hsl(0, 0%, 0%); + border: 1px solid hsl(42, 100%, 50%); + + /* 1. The Offset Drop Shadow (Bottom-Right) + 2. The Ambient Glow (Centered) + */ + box-shadow: 15px 15px 30px rgba(0, 0, 0, 0.9), + 0 0 15px hsl(42, 100%, 15%); + + height: auto; + + /* Ensure the shadow isn't cut off by the container's edges */ + overflow: visible; + } + `; + document.head.appendChild(style_el); + } + + if (RT.debug) RT.debug.log('style', 'CSS block updated with 15px shadow offset.'); }; diff --git a/developer/document/style/page_css.js b/developer/document/style/page_css.js new file mode 100644 index 0000000..0383b05 --- /dev/null +++ b/developer/document/style/page_css.js @@ -0,0 +1,35 @@ +/* + Defines the appearance of the container. + Uses the high-performance 'filter: drop-shadow' discovered in testing. +*/ +window.StyleRT = window.StyleRT || {}; + +window.StyleRT.page = function() { + const RT = window.StyleRT; + const style_id = 'rt-page-styles'; + + if (!document.getElementById(style_id)) { + const style_el = document.createElement('style'); + style_el.id = style_id; + style_el.textContent = ` + rt-page { + display: block; + max-width: 50rem; + width: 100%; + margin: 4rem auto 6rem auto; + padding: 3rem; + box-sizing: border-box; + background-color: hsl(0, 0%, 0%); + border: 1px solid hsl(42, 100%, 50%); + + /* Using the discovered Gold Leaf HSL */ + filter: drop-shadow(8px 12px 40px hsl(40, 96%, 47%)); + + height: auto; + } + `; + document.head.appendChild(style_el); + } + + if (RT.debug) RT.debug.log('style', 'CSS block updated with Gold Leaf drop-shadow filter.'); +}; diff --git a/developer/document/style/page_each_H1.js b/developer/document/style/page_each_H1.js deleted file mode 100644 index ac19e83..0000000 --- a/developer/document/style/page_each_H1.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - Wraps child elements into pages based on H1 headers. -*/ -function page_each_H1(){ - const body = document.body; - const elements = Array.from(body.children); - const pages = []; - let current_page_elements = []; - - elements.forEach(el => { - if ( el.tagName === 'SCRIPT' || el.tagName === 'STYLE' ){ - return; - } - - if (el.tagName === 'H1'){ - if (current_page_elements.length > 0){ - pages.push(current_page_elements); - } - current_page_elements = [el]; - } else { - current_page_elements.push(el); - } - }); - - if (current_page_elements.length > 0){ - pages.push(current_page_elements); - } - - const scripts = Array.from(document.querySelectorAll('script')); - body.innerHTML = ''; - - pages.forEach(element_list => { - const page_div = document.createElement('div'); - page_div.className = 'page'; - element_list.forEach(el => page_div.appendChild(el)); - body.appendChild(page_div); - }); - - scripts.forEach(s => body.appendChild(s)); -} - -window.StyleRT = window.StyleRT || {}; -window.StyleRT.page_each_H1 = page_each_H1; diff --git a/developer/document/style/paginate_by_element.js b/developer/document/style/paginate_by_element.js new file mode 100644 index 0000000..0da6ef3 --- /dev/null +++ b/developer/document/style/paginate_by_element.js @@ -0,0 +1,63 @@ +/* + Layout Paginator: paginate_by_element + Measures heights and groups elements. + Logic: Headings must stay with the element immediately following them. +*/ +window.StyleRT = window.StyleRT || {}; + +window.StyleRT.paginate_by_element = function() { + const RT = window.StyleRT; + const body = document.body; + const limit = RT.page_height || 1000; + + const elements = Array.from(body.children).filter(el => + el.tagName !== 'SCRIPT' && el.tagName !== 'STYLE' && el.tagName !== 'RT-PAGE' + ); + + 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 + margin; + }; + + for (let i = 0; i < elements.length; i++) { + const el = elements[i]; + const h = get_el_height(el); + const is_heading = /H[1-6]/.test(el.tagName); + + // Lookahead: If this is a heading, check the next element too + let total_required_h = h; + if (is_heading && i + 1 < elements.length) { + total_required_h += get_el_height(elements[i + 1]); + } + + // If the element (or heading + next) exceeds limit, start new page + if (current_h + total_required_h > limit && current_batch.length > 0) { + pages.push(current_batch); + current_batch = []; + current_h = 0; + } + + current_batch.push(el); + current_h += h; + } + + if (current_batch.length > 0) pages.push(current_batch); + + // Rebuild DOM + const assets = Array.from(document.querySelectorAll('script, style')); + body.innerHTML = ''; + pages.forEach(list => { + const page_el = document.createElement('rt-page'); + list.forEach(item => page_el.appendChild(item)); + body.appendChild(page_el); + }); + assets.forEach(a => body.appendChild(a)); + + if (RT.debug) RT.debug.log('layout', `Pagination complete: ${pages.length} pages.`); +}; diff --git a/developer/document/style/theme_RT.js b/developer/document/style/theme_RT.js index 937ceba..63fcec5 100644 --- a/developer/document/style/theme_RT.js +++ b/developer/document/style/theme_RT.js @@ -1,5 +1,5 @@ /* - Provides the color palette for the RT theme. + Provides the color palette and layout layout for the RT theme. Registers itself as the active system theme upon load. */ function theme_RT(){ @@ -11,7 +11,7 @@ function theme_RT(){ foreground: 'hsl(42, 100%, 80%)', accent: 'hsl(42, 100%, 50%)', faded: 'hsl(42, 100%, 20%)', - highlight: 'hsl(42, 100%, 90%)' + highlight: 'hsl(42, 100%, 90%)', }; } diff --git a/developer/document/style/toc.js b/developer/document/style/toc.js deleted file mode 100644 index 220afa6..0000000 --- a/developer/document/style/toc.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - Generates a Table of Contents. - Inserts it at the very top of the document body. -*/ -window.StyleRT = window.StyleRT || {}; - -window.StyleRT.toc = function() { - const RT = window.StyleRT; - // Use 'pipeline' token if available, otherwise silent - const debug = RT.debug ? RT.debug.log.bind(RT.debug) : () => {}; - - debug('pipeline', 'Generating TOC...'); - - // 1. Create Container (reusing 'page' class so it picks up your gold style) - const container = document.createElement('div'); - container.className = 'page'; - container.id = 'rt-toc'; - - // 2. Title - const title = document.createElement('h1'); - title.textContent = 'Table of Contents'; - title.style.textAlign = 'center'; - container.appendChild(title); - - // 3. Build List - const list = document.createElement('ul'); - document.querySelectorAll('h1').forEach((header, i) => { - if (header === title) return; - if (!header.id) header.id = `section-${i}`; - - const li = document.createElement('li'); - const a = document.createElement('a'); - a.href = `#${header.id}`; - a.textContent = header.textContent; - a.style.textDecoration = 'none'; - a.style.color = 'inherit'; - - li.appendChild(a); - list.appendChild(li); - }); - - container.appendChild(list); - - // 4. Insert at Top (Prepend) - document.body.insertBefore(container, document.body.firstChild); -}; diff --git a/developer/document/style/utility.js b/developer/document/style/utility.js index 4bf452f..8cba0e6 100644 --- a/developer/document/style/utility.js +++ b/developer/document/style/utility.js @@ -10,8 +10,8 @@ window.StyleRT = window.StyleRT || {}; // --- DEBUG SYSTEM --- window.StyleRT.debug = { - // Add tokens here to enable specific logs: 'RT_code', 'physics', 'pipeline', 'layout' - active_tokens: new Set(['pipeline', 'layout']), + // Add tokens here to enable specific logs: 'RT_code', 'layout', 'style', 'layout' + active_tokens: new Set(['style', 'layout']), log: function(token, message) { if (this.active_tokens.has(token)) { @@ -36,7 +36,7 @@ window.StyleRT.utility = { // --- FONT PHYSICS --- measure_ink_ratio: function(target_font, ref_font = null) { const debug = window.StyleRT.debug; - debug.log('physics', `Measuring ink ratio for ${target_font}`); + debug.log('layout', `Measuring ink ratio for ${target_font}`); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); @@ -59,7 +59,7 @@ window.StyleRT.utility = { const target_m = get_metrics(target_font); const ratio = ref_m.ascent / target_m.ascent; - debug.log('physics', `Ink Ratio calculated: ${ratio.toFixed(3)}`); + debug.log('layout', `Ink Ratio calculated: ${ratio.toFixed(3)}`); return { ratio: ratio, @@ -77,7 +77,7 @@ window.StyleRT.utility = { if (numbers && numbers.length >= 3) { const lightness = parseInt(numbers[2]); const is_light = lightness > 50; - debug.log('color_physics', `HSL ${color_string} -> Lightness ${lightness}% -> ${is_light ? 'LIGHT' : 'DARK'}`); + debug.log('color_layout', `HSL ${color_string} -> Lightness ${lightness}% -> ${is_light ? 'LIGHT' : 'DARK'}`); return is_light; } } @@ -85,7 +85,7 @@ window.StyleRT.utility = { // 2. RGB Check const rgb = color_string.match(/\d+/g); if (!rgb) { - debug.warn('color_physics', `Failed to parse color: "${color_string}". Defaulting to Light.`); + debug.warn('color_layout', `Failed to parse color: "${color_string}". Defaulting to Light.`); return true; } @@ -95,7 +95,7 @@ window.StyleRT.utility = { const luma = (r * 299 + g * 587 + b * 114) / 1000; const is_light = luma > 128; - debug.log('color_physics', `RGB (${r},${g},${b}) -> Luma ${luma.toFixed(1)} -> ${is_light ? 'LIGHT' : 'DARK'}`); + debug.log('color_layout', `RGB (${r},${g},${b}) -> Luma ${luma.toFixed(1)} -> ${is_light ? 'LIGHT' : 'DARK'}`); return is_light; },