+++ /dev/null
-/*
- indirect.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 || {};
-
-// --- 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.");
- }
- }
-
- window.RT.dirpr_library = style_path;
-
- document.write(
- '<script src="'
- + window.RT.dirpr_library
- + '/Core/RT-Manuscript_make.js"'
- + '><\/script>'
- );
-
-})();
<head>
<meta charset="UTF-8">
<title>Release howto</title>
- <script src="RT-Manuscript_locator.js"></script>
+ <script>
+ {
+ let dirpr_library = null;
+ try{ dirpr_library = localStorage.getItem("RT.dirpr_library"); }catch(e){}
+ window.RT = window.RT || {};
+ RT.dirpr_library = RT.dirpr_library || dirpr_library || "https://style.ReasoningTechnology.com/Manuscript";
+ document.write('<script src="' + RT.dirpr_library + '/Core/RT-Manuscript_make.js"><\/script>');
+ }
+ </script>
<script>
window.RT.theme_preference('inverse_wheat');
window.RT.load('Layout/paginate');
--- /dev/null
+#!/usr/bin/env python3
+# -*- mode: python; coding: utf-8; python-indent-offset: 2; indent-tabs-mode: nil -*-
+
+"""
+RT-Style_header_v5_to_v6
+
+Converts RT-Style version 5 document headers to version 6.
+
+A version 5 document loads the engine through a locator file beside it:
+
+ <script src="RT-Manuscript_locator.js"></script>
+
+A version 6 document carries an inline header block instead. The block takes
+the library from the record made by opening a Manuscript directory's
+setup.html, and falls back to the Reasoning Technology server.
+
+For each version 5 .html file found, the tool replaces the locator line in
+<head> with the version 6 block, keeping its indentation, and deletes
+RT-Manuscript_locator.js from that file's directory. Any other mention of
+RT-Manuscript_locator in the file (an escaped example, prose) is logged for a
+person to edit.
+
+Usage: RT-Style_header_v5_to_v6 <command> [file ...]
+ RT-Style_header_v5_to_v6 preview <command> [file ...]
+
+ help | -h | --help print this message (also printed when given no arguments)
+ project walk the directory tree rooted at $REPO_HOME
+ tree walk the directory tree rooted at the current directory
+ local only the current directory, no subdirectories
+ file <name> ... only the named .html files
+ preview <command> print the log of what <command> would do, change nothing
+
+Every directory is walked, whatever its name. Symbolic links to directories
+are not followed, so a link back up the tree cannot cause a loop or reach
+outside it.
+"""
+
+import sys ,os ,re
+from pathlib import Path
+
+LOCATOR_FILE = "RT-Manuscript_locator.js"
+V6_MARK = 'localStorage.getItem("RT.dirpr_library")'
+
+V6_BLOCK = [
+ '<script>'
+ ,' {'
+ ,' let dirpr_library = null;'
+ ,' try{ dirpr_library = localStorage.getItem("RT.dirpr_library"); }catch(e){}'
+ ,' window.RT = window.RT || {};'
+ ,' RT.dirpr_library = RT.dirpr_library || dirpr_library || "https://style.ReasoningTechnology.com/Manuscript";'
+ ,' document.write(\'<script src="\' + RT.dirpr_library + \'/Core/RT-Manuscript_make.js"><\\/script>\');'
+ ,' }'
+ ,'</script>'
+]
+
+LOCATOR_LINE = re.compile(
+ r'^(?P<indent>[ \t]*)<script\s+src\s*=\s*["\'](?:[^"\']*/)?RT-Manuscript_locator\.js["\']\s*>\s*</script>\s*$'
+ ,re.IGNORECASE
+)
+HEAD_END = re.compile(r'</head\s*>' ,re.IGNORECASE)
+
+
+# ---------------------------------------------------------------- log
+
+class Log:
+ def __init__(self ,preview: bool ,base: Path):
+ self.preview = preview
+ self.base = base
+ self.count = {"converted": 0 ,"deleted": 0 ,"already": 0 ,"hand": 0
+ ,"untouched": 0 ,"stray": 0 ,"error": 0}
+
+ def rel(self ,p: Path) -> str:
+ try: return str(p.resolve().relative_to(self.base))
+ except ValueError: return str(p)
+
+ def line(self ,tag: str ,text: str):
+ print(f" {tag:<15} {text}")
+
+ def act(self ,done: str ,would: str ,p: Path ,key: str):
+ self.line(would if self.preview else done ,self.rel(p))
+ self.count[key] += 1
+
+ def summary(self):
+ c = self.count
+ v = "would be " if self.preview else ""
+ print()
+ print("summary:")
+ print(f" {c['converted']:>4} .html files {v}converted to version 6")
+ print(f" {c['deleted']:>4} {LOCATOR_FILE} files {v}deleted")
+ print(f" {c['already']:>4} .html files already version 6")
+ print(f" {c['hand']:>4} .html files with mentions to edit by hand")
+ print(f" {c['untouched']:>4} other .html files left alone")
+ if c['stray']:
+ print(f" {c['stray']:>4} {LOCATOR_FILE} files kept, no version 5 document beside them")
+ if c['error']:
+ print(f" {c['error']:>4} errors")
+ if self.preview:
+ print("preview only: nothing was changed")
+
+
+# ---------------------------------------------------------------- finding files
+
+def walk(root: Path ,recursive: bool):
+ """Yields (directory ,[.html files] ,has_locator) for each directory."""
+ if not recursive:
+ entries = sorted(root.iterdir())
+ yield root ,[e for e in entries if e.is_file() and e.suffix == ".html"] ,(root / LOCATOR_FILE).is_file()
+ return
+ for d ,dirs ,files in os.walk(root):
+ dirs.sort()
+ files = sorted(files)
+ yield Path(d) ,[Path(d) / f for f in files if f.endswith(".html")] ,LOCATOR_FILE in files
+
+
+# ---------------------------------------------------------------- conversion
+
+def convert(text: str):
+ """Returns (new_text ,replaced_count ,leftover). leftover lists
+ (line_number ,line) for locator mentions that were not replaced."""
+ lines = text.split("\n")
+ out = []
+ replaced = 0
+ leftover = []
+ in_head = True
+ for n ,line in enumerate(lines ,1):
+ m = LOCATOR_LINE.match(line) if in_head else None
+ if m:
+ eol = "\r" if line.endswith("\r") else ""
+ out.extend(m.group("indent") + b + eol for b in V6_BLOCK)
+ replaced += 1
+ else:
+ out.append(line)
+ if LOCATOR_FILE.removesuffix(".js") in line:
+ leftover.append((n ,line.strip()))
+ if in_head and HEAD_END.search(line):
+ in_head = False
+ return "\n".join(out) ,replaced ,leftover
+
+def do_file(f: Path ,log: Log) -> bool:
+ """Converts one .html file. Returns True when it was version 5."""
+ try:
+ text = f.read_text(encoding="utf-8")
+ except Exception as e:
+ log.line("error" ,f"{log.rel(f)}: cannot read: {e}")
+ log.count["error"] += 1
+ return False
+
+ if V6_MARK in text and LOCATOR_FILE.removesuffix(".js") not in text:
+ log.line("already v6" ,log.rel(f))
+ log.count["already"] += 1
+ return False
+
+ new_text ,replaced ,leftover = convert(text)
+
+ if replaced:
+ if not log.preview:
+ try:
+ mode = f.stat().st_mode
+ f.write_text(new_text ,encoding="utf-8")
+ os.chmod(f ,mode)
+ except Exception as e:
+ log.line("error" ,f"{log.rel(f)}: cannot write: {e}")
+ log.count["error"] += 1
+ return False
+ log.act("converted" ,"would convert" ,f ,"converted")
+ if replaced > 1:
+ log.line("note" ,f"{log.rel(f)}: {replaced} locator lines in <head>, all replaced")
+ elif not leftover:
+ log.count["untouched"] += 1
+
+ if leftover:
+ log.count["hand"] += 1
+ for n ,line in leftover:
+ log.line("edit by hand" ,f"{log.rel(f)}:{n}: {line[:100]}")
+
+ return replaced > 0
+
+def do_locator(d: Path ,log: Log):
+ loc = d / LOCATOR_FILE
+ if not log.preview:
+ try:
+ loc.unlink()
+ except Exception as e:
+ log.line("error" ,f"{log.rel(loc)}: cannot delete: {e}")
+ log.count["error"] += 1
+ return
+ log.act("deleted" ,"would delete" ,loc ,"deleted")
+
+def run_dirs(root: Path ,recursive: bool ,log: Log):
+ for d ,html ,has_locator in walk(root ,recursive):
+ any_v5 = False
+ for f in html:
+ any_v5 = do_file(f ,log) or any_v5
+ if has_locator:
+ if any_v5:
+ do_locator(d ,log)
+ else:
+ log.line("kept" ,f"{log.rel(d / LOCATOR_FILE)} (no version 5 document beside it)")
+ log.count["stray"] += 1
+
+def run_files(files: list[Path] ,log: Log):
+ v5_dirs = []
+ for f in files:
+ if do_file(f ,log):
+ d = f.parent.resolve()
+ if d not in v5_dirs: v5_dirs.append(d)
+ for d in v5_dirs:
+ if (d / LOCATOR_FILE).is_file():
+ do_locator(d ,log)
+
+
+# ---------------------------------------------------------------- command line
+
+def help() -> int:
+ print(__doc__.strip())
+ return 0
+
+def CLI(argv=None) -> int:
+ if argv is None:
+ argv = sys.argv[1:]
+ if not argv or argv[0] in ("help" ,"-h" ,"--help"):
+ return help()
+
+ preview = False
+ if argv[0] == "preview":
+ preview = True
+ argv = argv[1:]
+ if not argv:
+ print("Error: 'preview' needs a command after it.\n" ,file=sys.stderr)
+ help()
+ return 1
+
+ command ,rest = argv[0] ,argv[1:]
+
+ if command == "file":
+ if not rest:
+ print("Error: 'file' needs at least one file name." ,file=sys.stderr)
+ return 1
+ files = [Path(a) for a in rest]
+ for f in files:
+ if not f.is_file():
+ print(f"Error: {f} is not a file." ,file=sys.stderr)
+ return 1
+ base = Path.cwd().resolve()
+ log = Log(preview ,base)
+ print(f"RT-Style_header_v5_to_v6 {'preview ' if preview else ''}file in {base}")
+ run_files(files ,log)
+ log.summary()
+ return 1 if log.count["error"] else 0
+
+ if rest:
+ print(f"Error: '{command}' takes no arguments." ,file=sys.stderr)
+ return 1
+
+ if command == "project":
+ repo_home = os.environ.get("REPO_HOME")
+ if not repo_home:
+ print("Error: 'project' needs REPO_HOME to be set." ,file=sys.stderr)
+ return 1
+ root ,recursive = Path(repo_home) ,True
+ elif command == "tree":
+ root ,recursive = Path.cwd() ,True
+ elif command == "local":
+ root ,recursive = Path.cwd() ,False
+ else:
+ print(f"Error: unknown command '{command}'.\n" ,file=sys.stderr)
+ help()
+ return 1
+
+ if not root.is_dir():
+ print(f"Error: {root} is not a directory." ,file=sys.stderr)
+ return 1
+
+ base = root.resolve()
+ log = Log(preview ,base)
+ print(f"RT-Style_header_v5_to_v6 {'preview ' if preview else ''}{command} in {base}")
+ run_dirs(base ,recursive ,log)
+ log.summary()
+ return 1 if log.count["error"] else 0
+
+if __name__ == "__main__":
+ sys.exit(CLI())
+++ /dev/null
-#!/usr/bin/env python3
-import sys
-import os
-import stat
-import shutil
-from pathlib import Path
-
-def deploy_RT_Manuscript_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"}
- 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:
- for line in f:
- if "RT-Manuscript_locator.js" in line:
- needs_locator = True
- break
- if "</head>" in line.lower():
- break
- if needs_locator:
- break
- except Exception as e:
- print(f"Warning: Could not read {file_path}: {e}")
-
- if needs_locator:
- target_file = current_path / "RT-Manuscript_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}")
-
- updated_dirs.add(current_path)
-
-if __name__ == "__main__":
- if len(sys.argv) != 2:
- print("Usage: python3 deploy_RT_Manuscript_indirect_locators.py <path_to_Locator_directory>")
- sys.exit(1)
-
- deploy_RT_Manuscript_indirect_locators(sys.argv[1])
+++ /dev/null
-/*
- indirect.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 || {};
-
-// --- 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.");
- }
- }
-
- window.RT.dirpr_library = style_path;
-
- document.write(
- '<script src="'
- + window.RT.dirpr_library
- + '/Core/RT-Manuscript_make.js"'
- + '><\/script>'
- );
-
-})();
<head>
<meta charset="UTF-8">
<title>File and directory naming conventions</title>
- <script src="RT-Manuscript_locator.js"></script>
+ <script>
+ {
+ let dirpr_library = null;
+ try{ dirpr_library = localStorage.getItem("RT.dirpr_library"); }catch(e){}
+ window.RT = window.RT || {};
+ RT.dirpr_library = RT.dirpr_library || dirpr_library || "https://style.ReasoningTechnology.com/Manuscript";
+ document.write('<script src="' + RT.dirpr_library + '/Core/RT-Manuscript_make.js"><\/script>');
+ }
+ </script>
<script>
window.RT.theme_preference('inverse_wheat');
window.RT.load('Layout/paginate');
<head>
<meta charset="UTF-8">
<title>C modules, namespaces, and the build lifecycle</title>
- <script src="RT-Manuscript_locator.js"></script>
+ <script>
+ {
+ let dirpr_library = null;
+ try{ dirpr_library = localStorage.getItem("RT.dirpr_library"); }catch(e){}
+ window.RT = window.RT || {};
+ RT.dirpr_library = RT.dirpr_library || dirpr_library || "https://style.ReasoningTechnology.com/Manuscript";
+ document.write('<script src="' + RT.dirpr_library + '/Core/RT-Manuscript_make.js"><\/script>');
+ }
+ </script>
<script>
window.RT.theme_preference('inverse_wheat');
window.RT.load('Layout/paginate');
+++ /dev/null
-/*
- indirect.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 || {};
-
-// --- 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.");
- }
- }
-
- window.RT.dirpr_library = style_path;
-
- document.write(
- '<script src="'
- + window.RT.dirpr_library
- + '/Core/RT-Manuscript_make.js"'
- + '><\/script>'
- );
-
-})();
<head>
<meta charset="UTF-8">
<title>Introduction to Harmony</title>
- <script src="RT-Manuscript_locator.js"></script>
+ <script>
+ {
+ let dirpr_library = null;
+ try{ dirpr_library = localStorage.getItem("RT.dirpr_library"); }catch(e){}
+ window.RT = window.RT || {};
+ RT.dirpr_library = RT.dirpr_library || dirpr_library || "https://style.ReasoningTechnology.com/Manuscript";
+ document.write('<script src="' + RT.dirpr_library + '/Core/RT-Manuscript_make.js"><\/script>');
+ }
+ </script>
<script>
window.RT.theme_preference('inverse_wheat');
window.RT.load('Layout/paginate');
<head>
<meta charset="UTF-8">
<title>Product development roles and workflow</title>
- <script src="RT-Manuscript_locator.js"></script>
+ <script>
+ {
+ let dirpr_library = null;
+ try{ dirpr_library = localStorage.getItem("RT.dirpr_library"); }catch(e){}
+ window.RT = window.RT || {};
+ RT.dirpr_library = RT.dirpr_library || dirpr_library || "https://style.ReasoningTechnology.com/Manuscript";
+ document.write('<script src="' + RT.dirpr_library + '/Core/RT-Manuscript_make.js"><\/script>');
+ }
+ </script>
<script>
window.RT.theme_preference('inverse_wheat');
window.RT.load('Layout/paginate');
<head>
<meta charset="UTF-8">
<title>Product maintenance roles and workflow</title>
- <script src="RT-Manuscript_locator.js"></script>
+ <script>
+ {
+ let dirpr_library = null;
+ try{ dirpr_library = localStorage.getItem("RT.dirpr_library"); }catch(e){}
+ window.RT = window.RT || {};
+ RT.dirpr_library = RT.dirpr_library || dirpr_library || "https://style.ReasoningTechnology.com/Manuscript";
+ document.write('<script src="' + RT.dirpr_library + '/Core/RT-Manuscript_make.js"><\/script>');
+ }
+ </script>
<script>
window.RT.theme_preference('inverse_wheat');
window.RT.load('Layout/paginate');
+++ /dev/null
-/*
- 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 || {};
-
-// --- 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.");
- }
- }
-
- window.RT.dirpr_library = style_path;
-
- // 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");' +
- 'window.RT.load("Core/block_visibility_during_layout");' +
- 'window.RT.load("Theme");' +
- 'window.RT.load("Element/theme_selector");' +
- '<\/script>'
- );
-})();