fixes penchant to orphan headings .. looking good
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 1 Jul 2026 10:27:08 +0000 (10:27 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 1 Jul 2026 10:27:08 +0000 (10:27 +0000)
developer/authored/Manuscript.copy/Document/manual.html
developer/authored/Manuscript.copy/Layout/paginate.js

index d5ff9f2..d9bbc77 100644 (file)
@@ -44,7 +44,7 @@
       </p>
 
       
-      <h1>Manuscript Types</h1>
+      <h1>Manuscript types</h1>
       <p>
         These are the current top level semantic tag environments. They affect the formatting of scoped content. This includes the custom semantic tags, and can also include standard HTML tags.
       </p>
@@ -72,7 +72,7 @@
         </tbody>
       </table>
 
-      <h2>Article Manuscript</h2>
+      <h2>Article manuscript</h2>
 
       <p>Here is an example header for an article</p>
 
         </tbody>
       </table>
 
-      <h3>Layout Environments</h3>
+      <h3>Layout environments</h3>
       <p>
         This can be written inline with text, or as blocks.
         </p>
         </tbody>
       </table>
 
+      <h3>Cross reference</h3>
+      <p>
+        The Note tags provide a two pass mechanism for cross referencing content and page numbers throughout the document.
+      </p>
+      <table>
+        <thead>
+          <tr>
+            <th style="width: 25%;">Tag</th>
+            <th>Description & Arguments</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr>
+            <td><RT·code>&lt;RT·Note·write&gt;</RT·code></td>
+            <td>
+              Records the scoped content and its resolved page number into the reference dictionary.<br>
+              <div class="attr-list">
+                <strong>Attributes:</strong><br>
+                <code>key</code>: Required unique identifier for the note.
+              </div>
+            </td>
+          </tr>
+          <tr>
+            <td><RT·code>&lt;RT·Note·read&gt;</RT·code></td>
+            <td>
+              Retrieves data from a previously recorded note and injects it as innerHTML.<br>
+              <div class="attr-list">
+                <strong>Attributes:</strong><br>
+                <code>key</code>: Required identifier matching a write tag.<br>
+                <code>field</code>: Selects the data to retrieve. Valid options are "content" (the original scoped HTML) or "page" (the computed page number). (Default: "content")
+              </div>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+
       <h3>Annotation</h3>
       <table>
         <thead>
         The <RT·code>&lt;RT·book&gt;</RT·code> container is reserved for multi chapter compilations. It introduces tags designed exclusively for macro level document orchestration. (Does not currently exist, rather using the Article Tech Ref format.)
       </p>
 
-      <h3>Book Specific Tags</h3>
+      <h3>Book specific tags</h3>
       <table>
         <thead>
           <tr>
         </tbody>
       </table>
 
-      <h1>Global Widgets</h1>
+      <h1>Global widgets</h1>
       <table>
         <thead>
           <tr>
index bff6dce..e9d8060 100644 (file)
   // =========================================================
   // PAGINATE 0: CHUNKING & INJECTING STRUCTURE
   // =========================================================
-  paginate_0 = function(){
+  function paginate_0(){
     if(debug.log) debug.log('paginate_0' ,'Running initial document chunking');
 
     const article_seq = document.querySelectorAll('RT·article');
 
     function paginateArticle(article){
       const raw_element_seq = Array.from(article.children).filter(el =>
-        !['SCRIPT' ,'STYLE' ,'RT·PAGE'].includes(el.tagName)
+        !['SCRIPT' ,'STYLE' ,'RT·PAGE'].includes((el.tagName || '').toUpperCase())
       );
 
       if(raw_element_seq.length === 0) return;
               current_batch_seq.push(frame);
               i++; 
             } else {
-              page_seq.push(current_batch_seq);
-              current_batch_seq = [];
-              current_h = 0;
-              raw_element_seq[i] = rest || el; 
+              // Element is split but first chunk fails to fit. Evict any stranded headings.
+              let backtrack_seq = [];
+              let backtrack_h = 0;
+              
+              while(current_batch_seq.length > 0){
+                const last = current_batch_seq[current_batch_seq.length - 1];
+                if(!/^H[1-6]$/i.test(last.tagName)) break;
+                const popped = current_batch_seq.pop();
+                backtrack_seq.unshift(popped);
+                backtrack_h += getElHeight(popped);
+              }
+
+              if(current_batch_seq.length > 0){
+                page_seq.push(current_batch_seq);
+                current_batch_seq = backtrack_seq;
+                current_h = backtrack_h;
+                // Leave 'i' alone to re-evaluate 'el' against the fresh page sequence
+              } else {
+                // If only headings existed, accept the massive frame inline to avoid loops
+                const frame = document.createElement('RT·scroll-frame');
+                frame.style.display = 'block';
+                frame.style.overflowY = 'auto';
+                frame.style.maxHeight = page_height_limit + 'px';
+                frame.appendChild(el);
+                
+                current_batch_seq = backtrack_seq;
+                current_h = backtrack_h;
+                
+                current_batch_seq.push(frame);
+                i++;
+              }
             }
           }
           continue;
         const h = getElHeight(el);
         const is_RT_page_break = el.tagName && el.tagName.toLowerCase() === 'rt·page-break';
 
-        if( (is_RT_page_break || current_h + h > page_height_limit) && current_batch_seq.length > 0 ){
+        // Explicit Page Break Logic - Execute immediately without backward traversal
+        if(is_RT_page_break){
+          if(current_batch_seq.length > 0){
+            page_seq.push(current_batch_seq);
+            current_batch_seq = [];
+            current_h = 0;
+          }
+          i++;
+          continue; 
+        }
+
+        // Standard Dimension Overflow Logic - Check for orphaned headers
+        if( current_h + h > page_height_limit && current_batch_seq.length > 0 ){
           let backtrack_seq = [];
           let backtrack_h = 0;
           
           while(current_batch_seq.length > 0){
             const last = current_batch_seq[current_batch_seq.length - 1];
-            if(!/^H[1-6]/.test(last.tagName)) break;
+            if(!/^H[1-6]$/i.test(last.tagName)) break;
             const popped = current_batch_seq.pop();
             backtrack_seq.unshift(popped);
             backtrack_h += getElHeight(popped);
             current_batch_seq = backtrack_seq;
             current_h = backtrack_h;
           } else {
-            page_seq.push(backtrack_seq);
-            current_batch_seq = [];
-            current_h = 0;
+            // Document structure resolved entirely to sequential headings that breached bounds.
+            current_batch_seq = backtrack_seq;
+            current_h = backtrack_h;
           }
         }
 
       measureContainer.remove();
       measureContainer = null;
     }
-  };
+  }
 
   // =========================================================
   // PAGINATE 1: ABSORB DIMENSIONAL DELTA
   // =========================================================
-  paginate_1 = function(){
+  function paginate_1(){
     if(debug.log) debug.log('paginate_1' ,'Adjusting final page heights after component injections');
 
     const rendered_pages = document.querySelectorAll('RT·page');
         page.style.minHeight = actual_height + 'px';
       }
     });
-  };
+  }
 
   //----------------------------------------
   // Registration upon load