counter foundation
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 24 Jun 2026 14:20:42 +0000 (14:20 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 24 Jun 2026 14:20:42 +0000 (14:20 +0000)
18 files changed:
administrator/document/RT-Style_locator.js
administrator/tool/deploy_RT-Style_indirect_locators [deleted file]
administrator/tool/deploy_RT-Style_locators [new file with mode: 0755]
developer/authored/Manuscript.copy/Document/RT-Style_locator.js
developer/authored/Manuscript.copy/Document/style_manual.html
developer/authored/Manuscript.copy/Element/counter.js [new file with mode: 0644]
developer/authored/Manuscript.copy/Layout/article_tech_ref.js
developer/authored/Manuscript.copy/Locator/URL-only.js
developer/authored/Manuscript.copy/Locator/direct.js
developer/authored/Manuscript.copy/Locator/immediate.js
developer/authored/Manuscript.copy/Locator/indirect.js
developer/document/RT-Style_locator.js
developer/document/counter_tags.txt
document/RT-Style_locator.js
shared/document/RT-Style_locator.js
tester/authored/Counter/RT-Style_locator.js [new file with mode: 0644]
tester/authored/Counter/test_0.html [new file with mode: 0644]
tester/authored/test_routine.sh [deleted file]

index 39b2706..2f93eb7 100644 (file)
@@ -1,48 +1,34 @@
 /*
+  direct.js
+
+
   We have four scenarios
 
-  immediate - used in the RT-Style distribution itself (authored, consumer, staged)
-  direct - used in the RT-Style project itself, but not in the distribution
+  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
+  URL_only - always pulls style through a URL, a webserver must be present
   
 */
 
 window.RT = window.RT || {};
 
-// --- Configuration ---
-// Define the consumer project name to allow dynamic local file:// calculation.
-window.RT.project_name = "Harmony"; 
-
-// Fallback URL when served over a network where the project root is not in the URI.
-window.RT.server_url = "http://localhost:8000/shared/linked-project/RT-Style/Manuscript";
-
 (function() {
-  let style_path = window.RT.server_url;
-
-  if (window.RT.project_name) {
-    const path = window.location.pathname;
-    const project_root_index = path.indexOf('/' + window.RT.project_name + '/');
-    
-    if (project_root_index !== -1) {
-      // substring(0, stop) extracts up to the project name, leaving off the trailing slash.
-      // We append the explicit forward slash before navigating into the shared boundary.
-      const absolute_project_root = path.substring(0, project_root_index + window.RT.project_name.length + 1);
-      
-      // The symlink 'RT-Style' already drops us inside the 'consumer/' directory, 
-      // so we proceed directly to 'Manuscript'.
-      style_path = absolute_project_root + "/shared/linked-project/RT-Style/Manuscript";
-    } else {
-      console.warn("RT-Style: Cannot locate project root '/" + window.RT.project_name + "/' in URI. Falling back to server_url.");
-    }
-  }
+  const project_name = "RT-Style"; 
+  const path = window.location.pathname;
+  const project_root_index = path.indexOf('/' + project_name + '/');
   
-  window.RT.dirpr_library = style_path;
+  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";
+  }
   
-  // 1. Inject the loader script
   document.write('<script src="' + window.RT.dirpr_library + '/Core/loader.js"><\/script>');
   
-  // 2. Inject the secondary script block for core dependencies
   document.write(
     '<script>' +
     'window.RT.load("Core/utility");' +
diff --git a/administrator/tool/deploy_RT-Style_indirect_locators b/administrator/tool/deploy_RT-Style_indirect_locators
deleted file mode 100755 (executable)
index 0f98eae..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-import sys
-import os
-import stat
-import shutil
-from pathlib import Path
-
-def deploy_RT_Style_indirect_locators(locator_dir_path):
-    locator_dir = Path(locator_dir_path)
-    if not locator_dir.is_dir():
-        print(f"Error: Locator directory not found at {locator_dir_path}")
-        sys.exit(1)
-
-    indirect_js = locator_dir / "indirect.js"
-    if not indirect_js.exists():
-        print("Error: indirect.js missing in the specified directory.")
-        sys.exit(1)
-
-    repo_home = Path(os.environ.get("REPO_HOME", "."))
-    IGNORED_DIRS = {".git"}
-
-    for root, dirs, files in os.walk(repo_home):
-        # Prune ignored directories in place
-        dirs[:] = [d for d in dirs if d not in IGNORED_DIRS]
-        
-        current_path = Path(root)
-        if current_path.name.lower() == "document":
-            target_file = current_path / "RT-Style_locator.js"
-            
-            # Eliminate permission denial on read-only artifacts
-            if target_file.exists():
-                target_file.chmod(target_file.stat().st_mode | stat.S_IWUSR)
-            
-            shutil.copyfile(indirect_js, target_file)
-            print(f"Copied indirect.js -> {target_file}")
-
-if __name__ == "__main__":
-    if len(sys.argv) != 2:
-        print("Usage: python3 deploy_RT_Style_indirect_locators.py <path_to_Locator_directory>")
-        sys.exit(1)
-        
-    deploy_RT_Style_indirect_locators(sys.argv[1])
-
diff --git a/administrator/tool/deploy_RT-Style_locators b/administrator/tool/deploy_RT-Style_locators
new file mode 100755 (executable)
index 0000000..6910cea
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+import sys
+import os
+import stat
+import shutil
+from pathlib import Path
+
+def deploy_RT_Style_locators(locator_dir_path):
+    locator_dir = Path(locator_dir_path)
+    if not locator_dir.is_dir():
+        print(f"Error: Locator directory not found at {locator_dir_path}")
+        sys.exit(1)
+
+    immediate_js = locator_dir / "immediate.js"
+    direct_js = locator_dir / "direct.js"
+
+    if not immediate_js.exists() or not direct_js.exists():
+        print("Error: Required locator source files missing in the specified directory.")
+        sys.exit(1)
+
+    repo_home = Path(os.environ.get("REPO_HOME", "."))
+    IGNORED_DIRS = {".git"}
+    updated_dirs = set()
+
+    for root, dirs, files in os.walk(repo_home):
+        # Prune ignored directories in place
+        dirs[:] = [d for d in dirs if d not in IGNORED_DIRS]
+        current_path = Path(root)
+
+        # Skip if the directory has already received a locator during this run
+        if current_path in updated_dirs:
+            continue
+
+        needs_locator = False
+        for file_name in files:
+            if file_name.endswith(".html"):
+                file_path = current_path / file_name
+                try:
+                    with open(file_path, "r", encoding="utf-8") as f:
+                        content = f.read()
+                        if "RT-Style_locator.js" in content:
+                            needs_locator = True
+                            break
+                except Exception as e:
+                    print(f"Warning: Could not read {file_path}: {e}")
+
+        if needs_locator:
+            target_file = current_path / "RT-Style_locator.js"
+            
+            # Evaluate the physical location to select the proper locator
+            is_release_candidate = "Manuscript" in current_path.parts or "Manuscript.copy" in current_path.parts
+            source_js = immediate_js if is_release_candidate else direct_js
+            
+            # Eliminate permission denial on read-only artifacts
+            if target_file.exists():
+                target_file.chmod(target_file.stat().st_mode | stat.S_IWUSR)
+            
+            shutil.copyfile(source_js, target_file)
+            print(f"Copied {source_js.name} -> {target_file}")
+            
+            updated_dirs.add(current_path)
+
+if __name__ == "__main__":
+    if len(sys.argv) != 2:
+        print("Usage: deploy_RT-Style_locators <path_to_Locator_directory>")
+        sys.exit(1)
+        
+    deploy_RT_Style_locators(sys.argv[1])
index 07d9fb6..0fac1e3 100644 (file)
@@ -1,4 +1,6 @@
 /*
+  immediate.js
+
   We have four scenarios
 
   immediate - used in the RT-style distribution itself (authored, consummer, staged)
index deffcfe..16d795f 100644 (file)
@@ -2,7 +2,7 @@
 <html lang="en">
   <head>
     <meta charset="UTF-8">
-    <title>Your Document Title</title>
+    <title>RT Style System</title>
     
     <script src="RT-Style_locator.js"></script>
     <script>
diff --git a/developer/authored/Manuscript.copy/Element/counter.js b/developer/authored/Manuscript.copy/Element/counter.js
new file mode 100644 (file)
index 0000000..240675b
--- /dev/null
@@ -0,0 +1,92 @@
+window.RT = window.RT || {};
+
+// Dictionary for cross-referencing, strictly within the RT namespace.
+window.RT.dict_label = {};
+
+window.RT.counter_do_count = function (root_node) {
+    let counters_state = {};
+
+    function walk(node) {
+        if (node.nodeType !== Node.ELEMENT_NODE) return;
+
+        const tag = node.tagName.toLowerCase();
+        let pushed_name = null;
+
+        if (tag === 'rt-counter-init') {
+            const name = node.getAttribute('name');
+            if (name) {
+                let initial_val = parseInt(node.getAttribute('initial'), 10);
+                if (isNaN(initial_val)) {
+                    initial_val = 1;
+                }
+                
+                // We start one integer below the initial value so the 
+                // first increment lands precisely on the initial value.
+                counters_state[name] = {
+                    stack: [initial_val - 1], 
+                    separator: node.getAttribute('separator') || '.',
+                    current_count_str: ''
+                };
+            }
+        } else if (tag === 'rt-counter-indent') {
+            const name = node.getAttribute('name');
+            if (name && counters_state[name]) {
+                counters_state[name].stack.push(0);
+                pushed_name = name;
+            }
+        } else if (tag === 'rt-counter-inc') {
+            const name = node.getAttribute('name');
+            if (name && counters_state[name]) {
+                const state = counters_state[name];
+                state.stack[state.stack.length - 1] += 1;
+                state.current_count_str = state.stack.join(state.separator);
+                
+                // Stamp the count onto the increment node for immediate layout
+                node.setAttribute('data-count', state.current_count_str);
+                node.innerHTML = state.current_count_str; 
+            }
+        } else if (tag === 'rt-counter-label') {
+            const name = node.getAttribute('name');
+            if (name && counters_state[name]) {
+                // Stamp the most recent count onto the label node for the next pass
+                node.setAttribute('data-count', counters_state[name].current_count_str);
+            }
+        }
+
+        // Evaluate children sequentially
+        let child = node.firstElementChild;
+        while (child) {
+            walk(child);
+            child = child.nextElementSibling;
+        }
+
+        // Retreat up the hierarchy
+        if (pushed_name) {
+            counters_state[pushed_name].stack.pop();
+        }
+    }
+
+    walk(root_node);
+};
+
+window.RT.counter_do_label = function (root_node) {
+    window.RT.dict_label = {};
+    const labels = root_node.querySelectorAll('rt-counter-label');
+    for (let i = 0; i < labels.length; i++) {
+        const lbl = labels[i].getAttribute('label');
+        const count = labels[i].getAttribute('data-count');
+        if (lbl && count !== null) {
+            window.RT.dict_label[lbl] = count;
+        }
+    }
+};
+
+window.RT.counter_do_read = function (root_node) {
+    const reads = root_node.querySelectorAll('rt-counter-read');
+    for (let i = 0; i < reads.length; i++) {
+        const label = reads[i].getAttribute('label');
+        if (label && window.RT.dict_label[label]) {
+            reads[i].innerHTML = window.RT.dict_label[label];
+        }
+    }
+};
index 9da5d5d..ae2f517 100644 (file)
@@ -40,6 +40,7 @@
   }
 
   // 5. Declare Dependencies
+  RT.load('Element/counter');
   RT.load('Element/chapter');
   RT.load('Element/endnote');
   RT.load('Element/math');
     if(RT.theme) RT.theme();     
     if(RT.endnote) RT.endnote();
     RT.article(); 
+    if(RT.counter_do_count){
+      RT.counter_do_count(document.body);
+      if(RT.counter_do_label){
+        RT.counter_do_label(document.body);
+        if(RT.counter_do_read) RT.counter_do_read(document.body);
+      }}
     if(RT.title) RT.title(); 
     if(RT.term) RT.term();
     if(RT.math) RT.math();
index 66e47d7..6bbbea5 100644 (file)
@@ -1,4 +1,14 @@
-// RT-style_url_only.js
+/*
+    URL_only.js
+
+  We have four scenarios
+
+  immediate - used in the RT-Style distribution itself (authored, consumer, 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() {
index 4ded0e8..2f93eb7 100644 (file)
@@ -1,4 +1,7 @@
 /*
+  direct.js
+
+
   We have four scenarios
 
   immediate - used in the RT-style distribution itself (authored, consummer, staged)
@@ -18,7 +21,7 @@ window.RT = window.RT || {};
   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/made/Manuscript";
+    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";
index 07d9fb6..0fac1e3 100644 (file)
@@ -1,4 +1,6 @@
 /*
+  immediate.js
+
   We have four scenarios
 
   immediate - used in the RT-style distribution itself (authored, consummer, staged)
index 39b2706..8e577b9 100644 (file)
@@ -1,4 +1,6 @@
 /*
+  indirect.js
+
   We have four scenarios
 
   immediate - used in the RT-Style distribution itself (authored, consumer, staged)
index 4ded0e8..2f93eb7 100644 (file)
@@ -1,4 +1,7 @@
 /*
+  direct.js
+
+
   We have four scenarios
 
   immediate - used in the RT-style distribution itself (authored, consummer, staged)
@@ -18,7 +21,7 @@ window.RT = window.RT || {};
   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/made/Manuscript";
+    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";
index b9ba678..2c3535d 100644 (file)
@@ -1,6 +1,39 @@
 
-1.
+1. The tags
+
+
+  1.1.declares a counter
+
+    declare: <RT-counter_init name="figure" style="Natural" initial="1" separator="." separator-placement="embeded-only">
+    increment: <RT-counter_inc name="figure">
+    scoped indent:  <RT-counter_indent name="figure"> ... </RT-counter-indent>
+
+
+  scoped indent can be nested, it adds a level to the counting based on the separator.
+
+    style: "Natural"  "roman"  "roman-outline"
+    separator_placement: embedded, embedded-after   (1  1.1  1.1.1  vs   1. 1.1.  1.1.1.)
+
+  1.2.
+
+    <RT-counter_label  name="figure"  label="a cute figure">
+    <RT-counter-read  label="a cute figure" key="count">
+
+    `label` puts in a dictionary, keyed by label, the value being a pair, a reference to the counter object associated with the name, and the count at the given point in the code
+    `reference` 
+
+    `read` is given either a name or a label, and returns the keyed value. The key "count" is set by the layout elements of 1.1 of course. Other keys include 'name' 'label' 'style', 'initial', 'separator', 'separator-placement'.  read replaces its innerHTML with the read value.
+
+
+2. The algorithm
+
+  The counter uses layout tags that come before paginate. Each receive the entire DOM and do their work to completion before returning
+
+  counter_do_count() : finds the counter tags, in order, and sets the count values
+
+  counter_do_label() : builds the label dictionary
+
+  counter_do_read() : finds all the read tags, and sets the innerHTML
+
 
-<RT-counter name="figure" style="Natural" initial="1" separator=".">
 
-name can be any string
index 4ded0e8..2f93eb7 100644 (file)
@@ -1,4 +1,7 @@
 /*
+  direct.js
+
+
   We have four scenarios
 
   immediate - used in the RT-style distribution itself (authored, consummer, staged)
@@ -18,7 +21,7 @@ window.RT = window.RT || {};
   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/made/Manuscript";
+    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";
index 4ded0e8..2f93eb7 100644 (file)
@@ -1,4 +1,7 @@
 /*
+  direct.js
+
+
   We have four scenarios
 
   immediate - used in the RT-style distribution itself (authored, consummer, staged)
@@ -18,7 +21,7 @@ window.RT = window.RT || {};
   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/made/Manuscript";
+    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";
diff --git a/tester/authored/Counter/RT-Style_locator.js b/tester/authored/Counter/RT-Style_locator.js
new file mode 100644 (file)
index 0000000..2f93eb7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+  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/loader.js"><\/script>');
+  
+  document.write(
+    '<script>' +
+    'window.RT.load("Core/utility");' +
+    'window.RT.load("Core/block_visibility_during_layout");' +
+    'window.RT.load("Theme");' +
+    'window.RT.load("Element/theme_selector");' +
+    '<\/script>'
+  );
+})();
diff --git a/tester/authored/Counter/test_0.html b/tester/authored/Counter/test_0.html
new file mode 100644 (file)
index 0000000..ec44d60
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Manuscript Counter Test Bench</title>
+    <script src="RT-Style_locator.js"></script>
+    <script>
+      window.RT.load('Layout/article_tech_ref');
+    </script>
+</head>
+<body>
+
+    <rt-counter-init name="figure" style="Natural" initial="1" separator="."></rt-counter-init>
+    
+    <h1>Primary Analysis</h1>
+    <p>
+        Observe the data in Figure <rt-counter-inc name="figure"></rt-counter-inc>.
+    </p>
+    <rt-counter-label name="figure" label="fig-primary"></rt-counter-label>
+
+    <rt-counter-indent name="figure">
+        <p>
+            Detail view of the left quadrant: Figure <rt-counter-inc name="figure"></rt-counter-inc>.
+        </p>
+        <rt-counter-label name="figure" label="fig-sub-left"></rt-counter-label>
+        
+        <p>
+            Detail view of the right quadrant: Figure <rt-counter-inc name="figure"></rt-counter-inc>.
+        </p>
+        <rt-counter-label name="figure" label="fig-sub-right"></rt-counter-label>
+        
+        <rt-counter-indent name="figure">
+            <p>
+                Microscopic inspection: Figure <rt-counter-inc name="figure"></rt-counter-inc>.
+            </p>
+            <rt-counter-label name="figure" label="fig-micro"></rt-counter-label>
+        </rt-counter-indent>
+    </rt-counter-indent>
+
+    <h1>Secondary Analysis</h1>
+    <p>
+        Proceeding to the next major component, shown in Figure <rt-counter-inc name="figure"></rt-counter-inc>.
+    </p>
+
+    <div class="reference-box">
+        <h2>Forward Reference Validation</h2>
+        <p>This text proves we can accurately call back to earlier elements.</p>
+        <ul>
+            <li>The primary analysis was Figure <rt-counter-read label="fig-primary" key="count"></rt-counter-read>.</li>
+            <li>The left quadrant was Figure <rt-counter-read label="fig-sub-left" key="count"></rt-counter-read>.</li>
+            <li>The microscopic view was Figure <rt-counter-read label="fig-micro" key="count"></rt-counter-read>.</li>
+        </ul>
+    </div>
+
+    <script>
+        // Insert the three layout functions here
+        // ... (counter_do_count, counter_do_label, counter_do_read) ...
+
+        // Execute the layout pipeline
+        window.RT.counter_do_count(document.body);
+        window.RT.counter_do_label(document.body);
+        window.RT.counter_do_read(document.body);
+    </script>
+</body>
+</html>
diff --git a/tester/authored/test_routine.sh b/tester/authored/test_routine.sh
deleted file mode 100644 (file)
index f22c3ba..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-# test_routing.sh
-# Sends mock HTTP requests to the local unix socket to verify domain routing.
-
-SOCKET_FP="../user/release/scratchpad/network_interface/RT_server.sock"
-
-if [ ! -S "${SOCKET_FP}" ]; then
-  echo "Error: Socket not found at ${SOCKET_FP}" >&2
-  echo "Make sure the HTTP_server.js process is running in the user workspace." >&2
-  exit 1
-fi
-
-echo "=== Testing Reasoning Technology domain ==="
-curl --unix-socket "${SOCKET_FP}" \
-  -H "Host: x6.reasoningtechnology.com" \
-  http://localhost/
-
-echo -e "\n\n=== Testing Thomas Walker Lynch domain ==="
-curl --unix-socket "${SOCKET_FP}" \
-  -H "Host: x6.thomas-walker-lynch.com" \
-  http://localhost/
-
-echo -e "\n\n=== Testing Unknown domain ==="
-curl --unix-socket "${SOCKET_FP}" \
-  -H "Host: nonexistent-domain.com" \
-  http://localhost/