grid repair
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Sun, 2 Aug 2026 14:44:55 +0000 (14:44 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Sun, 2 Aug 2026 14:44:55 +0000 (14:44 +0000)
developer/authored/Manuscript.copy/Element/grid.js
tester/authored/Grid/RT-Manuscript_locator.js [changed from symlink to file mode: 0644]
tester/authored/Grid/test_grid.html

index 11cec85..7fa3ff1 100644 (file)
     }
   }
 
-  // 2. The Physical Projection Engine (Tier 2 -> Tier 3)
+// 2. The Projection Dispatcher (Tier 2 -> Tier 3)
   function project_grid(container_node, grid_state, model, options = {}) {
     const debug = window.RT.Debug || { log: function(){}, error: function(){} };
-    
+
+    switch (model) {
+      case 'html-grid-direct':
+        return render_model_html_standard(container_node, grid_state, options, false);
+      case 'html-grid-transpose':
+        return render_model_html_standard(container_node, grid_state, options, true);
+      case 'html-grid-dictionary':
+        return render_model_html_dictionary(container_node, grid_state, options);
+      default:
+        debug.error('Grid', `Unknown projection model requested: ${model}. Defaulting to direct.`);
+        return render_model_html_standard(container_node, grid_state, options, false);
+    }
+  }
+
+  // 2a. Standard & Transposed Cartesian Layout
+  function render_model_html_standard(container_node, grid_state, options, is_transposed) {
+    const debug = window.RT.Debug || { log: function(){}, error: function(){} };
     const wrapper = document.createElement('div');
     wrapper.style.display = 'grid';
+    wrapper.style.gridAutoColumns = 'max-content';
+    wrapper.style.justifyContent = 'start';
     wrapper.className = `RT_grid_container ${options.css_class || ''}`;
 
     if (options.delimiters) {
       wrapper.style.borderLeft = '2px solid var(--RT·content-main)';
       wrapper.style.borderRight = '2px solid var(--RT·content-main)';
-      wrapper.style.borderRadius = '5px'; // Simulates matrix brackets
-      wrapper.style.padding = '0.5rem';
+      wrapper.style.borderRadius = '5px'; 
+      wrapper.style.padding = '0.2rem';
+      wrapper.style.margin = '1rem 0';
+    } else {
+      wrapper.style.margin = '1.5rem 0';
     }
 
-    const is_transposed = model === 'html-grid-transpose';
-
     grid_state.cells.forEach(cell => {
       let render_x = is_transposed ? cell.y : cell.x;
       let render_y = is_transposed ? cell.x : cell.y;
 
       const el = cell.element;
       
-      // CSS Grid lines are 1-indexed. 
-      // Extent is the rightmost cell index. End line is rightmost index + 2.
       el.style.gridColumn = `${render_x + 1} / ${render_x_extent + 2}`;
       el.style.gridRow = `${render_y + 1} / ${render_y_extent + 2}`;
       el.className = `RT_grid_${cell.type}`;
       
-      // Base geometric formatting
-      el.style.padding = '0.5rem 1rem';
-      if (cell.type === 'column-header' || cell.type === 'row-header') {
+      // Tightened baseline geometry & CSS collision defense
+      el.style.padding = '0.25rem 0.5rem';
+      el.style.margin = '0';
+      el.style.lineHeight = '1.3';
+
+      if (cell.type === 'x-label' || cell.type === 'y-label' || cell.type === 'name') {
+        el.style.fontWeight = '600';
+      }
+      
+      if (cell.type === (is_transposed ? 'y-label' : 'x-label')) {
+         el.style.borderBottom = '2px solid var(--RT·border-strong)';
+      }
+      
+      if (cell.type === 'name') {
+        el.style.borderRight = '1px solid var(--RT·border-faint)';
+      }
+
+      if (cell.type === 'data') el.style.textAlign = 'center';
+      if (cell.type === 'x-label') el.style.textAlign = 'center';
+      
+      if (cell.type === (is_transposed ? 'x-label' : 'y-label') || cell.type === 'name') {
+        el.style.textAlign = 'right';
+        el.style.paddingRight = '0.5rem'; 
+      }
+
+      if (options.no_wrap) {
+        el.style.whiteSpace = 'nowrap';
+        el.style.padding = '0.15rem 0.5rem';
+      }
+
+      wrapper.appendChild(el);
+    });
+
+    container_node.replaceWith(wrapper);
+    execute_two_pass_measurement(wrapper, options, debug);
+  }
+
+  // 2b. Typographic Dictionary Layout
+  function render_model_html_dictionary(container_node, grid_state, options) {
+    const debug = window.RT.Debug || { log: function(){}, error: function(){} };
+    const wrapper = document.createElement('div');
+    wrapper.style.display = 'grid';
+    wrapper.style.gridAutoColumns = 'max-content';
+    wrapper.style.justifyContent = 'start';
+    wrapper.className = `RT_grid_container ${options.css_class || ''}`;
+    wrapper.style.margin = '1.5rem 0';
+
+    grid_state.cells.forEach(cell => {
+      const el = cell.element;
+      
+      el.style.gridColumn = `${cell.x + 1} / ${cell.x_extent + 2}`;
+      el.style.gridRow = `${cell.y + 1} / ${cell.y_extent + 2}`;
+      el.className = `RT_grid_${cell.type}`;
+      
+      // Tightened baseline geometry & CSS collision defense
+      el.style.padding = '0.25rem 0.75rem';
+      el.style.margin = '0';
+      el.style.lineHeight = '1.3';
+
+      if (cell.type === 'x-label' || cell.type === 'y-label' || cell.type === 'name') {
         el.style.fontWeight = '600';
-        if (cell.type === 'column-header') el.style.borderBottom = '2px solid var(--RT·border-strong)';
       }
+      
+      if (cell.type === 'x-label') {
+         el.style.borderBottom = '2px solid var(--RT·border-strong)';
+      }
+      
       if (cell.type === 'name') {
-        el.style.fontWeight = '500';
         el.style.borderRight = '1px solid var(--RT·border-faint)';
+        el.style.textAlign = 'right';
+      }
+      
+      if (cell.type === 'data') {
+        el.style.textAlign = 'left';
       }
 
-      // Matrix forces rigidity
       if (options.no_wrap) {
         el.style.whiteSpace = 'nowrap';
-        el.style.padding = '0.25rem 0.5rem';
       }
 
       wrapper.appendChild(el);
     });
 
     container_node.replaceWith(wrapper);
+    execute_two_pass_measurement(wrapper, options, debug);
+  }
 
-    // Two-Pass Measurement & Overflow Validation
+  // 2c. Common Measurement Logic
+  function execute_two_pass_measurement(wrapper, options, debug) {
     requestAnimationFrame(() => {
       if (options.wrap_check) {
         const data_cells = wrapper.querySelectorAll('.RT_grid_data, .RT_grid_name');
           const computed = window.getComputedStyle(cell);
           const line_height = parseFloat(computed.lineHeight) || (parseFloat(computed.fontSize) * 1.2);
           
-          // Structural wrap detection
-          if (cell.scrollHeight > line_height * 1.5) {
-            cell.style.paddingBottom = '1.5rem'; // Enforce visual row separation
+          const pTop = parseFloat(computed.paddingTop) || 0;
+          const pBot = parseFloat(computed.paddingBottom) || 0;
+          const content_height = cell.scrollHeight - pTop - pBot;
+          
+          if (content_height > line_height * 1.5) {
+            cell.style.paddingBottom = '1.25rem'; 
           }
         });
       }
         const attr_x = e.getAttribute('x');
         const attr_y = e.getAttribute('y');
         
-        // Carriage return logic
+        // Carriage return logic with state-aware redundancy check
         if (major_axis === 'x') {
-          if (attr_y && !attr_x) cursor_x = 0;
+          if (attr_y && !attr_x && attr_y !== String(cursor_y)) cursor_x = 0;
         } else {
-          if (attr_x && !attr_y) cursor_y = 0;
+          if (attr_x && !attr_y && attr_x !== String(cursor_x)) cursor_y = 0;
         }
 
         const parsed_x = parse_coordinate(attr_x, cursor_x);
       const key_label = node.getAttribute('key');
       const def_label = node.getAttribute('definition');
       
+      let y = 0;
+
       if (key_label || def_label) {
         const h1 = document.createElement('RT·e'); h1.textContent = key_label || '';
         const h2 = document.createElement('RT·e'); h2.textContent = def_label || '';
-        state.insert({ element: h1, type: 'column-header', x: 0, y: 0, x_extent: 0, y_extent: 0 });
-        state.insert({ element: h2, type: 'column-header', x: 1, y: 0, x_extent: 1, y_extent: 0 });
+        state.insert({ element: h1, type: 'x-label', x: 0, y: y, x_extent: 0, y_extent: y });
+        state.insert({ element: h2, type: 'x-label', x: 1, y: y, x_extent: 1, y_extent: y });
+        y++;
       }
 
-      let y = (key_label || def_label) ? 1 : 0;
-
       node.querySelectorAll('RT·entry, rt·entry').forEach(entry => {
         const k = document.createElement('RT·e');
         k.textContent = entry.getAttribute('key') || '';
-        k.style.textAlign = 'right';
         
         const v = document.createElement('RT·e');
         v.innerHTML = entry.innerHTML;
         
-        state.insert({ element: k, type: 'name', x: 0, y: y, x_extent: 0, y_extent: 0 });
-        state.insert({ element: v, type: 'data', x: 1, y: y, x_extent: 1, y_extent: 0 });
+        state.insert({ element: k, type: 'name', x: 0, y: y, x_extent: 0, y_extent: y });
+        state.insert({ element: v, type: 'data', x: 1, y: y, x_extent: 1, y_extent: y });
         y++;
       });
 
-      project_grid(node, state, 'html-grid-direct', { wrap_check: true });
+      project_grid(node, state, 'html-grid-dictionary', { wrap_check: true });
     });
 
     // --- C. Relation Parser ---
       let offset_x = 0;
       let offset_y = 0;
 
-      const col_head = node.querySelector('RT·column-header, rt·column-header');
+      const col_head = node.querySelector('RT·x-label, rt·x-label');
       if (col_head) {
         offset_y = 1;
-        let cx = node.querySelector('RT·row-header') || node.querySelector('RT·name') ? 1 : 0;
+        let cx = node.querySelector('RT·y-label, rt·y-label') || node.querySelector('RT·name, rt·name') ? 1 : 0;
         col_head.querySelectorAll('RT·e, rt·e').forEach(e => {
-          state.insert({ element: e.cloneNode(true), type: 'column-header', x: cx, y: 0, x_extent: cx, y_extent: 0 });
+          state.insert({ element: e.cloneNode(true), type: 'x-label', x: cx, y: 0, x_extent: cx, y_extent: 0 });
           cx++;
         });
       }
 
-      const row_head = node.querySelector('RT·row-header, rt·row-header');
+      const row_head = node.querySelector('RT·y-label, rt·y-label');
       if (row_head) {
         offset_x = 1;
         let ry = offset_y;
         row_head.querySelectorAll('RT·e, rt·e').forEach(e => {
-          state.insert({ element: e.cloneNode(true), type: 'row-header', x: 0, y: ry, x_extent: 0, y_extent: ry });
+          state.insert({ element: e.cloneNode(true), type: 'y-label', x: 0, y: ry, x_extent: 0, y_extent: ry });
           ry++;
         });
       }
       let offset_x = 0;
       let offset_y = 0;
 
-      const col_head = node.querySelector('RT·column-header, rt·column-header');
+      const col_head = node.querySelector('RT·x-label, rt·x-label');
       if (col_head) {
         offset_y = 1;
-        let cx = node.querySelector('RT·name') ? 1 : 0;
+        let cx = node.querySelector('RT·name, rt·name') ? 1 : 0;
         col_head.querySelectorAll('RT·e, rt·e').forEach(e => {
-          state.insert({ element: e.cloneNode(true), type: 'column-header', x: cx, y: 0, x_extent: cx, y_extent: 0 });
+          state.insert({ element: e.cloneNode(true), type: 'x-label', x: cx, y: 0, x_extent: cx, y_extent: 0 });
           cx++;
         });
       }
deleted file mode 120000 (symlink)
index 041111fae36bd578aceb4fcc449fb3fdefcc6d15..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1 +0,0 @@
-../RT-Manuscript_locator.js
\ No newline at end of file
new file mode 100644 (file)
index 0000000000000000000000000000000000000000..4a1b9364cf1d40de2cdc261ce2ca52f89598672a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+  direct.js
+
+
+  We have four scenarios
+
+  immediate - used in the RT-style distribution itself (authored, consummer, staged)
+  direct - used in the RT-style project itself, but not in the distribution
+  indirect - the version all Harmony projects use
+  URL_only - always pulls style through a URL, a webserver must be present
+  
+*/
+
+window.RT = window.RT || {};
+
+(function() {
+  const project_name = "RT-Style"; 
+  const path = window.location.pathname;
+  const project_root_index = path.indexOf('/' + project_name + '/');
+  
+  if (project_root_index !== -1) {
+    // substring(0, x) excludes the trailing slash. We must prepend it to the payload.
+    const absolute_project_root = path.substring(0, project_root_index + project_name.length + 1);
+    window.RT.dirpr_library = absolute_project_root + "/consumer/Manuscript";
+  } else {
+    // Fallback for when served via local Python HTTP daemon from the project root
+    window.RT.dirpr_library = "../consumer/made/Manuscript";
+  }
+  
+  document.write(
+      '<script src="'
+      + window.RT.dirpr_library
+      + '/Core/RT-Manuscript_make.js"'
+      + '><\/script>'
+  );
+
+})();
index a7c03d6..c156789 100644 (file)
       <p>Validates the underlying sparse array generation, major axis auto-incrementing, and coordinate overrides.</p>
       
       <RT·grid major="x">
-        <RT·e type="column-header" x="1" y="0">Cycles</RT·e>
-        <RT·e type="row-header" x="0" y="1">Row 1</RT·e>
-        <RT·e type="data" x="1-2" y="1">Spanning Data</RT·e>
-        <RT·e type="data" x="1" y="2">Offset Data</RT·e>
+        <RT·e type="x-label" y="0" x="1"   >Cycles</RT·e>
+        <RT·e type="x-label"               >Period</RT·e>
+        <RT·e type="x-label"           "   >rightmost column</RT·e>
+
+        <RT·e type="y-label" y="1" x="0"   >Row 1</RT·e>
+        <RT·e type="data"          x="1-2" >Spanning Data</RT·e>
+        <RT·e type="data"                  >(1,3)</RT·e>
+
+        <RT·e type="data"    y="2" x="1"   >field 1</RT·e>
+        <RT·e type="data"                  >field 2</RT·e>
+        <RT·e type="data"                  >field 3</RT·e>
+
+        <RT·e type="y-label" y="3"         >row 3</RT·e>
+        <RT·e type="data"                  >(3,1)</RT·e>
+        <RT·e type="data"          x="3"   >(3,3)</RT·e>
       </RT·grid>
+
+      <!-- expected
+
+          in current layout scheme borders do not print
+
+           |          | Cycles  |         | rightmost column  |
+           |  Row 1   |   Spanning Data   |     (1,3)         |
+           |          | field 1 | field 2 |    field 3        |
+           |  row 3   |  (3,1)  | (3,2)   |     (3,3)         | 
+
+     -->
+
     </RT·article>
   </body>
 </html>