/*
- Element/endnote.js
- Processes <RT·endnote> tags inline and dumps them when <RT·endnotes> is encountered.
+ Element/grid.js
+ Compiles semantic tabular structures into a Cartesian GridState.
*/
-(function(){
+(function() {
+ if (!window.RT) return;
- if(!window.RT) return;
-
- const apply_style = function(link, config) {
- link.style.cursor = 'pointer';
- link.style.color = config.brand_link || '#0056b3';
- link.style.textDecoration = 'none';
- };
-
- const apply_list_style = function(list_container, config) {
- list_container.style.marginTop = '1rem';
- list_container.style.borderTop = '1px solid ' + (config.surface_3 || '#ccc');
- list_container.style.paddingTop = '1rem';
- list_container.style.listStyle = 'none';
- list_container.style.paddingLeft = '0';
- list_container.style.margin = '0';
- };
-
- function process_endnotes(){
- const config = window.RT.layout_config || {};
- const article = document.querySelector('RT·article, rt·article, RT·memo, rt·memo');
-
- if(!article) return;
-
- const initial_make = document.createElement('RT·counter·make');
- initial_make.setAttribute('counter', 'EndNoteCounter');
- initial_make.setAttribute('style', 'CountingNumber');
- initial_make.setAttribute('on-first-step', '0');
- article.insertBefore(initial_make, article.firstChild);
-
- const nodes = document.querySelectorAll('RT·endnote, rt·endnote, RT-endnote, rt-endnote, RT·endnotes, rt·endnotes, RT-endnotes, rt-endnotes');
-
- let endnote_buffer = [];
- let anchor_id_counter = 1;
-
- for(let i = 0; i < nodes.length; i++){
- const node = nodes[i];
- const tag = node.tagName.toLowerCase();
-
- if(tag === 'rt·endnote' || tag === 'rt-endnote'){
- const snap_name = 'endnote_cite_' + anchor_id_counter;
- const ref_text = node.innerHTML;
-
- const step = document.createElement('RT·counter·step');
- step.setAttribute('counter', 'EndNoteCounter');
+ class GridState {
+ constructor() {
+ this.cells = [];
+ this.max_x = 0;
+ this.max_y = 0;
+ }
- const snapshot = document.createElement('RT·counter·snapshot');
- snapshot.setAttribute('counter', 'EndNoteCounter');
- snapshot.setAttribute('snapshot', snap_name);
+ insert(cell_data) {
+ this.cells.push(cell_data);
+ if (cell_data.x_extent > this.max_x) this.max_x = cell_data.x_extent;
+ if (cell_data.y_extent > this.max_y) this.max_y = cell_data.y_extent;
+ }
+ }
- const link = document.createElement('a');
- link.href = '#note_' + anchor_id_counter;
- link.id = 'cite_' + anchor_id_counter;
- link.innerHTML = '[<RT·counter·read snapshot="' + snap_name + '"></RT·counter·read>]';
-
- apply_style(link, config);
+ function pad_headers(grid_state) {
+ const max_x = grid_state.max_x;
+ const max_y = grid_state.max_y;
+
+ // Pad horizontal headers (x-label)
+ const x_labels = grid_state.cells.filter(c => c.type === 'x-label');
+ if (x_labels.length > 0) {
+ const header_y = x_labels[0].y;
+ const existing_xs = new Set(x_labels.map(c => c.x));
+ for (let i = 0; i <= max_x; i++) {
+ if (!existing_xs.has(i)) {
+ const empty_el = document.createElement('RT·e');
+ empty_el.textContent = '';
+ grid_state.insert({
+ element: empty_el, type: 'x-label',
+ x: i, y: header_y, x_extent: i, y_extent: header_y
+ });
+ }
+ }
+ }
- step.appendChild(snapshot);
- step.appendChild(link);
+ // Pad vertical headers (y-label)
+ const y_labels = grid_state.cells.filter(c => c.type === 'y-label');
+ if (y_labels.length > 0) {
+ const header_x = y_labels[0].x;
+ const existing_ys = new Set(y_labels.map(c => c.y));
+ for (let i = 0; i <= max_y; i++) {
+ if (!existing_ys.has(i)) {
+ const empty_el = document.createElement('RT·e');
+ empty_el.textContent = '';
+ grid_state.insert({
+ element: empty_el, type: 'y-label',
+ x: header_x, y: i, x_extent: header_x, y_extent: i
+ });
+ }
+ }
+ }
- node.parentNode.replaceChild(step, node);
+ // Pad tuple names (name)
+ const names = grid_state.cells.filter(c => c.type === 'name');
+ if (names.length > 0) {
+ const name_x = names[0].x;
+ const existing_ys = new Set(names.map(c => c.y));
+ for (let i = 0; i <= max_y; i++) {
+ if (!existing_ys.has(i)) {
+ const empty_el = document.createElement('RT·e');
+ empty_el.textContent = '';
+ grid_state.insert({
+ element: empty_el, type: 'name',
+ x: name_x, y: i, x_extent: name_x, y_extent: i
+ });
+ }
+ }
+ }
+ }
- endnote_buffer.push({ id: anchor_id_counter, text: ref_text, snap: snap_name });
- anchor_id_counter++;
+ const apply_style = function(el, cell, is_transposed, options, config) {
+ el.style.padding = '0.25rem 0.5rem';
+ el.style.margin = '0';
+ el.style.lineHeight = '1.3';
- } else if(tag === 'rt·endnotes' || tag === 'rt-endnotes'){
- if(endnote_buffer.length === 0){
- node.parentNode.removeChild(node);
- continue;
- }
+ if (cell.type === 'x-label' || cell.type === 'y-label' || cell.type === 'name') {
+ el.style.fontWeight = '600';
+ }
- const frag = document.createDocumentFragment();
+ // Direct cell boundary mapping handles continuous lines if cells are padded
+ if (cell.type === 'x-label') {
+ if (is_transposed) el.style.borderRight = '2px solid ' + (config.border_strong || '#000');
+ else el.style.borderBottom = '2px solid ' + (config.border_strong || '#000');
+ }
+ if (cell.type === 'y-label') {
+ if (is_transposed) el.style.borderBottom = '2px solid ' + (config.border_strong || '#000');
+ else el.style.borderRight = '2px solid ' + (config.border_strong || '#000');
+ }
+ if (cell.type === 'name') {
+ if (is_transposed) el.style.borderBottom = '1px solid ' + (config.border_faint || '#ccc');
+ else el.style.borderRight = '1px solid ' + (config.border_faint || '#ccc');
+ }
- const pb = document.createElement('RT·page-break');
- frag.appendChild(pb);
+ 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';
+ }
- const header = document.createElement('h1');
- header.innerText = 'Endnotes';
- frag.appendChild(header);
+ if (options && options.no_wrap) {
+ el.style.whiteSpace = 'nowrap';
+ el.style.padding = '0.15rem 0.5rem';
+ }
+ };
- const list_container = document.createElement('ul');
- list_container.className = 'RT_endnote_list';
- apply_list_style(list_container, config);
+ function project_grid(container_node, grid_state, model, options = {}) {
+ const config = window.RT.layout_config || {};
+ switch (model) {
+ case 'html-grid-direct':
+ return render_model_html_standard(container_node, grid_state, options, false, config);
+ case 'html-grid-transpose':
+ return render_model_html_standard(container_node, grid_state, options, true, config);
+ case 'html-grid-dictionary':
+ return render_model_html_dictionary(container_node, grid_state, options, config);
+ }
+ }
- for(let j = 0; j < endnote_buffer.length; j++){
- const item = endnote_buffer[j];
+ function render_model_html_standard(container_node, grid_state, options, is_transposed, config) {
+ const wrapper = document.createElement('div');
+ wrapper.style.display = 'grid';
+ wrapper.style.justifyContent = 'start';
+ wrapper.className = `RT_grid_container ${options.css_class || ''}`;
+
+ if (options.delimiters) {
+ wrapper.style.borderLeft = '2px solid ' + (config.content_main || '#000');
+ wrapper.style.borderRight = '2px solid ' + (config.content_main || '#000');
+ wrapper.style.borderRadius = '5px';
+ wrapper.style.padding = '0.2rem';
+ wrapper.style.margin = '1rem 0';
+ } else {
+ wrapper.style.margin = '1.5rem 0';
+ }
- const li = document.createElement('li');
- li.id = 'note_' + item.id;
- li.style.display = 'flex';
- li.style.marginBottom = '0.5rem';
+ grid_state.cells.forEach(cell => {
+ let render_x = is_transposed ? cell.y : cell.x;
+ let render_y = is_transposed ? cell.x : cell.y;
+ let render_x_extent = is_transposed ? cell.y_extent : cell.x_extent;
+ let render_y_extent = is_transposed ? cell.x_extent : cell.y_extent;
+
+ const el = cell.element;
+ 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}`;
+
+ apply_style(el, cell, is_transposed, options, config);
+ wrapper.appendChild(el);
+ });
+
+ container_node.replaceWith(wrapper);
+ execute_two_pass_measurement(wrapper, options);
+ }
- const left_div = document.createElement('div');
- left_div.style.marginRight = '0.5rem';
- left_div.innerHTML = '[<RT·counter·read snapshot="' + item.snap + '"></RT·counter·read>]';
+ function render_model_html_dictionary(container_node, grid_state, options, config) {
+ 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}`;
+
+ apply_style(el, cell, false, options, config);
+ if (cell.type === 'data') el.style.textAlign = 'left';
+
+ wrapper.appendChild(el);
+ });
+
+ container_node.replaceWith(wrapper);
+ execute_two_pass_measurement(wrapper, options);
+ }
- const right_div = document.createElement('div');
- const return_link = document.createElement('a');
- return_link.href = '#cite_' + item.id;
- return_link.style.textDecoration = 'none';
- return_link.innerHTML = '↩';
- return_link.style.marginLeft = '0.5em';
+ function execute_two_pass_measurement(wrapper, options) {
+ requestAnimationFrame(() => {
+ if (options.wrap_check) {
+ const data_cells = wrapper.querySelectorAll('.RT_grid_data, .RT_grid_name');
+ data_cells.forEach(cell => {
+ const computed = window.getComputedStyle(cell);
+ const line_height = parseFloat(computed.lineHeight) || (parseFloat(computed.fontSize) * 1.2);
+ 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';
+ }
+ });
+ }
+ });
+ }
- right_div.innerHTML = item.text + ' ';
- right_div.appendChild(return_link);
+ function parse_coordinate(attr_value, current_val) {
+ if (!attr_value) return { start: current_val, extent: current_val };
+ const parts = attr_value.split('-');
+ const start = parseInt(parts[0], 10);
+ const extent = parts.length > 1 ? parseInt(parts[1], 10) : start;
+ return { start, extent };
+ }
- li.appendChild(left_div);
- li.appendChild(right_div);
- list_container.appendChild(li);
+ RT.Element.add(function process_grids() {
+ document.querySelectorAll('RT·grid, rt·grid').forEach(node => {
+ const state = new GridState();
+ const model = node.getAttribute('model') || 'html-grid-direct';
+ const major_axis = node.getAttribute('major') || 'x';
+
+ let cursor_x = 0;
+ let cursor_y = 0;
+
+ node.querySelectorAll('RT·e, rt·e').forEach(e => {
+ const attr_x = e.getAttribute('x');
+ const attr_y = e.getAttribute('y');
+
+ if (major_axis === 'x') {
+ if (attr_y && !attr_x && attr_y !== String(cursor_y)) cursor_x = 0;
+ } else {
+ if (attr_x && !attr_y && attr_x !== String(cursor_x)) cursor_y = 0;
}
- frag.appendChild(list_container);
-
- const counter_reset = document.createElement('RT·counter·make');
- counter_reset.setAttribute('counter', 'EndNoteCounter');
- counter_reset.setAttribute('style', 'CountingNumber');
- counter_reset.setAttribute('on-first-step', '0');
- frag.appendChild(counter_reset);
+ const parsed_x = parse_coordinate(attr_x, cursor_x);
+ const parsed_y = parse_coordinate(attr_y, cursor_y);
+
+ cursor_x = parsed_x.start;
+ cursor_y = parsed_y.start;
+
+ const type = e.getAttribute('type') || 'data';
+ state.insert({
+ element: e.cloneNode(true), type: type,
+ x: cursor_x, y: cursor_y,
+ x_extent: parsed_x.extent, y_extent: parsed_y.extent
+ });
+
+ if (major_axis === 'x') cursor_x = parsed_x.extent + 1;
+ else cursor_y = parsed_y.extent + 1;
+ });
+
+ pad_headers(state);
+ project_grid(node, state, model, { wrap_check: true });
+ });
+
+ document.querySelectorAll('RT·dictionary, rt·dictionary').forEach(node => {
+ const state = new GridState();
+ 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: '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++;
+ }
- // Unpack fragment directly into the article context to enable native UL splitting
- node.parentNode.replaceChild(frag, node);
+ node.querySelectorAll('RT·entry, rt·entry').forEach(entry => {
+ const k = document.createElement('RT·e');
+ k.textContent = entry.getAttribute('key') || '';
+
+ 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: y });
+ state.insert({ element: v, type: 'data', x: 1, y: y, x_extent: 1, y_extent: y });
+ y++;
+ });
+
+ pad_headers(state);
+ project_grid(node, state, 'html-grid-dictionary', { wrap_check: true });
+ });
+
+ document.querySelectorAll('RT·relation, rt·relation').forEach(node => {
+ const state = new GridState();
+ const layout_intent = node.getAttribute('layout-intention') || 'row-tuple';
+ const model = layout_intent === 'column-tuple' ? 'html-grid-transpose' : 'html-grid-direct';
+
+ let offset_x = 0;
+ let offset_y = 0;
+
+ const col_head = node.querySelector('RT·tuple-meta, rt·tuple-meta');
+ if (col_head) {
+ offset_y = 1;
+ 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: 'x-label', x: cx, y: 0, x_extent: cx, y_extent: 0 });
+ cx++;
+ });
+ }
- endnote_buffer = [];
+ let y = offset_y;
+ node.querySelectorAll('RT·tuple, rt·tuple').forEach(tuple => {
+ let x = 0;
+ const name = tuple.querySelector('RT·name, rt·name');
+ if (name) {
+ offset_x = 1;
+ state.insert({ element: name.cloneNode(true), type: 'name', x: 0, y: y, x_extent: 0, y_extent: y });
+ }
+ x = offset_x;
+ tuple.querySelectorAll('RT·e, rt·e').forEach(e => {
+ state.insert({ element: e.cloneNode(true), type: 'data', x: x, y: y, x_extent: x, y_extent: y });
+ x++;
+ });
+ y++;
+ });
+
+ pad_headers(state);
+ project_grid(node, state, model, { wrap_check: true });
+ });
+
+ document.querySelectorAll('RT·matrix, rt·matrix').forEach(node => {
+ const state = new GridState();
+ const layout_intent = node.getAttribute('layout-intention') || 'row-vector';
+ const model = layout_intent === 'column-vector' ? 'html-grid-transpose' : 'html-grid-direct';
+
+ let offset_j = 0;
+ let offset_i = 0;
+
+ const vector_meta = node.querySelector('RT·vector-meta, rt·vector-meta');
+ if (vector_meta) {
+ offset_i = 1;
+ let cj = node.querySelector('RT·name, rt·name') ? 1 : 0;
+ vector_meta.querySelectorAll('RT·label, rt·label').forEach(e => {
+ state.insert({ element: e.cloneNode(true), type: 'x-label', x: cj, y: 0, x_extent: cj, y_extent: 0 });
+ cj++;
+ });
}
- }
- }
- window.RT.Element.add(process_endnotes);
+ let i = offset_i;
+ node.querySelectorAll('RT·vector, rt·vector').forEach(vec => {
+ let j = 0;
+ const name = vec.querySelector('RT·name, rt·name');
+ if (name) {
+ offset_j = 1;
+ state.insert({ element: name.cloneNode(true), type: 'name', x: 0, y: i, x_extent: 0, y_extent: i });
+ }
+ j = offset_j;
+ vec.querySelectorAll('RT·e, rt·e').forEach(e => {
+ state.insert({ element: e.cloneNode(true), type: 'data', x: j, y: i, x_extent: j, y_extent: i });
+ j++;
+ });
+ i++;
+ });
+
+ pad_headers(state);
+ project_grid(node, state, model, { wrap_check: false, no_wrap: true, delimiters: true });
+ });
+ });
})();
/*
Element/grid.js
Compiles semantic tabular structures into a Cartesian GridState.
+ [INSTRUMENTED DIAGNOSTIC BUILD]
*/
(function() {
if (!window.RT) return;
+ console.warn(">>> [RT GRID DIAGNOSTIC] grid.js parsed by browser at: " + new Date().toISOString() + " <<<");
+
class GridState {
constructor() {
this.cells = [];
}
}
- function pad_headers(grid_state) {
- const headers = grid_state.cells.filter(c => c.type === 'x-label');
- if (headers.length === 0) return;
-
- const max_x = Math.max(...grid_state.cells.map(c => c.x_extent));
- const min_header_x = Math.min(...headers.map(c => c.x));
- const existing_xs = new Set(headers.map(c => c.x));
-
- for (let i = min_header_x; i <= max_x; i++) {
- if (!existing_xs.has(i)) {
- const empty_el = document.createElement('RT·e');
- empty_el.innerHTML = ' ';
- grid_state.insert({
- element: empty_el,
- type: 'x-label',
- x: i,
- y: 0,
- x_extent: i,
- y_extent: 0
- });
- }
- }
- }
-
const apply_style = function(el, cell, is_transposed, options, config) {
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') {
+ const type = cell.type;
+ const border_strong = '2px solid ' + (config.border_strong || '#000');
+ const border_faint = '1px solid ' + (config.border_faint || '#ccc');
+
+ if (type === 'x-label' || type === 'y-label' || type === 'name' || type === 'corner') {
el.style.fontWeight = '600';
}
- if (cell.type === 'x-label') {
+ if (type === 'x-label') {
+ if (is_transposed) el.style.borderRight = border_strong;
+ else el.style.borderBottom = border_strong;
+ }
+
+ if (type === 'y-label') {
+ if (is_transposed) el.style.borderBottom = border_strong;
+ else el.style.borderRight = border_strong;
+ }
+
+ if (type === 'name') {
+ if (is_transposed) el.style.borderBottom = border_faint;
+ else el.style.borderRight = border_faint;
+ }
+
+ if (type === 'corner') {
if (is_transposed) {
- el.style.borderRight = '2px solid ' + (config.border_strong || '#000');
+ el.style.borderRight = border_strong;
+ el.style.borderBottom = border_faint;
} else {
- el.style.borderBottom = '2px solid ' + (config.border_strong || '#000');
+ el.style.borderBottom = border_strong;
+ el.style.borderRight = border_faint;
}
}
-
- if (cell.type === 'name') {
- el.style.borderRight = '1px solid ' + (config.border_faint || '#ccc');
- }
- if (cell.type === 'data') el.style.textAlign = 'center';
- if (cell.type === 'x-label') el.style.textAlign = 'center';
+ if (type === 'data' || type === 'x-label') {
+ el.style.textAlign = 'center';
+ }
- if (cell.type === (is_transposed ? 'x-label' : 'y-label') || cell.type === 'name') {
+ if ((is_transposed ? type === 'x-label' : type === 'y-label') || type === 'name' || type === 'corner') {
el.style.textAlign = 'right';
el.style.paddingRight = '0.5rem';
}
}
RT.Element.add(function process_grids() {
- document.querySelectorAll('RT·grid, rt·grid').forEach(node => {
+ console.error(">>> [RT GRID DIAGNOSTIC] process_grids() triggered by stage_manager <<<");
+
+ // 1. Native Grid
+ document.querySelectorAll('RT·grid, rt·grid, RT-grid, rt-grid').forEach(node => {
const state = new GridState();
const model = node.getAttribute('model') || 'html-grid-direct';
const major_axis = node.getAttribute('major') || 'x';
let cursor_x = 0;
let cursor_y = 0;
- node.querySelectorAll('RT·e, rt·e').forEach(e => {
+ node.querySelectorAll('RT·e, rt·e, RT-e, rt-e').forEach(e => {
const attr_x = e.getAttribute('x');
const attr_y = e.getAttribute('y');
else cursor_y = parsed_y.extent + 1;
});
- pad_headers(state);
project_grid(node, state, model, { wrap_check: true });
});
- document.querySelectorAll('RT·dictionary, rt·dictionary').forEach(node => {
+ // 2. Dictionary
+ document.querySelectorAll('RT·dictionary, rt·dictionary, RT-dictionary, rt-dictionary').forEach(node => {
const state = new GridState();
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 || '';
+ const h1 = document.createElement('RT·e'); h1.textContent = key_label || 'X';
+ const h2 = document.createElement('RT·e'); h2.textContent = def_label || 'X';
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++;
}
- node.querySelectorAll('RT·entry, rt·entry').forEach(entry => {
+ node.querySelectorAll('RT·entry, rt·entry, RT-entry, rt-entry').forEach(entry => {
const k = document.createElement('RT·e');
- k.textContent = entry.getAttribute('key') || '';
+ k.textContent = entry.getAttribute('key') || 'X';
const v = document.createElement('RT·e');
v.innerHTML = entry.innerHTML;
y++;
});
- pad_headers(state);
project_grid(node, state, 'html-grid-dictionary', { wrap_check: true });
});
- document.querySelectorAll('RT·relation, rt·relation').forEach(node => {
+ // 3. Relation
+ document.querySelectorAll('RT·relation, rt·relation, RT-relation, rt-relation').forEach(node => {
+ console.warn(">>> [RT GRID DIAGNOSTIC] <RT·relation> node found <<<");
+
const state = new GridState();
const layout_intent = node.getAttribute('layout-intention') || 'row-tuple';
const model = layout_intent === 'column-tuple' ? 'html-grid-transpose' : 'html-grid-direct';
+ const tuples = node.querySelectorAll('RT·tuple, rt·tuple, RT-tuple, rt-tuple');
+
+ let row_labels_debug = [];
+ let has_any_name = false;
+
+ tuples.forEach(tuple => {
+ const names = tuple.querySelectorAll('RT·name, rt·name, RT-name, rt-name');
+ if (names.length > 0) {
+ has_any_name = true;
+ let sublist = [];
+ names.forEach(n => sublist.push(n.textContent.trim()));
+ row_labels_debug.push(sublist);
+ } else {
+ row_labels_debug.push(['X']);
+ }
+ });
- let offset_x = 0;
+ console.error(`>>> [RT GRID DIAGNOSTIC] Relation row labels: ${JSON.stringify(row_labels_debug)} <<<`);
+
+ let offset_x = has_any_name ? 1 : 0;
let offset_y = 0;
- const col_head = node.querySelector('RT·tuple-meta, rt·tuple-meta');
+ const col_head = node.querySelector('RT·tuple-meta, rt·tuple-meta, RT-tuple-meta, rt-tuple-meta');
if (col_head) {
offset_y = 1;
- let cx = node.querySelector('RT·name, rt·name') ? 1 : 0;
- col_head.querySelectorAll('RT·e, rt·e').forEach(e => {
+ let cx = offset_x;
+ col_head.querySelectorAll('RT·e, rt·e, RT-e, rt-e').forEach(e => {
state.insert({ element: e.cloneNode(true), type: 'x-label', x: cx, y: 0, x_extent: cx, y_extent: 0 });
cx++;
});
+
+ if (has_any_name) {
+ const corner_el = document.createElement('RT·e');
+ corner_el.textContent = 'X';
+ state.insert({ element: corner_el, type: 'corner', x: 0, y: 0, x_extent: 0, y_extent: 0 });
+ }
}
let y = offset_y;
- node.querySelectorAll('RT·tuple, rt·tuple').forEach(tuple => {
- let x = 0;
- const name = tuple.querySelector('RT·name, rt·name');
- if (name) {
- offset_x = 1;
- state.insert({ element: name.cloneNode(true), type: 'name', x: 0, y: y, x_extent: 0, y_extent: y });
+ tuples.forEach(tuple => {
+ if (has_any_name) {
+ const names = tuple.querySelectorAll('RT·name, rt·name, RT-name, rt-name');
+ const name_container = document.createElement('RT·e');
+ if (names.length > 0) {
+ names.forEach(n => name_container.appendChild(n.cloneNode(true)));
+ } else {
+ name_container.textContent = 'X';
+ }
+ state.insert({ element: name_container, type: 'name', x: 0, y: y, x_extent: 0, y_extent: y });
}
- x = offset_x;
- tuple.querySelectorAll('RT·e, rt·e').forEach(e => {
+
+ let x = offset_x;
+ tuple.querySelectorAll('RT·e, rt·e, RT-e, rt-e').forEach(e => {
state.insert({ element: e.cloneNode(true), type: 'data', x: x, y: y, x_extent: x, y_extent: y });
x++;
});
y++;
});
- pad_headers(state);
project_grid(node, state, model, { wrap_check: true });
});
- document.querySelectorAll('RT·matrix, rt·matrix').forEach(node => {
+ // 4. Matrix
+ document.querySelectorAll('RT·matrix, rt·matrix, RT-matrix, rt-matrix').forEach(node => {
const state = new GridState();
const layout_intent = node.getAttribute('layout-intention') || 'row-vector';
const model = layout_intent === 'column-vector' ? 'html-grid-transpose' : 'html-grid-direct';
+ const vectors = node.querySelectorAll('RT·vector, rt·vector, RT-vector, rt-vector');
+
+ let row_labels_debug = [];
+ let has_any_name = false;
+
+ vectors.forEach(vec => {
+ const names = vec.querySelectorAll('RT·name, rt·name, RT-name, rt-name');
+ if (names.length > 0) {
+ has_any_name = true;
+ let sublist = [];
+ names.forEach(n => sublist.push(n.textContent.trim()));
+ row_labels_debug.push(sublist);
+ } else {
+ row_labels_debug.push(['X']);
+ }
+ });
- let offset_j = 0;
- let offset_i = 0;
+ let offset_x = has_any_name ? 1 : 0;
+ let offset_y = 0;
- const vector_meta = node.querySelector('RT·vector-meta, rt·vector-meta');
+ const vector_meta = node.querySelector('RT·vector-meta, rt·vector-meta, RT-vector-meta, rt-vector-meta');
if (vector_meta) {
- offset_i = 1;
- let cj = node.querySelector('RT·name, rt·name') ? 1 : 0;
- vector_meta.querySelectorAll('RT·label, rt·label').forEach(e => {
- state.insert({ element: e.cloneNode(true), type: 'x-label', x: cj, y: 0, x_extent: cj, y_extent: 0 });
- cj++;
+ offset_y = 1;
+ let cx = offset_x;
+ vector_meta.querySelectorAll('RT·label, rt·label, RT-label, rt-label').forEach(e => {
+ state.insert({ element: e.cloneNode(true), type: 'x-label', x: cx, y: 0, x_extent: cx, y_extent: 0 });
+ cx++;
});
+
+ if (has_any_name) {
+ const corner_el = document.createElement('RT·e');
+ corner_el.textContent = 'X';
+ state.insert({ element: corner_el, type: 'corner', x: 0, y: 0, x_extent: 0, y_extent: 0 });
+ }
}
- let i = offset_i;
- node.querySelectorAll('RT·vector, rt·vector').forEach(vec => {
- let j = 0;
- const name = vec.querySelector('RT·name, rt·name');
- if (name) {
- offset_j = 1;
- state.insert({ element: name.cloneNode(true), type: 'name', x: 0, y: i, x_extent: 0, y_extent: i });
+ let y = offset_y;
+ vectors.forEach(vec => {
+ if (has_any_name) {
+ const names = vec.querySelectorAll('RT·name, rt·name, RT-name, rt-name');
+ const name_container = document.createElement('RT·e');
+ if (names.length > 0) {
+ names.forEach(n => name_container.appendChild(n.cloneNode(true)));
+ } else {
+ name_container.textContent = 'X';
+ }
+ state.insert({ element: name_container, type: 'name', x: 0, y: y, x_extent: 0, y_extent: y });
}
- j = offset_j;
- vec.querySelectorAll('RT·e, rt·e').forEach(e => {
- state.insert({ element: e.cloneNode(true), type: 'data', x: j, y: i, x_extent: j, y_extent: i });
- j++;
+
+ let x = offset_x;
+ vec.querySelectorAll('RT·e, rt·e, RT-e, rt-e').forEach(e => {
+ state.insert({ element: e.cloneNode(true), type: 'data', x: x, y: y, x_extent: x, y_extent: y });
+ x++;
});
- i++;
+ y++;
});
- pad_headers(state);
project_grid(node, state, model, { wrap_check: false, no_wrap: true, delimiters: true });
});
});
-#!/usr/bin/env bash
+#!/usr/bin/env python3
# setup - enter a project role environment
-# (must be sourced)
-
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
- echo "${script_afp}:: This script must be sourced, not executed."
- exit 1
-fi
-
-project_roles="administrator consumer developer tester"
-
-print_usage(){
- echo "usage: . setup <role>"
- echo "known roles: ${project_roles}"
-}
-
-if [ -z "${1:-}" ] || [ "${1}" == "-h" ] || [ "${1}" == "--help" ]; then
- print_usage
- return 0
-fi
-
-role_is_valid=false
-for r in ${project_roles}; do
- if [ "${1}" == "${r}" ]; then
- role_is_valid=true
- break
- fi
-done
-
-if [ "${role_is_valid}" == "false" ]; then
- echo "setup: unrecognized role or option '${1}'"
- print_usage
- return 1
-fi
-
-# setup the project
-#
- source shared/tool/setup
- if [[ -f "shared/authored/setup" ]]; then
- source shared/authored/setup
- fi
-
-# setup the role
-#
- export ROLE="${1}"
- export ROLE_HOME="$REPO_HOME/$ROLE"
- echo ROLE_HOME "$ROLE_HOME"
-
- tool="${ROLE_HOME}/tool"
- if [[ ":${PATH}:" != *":${tool}:"* ]]; then
- export PATH="${tool}:${PATH}"
- fi
-
- export SETUP="${ROLE}/tool/setup"
-
- cd "${ROLE}" || return 1
- if [ -f "tool/setup" ]; then
- source "tool/setup"
- echo "in environment: ${SETUP}"
- else
- echo "not found: ${SETUP}"
- fi
+
+import os
+import sys
+import argparse
+import tempfile
+
+PROJECT_ROLES = ["administrator", "consumer", "developer", "tester"]
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Enter a project role environment by spawning an isolated subshell."
+ )
+ parser.add_argument("role", choices=PROJECT_ROLES, help="The project role to assume.")
+ args = parser.parse_args()
+
+ env = os.environ.copy()
+
+ # Python-domain logic: Variables and Paths
+ repo_home = env.get("REPO_HOME", os.getcwd())
+ role = args.role
+ role_home = os.path.join(repo_home, role)
+ tool_dir = os.path.join(role_home, "tool")
+ setup_file = os.path.join(role, "tool", "setup")
+
+ env["ROLE"] = role
+ env["ROLE_HOME"] = role_home
+ env["SETUP"] = setup_file
+
+ print(f"ROLE_HOME {role_home}")
+
+ # Python-domain logic: PATH injection
+ path_parts = env.get("PATH", "").split(os.pathsep)
+ if tool_dir not in path_parts:
+ env["PATH"] = f"{tool_dir}{os.pathsep}{env.get('PATH', '')}"
+
+ # Python-domain logic: Directory validation
+ if not os.path.isdir(role):
+ print(f"setup: failed to locate directory for role '{role}'")
+ sys.exit(1)
+
+ # Bash-domain logic: The rcfile only handles operations Python cannot inherit
+ # (sourcing bash functions) and performs the directory change internally to
+ # guarantee the shared scripts are sourced from the project root.
+ bash_logic = [
+ 'if [[ -f ~/.bashrc ]]; then source ~/.bashrc; fi',
+ 'if [[ -f "shared/tool/setup" ]]; then source "shared/tool/setup"; fi',
+ 'if [[ -f "shared/authored/setup" ]]; then source "shared/authored/setup"; fi',
+ f'cd "{role}"',
+ 'if [[ -f "tool/setup" ]]; then',
+ ' source "tool/setup"',
+ f' echo "in environment: {setup_file}"',
+ 'else',
+ f' echo "not found: {setup_file}"',
+ 'fi',
+ 'if [[ -n "${INSIDE_EMACS}" ]] && command -v env_to_emacs >/dev/null 2>&1; then',
+ ' env_to_emacs',
+ 'fi',
+ 'rm -f "${BASH_SOURCE[0]}"'
+ ]
+
+ fd, rcfile_path = tempfile.mkstemp(suffix="-rt-setup.sh")
+ with os.fdopen(fd, "w") as f:
+ f.write("\n".join(bash_logic) + "\n")
+
+ os.execvpe("bash", ["bash", "--rcfile", rcfile_path], env)
+
+if __name__ == "__main__":
+ main()