From: Thomas Walker Lynch Date: Tue, 23 Jun 2026 07:43:26 +0000 (+0000) Subject: puts back Manuscript namespace, updates document style methodology X-Git-Url: https://git.reasoningtechnology.com/RT-style.js?a=commitdiff_plain;h=6321ecd606689a220582a3ccfd7c7ea080331b14;p=RT-Style puts back Manuscript namespace, updates document style methodology --- diff --git a/0pus_RT-style b/0pus_RT-style new file mode 100644 index 0000000..e69de29 diff --git a/0pus_RT-style-JS_public b/0pus_RT-style-JS_public deleted file mode 100644 index e69de29..0000000 diff --git a/administrator/document/RT-style.js b/administrator/document/RT-style.js new file mode 100644 index 0000000..34cfb22 --- /dev/null +++ b/administrator/document/RT-style.js @@ -0,0 +1,28 @@ +// RT-style.js (Internal RT-style project router) +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/made/Manuscript"; + } else { + // Fallback for when served via local Python HTTP daemon from the project root + window.RT.dirpr_library = "../consumer/made/Manuscript"; + } + + document.write(' - diff --git a/administrator/document/installation_Python.org b/administrator/document/installation_Python.org new file mode 100644 index 0000000..06155b7 --- /dev/null +++ b/administrator/document/installation_Python.org @@ -0,0 +1,73 @@ +#+TITLE: Installing Python in Harmony +#+AUTHOR: Thomas Walker Lynch +#+OPTIONS: toc:2 num:nil + +* Overview + +This document describes how to install a project-local Python environment under: + +#+begin_src bash +shared/linked-project/Python +#+end_src + +* Precondition + +Ensure the following: + +- You are in a POSIX shell with =python3= installed. +- The =python3-venv= package is available (on Debian: =sudo apt install python3-venv=). +- You have sourced the Harmony environment via =env_toolsmith= to initialize =REPO_HOME= and related variables. + +* Step-by-Step Installation + +1. Source the Harmony environment: + #+begin_src bash + source env_toolsmith + #+end_src + +2. Create the virtual environment: + #+begin_src bash + python3 -m venv "$REPO_HOME/shared/linked-project/Python" + #+end_src + +3. Activate it temporarily to install required packages: + #+begin_src bash + source "$REPO_HOME/shared/linked-project/Python/bin/activate" + pip install --upgrade pip + pip install pytest # Add any shared packages here + deactivate + #+end_src + +4. Rename Python's default activate and deactivate: + Harmony provides its own role-aware environment management. Using Python’s default activation scripts may interfere with prompt logic, PATH order, and role-specific behavior. + + Disable the default scripts by renaming them: + #+begin_src bash + mv "$REPO_HOME/shared/linked-project/Python/bin/activate" \ + "$REPO_HOME/shared/linked-project/Python/bin/activate_deprecated" + #+end_src + + This ensures that accidental sourcing of Python’s =activate= script won't override Harmony's environment setup. + +5. Verify installation: + #+begin_src bash + ls "$REPO_HOME/shared/linked-project/Python/bin/python3" + #+end_src + + The binary should exist and report a working Python interpreter when run. + +* Notes + +- The virtual environment is deliberately named =Python=, not =venv=, to reflect its role as a shared system component. +- Harmony environment scripts define and control =VIRTUAL_ENV=, =PYTHON_HOME=, and =PATH=, making Python activation seamless and uniform. +- There is no need to use Python’s =bin/activate= directly — it is fully replaced by Harmony’s environment logic. + +* Related Files + +- =shared/authored/env= +- =shared/authored/env_source= +- =env_developer=, =env_tester=, =env_toolsmith= + +* Last Verified + +2025-05-19 :: Activate/deactivate renamed post-install. Requires Harmony environment sourcing prior to execution. diff --git a/administrator/document/installation_generic.org b/administrator/document/installation_generic.org new file mode 100644 index 0000000..db88651 --- /dev/null +++ b/administrator/document/installation_generic.org @@ -0,0 +1,81 @@ + +This is the generic install.org doc that comes with the skeleton. + +1. $REPO_HOME/shared/linked-project/.gitignore: + + * + !/.gitignore + !/patch + + The only things from the third party directory that will be pushed to the repo origin is the .gitignore file and the patches. + + +2. downloaded tar files etc. go into the directory `upstream` + + $REPO_HOME/shared/upstream + + Typically the contents of upstream are deleted after the install. + +3. for the base install + + cd $REPO_HOME/shared/linked-project + do whatever it takes to install tool, as examples: + git clone + tar -xzf ../upstream/tar + ... + + Be sure to add the path to the tool executable(s) in the $REPO_HOME/env_$ROLE files for the $ROLE who uses the tool. + + Assuming you are not also developing the tool, for safety + change each installed git project to a local branch: + + b=__local_$USER + git switch -c "$b" + + +4. Define some variables to simplify our discussion. Lowercase variable names + are not exported from the shell. + + # already set in the environment + # REPO_HOME + # PROJECT + # USER + + # example tool names: 'RT_gcc' 'RT-project share` etc. + tool= + tool_dpath="$REPO_HOME/shared/linked-project/$tool" + patch_dpath="$REPO_HOME/shared/patch/" + + +5. create a patch series (from current vendor state → your local edits) + + # this can be repeated and will create an encompassing diff file + + # optionally crate a new branch after cloning the third party tool repo and work from there. You won't make any commits, but in case you plan to ever check the changes in, or have a the bad habit of doing ommits burned into your brain-stem, making a brnch will help. + + # make changes + + cd "$tool_dpath" + + # do your edits + + # Stage edits. Do not commit them!! Be sure you are in the third party + # tool directory when doing `git add -A` and `git diff` commands. + git add -A + + # diff the stage from the current repo to create the patch file + git diff --staged > "$patch_dpath/$tool" + + # the diff file can be added to the project and checked in at the project level. + + +6. how to apply an existing patch + + Get a fresh clone of the tool into $tool_dpath. + + cd "$tool_dpath" + git apply "$patch_dpath/$tool" + + You can see what `git apply` would do by running + + git apply --check /path/to/your/patch_dpath/$tool diff --git a/developer/authored/.gitkeep b/developer/authored/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/developer/authored/Core.copy/block_visibility_during_layout.js b/developer/authored/Core.copy/block_visibility_during_layout.js deleted file mode 100644 index 8513f01..0000000 --- a/developer/authored/Core.copy/block_visibility_during_layout.js +++ /dev/null @@ -1,19 +0,0 @@ -// block_visibility_during_layout.js - -// 1. Hide the document immediately upon execution in the -document.documentElement.style.visibility = "hidden"; - -// 2. Define the restoration function -const restore_visibility = function() { - document.documentElement.style.visibility = ""; - document.removeEventListener("RT_layout_complete", restore_visibility); - window.removeEventListener("load", restore_visibility); -}; - -// 3. Listen for a specific completion signal from the layout engine -document.addEventListener("RT_layout_complete", restore_visibility); - -// 4. Structural Safety Net: If the layout engine fails or is never loaded, -// restore visibility on the final window 'load' event so the page doesn't remain blank. -window.addEventListener("load", restore_visibility); - diff --git a/developer/authored/Core.copy/loader.js b/developer/authored/Core.copy/loader.js deleted file mode 100644 index 5334d08..0000000 --- a/developer/authored/Core.copy/loader.js +++ /dev/null @@ -1,22 +0,0 @@ -window.RT = window.RT || {}; - -window.RT.load = function(module_path){ - let target_module = module_path; - - if(target_module === 'theme'){ - let saved_theme = localStorage.getItem('RT_theme_preference'); - if(!saved_theme){ - saved_theme = 'dark_gold'; - localStorage.setItem('RT_theme_preference', saved_theme); - } - target_module = 'theme/' + saved_theme; - } - - let resolved_path = window.RT.dirpr_library + '/' + target_module; - - if(!resolved_path.endsWith('.js')){ - resolved_path = resolved_path + '.js'; - } - - document.write(''); -}; diff --git a/developer/authored/Core.copy/utility.js b/developer/authored/Core.copy/utility.js deleted file mode 100644 index d6f2ddd..0000000 --- a/developer/authored/Core.copy/utility.js +++ /dev/null @@ -1,109 +0,0 @@ -/* - General utilities for the RT Style library. -*/ - -window.RT = window.RT || {}; - -// --- DEBUG SYSTEM --- -window.RT.debug = { - - // all debug messages enabled -/* - active_tokens: new Set([ - 'style', 'layout', 'pagination' - ,'selector', 'config', 'error' - ,'term' - ,'scroll' - ]), - - active_tokens: new Set([ - 'term' - ]), -*/ - - active_tokens: new Set([ - ]), - - log: function(token, message) { - if (this.active_tokens.has(token)) { - console.log(`[RT:${token}]`, message); - } - }, - - warn: function(token, message) { - if (this.active_tokens.has(token)) { - console.warn(`[RT:${token}]`, message); - } - }, - - error: function(token, message) { - console.error(`[RT:${token}] CRITICAL:`, message); - }, - - enable: function(token) { this.active_tokens.add(token); console.log(`Enabled: ${token}`); }, - disable: function(token) { this.active_tokens.delete(token); console.log(`Disabled: ${token}`); } -}; - -// --- UTILITIES --- -window.RT.utility = { - // --- FONT PHYSICS --- - measure_ink_ratio: function(target_font, ref_font = null) { - const debug = window.RT.debug; - debug.log('layout', `Measuring ink ratio for ${target_font}`); - - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - - if (!ref_font) { - const bodyStyle = window.getComputedStyle(document.body); - ref_font = bodyStyle.fontFamily; - } - - const get_metrics = (font) => { - ctx.font = '100px ' + font; - const metrics = ctx.measureText('M'); - return { - ascent: metrics.actualBoundingBoxAscent, - descent: metrics.actualBoundingBoxDescent - }; - }; - - const ref_m = get_metrics(ref_font); - const target_m = get_metrics(target_font); - - const ratio = ref_m.ascent / target_m.ascent; - - return { - ratio: ratio, - baseline_diff: ref_m.descent - target_m.descent - }; - }, - - // --- COLOR PHYSICS --- - is_color_light: function(color_string) { - // 1. HSL Check - if (color_string.startsWith('hsl')) { - const numbers = color_string.match(/\d+/g); - if (numbers && numbers.length >= 3) { - const lightness = parseInt(numbers[2]); - return lightness > 50; - } - } - - // 2. RGB Check - const rgb = color_string.match(/\d+/g); - if (!rgb) { - return true; - } - - const r = parseInt(rgb[0]); - const g = parseInt(rgb[1]); - const b = parseInt(rgb[2]); - const luma = (r * 299 + g * 587 + b * 114) / 1000; - return luma > 128; - }, - - is_block_content: function(element) { - return element.textContent.trim().includes('\n'); - } -}; diff --git a/developer/authored/Document.copy/RT0 b/developer/authored/Document.copy/RT0 deleted file mode 120000 index 2a6dec2..0000000 --- a/developer/authored/Document.copy/RT0 +++ /dev/null @@ -1 +0,0 @@ -/home/Thomas/subu_data/developer/project/RT-style-JS_public/shared/linked-project/RT-style-JS_public/consumer/release/RT \ No newline at end of file diff --git a/developer/authored/Document.copy/style_manual.html b/developer/authored/Document.copy/style_manual.html deleted file mode 100644 index 41ff112..0000000 --- a/developer/authored/Document.copy/style_manual.html +++ /dev/null @@ -1,420 +0,0 @@ - - - - - RT Style System: Reference Manual - - - - - - - - - - - - - - Table of custom tags - -

Style tag reference

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TagDescription
<RT-article>Article container.
<RT-title> - Title block and metadata. -
<RT-TOC>Compiles TOC.
<RT-index>Compiles an alphabetical glossary of defined terms.
<RT-term>Conventional term.
<RT-term-em>Forces emphasis for a term even after first occurrence.
<RT-neologism>Project specific term.
<RT-neologism-em>Forces emphasis for a neologism even after first occurrence.
<RT-code>Code span or code block.
<RT-math>Inline or block math.
<RT-footnote>Inline text to be extracted and rendered at the bottom of the page.
<RT-cite>Bibliographic citation marker.
<RT-ref>Dynamic cross reference to another element in the document.
<RT-page>Automatically inserted pagination container.
<RT-chapter>Chapter heading with implied page break.
<RT-page-break>Explicit page break directive. Must be explicitly closed.
- - Architecture overview -

- The RT Style System is a client-side, JavaScript-driven publishing framework designed to turn raw HTML into high-readability technical documentation. Unlike standard CSS frameworks, RT uses JavaScript to handle complex layout tasks like ink-ratio balancing and dynamic pagination. -

- -

Pulling style files into a document

-

Put `setup.js` in the directory, and include it at the top of the document, - `setup.js` points at the style files and is installation specific.

- - - Semantic tags -

- The system relies on a specific set of custom tags in the RT- namespace to separate meaning from presentation. -

- -

Terminology

- -

Conventional terms

-

- Use <RT-term> for standard, industry accepted technical terms. The system decorates only the first occurrence of each unique term so that the first appearance functions as a definition point, and later appearances do not overload the page with styling. -

- - - The Singleton Pattern restricts instantiation... - - -

- Renders as: The Singleton Pattern restricts instantiation... -

- -

Neologisms

-

- Use <RT-neologism> for terms invented specifically for the current document or project. Neologisms are styled more strongly than conventional terms, visually distinguishing "jargon you should know" from "jargon we invented." -

- - - We define the Hyper Tape as a construct... - - -

- Renders as: We define the Hyper Tape as a construct... -

- -

First occurrence rule

-

- The term system is intentionally conservative. For the tags <RT-term> and <RT-neologism>, only the first occurrence of a unique term is decorated. Subsequent mentions are rendered as normal prose. -

- -

- Uniqueness is tracked by normalizing the term text (trimmed, then lowercased). This means that Symbol and symbol count as the same term. -

- -

Forced emphasis variants

-

- Sometimes a later mention of a term should be emphasized again. For that purpose, the system provides explicit emphasis tags: -

- -
    -
  • <RT-term-em>
  • -
  • <RT-neologism-em>
  • -
- -

- These variants are always decorated, even if the term appeared earlier. -

- -

Automatic definition anchors

-

- For first occurrences, the term module automatically assigns an id attribute if one does not already exist. This establishes stable anchors for future indexing and linking. -

- - - We define a Symbol as... - - -

- The first occurrence will be given an id similar to def-symbol. For neologisms, an additional marker is used, for example def-neo-hyper-tape. -

- -

Technical content

- -

Code

-

- Use <RT-code>. If placed inline, it acts like a span. If placed as a block (with newlines), it acts like a pre formatted block with a theme aware border. -

- - - # Block Code Example - def hello(): - return "World" - - -

Mathematics

-

- Use <RT-math>. The system auto detects if it is a block equation or inline variable and wraps it in MathJax delimiters. -

-

- Inline: Let x be the input. -

-

- Block: -

- - f(x) = \sum_{i=0}^{n} x_i - - -

References, citations, and indexing

- -

Footnotes

-

- Use <RT-footnote> to author footnote content directly inline with the text it references. During the layout phase, the pagination engine extracts the text, replaces the element with an invisible structural marker, and compiles a formatted footnote container at the bottom of the active <RT-page>. -

- -

Citations

-

- Use <RT-cite> with the ref attribute to insert bibliographic citations. This ensures formatting remains consistent and separates citation data from standard prose. -

- - ... formalized as Basic Law V . - - -

Dynamic cross referencing

-

- A person authoring a technical document frequently refers back to tables, equations, or previous sections. Use <RT-ref target="element-id"> to link to specific content. This tag dynamically retrieves the numbering or caption of the target element, maintaining correct references even if preceding elements shift during editing. -

- -

Glossary indexing

-

- Use <RT-index> at the end of the document to compile a glossary. Similar to the TOC compiler, this tag scans the DOM for automatic definition anchors produced by the term module and generates an alphabetized list of defined terms and neologisms. -

- - Navigation and layout - -

Automatic table of contents

-

- Use <RT-TOC> to insert a compiled table of contents. The tag scans the document forward from its current position to collect headings. -

- -

Explicit mode

-

- Use the level="N" attribute to target a specific heading depth. -

-
    -
  • <RT-TOC level="1">: Collects all <h1> elements until the end of the document. Best for the main document index.
  • -
  • <RT-TOC level="2">: Collects all <h2> elements until it encounters the next <h1>. Best for chapter summaries.
  • -
- -

Implicit mode

-

- If no level is specified, the TOC scans backwards to find the nearest heading (for example H1) and assumes you want to collect children one level deeper (for example H2). -

-

- Note: Implicit mode can fail if placed before the first heading of a section. Use explicit levels for robust results. -

- -

The title block

-

- Use <RT-title> as the first element in your <body> (before the article container). This tag produces a standardized, styled header block with the document title and metadata. -

- -

Attributes

-
    -
  • title (Required): The main heading of the document.
  • -
  • author (Optional): The author's name. Renders in a bold accent color.
  • -
  • date (Optional): The publication or revision date.
  • -
- -

Example

- - - - - -

- Renders as: A centered, high contrast H1 followed by a serif styled metadata row containing the author and date. -

- -

The article container

-

- The root element must be <RT-article>. This is the boundary for the pagination logic. -

- -

Pagination

-

- The script paginate_by_element.js scans the article. It calculates the height of every element (including margins) and bundles them into <RT-page> elements. -

-

- Soft Limit Pagination: The system attempts to keep headers with their following paragraphs. It will break a page early rather than stranding a header at the bottom. -

- -

Manual page breaks and chapters

-

- A person can assert explicit control over the layout engine using the <RT-page-break></RT-page-break> tag. This tag forces the engine to close the current page and push all subsequent content to the top of the next page. Standard HTML5 parsing requires this custom tag to be explicitly closed; self-closing syntax will fail. -

-

- For major document divisions, use <RT-chapter>. The semantic processor translates this tag into an <RT-page-break> followed by an <h1 class="RT-chapter">. This ensures the chapter starts on a new page, inherits standard typography, and is automatically indexed by the TOC engine. -

- - Debugging - -

Debug tokens

-

- RT provides a lightweight debug logging system in utility.js. Logging is controlled by a set of active debug tokens. Each log message is assigned a token, and the message prints only if that token is enabled. -

- -

- Examples of common tokens include style, layout, pagination, selector, config, and term. -

- -

How logging is gated

-

- Normal log and warning output are gated. The methods debug.log(token,message) and debug.warn(token,message) will print only when the token exists in debug.active_tokens. -

- -

- This prevents the console from being flooded during normal use, while still allowing deep visibility during development. -

- -

Errors are always printed

-

- Errors are treated differently. The method debug.error(token,message) always prints, regardless of token state. These messages represent failures that require attention. -

- -

Enabling and disabling tokens

-

- Tokens are enabled or disabled in two ways: by editing the active_tokens set in utility.js, or at runtime by calling: -

- - - window.RT.debug.enable('term') - window.RT.debug.disable('term') - - -

- For example, the term system (RT_term.js) uses the term token. When that token is enabled, the module will print messages describing how terms were detected and which term definitions were assigned IDs. -

- - Themes -

- The system supports hot swapping themes by changing the script import in the head. -

-
    -
  • Dark: style/theme_dark_gold.js (Default)
  • -
  • Light: style/theme_light_gold.js
  • -
- - Manifest - - 2. utility.js (Math/Color physics) - 3. article_tech_ref.js (Typography and CSS injection) - 4. RT_code.js (Code block logic) - 5. RT_math.js (MathJax wrapper) - 6. RT_term.js (Term styling) - 7. RT_TOC.js (Navigation generator) - 8. paginate_by_element.js (Page splitter) - 9. page_fixed_glow.js (Visual page container) - - - RT conventions -

Headings are first letter capitalized. Remaining words are as they would be in English prose.

- - Exercises - -
    -
  1. -

    - Term occurrences: If an author tags a word with <RT-term> five times in a document, how many times will the term be visually decorated by the styling engine? How does a person force the engine to decorate a later occurrence? -

    -
  2. -
  3. -

    - Term normalization: A person writes <RT-term>Parse Tree</RT-term> in paragraph one, and <RT-term>parse tree</RT-term> in paragraph two. Will the system assign a definition anchor to the second occurrence? -

    -
  4. -
  5. -

    - TOC compilation: What happens if a person places an <RT-TOC> tag without a level attribute before the first heading of a section? -

    -
  6. -
  7. -

    - Code and math formatting: How does the RT system determine whether to render an <RT-code> or <RT-math> element inline with the text versus as a standalone block? -

    -
  8. -
  9. -

    - Pagination logic: When the script bundles elements into an <RT-page> container, how does the soft limit pagination handle a heading that falls at the very bottom of the page capacity? -

    -
  10. -
- -
- - diff --git a/developer/authored/Element.copy/TOC.js b/developer/authored/Element.copy/TOC.js deleted file mode 100644 index 2f3bc6f..0000000 --- a/developer/authored/Element.copy/TOC.js +++ /dev/null @@ -1,162 +0,0 @@ -/* - Processes tags. - Populates each with headings found below it. - - Attributes: - level="N" : Explicitly sets the target heading level (1-6). - e.g., level="1" collects H1s. level="2" collects H2s. - Stops collecting if it hits a heading of (level - 1) or higher. - - Default (No attribute): - Context Aware. Looks backwards for the nearest heading H(N). - Targets H(N+1). Stops at the next H(N). - -First heading 1 1 - First heading 2 2 - Next heading 2 2 -Next heading 2 3 - -*/ - -window.RT = window.RT || {}; - -window.RT.TOC = function(){ - const debug = window.RT.debug || { log: function(){} }; - const TOC_seq = document.querySelectorAll('rt-toc'); - - TOC_seq.forEach( (container ,TOC_index) => { - container.style.display = 'block'; - - // 1. Parse attribute: single number N or range A-B - const attr_val = container.getAttribute('level'); - let start_level, end_level; - - if (attr_val) { - const rangeMatch = attr_val.match(/^(\d)-(\d)$/); - if (rangeMatch) { - const a = parseInt(rangeMatch[1]); - const b = parseInt(rangeMatch[2]); - if (a >= 1 && a <= 6 && b >= 1 && b <= 6 && a <= b) { - start_level = a; - end_level = b; - if (debug.log) debug.log('TOC', `TOC #${TOC_index} range: H${a}-H${b}`); - } else { - if (debug.log) debug.log('TOC', `Invalid range "${attr_val}" → implicit mode`); - } - } else { - const single = parseInt(attr_val); - if (!isNaN(single) && single >= 1 && single <= 6) { - start_level = single; - end_level = single; - if (debug.log) debug.log('TOC', `TOC #${TOC_index} single level: H${single}`); - } else { - if (debug.log) debug.log('TOC', `Invalid level "${attr_val}" → implicit mode`); - } - } - } - - // 2. Implicit mode (no attribute or invalid) - if (start_level === undefined || end_level === undefined) { - let context_level = 0; - let prev = container.previousElementSibling; - while (prev) { - const match = prev.tagName.match(/^H([1-6])$/); - if (match) { - context_level = parseInt(match[1]); - break; - } - prev = prev.previousElementSibling; - } - const target_level = Math.min(context_level + 1, 6); - start_level = target_level; - end_level = target_level; - if (debug.log) debug.log('TOC', `TOC #${TOC_index} implicit target: H${target_level}`); - } - - // 3. Collect all matching headings until a higher-level heading stops us - const headings = []; - let next_el = container.nextElementSibling; - while (next_el) { - const match = next_el.tagName.match(/^H([1-6])$/); - if (match) { - const found_level = parseInt(match[1]); - - // Stop if we hit a heading that is a parent of the lowest level we collect - if (found_level < start_level) break; - - // Collect if within the requested range - if (found_level >= start_level && found_level <= end_level) { - // Ensure it has an id - if (!next_el.id) { - next_el.id = `TOC-ref-${TOC_index}-${found_level}-${headings.length}`; - } - headings.push({ el: next_el, level: found_level }); - } - } - next_el = next_el.nextElementSibling; - } - - // 4. Build the container (title + list) - container.innerHTML = ''; - const title = document.createElement('h1'); - title.textContent = start_level === 1 ? 'Table of Contents' : 'Section Contents'; - title.style.textAlign = 'center'; - container.appendChild(title); - - if (headings.length === 0) return; // nothing to show - - // Top-level list - const topList = document.createElement('ul'); - topList.style.listStyle = 'none'; - topList.style.paddingLeft = '0'; - container.appendChild(topList); - - // Stack of
    elements; index 0 = top-level list - const listStack = [topList]; - - for (const item of headings) { - // Depth relative to start_level - const depth = item.level - start_level; // 0 = top-level, 1 = sub-level, etc. - - // Ensure we have the correct nesting depth - while (listStack.length - 1 > depth) { - // Pop until we are at the right depth - listStack.pop(); - } - - // If we need to go deeper, open new sub-lists inside the last
  • - while (listStack.length - 1 < depth) { - const parentList = listStack[listStack.length - 1]; - const lastLi = parentList.lastElementChild; - if (lastLi) { - const subList = document.createElement('ul'); - subList.style.listStyle = 'none'; - subList.style.paddingLeft = '1.5rem'; // indentation for nested items - lastLi.appendChild(subList); - listStack.push(subList); - } else { - // No parent
  • yet – stay at current depth (flatten) - break; - } - } - - // Create the
  • for this heading - const li = document.createElement('li'); - li.style.marginBottom = '0.5rem'; - - const a = document.createElement('a'); - a.href = `#${item.el.id}`; - a.textContent = item.el.textContent; - a.style.textDecoration = 'none'; - a.style.color = 'inherit'; - a.style.display = 'block'; - - a.onmouseover = () => a.style.color = 'var(--rt-brand-primary)'; - a.onmouseout = () => a.style.color = 'inherit'; - - li.appendChild(a); - // Add to the current deepest list - listStack[listStack.length - 1].appendChild(li); - } - }); -}; diff --git a/developer/authored/Element.copy/chapter.js b/developer/authored/Element.copy/chapter.js deleted file mode 100644 index 42ba956..0000000 --- a/developer/authored/Element.copy/chapter.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - Processes tags. - Transforms the tag into an followed by an

    with the RT-chapter class. -*/ -window.RT = window.RT || {}; - -window.RT.chapter = function(){ - const debug = window.RT.debug || { log: function(){} }; - - document.querySelectorAll('RT-chapter').forEach( (el ,index) => { - if(debug.log) debug.log('chapter' ,`Processing chapter ${index + 1}`); - - const brk = document.createElement('RT-page-break'); - const h1 = document.createElement('h1'); - - h1.innerHTML = el.innerHTML; - - if(el.className){ - h1.className = el.className; - } - h1.classList.add('RT-chapter'); - - Array.from(el.attributes).forEach( (attr) => { - if(attr.name !== 'class'){ - h1.setAttribute(attr.name ,attr.value); - } - }); - - el.parentNode.insertBefore(brk ,el); - el.replaceWith(h1); - }); -}; diff --git a/developer/authored/Element.copy/code.js b/developer/authored/Element.copy/code.js deleted file mode 100644 index 0a97f16..0000000 --- a/developer/authored/Element.copy/code.js +++ /dev/null @@ -1,129 +0,0 @@ -/* - Processes tags. - Uses the central config or CSS variables from the theme. - - Removes common indent from lines of code. -*/ -function code() { - const RT = window.RT; - const U = RT.utility; - const debug = RT.debug; - - debug.log('code', 'Starting render cycle.'); - - const metrics = U.measure_ink_ratio('monospace'); - - document.querySelectorAll('rt-code').forEach((el) => { - el.style.fontFamily = 'monospace'; - - const computed = window.getComputedStyle(el); - const accent = computed.getPropertyValue('--rt-accent').trim() || 'gold'; - - const is_block = U.is_block_content(el); - const parentColor = computed.color; - const is_text_light = U.is_color_light(parentColor); - - const alpha = is_block ? 0.08 : 0.15; - const overlay = is_text_light ? `rgba(255,255,255,${alpha})` : `rgba(0,0,0,${alpha})`; - const text_color = is_text_light ? '#ffffff' : '#000000'; - - el.style.backgroundColor = overlay; - - if (is_block) { - el.style.display = 'block'; - - // --- Tag-Relative Auto-Dedent Logic --- - - // 1. Get Tag Indentation (The Anchor) - let tagIndent = ''; - const prevNode = el.previousSibling; - if (prevNode && prevNode.nodeType === 3) { - const prevText = prevNode.nodeValue; - const lastNewLineIndex = prevText.lastIndexOf('\n'); - if (lastNewLineIndex !== -1) { - tagIndent = prevText.substring(lastNewLineIndex + 1); - } else if (/^\s*$/.test(prevText)) { - tagIndent = prevText; - } - } - - // 2. Calculate Common Leading Whitespace from Content - const rawLines = el.textContent.split('\n'); - - // Filter out empty lines for calculation purposes so they don't break the logic - const contentLines = rawLines.filter(line => line.trim().length > 0); - - let commonIndent = null; - - if (contentLines.length > 0) { - // Assume the first line sets the standard - const firstMatch = contentLines[0].match(/^\s*/); - commonIndent = firstMatch ? firstMatch[0] : ''; - - // Reduce the commonIndent if subsequent lines have LESS indentation - for (let i = 1; i < contentLines.length; i++) { - const line = contentLines[i]; - // Determine how much of commonIndent this line shares - let j = 0; - while (j < commonIndent.length && j < line.length && commonIndent[j] === line[j]) { - j++; - } - commonIndent = commonIndent.substring(0, j); - if (commonIndent.length === 0) break; // Optimization - } - } else { - commonIndent = ''; - } - - // 3. Process Content - // Rule: Only strip if the Common Indent contains the Tag Indent (Safety Check) - // This handles the Emacs case: Tag is " ", Common is " ". " " starts with " ". - // We strip " ", leaving the code flush left. - let finalString = ''; - - if (commonIndent.length > 0 && commonIndent.startsWith(tagIndent)) { - const cleanedLines = rawLines.map(line => { - // Strip the common indent from valid lines - return line.startsWith(commonIndent) ? line.replace(commonIndent, '') : line; - }); - - // Remove artifact lines (first/last empty lines) - if (cleanedLines.length > 0 && cleanedLines[0].length === 0) { - cleanedLines.shift(); - } - if (cleanedLines.length > 0 && cleanedLines[cleanedLines.length - 1].trim().length === 0) { - cleanedLines.pop(); - } - finalString = cleanedLines.join('\n'); - } else { - // Fallback: Code is to the left of the tag or weirdly formatted. - // Just trim the wrapper newlines. - finalString = el.textContent.trim(); - } - - el.textContent = finalString; - // --- End Indentation Logic --- - - el.style.whiteSpace = 'pre'; - el.style.fontSize = (parseFloat(computed.fontSize) * metrics.ratio * 0.95) + 'px'; - el.style.padding = '1.2rem'; - el.style.margin = '1.5rem 0'; - el.style.borderLeft = `4px solid ${accent}`; - el.style.color = 'inherit'; - } else { - el.style.display = 'inline'; - const exactPx = parseFloat(computed.fontSize) * metrics.ratio * 1.0; - el.style.fontSize = exactPx + 'px'; - el.style.padding = '0.1rem 0.35rem'; - el.style.borderRadius = '3px'; - const offsetPx = metrics.baseline_diff * (exactPx / 100); - el.style.verticalAlign = offsetPx + 'px'; - el.style.color = text_color; - } - }); - - debug.log('code', 'Render cycle complete.'); -} - -window.RT = window.RT || {}; -window.RT.code = code; diff --git a/developer/authored/Element.copy/constraint.js b/developer/authored/Element.copy/constraint.js deleted file mode 100644 index c33b7b0..0000000 --- a/developer/authored/Element.copy/constraint.js +++ /dev/null @@ -1,13 +0,0 @@ -// developer/authored/RT/element/constraint.js -window.RT = window.RT || {}; - -window.RT.constraint = function(){ - document.querySelectorAll('rt-constraint').forEach( (el) => { - el.style.display = 'block'; - el.style.borderLeft = '4px solid var(--rt-state-warning)'; - el.style.backgroundColor = 'var(--rt-surface-1)'; - el.style.padding = '1rem'; - el.style.margin = '1.5rem 0'; - el.style.color = 'var(--rt-content-main)'; - }); -}; diff --git a/developer/authored/Element.copy/crossref.js b/developer/authored/Element.copy/crossref.js deleted file mode 100644 index aaea2bc..0000000 --- a/developer/authored/Element.copy/crossref.js +++ /dev/null @@ -1,15 +0,0 @@ -// developer/authored/RT/element/crossref.js -window.RT = window.RT || {}; - -window.RT.crossref = function(){ - document.querySelectorAll('rt-crossref').forEach( (el) => { - el.style.color = 'var(--rt-brand-link)'; - el.style.textDecoration = 'underline'; - el.style.cursor = 'pointer'; - el.style.fontWeight = '500'; - - // Note: To make this fully context-aware across soft limits, - // this module will eventually need to hook into the page - // registry built by paginate_by_element.js. - }); -}; diff --git a/developer/authored/Element.copy/endnote.js b/developer/authored/Element.copy/endnote.js deleted file mode 100644 index dd887b3..0000000 --- a/developer/authored/Element.copy/endnote.js +++ /dev/null @@ -1,55 +0,0 @@ -window.RT = window.RT || {}; - -window.RT.end_note = function(){ - const citations = document.querySelectorAll('rt-cite'); - if(citations.length === 0) return; - - const article = document.querySelector('rt-article'); - if(!article) return; - - // 1. Ensure the H1 is a direct child of the article so the TOC can see it - let endnotesHeader = document.getElementById('endnotes-header'); - if (!endnotesHeader) { - endnotesHeader = document.createElement('h1'); - endnotesHeader.id = 'endnotes-header'; - endnotesHeader.innerText = 'Endnotes'; - article.appendChild(endnotesHeader); - } - - // 2. Locate or generate the endnotes list container - let endnoteContainer = document.querySelector('rt-endnotes'); - if(!endnoteContainer) { - endnoteContainer = document.createElement('rt-endnotes'); - article.appendChild(endnoteContainer); - } - - // 3. Ensure the list structure exists - if(!endnoteContainer.querySelector('ol')) { - endnoteContainer.innerHTML = '
      '; - } - - const list = endnoteContainer.querySelector('ol'); - - // Process each inline citation - citations.forEach((cite, index) => { - const refNum = index + 1; - const refText = cite.getAttribute('ref') || cite.innerHTML; - - cite.innerHTML = `[${refNum}]`; - cite.style.cursor = 'pointer'; - cite.style.color = 'var(--rt-brand-link)'; - cite.style.textDecoration = 'none'; - - // Append the corresponding entry into the endnotes list - const li = document.createElement('li'); - li.id = `note-${refNum}`; - li.innerHTML = `${refText} `; - list.appendChild(li); - }); - - // Style the container - endnoteContainer.style.display = 'block'; - endnoteContainer.style.marginTop = '1rem'; - endnoteContainer.style.borderTop = '1px solid var(--rt-surface-3)'; - endnoteContainer.style.paddingTop = '1rem'; -}; diff --git a/developer/authored/Element.copy/math.js b/developer/authored/Element.copy/math.js deleted file mode 100644 index 51d86a7..0000000 --- a/developer/authored/Element.copy/math.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - Processes tags. - JavaScript: math() - HTML Tag: (parsed as rt-math) -*/ -function math(){ - // querySelector treats 'rt-math' as case-insensitive for the tag - document.querySelectorAll('rt-math').forEach(el => { - if (el.textContent.startsWith('$')) return; - - const is_block = el.parentElement.tagName === 'DIV' || - el.textContent.includes('\n') || - el.parentElement.childNodes.length === 1; - - const delimiter = is_block ? '$$' : '$'; - el.style.display = is_block ? 'block' : 'inline'; - el.textContent = `${delimiter}${el.textContent.trim()}${delimiter}`; - }); - - // MathJax must find its config at window.MathJax - window.MathJax = { - tex: { - inlineMath: [['$', '$']], - displayMath: [['$$', '$$']] - } - }; - - const script = document.createElement('script'); - script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'; - script.async = true; - document.head.appendChild(script); -} - -window.RT = window.RT || {}; -window.RT.math = math; diff --git a/developer/authored/Element.copy/symbol.js b/developer/authored/Element.copy/symbol.js deleted file mode 100644 index 7199fda..0000000 --- a/developer/authored/Element.copy/symbol.js +++ /dev/null @@ -1,10 +0,0 @@ -// developer/authored/RT/element/symbol.js -window.RT = window.RT || {}; - -window.RT.symbol = function(){ - document.querySelectorAll('rt-symbol').forEach( (el) => { - el.style.fontFamily = '"Courier New", Courier, monospace'; - el.style.fontWeight = '600'; - el.style.padding = '0 0.1em'; - }); -}; diff --git a/developer/authored/Element.copy/term.js b/developer/authored/Element.copy/term.js deleted file mode 100644 index 1cc779c..0000000 --- a/developer/authored/Element.copy/term.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - Processes and tags. - - Styles only the first occurrence of a unique term/neologism. - - The "-em" variants (e.g., ) are always styled. - - Automatically generates IDs for first occurrences for future indexing. -*/ - -window.RT = window.RT || {}; - -window.RT.term = function() { - const RT = window.RT; - - const debug = RT.debug || { - log: function() {} - ,warn: function() {} - ,error: function() {} - }; - - const DEBUG_TOKEN_S = 'term'; - - try { - // Track seen terms so only the first occurrence is decorated - const seen_terms_dpa = new Set(); - - const apply_style = (el, is_neologism_b) => { - el.style.fontStyle = 'italic'; - el.style.fontWeight = is_neologism_b ? '600' : '500'; - el.style.color = is_neologism_b - ? 'var(--rt-brand-secondary)' - : 'var(--rt-brand-primary)'; - el.style.paddingRight = '0.1em'; // Compensation for italic slant - el.style.display = 'inline'; - }; - - const clear_style = (el) => { - el.style.fontStyle = 'normal'; - el.style.color = 'inherit'; - el.style.fontWeight = 'inherit'; - el.style.paddingRight = ''; - el.style.display = ''; - }; - - const selector_s = [ - 'rt-term' - ,'rt-term-em' - ,'rt-neologism' - ,'rt-neologism-em' - ].join(','); - - const tags_dpa = document.querySelectorAll(selector_s); - - debug.log(DEBUG_TOKEN_S, `Scanning ${tags_dpa.length} term tags`); - - tags_dpa.forEach(el => { - const tag_name_s = el.tagName.toLowerCase(); - const is_neologism_b = tag_name_s.includes('neologism'); - const is_explicit_em_b = tag_name_s.endsWith('-em'); - - const term_text_raw_s = (el.textContent || '').trim(); - if (!term_text_raw_s.length) { - debug.warn(DEBUG_TOKEN_S, `Empty term tag encountered: <${tag_name_s}>`); - return; - } - - // Normalize text for uniqueness tracking - const term_norm_s = term_text_raw_s.toLowerCase(); - - // Slug for ID generation (simple + stable) - const slug_s = term_norm_s.replace(/\s+/g, '-'); - - const is_first_occurrence_b = !seen_terms_dpa.has(term_norm_s); - - if (is_explicit_em_b || is_first_occurrence_b) { - apply_style(el, is_neologism_b); - - if (!is_explicit_em_b && is_first_occurrence_b) { - seen_terms_dpa.add(term_norm_s); - - if (!el.id) { - el.id = `def-${is_neologism_b ? 'neo-' : ''}${slug_s}`; - debug.log( - DEBUG_TOKEN_S - ,`First occurrence: "${term_norm_s}" -> id="${el.id}"` - ); - } else { - debug.log( - DEBUG_TOKEN_S - ,`First occurrence: "${term_norm_s}" (existing id="${el.id}")` - ); - } - } else if (is_explicit_em_b) { - debug.log( - DEBUG_TOKEN_S - ,`Emphasized occurrence: "${term_norm_s}" (<${tag_name_s}>)` - ); - } - } else { - // Subsequent mentions render as normal prose - clear_style(el); - } - }); - - debug.log(DEBUG_TOKEN_S, `Unique terms defined: ${seen_terms_dpa.size}`); - } catch (e) { - debug.error('error', `term failed: ${e && e.message ? e.message : String(e)}`); - } -}; diff --git a/developer/authored/Element.copy/theme_selector.js b/developer/authored/Element.copy/theme_selector.js deleted file mode 100644 index 05759d2..0000000 --- a/developer/authored/Element.copy/theme_selector.js +++ /dev/null @@ -1,27 +0,0 @@ -class ThemeSelector extends HTMLElement{ - connectedCallback(){ - let current_theme = localStorage.getItem('RT_theme_preference'); - if(!current_theme){ - current_theme = 'dark_gold'; - } - - this.innerHTML = ` -
      - Theme Selection
      -
      - -
      - `; - - this.addEventListener( 'change' ,(e) => { - localStorage.setItem('RT_theme_preference' ,e.target.value); - location.reload(); - } ); - } -} - -customElements.define('rt-theme-selector' ,ThemeSelector); diff --git a/developer/authored/Element.copy/title.js b/developer/authored/Element.copy/title.js deleted file mode 100644 index bfb8d4e..0000000 --- a/developer/authored/Element.copy/title.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - Processes tags. - Generates a standard document header block. - - Usage: - -*/ -window.RT = window.RT || {}; - -window.RT.title = function() { - const debug = window.RT.debug || { log: function(){} }; - - document.querySelectorAll('rt-title').forEach(el => { - const title = el.getAttribute('title') || 'Untitled Document'; - const author = el.getAttribute('author'); - const date = el.getAttribute('date'); - const copyright = el.getAttribute('copyright'); - - if (debug.log) debug.log('title', `Generating title block: ${title}`); - - // Container - const container = document.createElement('div'); - container.style.textAlign = 'center'; - container.style.marginBottom = '3rem'; - container.style.marginTop = '2rem'; - container.style.borderBottom = '1px solid var(--rt-border-default)'; - container.style.paddingBottom = '1.5rem'; - - // Main Title (H1) - const h1 = document.createElement('h1'); - h1.textContent = title; - h1.style.margin = '0 0 0.8rem 0'; - h1.style.border = 'none'; // Override standard H1 border - h1.style.padding = '0'; - h1.style.color = 'var(--rt-brand-primary)'; - h1.style.fontSize = '2.5em'; - h1.style.lineHeight = '1.1'; - h1.style.letterSpacing = '-0.03em'; - - container.appendChild(h1); - - // Metadata Row (Author | Date) - if (author || date) { - const meta = document.createElement('div'); - meta.style.color = 'var(--rt-content-muted)'; - meta.style.fontStyle = 'italic'; - meta.style.fontSize = '1.1em'; - meta.style.fontFamily = '"Georgia", "Times New Roman", serif'; // Classy serif - - const parts = []; - if (author) parts.push(`${author}`); - if (date) parts.push(date); - - meta.innerHTML = parts.join('  —  '); - container.appendChild(meta); - } - - // Copyright Row - if (copyright) { - const copy_div = document.createElement('div'); - copy_div.style.color = 'var(--rt-content-muted)'; - copy_div.style.fontSize = '0.9em'; - copy_div.style.marginTop = '0.5rem'; - // Automatically injects the copyright symbol - copy_div.innerHTML = `© ${copyright}`; - container.appendChild(copy_div); - } - - // Replace the raw tag with the generated block - el.replaceWith(container); - }); -}; diff --git a/developer/authored/Layout.copy/article_tech_ref.js b/developer/authored/Layout.copy/article_tech_ref.js deleted file mode 100644 index fc7034b..0000000 --- a/developer/authored/Layout.copy/article_tech_ref.js +++ /dev/null @@ -1,295 +0,0 @@ -// debug messages don't work here, because core/utility isn't loaded until after the function runs. -(function(){ - const RT = window.RT = window.RT || {}; - const debug = RT.debug || { log: function(){} }; - - debug.log('scroll', "1. Initializing script."); - - // 1. Intercept native history restoration immediately - if ('scrollRestoration' in history) { - history.scrollRestoration = 'manual'; - debug.log('scroll', "2. history.scrollRestoration set to manual."); - } - - // 2. Read coordinate from memory before any layout shifts occur - const raw_target = sessionStorage.getItem('RT_saved_y'); - const target_y = raw_target !== null ? parseInt(raw_target, 10) : 0; - - // 3. Determine if the execution is a page reload - let is_reload = false; - if (window.performance) { - const nav_entries = performance.getEntriesByType("navigation"); - if (nav_entries.length > 0) { - is_reload = (nav_entries[0].type === "reload"); - } else if (performance.navigation) { - is_reload = (performance.navigation.type === 1); - } - } - - debug.log('scroll', `3. Target Y: ${target_y} | Is Reload: ${is_reload}`); - - // 4. The Lock - let is_layout_locked = true; - - // Helper to ensure we only signal completion once - function unlock_layout() { - if (!is_layout_locked) return; - is_layout_locked = false; - debug.log('scroll', "10. Layout fully unlocked. Emitting completion signal."); - document.dispatchEvent(new Event("RT_layout_complete")); - } - - // 5. Declare Dependencies - RT.load('element/chapter'); - RT.load('element/endnote'); - RT.load('element/math'); - RT.load('element/code'); - RT.load('element/term'); - RT.load('element/TOC'); - RT.load('element/title'); - RT.load('element/theme_selector'); - RT.load('element/symbol'); - RT.load('element/constraint'); - RT.load('element/crossref'); - - RT.load('layout/paginate_by_element'); - RT.load('layout/page_fixed_glow'); - - // 6. The Typography Layout - RT.article = function(){ - RT.config = RT.config || {}; - RT.config.article = { - font_family: '"Noto Sans", "Segoe UI", "Helvetica Neue", sans-serif' - ,line_height: "1.8" - ,font_size: "16px" - ,font_weight: "400" - ,max_width: "820px" - ,margin: "0 auto" - }; - - if( RT.config.theme && RT.config.theme.meta_is_dark === false ){ - RT.config.article.font_weight = "600"; - } - - const conf = RT.config.article; - const article_seq = document.querySelectorAll("RT-article"); - - if(article_seq.length === 0) return; - - for(let i = 0; i < article_seq.length; i++){ - let style = article_seq[i].style; - style.display = "block"; - style.fontFamily = conf.font_family; - style.fontSize = conf.font_size; - style.lineHeight = conf.line_height; - style.fontWeight = conf.font_weight; - style.maxWidth = conf.max_width; - style.margin = conf.margin; - style.padding = "0 20px"; - style.color = "var(--rt-content-main)"; - } - - window.RT = window.RT || {}; - window.RT.config = window.RT.config || {}; - window.RT.config.page = window.RT.config.page || {}; - window.RT.config.page.height_limit = 900; - - const style_node = document.createElement("style"); - style_node.innerHTML = ` - body, html, rt-article { - overflow-anchor: none !important; - } - - rt-article { - font-family: 'Noto Sans JP', Arial, sans-serif; - background-color: var(--rt-surface-0); - color: var(--rt-content-main); - max-width: 46.875rem !important; - box-sizing: border-box !important; - } - - rt-article:not(:has(rt-page)) { - padding: 3rem !important; - } - - rt-article:has(rt-page) { - padding: 0 !important; - } - - rt-article rt-page { - position: relative; - display: block; - padding: 3rem; - margin: 1.25rem auto; - background-color: var(--rt-surface-0); - box-shadow: 0 0 0.625rem var(--rt-brand-primary); - } - - rt-article h1 { - font-size: 1.5rem; - text-align: center; - color: var(--rt-brand-primary); - font-weight: 500; - margin-top: 1.5rem; - line-height: 1.15; - } - rt-article h2 { - font-size: 1.25rem; - color: var(--rt-brand-secondary); - text-align: left; - margin-top: 2rem; - margin-left: 0; - } - rt-article h3 { - font-size: 1.125rem; - color: var(--rt-brand-tertiary); - text-align: left; - margin-top: 1.5rem; - margin-left: 4ch; - } - rt-article h4 { - font-size: 1.05rem; - color: var(--rt-content-main); - font-weight: 600; - text-align: left; - margin-top: 1.25rem; - margin-left: 8ch; - } - - rt-article p, - rt-article ul, - rt-article ol { - color: var(--rt-content-main); - text-align: justify; - margin-bottom: 1rem; - margin-left: 0; - } - rt-article li { - margin-bottom: 0.5rem; - } - - rt-article rt-code { - font-family: 'Courier New', Courier, monospace; - background-color: var(--rt-surface-code); - padding: 0.125rem 0.25rem; - color: var(--rt-content-main); - } - - rt-article img { - max-width: 100%; - height: auto; - display: block; - margin: 1.5rem auto; - } - `; - document.head.appendChild(style_node); - }; - - // 7. The Execution Sequence - function run_semantics(){ - debug.log('scroll' ,`4. run_semantics starting.`); - if(RT.theme) RT.theme(); - if(RT.endnote) RT.endnote(); - RT.article(); - if(RT.title) RT.title(); - if(RT.term) RT.term(); - if(RT.math) RT.math(); - if(RT.code) RT.code(); - if(RT.symbol) RT.symbol(); - if(RT.constraint) RT.constraint(); - if(RT.crossref) RT.crossref(); - - if( window.MathJax && MathJax.Hub && MathJax.Hub.Queue ){ - MathJax.Hub.Queue( ["Typeset" ,MathJax.Hub] ,run_layout ); - }else{ - run_layout(); - } - } - - function run_layout() { - debug.log('scroll', `5. run_layout starting.`); - - if(RT.chapter) RT.chapter(); - if(RT.TOC) RT.TOC(); - if(RT.paginate_by_element) RT.paginate_by_element(); - if(RT.page) RT.page(); - - debug.log('scroll', `6. Pagination complete.`); - - let final_target = target_y; - let use_hash = false; - - if (window.location.hash && !is_reload) { - const hash_target = document.getElementById(window.location.hash.substring(1)); - if (hash_target) { - use_hash = true; - } - } - - debug.log('scroll', `7. Commencing viewport enforce loop. Mode: ${use_hash ? 'HASH' : 'Y-COORDINATE'}`); - enforce_scroll(final_target, use_hash, 0); - } - - // 8. The Enforcer Logic - function enforce_scroll(target, use_hash, attempts) { - if (attempts > 15) { - debug.log('scroll', "8. Scroll enforcement timed out. Unlocking."); - unlock_layout(); - return; - } - - if (use_hash) { - const hash_target = document.getElementById(window.location.hash.substring(1)); - if (hash_target) { - hash_target.scrollIntoView(); - debug.log('scroll', `8a. Attempt ${attempts}: Scrolled to Hash Target. Y is now ${window.scrollY}`); - } - } else { - window.scrollTo(0, target); - debug.log('scroll', `8b. Attempt ${attempts}: Scrolled to Y=${target}. Current Y is ${window.scrollY}`); - } - - let is_successful = false; - if (use_hash) { - is_successful = true; - } else { - is_successful = (Math.abs(window.scrollY - target) < 5 || target === 0); - } - - if (is_successful && document.body.scrollHeight > 1000) { - debug.log('scroll', `9. Viewport anchored successfully.`); - - setTimeout(() => { - if (!use_hash && Math.abs(window.scrollY - target) >= 5) { - debug.log('scroll', `9a. Browser late-stage rebellion detected. Re-enforcing.`); - enforce_scroll(target, use_hash, attempts + 1); - } else { - unlock_layout(); - } - }, 100); - } else { - setTimeout(() => enforce_scroll(target, use_hash, attempts + 1), 50); - } - } - - // 9. The Ledger - let scroll_timer; - window.addEventListener('scroll', () => { - if (is_layout_locked) return; - clearTimeout(scroll_timer); - scroll_timer = setTimeout(() => { - sessionStorage.setItem('RT_saved_y', window.scrollY); - debug.log('scroll', `X. User stopped scrolling. Saved Y: ${window.scrollY}`); - }, 200); - }, { passive: true }); - - window.addEventListener('beforeunload', () => { - is_layout_locked = true; - debug.log('scroll', "Y. Page unloading. Scroll listener locked."); - }); - - // 10. Bind to DOM Ready - document.addEventListener('DOMContentLoaded', run_semantics); - -})(); - diff --git a/developer/authored/Layout.copy/memo_State.js b/developer/authored/Layout.copy/memo_State.js deleted file mode 100644 index 5609705..0000000 --- a/developer/authored/Layout.copy/memo_State.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - - - - - - - -*/ - -(function(){ - const RT = window.RT = window.RT || {}; - - // 1. Declare Dependencies - RT.load('core/utility'); - RT.load('element/title'); - RT.load('element/term'); - RT.load('element/TOC'); - RT.load('core/body_visibility_visible'); - - // 2. The Typography Layout - RT.memo_state_dept = function(){ - const body = document.body; - const html = document.documentElement; - - // Force strict print colors regardless of user system settings - html.style.backgroundColor = "white"; - body.style.backgroundColor = "white"; - body.style.color = "black"; - - // Target the new semantic tag - const memo_seq = document.querySelectorAll("RT-memo"); - if(memo_seq.length === 0) return; - - for(let i = 0; i < memo_seq.length; i++){ - let style = memo_seq[i].style; - style.display = "block"; - style.fontFamily = '"Times New Roman", Times, serif'; - style.fontSize = "12pt"; - style.lineHeight = "1.15"; - // 8.5 inch standard width minus 1-inch margins on each side - style.maxWidth = "6.5in"; - style.margin = "1in auto"; - style.padding = "0"; - style.textAlign = "left"; - style.color = "black"; - } - }; - - // 3. The Execution Sequence - const run_semantics = function(){ - RT.memo_state_dept(); - - if(RT.title) RT.title(); - if(RT.term) RT.term(); - if(RT.TOC) RT.TOC(); - - run_layout(); - }; - - const run_layout = function(){ - if(RT.body_visibility_visible) RT.body_visibility_visible(); - }; - - // 4. Bind to DOM Ready - document.addEventListener('DOMContentLoaded' ,run_semantics); - -})(); diff --git a/developer/authored/Layout.copy/page_fixed_glow.js b/developer/authored/Layout.copy/page_fixed_glow.js deleted file mode 100644 index 6ef8819..0000000 --- a/developer/authored/Layout.copy/page_fixed_glow.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - Page Layout: Fixed Glow - Standard: Theme 1.0 - Description: A variable-height container with a glowing border effect that matches the active theme. -*/ -(function(){ - const RT = window.RT = window.RT || {}; - - RT.page = function() { - RT.config = RT.config || {}; - - // Default Configuration - const defaults = { - width: "100%" - ,min_height: "15rem" // Replaces fixed height - ,padding: "3rem" - ,margin: "4rem auto" - - ,bg_color: "var(--rt-surface-0)" - ,border_color: "var(--rt-brand-primary)" - ,text_color: "var(--rt-brand-primary)" - - ,shadow: "drop-shadow(0px 0px 15px var(--rt-brand-primary))" - }; - - RT.config.page = Object.assign({}, defaults, RT.config.page || {}); - - const conf = RT.config.page; - const style_id = 'rt-page-fixed-glow'; - - if (!document.getElementById(style_id)) { - const style_el = document.createElement('style'); - style_el.id = style_id; - - style_el.textContent = ` - /* Reset page counter on the article container */ - rt-article { - counter-reset: rt-page-counter; - } - - rt-page { - display: block; - position: relative; - box-sizing: border-box; - overflow: hidden; - - /* Dimensions */ - width: ${conf.width}; - min-height: ${conf.min_height}; - margin: ${conf.margin}; - padding: ${conf.padding}; - - /* Theming */ - background-color: ${conf.bg_color}; - border: 1px solid ${conf.border_color}; - - /* The "Glow" Effect */ - filter: ${conf.shadow}; - - /* Counter Increment */ - counter-increment: rt-page-counter; - } - - /* Page Numbering */ - rt-page::after { - content: "Page " counter(rt-page-counter); - position: absolute; - bottom: 1.5rem; - right: 3rem; - - font-family: "Noto Sans", sans-serif; - font-size: 0.9rem; - font-weight: bold; - - color: ${conf.text_color}; - opacity: 0.8; - pointer-events: none; - } - `; - document.head.appendChild(style_el); - } - }; -})(); diff --git a/developer/authored/Layout.copy/paginate_by_element.js b/developer/authored/Layout.copy/paginate_by_element.js deleted file mode 100644 index aca2122..0000000 --- a/developer/authored/Layout.copy/paginate_by_element.js +++ /dev/null @@ -1,399 +0,0 @@ -window.RT.paginate_by_element = function () { - const RT = window.RT; - const debug = RT.debug || { log: function(){}, error: function(){} }; - const page_conf = (RT.config && RT.config.page) ? RT.config.page : {}; - const page_height_limit = page_conf.height_limit || 1000; - - let measureContainer = null; - - // ========================================================= - // 1. DOM Measurement Utilities - // ========================================================= - function getElHeight(el) { - const wasInDOM = el.parentNode !== null; - if (!wasInDOM) document.body.appendChild(el); - const rect = el.getBoundingClientRect(); - const style = window.getComputedStyle(el); - const margin = parseFloat(style.marginTop) + parseFloat(style.marginBottom); - if (!wasInDOM) el.remove(); - return (rect.height || 0) + (margin || 0); - } - - function getMeasureContainer() { - if (measureContainer && measureContainer.parentNode) return measureContainer; - const article = document.querySelector('RT-article'); - if (!article) { - const temp = document.createElement('div'); - temp.style.visibility = 'hidden'; - temp.style.position = 'absolute'; - temp.style.width = '100%'; - document.body.appendChild(temp); - measureContainer = temp; - return temp; - } - const container = document.createElement('div'); - const articleStyle = window.getComputedStyle(article); - container.style.visibility = 'hidden'; - container.style.position = 'absolute'; - container.style.width = articleStyle.width; - container.style.fontFamily = articleStyle.fontFamily; - container.style.fontSize = articleStyle.fontSize; - container.style.lineHeight = articleStyle.lineHeight; - container.style.fontWeight = articleStyle.fontWeight; - document.body.appendChild(container); - measureContainer = container; - return container; - } - - function measureFragment(frag) { - const container = getMeasureContainer(); - container.appendChild(frag); - const h = getElHeight(frag); - container.removeChild(frag); - return h; - } - - // ========================================================= - // STEP 1: PREPARE FOOTNOTES (Strip and tag) - // ========================================================= - const article_seq = document.querySelectorAll('RT-article'); - if (article_seq.length === 0) { - debug.error('pagination', 'No elements found. Pagination aborted.'); - return; - } - - const footnote_registry = {}; - let footnote_counter = 1; - - Array.from(article_seq).forEach(article => { - // Bulletproof extraction: immune to XML/HTML case-sensitivity parsing quirks - const all_nodes = Array.from(article.querySelectorAll('*')); - const raw_footnotes = all_nodes.filter(node => node.tagName.toLowerCase() === 'rt-footnote'); - - raw_footnotes.forEach(fn => { - const id = footnote_counter++; - footnote_registry[id] = fn.innerHTML; // Save the payload - - // Trim any standard HTML whitespace immediately preceding the tag - const prev = fn.previousSibling; - if (prev && prev.nodeType === Node.TEXT_NODE) { - prev.textContent = prev.textContent.replace(/\s+$/, ''); - } - - // Replace with a zero-height marker that rides along with the text - const marker = document.createElement('rt-fn-marker'); - marker.setAttribute('data-id', id); - - if (fn.parentNode) { - fn.parentNode.replaceChild(marker, fn); - } - }); - }); - - // ========================================================= - // Splitting Logic (Clean and undisturbed) - // ========================================================= - function isSplittable(el) { - const tag = el.tagName; - if (tag === 'UL' || tag === 'OL') { - const items = Array.from(el.children).filter(c => c.tagName === 'LI'); - if (items.length === 0) return null; - - const itemHeights = items.map(li => getElHeight(li)); - const emptyClone = el.cloneNode(false); - const overhead = getElHeight(emptyClone); - - el._splitInfo = { type: 'list', itemHeights, overhead, offset: 0 }; - return makeListSplitter(el, el._splitInfo); - } - - if (tag === 'TABLE') { - const thead = el.querySelector('thead'); - const tbody = el.querySelector('tbody'); - const rows = tbody ? Array.from(tbody.rows) : Array.from(el.rows); - if (rows.length === 0) return null; - - const theadHeight = thead ? getElHeight(thead) : 0; - const rowHeights = rows.map(row => getElHeight(row)); - - const emptyClone = el.cloneNode(false); - if (thead) emptyClone.appendChild(thead.cloneNode(true)); - emptyClone.appendChild(document.createElement('tbody')); - const overhead = getElHeight(emptyClone) - theadHeight; - - el._splitInfo = { type: 'table', rowHeights, overhead, theadHeight, offset: 0 }; - return makeTableSplitter(el, el._splitInfo); - } - return null; - } - - function makeListSplitter(el, info) { - return (remaining) => { - const children = Array.from(el.children).filter(c => c.tagName === 'LI'); - const start = info.offset; - - let bestCount = 0; - let bestHeight = 0; - const tempList = el.cloneNode(false); - - for (let i = 0; i < children.length; i++) { - const itemClone = children[i].cloneNode(true); - tempList.appendChild(itemClone); - const fragHeight = measureFragment(tempList); - if (fragHeight <= remaining) { - bestCount = i + 1; - bestHeight = fragHeight; - } else { - tempList.removeChild(itemClone); - break; - } - } - - if (bestCount === 0) return { first: null, rest: el, firstHeight: 0 }; - - const first = el.cloneNode(false); - for (let i = 0; i < bestCount; i++) { - first.appendChild(children[i].cloneNode(true)); - } - - let rest = null; - if (bestCount < children.length) { - rest = el.cloneNode(false); - for (let i = bestCount; i < children.length; i++) { - rest.appendChild(children[i].cloneNode(true)); - } - - if (el.tagName === 'OL') { - const currentStart = parseInt(el.getAttribute('start'), 10) || 1; - rest.setAttribute('start', currentStart + bestCount); - } - - rest._splitInfo = { - type: 'list', - itemHeights: info.itemHeights, - overhead: info.overhead, - offset: start + bestCount - }; - } - - return { first, rest, firstHeight: bestHeight }; - }; - } - - function makeTableSplitter(el, info) { - const thead = el.querySelector('thead'); - const createShell = () => { - const shell = el.cloneNode(false); - if (thead) shell.appendChild(thead.cloneNode(true)); - const newTbody = document.createElement('tbody'); - shell.appendChild(newTbody); - return shell; - }; - - return (remaining) => { - const tbody = el.querySelector('tbody'); - const rows = tbody ? Array.from(tbody.rows) : Array.from(el.rows); - const start = info.offset; - - let bestCount = 0; - let bestHeight = 0; - const tempTable = createShell(); - const tempBody = tempTable.querySelector('tbody'); - - for (let i = 0; i < rows.length; i++) { - tempBody.appendChild(rows[i].cloneNode(true)); - const h = measureFragment(tempTable); - if (h <= remaining) { - bestCount = i + 1; - bestHeight = h; - } else { - tempBody.removeChild(tempBody.lastChild); - break; - } - } - - if (bestCount === 0) return { first: null, rest: el, firstHeight: 0 }; - - const first = createShell(); - const firstBody = first.querySelector('tbody'); - for (let i = 0; i < bestCount; i++) { - firstBody.appendChild(rows[i].cloneNode(true)); - } - - let rest = null; - if (bestCount < rows.length) { - rest = createShell(); - const restBody = rest.querySelector('tbody'); - for (let i = bestCount; i < rows.length; i++) { - restBody.appendChild(rows[i].cloneNode(true)); - } - - rest._splitInfo = { - type: 'table', - rowHeights: info.rowHeights, - overhead: info.overhead, - theadHeight: info.theadHeight, - offset: start + bestCount - }; - } - - return { first, rest, firstHeight: bestHeight }; - }; - } - - // ========================================================= - // STEP 2: NORMAL PAGINATOR - // ========================================================= - function paginateArticle(article) { - const raw_element_seq = Array.from(article.children).filter(el => - !['SCRIPT', 'STYLE', 'RT-PAGE'].includes(el.tagName) - ); - - if (raw_element_seq.length === 0) return; - - const page_seq = []; - let current_batch_seq = []; - let current_h = 0; - let i = 0; - - while (i < raw_element_seq.length) { - const el = raw_element_seq[i]; - const splitter = isSplittable(el); - - if (splitter) { - const remaining = page_height_limit - current_h; - const { first, rest, firstHeight } = splitter(remaining); - - if (first) { - current_batch_seq.push(first); - current_h += firstHeight; - - if (rest) { - raw_element_seq.splice(i, 1, rest); - } else { - raw_element_seq.splice(i, 1); - } - } else { - if (current_batch_seq.length === 0) { - 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.push(frame); - i++; - } else { - page_seq.push(current_batch_seq); - current_batch_seq = []; - current_h = 0; - raw_element_seq[i] = rest || el; - } - } - continue; - } - - - // --- Ordinary (non-splittable) element --- - 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 ){ - 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; - 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; - } else { - page_seq.push(backtrack_seq); - current_batch_seq = []; - current_h = 0; - } - } - - current_batch_seq.push(el); - current_h += h; - i++; - } - - if (current_batch_seq.length > 0) { - page_seq.push(current_batch_seq); - } - - // Rebuild article with wrappers - article.innerHTML = ''; - let p = 0; - while (p < page_seq.length) { - const batch = page_seq[p]; - const page_el = document.createElement('rt-page'); - page_el.id = `page-${p + 1}`; - batch.forEach(item => page_el.appendChild(item)); - article.appendChild(page_el); - p++; - } - } - - // Execute pagination - Array.from(article_seq).forEach(article => paginateArticle(article)); - - // ========================================================= - // STEP 3: RESOLVE FOOTNOTES & EXPAND PAGES - // ========================================================= - Array.from(article_seq).forEach(article => { - const rendered_pages = article.querySelectorAll('rt-page'); - - Array.from(rendered_pages).forEach(page => { - // Bulletproof extraction for the markers - const all_page_nodes = Array.from(page.querySelectorAll('*')); - const markers = all_page_nodes.filter(node => node.tagName.toLowerCase() === 'rt-fn-marker'); - - if (markers.length === 0) return; - - // Construct the footer block for this page - const fn_container = document.createElement('div'); - fn_container.className = 'rt-footnote-container'; - fn_container.style.borderTop = '1px solid var(--rt-border-default)'; - fn_container.style.marginTop = '2rem'; - fn_container.style.paddingTop = '1rem'; - fn_container.style.fontSize = '0.9em'; - - markers.forEach(marker => { - const id = marker.getAttribute('data-id'); - const html = footnote_registry[id]; - - // Replace the invisible marker with the visible naked superscript link - const sup = document.createElement('sup'); - sup.innerHTML = `${id}`; - - if (marker.parentNode) { - marker.parentNode.replaceChild(sup, marker); - } - - // Append the actual text to the footer with a clean, print-ready number format - const fn_line = document.createElement('div'); - fn_line.id = `fn-${id}`; - fn_line.style.marginBottom = '0.5rem'; - fn_line.innerHTML = `${id}.${html}`; - fn_container.appendChild(fn_line); - }); - - // Attach the footer. The page organically stretches to fit. - page.appendChild(fn_container); - }); - }); - - // Cleanup - if (measureContainer && measureContainer.parentNode) { - measureContainer.remove(); - measureContainer = null; - } -}; diff --git a/developer/authored/Manuscript.copy/Core/block_visibility_during_layout.js b/developer/authored/Manuscript.copy/Core/block_visibility_during_layout.js new file mode 100644 index 0000000..8513f01 --- /dev/null +++ b/developer/authored/Manuscript.copy/Core/block_visibility_during_layout.js @@ -0,0 +1,19 @@ +// block_visibility_during_layout.js + +// 1. Hide the document immediately upon execution in the +document.documentElement.style.visibility = "hidden"; + +// 2. Define the restoration function +const restore_visibility = function() { + document.documentElement.style.visibility = ""; + document.removeEventListener("RT_layout_complete", restore_visibility); + window.removeEventListener("load", restore_visibility); +}; + +// 3. Listen for a specific completion signal from the layout engine +document.addEventListener("RT_layout_complete", restore_visibility); + +// 4. Structural Safety Net: If the layout engine fails or is never loaded, +// restore visibility on the final window 'load' event so the page doesn't remain blank. +window.addEventListener("load", restore_visibility); + diff --git a/developer/authored/Manuscript.copy/Core/loader.js b/developer/authored/Manuscript.copy/Core/loader.js new file mode 100644 index 0000000..34218dc --- /dev/null +++ b/developer/authored/Manuscript.copy/Core/loader.js @@ -0,0 +1,34 @@ +window.RT = window.RT || {}; + +// 1. Establish the module registry +window.RT._loaded_modules = window.RT._loaded_modules || new Set(); + +window.RT.load = function(module_path){ + let target_module = module_path; + + // Strict enforcement of the PascalCase namespace + if (target_module === 'Theme') { + let saved_theme = localStorage.getItem('RT_theme_preference'); + if (!saved_theme) { + saved_theme = 'dark_gold'; + localStorage.setItem('RT_theme_preference', saved_theme); + } + target_module = 'Theme/' + saved_theme; + } + + // 2. The Idempotency Check: Abort if already loaded + if (window.RT._loaded_modules.has(target_module)) { + return; + } + + // 3. Register the module + window.RT._loaded_modules.add(target_module); + + let resolved_path = window.RT.dirpr_library + '/' + target_module; + + if (!resolved_path.endsWith('.js')) { + resolved_path = resolved_path + '.js'; + } + + document.write(''); +}; diff --git a/developer/authored/Manuscript.copy/Core/utility.js b/developer/authored/Manuscript.copy/Core/utility.js new file mode 100644 index 0000000..d6f2ddd --- /dev/null +++ b/developer/authored/Manuscript.copy/Core/utility.js @@ -0,0 +1,109 @@ +/* + General utilities for the RT Style library. +*/ + +window.RT = window.RT || {}; + +// --- DEBUG SYSTEM --- +window.RT.debug = { + + // all debug messages enabled +/* + active_tokens: new Set([ + 'style', 'layout', 'pagination' + ,'selector', 'config', 'error' + ,'term' + ,'scroll' + ]), + + active_tokens: new Set([ + 'term' + ]), +*/ + + active_tokens: new Set([ + ]), + + log: function(token, message) { + if (this.active_tokens.has(token)) { + console.log(`[RT:${token}]`, message); + } + }, + + warn: function(token, message) { + if (this.active_tokens.has(token)) { + console.warn(`[RT:${token}]`, message); + } + }, + + error: function(token, message) { + console.error(`[RT:${token}] CRITICAL:`, message); + }, + + enable: function(token) { this.active_tokens.add(token); console.log(`Enabled: ${token}`); }, + disable: function(token) { this.active_tokens.delete(token); console.log(`Disabled: ${token}`); } +}; + +// --- UTILITIES --- +window.RT.utility = { + // --- FONT PHYSICS --- + measure_ink_ratio: function(target_font, ref_font = null) { + const debug = window.RT.debug; + debug.log('layout', `Measuring ink ratio for ${target_font}`); + + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + + if (!ref_font) { + const bodyStyle = window.getComputedStyle(document.body); + ref_font = bodyStyle.fontFamily; + } + + const get_metrics = (font) => { + ctx.font = '100px ' + font; + const metrics = ctx.measureText('M'); + return { + ascent: metrics.actualBoundingBoxAscent, + descent: metrics.actualBoundingBoxDescent + }; + }; + + const ref_m = get_metrics(ref_font); + const target_m = get_metrics(target_font); + + const ratio = ref_m.ascent / target_m.ascent; + + return { + ratio: ratio, + baseline_diff: ref_m.descent - target_m.descent + }; + }, + + // --- COLOR PHYSICS --- + is_color_light: function(color_string) { + // 1. HSL Check + if (color_string.startsWith('hsl')) { + const numbers = color_string.match(/\d+/g); + if (numbers && numbers.length >= 3) { + const lightness = parseInt(numbers[2]); + return lightness > 50; + } + } + + // 2. RGB Check + const rgb = color_string.match(/\d+/g); + if (!rgb) { + return true; + } + + const r = parseInt(rgb[0]); + const g = parseInt(rgb[1]); + const b = parseInt(rgb[2]); + const luma = (r * 299 + g * 587 + b * 114) / 1000; + return luma > 128; + }, + + is_block_content: function(element) { + return element.textContent.trim().includes('\n'); + } +}; diff --git a/developer/authored/Manuscript.copy/Document/RT-style.js b/developer/authored/Manuscript.copy/Document/RT-style.js new file mode 100644 index 0000000..dcd7ff2 --- /dev/null +++ b/developer/authored/Manuscript.copy/Document/RT-style.js @@ -0,0 +1,20 @@ +// for documents in RT-style/Manuscript/document +window.RT = window.RT || {}; + +(function() { + // We are the style library, so ... + window.RT.dirpr_library = ".."; + + // 1. Inject the loader script + document.write(' + + + + + + + + + + + + Table of custom tags + +

      Style tag reference

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      TagDescription
      <RT-article>Article container.
      <RT-title> + Title block and metadata. +
      <RT-TOC>Compiles TOC.
      <RT-index>Compiles an alphabetical glossary of defined terms.
      <RT-term>Conventional term.
      <RT-term-em>Forces emphasis for a term even after first occurrence.
      <RT-neologism>Project specific term.
      <RT-neologism-em>Forces emphasis for a neologism even after first occurrence.
      <RT-code>Code span or code block.
      <RT-math>Inline or block math.
      <RT-footnote>Inline text to be extracted and rendered at the bottom of the page.
      <RT-cite>Bibliographic citation marker.
      <RT-ref>Dynamic cross reference to another element in the document.
      <RT-page>Automatically inserted pagination container.
      <RT-chapter>Chapter heading with implied page break.
      <RT-page-break>Explicit page break directive. Must be explicitly closed.
      + + Architecture overview +

      + The RT Style System is a client-side, JavaScript-driven publishing framework designed to turn raw HTML into high-readability technical documentation. Unlike standard CSS frameworks, RT uses JavaScript to handle complex layout tasks like ink-ratio balancing and dynamic pagination. +

      + +

      Pulling style files into a document

      +

      Put `setup.js` in the directory, and include it at the top of the document, + `setup.js` points at the style files and is installation specific.

      + + + Semantic tags +

      + The system relies on a specific set of custom tags in the RT- namespace to separate meaning from presentation. +

      + +

      Terminology

      + +

      Conventional terms

      +

      + Use <RT-term> for standard, industry accepted technical terms. The system decorates only the first occurrence of each unique term so that the first appearance functions as a definition point, and later appearances do not overload the page with styling. +

      + + + The Singleton Pattern restricts instantiation... + + +

      + Renders as: The Singleton Pattern restricts instantiation... +

      + +

      Neologisms

      +

      + Use <RT-neologism> for terms invented specifically for the current document or project. Neologisms are styled more strongly than conventional terms, visually distinguishing "jargon you should know" from "jargon we invented." +

      + + + We define the Hyper Tape as a construct... + + +

      + Renders as: We define the Hyper Tape as a construct... +

      + +

      First occurrence rule

      +

      + The term system is intentionally conservative. For the tags <RT-term> and <RT-neologism>, only the first occurrence of a unique term is decorated. Subsequent mentions are rendered as normal prose. +

      + +

      + Uniqueness is tracked by normalizing the term text (trimmed, then lowercased). This means that Symbol and symbol count as the same term. +

      + +

      Forced emphasis variants

      +

      + Sometimes a later mention of a term should be emphasized again. For that purpose, the system provides explicit emphasis tags: +

      + +
        +
      • <RT-term-em>
      • +
      • <RT-neologism-em>
      • +
      + +

      + These variants are always decorated, even if the term appeared earlier. +

      + +

      Automatic definition anchors

      +

      + For first occurrences, the term module automatically assigns an id attribute if one does not already exist. This establishes stable anchors for future indexing and linking. +

      + + + We define a Symbol as... + + +

      + The first occurrence will be given an id similar to def-symbol. For neologisms, an additional marker is used, for example def-neo-hyper-tape. +

      + +

      Technical content

      + +

      Code

      +

      + Use <RT-code>. If placed inline, it acts like a span. If placed as a block (with newlines), it acts like a pre formatted block with a theme aware border. +

      + + + # Block Code Example + def hello(): + return "World" + + +

      Mathematics

      +

      + Use <RT-math>. The system auto detects if it is a block equation or inline variable and wraps it in MathJax delimiters. +

      +

      + Inline: Let x be the input. +

      +

      + Block: +

      + + f(x) = \sum_{i=0}^{n} x_i + + +

      References, citations, and indexing

      + +

      Footnotes

      +

      + Use <RT-footnote> to author footnote content directly inline with the text it references. During the layout phase, the pagination engine extracts the text, replaces the element with an invisible structural marker, and compiles a formatted footnote container at the bottom of the active <RT-page>. +

      + +

      Citations

      +

      + Use <RT-cite> with the ref attribute to insert bibliographic citations. This ensures formatting remains consistent and separates citation data from standard prose. +

      + + ... formalized as Basic Law V . + + +

      Dynamic cross referencing

      +

      + A person authoring a technical document frequently refers back to tables, equations, or previous sections. Use <RT-ref target="element-id"> to link to specific content. This tag dynamically retrieves the numbering or caption of the target element, maintaining correct references even if preceding elements shift during editing. +

      + +

      Glossary indexing

      +

      + Use <RT-index> at the end of the document to compile a glossary. Similar to the TOC compiler, this tag scans the DOM for automatic definition anchors produced by the term module and generates an alphabetized list of defined terms and neologisms. +

      + + Navigation and layout + +

      Automatic table of contents

      +

      + Use <RT-TOC> to insert a compiled table of contents. The tag scans the document forward from its current position to collect headings. +

      + +

      Explicit mode

      +

      + Use the level="N" attribute to target a specific heading depth. +

      +
        +
      • <RT-TOC level="1">: Collects all <h1> elements until the end of the document. Best for the main document index.
      • +
      • <RT-TOC level="2">: Collects all <h2> elements until it encounters the next <h1>. Best for chapter summaries.
      • +
      + +

      Implicit mode

      +

      + If no level is specified, the TOC scans backwards to find the nearest heading (for example H1) and assumes you want to collect children one level deeper (for example H2). +

      +

      + Note: Implicit mode can fail if placed before the first heading of a section. Use explicit levels for robust results. +

      + +

      The title block

      +

      + Use <RT-title> as the first element in your <body> (before the article container). This tag produces a standardized, styled header block with the document title and metadata. +

      + +

      Attributes

      +
        +
      • title (Required): The main heading of the document.
      • +
      • author (Optional): The author's name. Renders in a bold accent color.
      • +
      • date (Optional): The publication or revision date.
      • +
      + +

      Example

      + + + + + +

      + Renders as: A centered, high contrast H1 followed by a serif styled metadata row containing the author and date. +

      + +

      The article container

      +

      + The root element must be <RT-article>. This is the boundary for the pagination logic. +

      + +

      Pagination

      +

      + The script paginate_by_element.js scans the article. It calculates the height of every element (including margins) and bundles them into <RT-page> elements. +

      +

      + Soft Limit Pagination: The system attempts to keep headers with their following paragraphs. It will break a page early rather than stranding a header at the bottom. +

      + +

      Manual page breaks and chapters

      +

      + A person can assert explicit control over the layout engine using the <RT-page-break></RT-page-break> tag. This tag forces the engine to close the current page and push all subsequent content to the top of the next page. Standard HTML5 parsing requires this custom tag to be explicitly closed; self-closing syntax will fail. +

      +

      + For major document divisions, use <RT-chapter>. The semantic processor translates this tag into an <RT-page-break> followed by an <h1 class="RT-chapter">. This ensures the chapter starts on a new page, inherits standard typography, and is automatically indexed by the TOC engine. +

      + + Debugging + +

      Debug tokens

      +

      + RT provides a lightweight debug logging system in utility.js. Logging is controlled by a set of active debug tokens. Each log message is assigned a token, and the message prints only if that token is enabled. +

      + +

      + Examples of common tokens include style, layout, pagination, selector, config, and term. +

      + +

      How logging is gated

      +

      + Normal log and warning output are gated. The methods debug.log(token,message) and debug.warn(token,message) will print only when the token exists in debug.active_tokens. +

      + +

      + This prevents the console from being flooded during normal use, while still allowing deep visibility during development. +

      + +

      Errors are always printed

      +

      + Errors are treated differently. The method debug.error(token,message) always prints, regardless of token state. These messages represent failures that require attention. +

      + +

      Enabling and disabling tokens

      +

      + Tokens are enabled or disabled in two ways: by editing the active_tokens set in utility.js, or at runtime by calling: +

      + + + window.RT.debug.enable('term') + window.RT.debug.disable('term') + + +

      + For example, the term system (RT_term.js) uses the term token. When that token is enabled, the module will print messages describing how terms were detected and which term definitions were assigned IDs. +

      + + Themes +

      + The system supports hot swapping themes by changing the script import in the head. +

      +
        +
      • Dark: style/theme_dark_gold.js (Default)
      • +
      • Light: style/theme_light_gold.js
      • +
      + + Manifest + + 2. utility.js (Math/Color physics) + 3. article_tech_ref.js (Typography and CSS injection) + 4. RT_code.js (Code block logic) + 5. RT_math.js (MathJax wrapper) + 6. RT_term.js (Term styling) + 7. RT_TOC.js (Navigation generator) + 8. paginate_by_element.js (Page splitter) + 9. page_fixed_glow.js (Visual page container) + + + RT conventions +

      Headings are first letter capitalized. Remaining words are as they would be in English prose.

      + + Exercises + +
        +
      1. +

        + Term occurrences: If an author tags a word with <RT-term> five times in a document, how many times will the term be visually decorated by the styling engine? How does a person force the engine to decorate a later occurrence? +

        +
      2. +
      3. +

        + Term normalization: A person writes <RT-term>Parse Tree</RT-term> in paragraph one, and <RT-term>parse tree</RT-term> in paragraph two. Will the system assign a definition anchor to the second occurrence? +

        +
      4. +
      5. +

        + TOC compilation: What happens if a person places an <RT-TOC> tag without a level attribute before the first heading of a section? +

        +
      6. +
      7. +

        + Code and math formatting: How does the RT system determine whether to render an <RT-code> or <RT-math> element inline with the text versus as a standalone block? +

        +
      8. +
      9. +

        + Pagination logic: When the script bundles elements into an <RT-page> container, how does the soft limit pagination handle a heading that falls at the very bottom of the page capacity? +

        +
      10. +
      + +
      + + diff --git a/developer/authored/Manuscript.copy/Element/TOC.js b/developer/authored/Manuscript.copy/Element/TOC.js new file mode 100644 index 0000000..2f3bc6f --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/TOC.js @@ -0,0 +1,162 @@ +/* + Processes tags. + Populates each with headings found below it. + + Attributes: + level="N" : Explicitly sets the target heading level (1-6). + e.g., level="1" collects H1s. level="2" collects H2s. + Stops collecting if it hits a heading of (level - 1) or higher. + + Default (No attribute): + Context Aware. Looks backwards for the nearest heading H(N). + Targets H(N+1). Stops at the next H(N). + +First heading 1 1 + First heading 2 2 + Next heading 2 2 +Next heading 2 3 + +*/ + +window.RT = window.RT || {}; + +window.RT.TOC = function(){ + const debug = window.RT.debug || { log: function(){} }; + const TOC_seq = document.querySelectorAll('rt-toc'); + + TOC_seq.forEach( (container ,TOC_index) => { + container.style.display = 'block'; + + // 1. Parse attribute: single number N or range A-B + const attr_val = container.getAttribute('level'); + let start_level, end_level; + + if (attr_val) { + const rangeMatch = attr_val.match(/^(\d)-(\d)$/); + if (rangeMatch) { + const a = parseInt(rangeMatch[1]); + const b = parseInt(rangeMatch[2]); + if (a >= 1 && a <= 6 && b >= 1 && b <= 6 && a <= b) { + start_level = a; + end_level = b; + if (debug.log) debug.log('TOC', `TOC #${TOC_index} range: H${a}-H${b}`); + } else { + if (debug.log) debug.log('TOC', `Invalid range "${attr_val}" → implicit mode`); + } + } else { + const single = parseInt(attr_val); + if (!isNaN(single) && single >= 1 && single <= 6) { + start_level = single; + end_level = single; + if (debug.log) debug.log('TOC', `TOC #${TOC_index} single level: H${single}`); + } else { + if (debug.log) debug.log('TOC', `Invalid level "${attr_val}" → implicit mode`); + } + } + } + + // 2. Implicit mode (no attribute or invalid) + if (start_level === undefined || end_level === undefined) { + let context_level = 0; + let prev = container.previousElementSibling; + while (prev) { + const match = prev.tagName.match(/^H([1-6])$/); + if (match) { + context_level = parseInt(match[1]); + break; + } + prev = prev.previousElementSibling; + } + const target_level = Math.min(context_level + 1, 6); + start_level = target_level; + end_level = target_level; + if (debug.log) debug.log('TOC', `TOC #${TOC_index} implicit target: H${target_level}`); + } + + // 3. Collect all matching headings until a higher-level heading stops us + const headings = []; + let next_el = container.nextElementSibling; + while (next_el) { + const match = next_el.tagName.match(/^H([1-6])$/); + if (match) { + const found_level = parseInt(match[1]); + + // Stop if we hit a heading that is a parent of the lowest level we collect + if (found_level < start_level) break; + + // Collect if within the requested range + if (found_level >= start_level && found_level <= end_level) { + // Ensure it has an id + if (!next_el.id) { + next_el.id = `TOC-ref-${TOC_index}-${found_level}-${headings.length}`; + } + headings.push({ el: next_el, level: found_level }); + } + } + next_el = next_el.nextElementSibling; + } + + // 4. Build the container (title + list) + container.innerHTML = ''; + const title = document.createElement('h1'); + title.textContent = start_level === 1 ? 'Table of Contents' : 'Section Contents'; + title.style.textAlign = 'center'; + container.appendChild(title); + + if (headings.length === 0) return; // nothing to show + + // Top-level list + const topList = document.createElement('ul'); + topList.style.listStyle = 'none'; + topList.style.paddingLeft = '0'; + container.appendChild(topList); + + // Stack of
        elements; index 0 = top-level list + const listStack = [topList]; + + for (const item of headings) { + // Depth relative to start_level + const depth = item.level - start_level; // 0 = top-level, 1 = sub-level, etc. + + // Ensure we have the correct nesting depth + while (listStack.length - 1 > depth) { + // Pop until we are at the right depth + listStack.pop(); + } + + // If we need to go deeper, open new sub-lists inside the last
      • + while (listStack.length - 1 < depth) { + const parentList = listStack[listStack.length - 1]; + const lastLi = parentList.lastElementChild; + if (lastLi) { + const subList = document.createElement('ul'); + subList.style.listStyle = 'none'; + subList.style.paddingLeft = '1.5rem'; // indentation for nested items + lastLi.appendChild(subList); + listStack.push(subList); + } else { + // No parent
      • yet – stay at current depth (flatten) + break; + } + } + + // Create the
      • for this heading + const li = document.createElement('li'); + li.style.marginBottom = '0.5rem'; + + const a = document.createElement('a'); + a.href = `#${item.el.id}`; + a.textContent = item.el.textContent; + a.style.textDecoration = 'none'; + a.style.color = 'inherit'; + a.style.display = 'block'; + + a.onmouseover = () => a.style.color = 'var(--rt-brand-primary)'; + a.onmouseout = () => a.style.color = 'inherit'; + + li.appendChild(a); + // Add to the current deepest list + listStack[listStack.length - 1].appendChild(li); + } + }); +}; diff --git a/developer/authored/Manuscript.copy/Element/chapter.js b/developer/authored/Manuscript.copy/Element/chapter.js new file mode 100644 index 0000000..42ba956 --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/chapter.js @@ -0,0 +1,32 @@ +/* + Processes tags. + Transforms the tag into an followed by an

        with the RT-chapter class. +*/ +window.RT = window.RT || {}; + +window.RT.chapter = function(){ + const debug = window.RT.debug || { log: function(){} }; + + document.querySelectorAll('RT-chapter').forEach( (el ,index) => { + if(debug.log) debug.log('chapter' ,`Processing chapter ${index + 1}`); + + const brk = document.createElement('RT-page-break'); + const h1 = document.createElement('h1'); + + h1.innerHTML = el.innerHTML; + + if(el.className){ + h1.className = el.className; + } + h1.classList.add('RT-chapter'); + + Array.from(el.attributes).forEach( (attr) => { + if(attr.name !== 'class'){ + h1.setAttribute(attr.name ,attr.value); + } + }); + + el.parentNode.insertBefore(brk ,el); + el.replaceWith(h1); + }); +}; diff --git a/developer/authored/Manuscript.copy/Element/code.js b/developer/authored/Manuscript.copy/Element/code.js new file mode 100644 index 0000000..0a97f16 --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/code.js @@ -0,0 +1,129 @@ +/* + Processes tags. + Uses the central config or CSS variables from the theme. + + Removes common indent from lines of code. +*/ +function code() { + const RT = window.RT; + const U = RT.utility; + const debug = RT.debug; + + debug.log('code', 'Starting render cycle.'); + + const metrics = U.measure_ink_ratio('monospace'); + + document.querySelectorAll('rt-code').forEach((el) => { + el.style.fontFamily = 'monospace'; + + const computed = window.getComputedStyle(el); + const accent = computed.getPropertyValue('--rt-accent').trim() || 'gold'; + + const is_block = U.is_block_content(el); + const parentColor = computed.color; + const is_text_light = U.is_color_light(parentColor); + + const alpha = is_block ? 0.08 : 0.15; + const overlay = is_text_light ? `rgba(255,255,255,${alpha})` : `rgba(0,0,0,${alpha})`; + const text_color = is_text_light ? '#ffffff' : '#000000'; + + el.style.backgroundColor = overlay; + + if (is_block) { + el.style.display = 'block'; + + // --- Tag-Relative Auto-Dedent Logic --- + + // 1. Get Tag Indentation (The Anchor) + let tagIndent = ''; + const prevNode = el.previousSibling; + if (prevNode && prevNode.nodeType === 3) { + const prevText = prevNode.nodeValue; + const lastNewLineIndex = prevText.lastIndexOf('\n'); + if (lastNewLineIndex !== -1) { + tagIndent = prevText.substring(lastNewLineIndex + 1); + } else if (/^\s*$/.test(prevText)) { + tagIndent = prevText; + } + } + + // 2. Calculate Common Leading Whitespace from Content + const rawLines = el.textContent.split('\n'); + + // Filter out empty lines for calculation purposes so they don't break the logic + const contentLines = rawLines.filter(line => line.trim().length > 0); + + let commonIndent = null; + + if (contentLines.length > 0) { + // Assume the first line sets the standard + const firstMatch = contentLines[0].match(/^\s*/); + commonIndent = firstMatch ? firstMatch[0] : ''; + + // Reduce the commonIndent if subsequent lines have LESS indentation + for (let i = 1; i < contentLines.length; i++) { + const line = contentLines[i]; + // Determine how much of commonIndent this line shares + let j = 0; + while (j < commonIndent.length && j < line.length && commonIndent[j] === line[j]) { + j++; + } + commonIndent = commonIndent.substring(0, j); + if (commonIndent.length === 0) break; // Optimization + } + } else { + commonIndent = ''; + } + + // 3. Process Content + // Rule: Only strip if the Common Indent contains the Tag Indent (Safety Check) + // This handles the Emacs case: Tag is " ", Common is " ". " " starts with " ". + // We strip " ", leaving the code flush left. + let finalString = ''; + + if (commonIndent.length > 0 && commonIndent.startsWith(tagIndent)) { + const cleanedLines = rawLines.map(line => { + // Strip the common indent from valid lines + return line.startsWith(commonIndent) ? line.replace(commonIndent, '') : line; + }); + + // Remove artifact lines (first/last empty lines) + if (cleanedLines.length > 0 && cleanedLines[0].length === 0) { + cleanedLines.shift(); + } + if (cleanedLines.length > 0 && cleanedLines[cleanedLines.length - 1].trim().length === 0) { + cleanedLines.pop(); + } + finalString = cleanedLines.join('\n'); + } else { + // Fallback: Code is to the left of the tag or weirdly formatted. + // Just trim the wrapper newlines. + finalString = el.textContent.trim(); + } + + el.textContent = finalString; + // --- End Indentation Logic --- + + el.style.whiteSpace = 'pre'; + el.style.fontSize = (parseFloat(computed.fontSize) * metrics.ratio * 0.95) + 'px'; + el.style.padding = '1.2rem'; + el.style.margin = '1.5rem 0'; + el.style.borderLeft = `4px solid ${accent}`; + el.style.color = 'inherit'; + } else { + el.style.display = 'inline'; + const exactPx = parseFloat(computed.fontSize) * metrics.ratio * 1.0; + el.style.fontSize = exactPx + 'px'; + el.style.padding = '0.1rem 0.35rem'; + el.style.borderRadius = '3px'; + const offsetPx = metrics.baseline_diff * (exactPx / 100); + el.style.verticalAlign = offsetPx + 'px'; + el.style.color = text_color; + } + }); + + debug.log('code', 'Render cycle complete.'); +} + +window.RT = window.RT || {}; +window.RT.code = code; diff --git a/developer/authored/Manuscript.copy/Element/constraint.js b/developer/authored/Manuscript.copy/Element/constraint.js new file mode 100644 index 0000000..c33b7b0 --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/constraint.js @@ -0,0 +1,13 @@ +// developer/authored/RT/element/constraint.js +window.RT = window.RT || {}; + +window.RT.constraint = function(){ + document.querySelectorAll('rt-constraint').forEach( (el) => { + el.style.display = 'block'; + el.style.borderLeft = '4px solid var(--rt-state-warning)'; + el.style.backgroundColor = 'var(--rt-surface-1)'; + el.style.padding = '1rem'; + el.style.margin = '1.5rem 0'; + el.style.color = 'var(--rt-content-main)'; + }); +}; diff --git a/developer/authored/Manuscript.copy/Element/crossref.js b/developer/authored/Manuscript.copy/Element/crossref.js new file mode 100644 index 0000000..aaea2bc --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/crossref.js @@ -0,0 +1,15 @@ +// developer/authored/RT/element/crossref.js +window.RT = window.RT || {}; + +window.RT.crossref = function(){ + document.querySelectorAll('rt-crossref').forEach( (el) => { + el.style.color = 'var(--rt-brand-link)'; + el.style.textDecoration = 'underline'; + el.style.cursor = 'pointer'; + el.style.fontWeight = '500'; + + // Note: To make this fully context-aware across soft limits, + // this module will eventually need to hook into the page + // registry built by paginate_by_element.js. + }); +}; diff --git a/developer/authored/Manuscript.copy/Element/endnote.js b/developer/authored/Manuscript.copy/Element/endnote.js new file mode 100644 index 0000000..dd887b3 --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/endnote.js @@ -0,0 +1,55 @@ +window.RT = window.RT || {}; + +window.RT.end_note = function(){ + const citations = document.querySelectorAll('rt-cite'); + if(citations.length === 0) return; + + const article = document.querySelector('rt-article'); + if(!article) return; + + // 1. Ensure the H1 is a direct child of the article so the TOC can see it + let endnotesHeader = document.getElementById('endnotes-header'); + if (!endnotesHeader) { + endnotesHeader = document.createElement('h1'); + endnotesHeader.id = 'endnotes-header'; + endnotesHeader.innerText = 'Endnotes'; + article.appendChild(endnotesHeader); + } + + // 2. Locate or generate the endnotes list container + let endnoteContainer = document.querySelector('rt-endnotes'); + if(!endnoteContainer) { + endnoteContainer = document.createElement('rt-endnotes'); + article.appendChild(endnoteContainer); + } + + // 3. Ensure the list structure exists + if(!endnoteContainer.querySelector('ol')) { + endnoteContainer.innerHTML = '
          '; + } + + const list = endnoteContainer.querySelector('ol'); + + // Process each inline citation + citations.forEach((cite, index) => { + const refNum = index + 1; + const refText = cite.getAttribute('ref') || cite.innerHTML; + + cite.innerHTML = `[${refNum}]`; + cite.style.cursor = 'pointer'; + cite.style.color = 'var(--rt-brand-link)'; + cite.style.textDecoration = 'none'; + + // Append the corresponding entry into the endnotes list + const li = document.createElement('li'); + li.id = `note-${refNum}`; + li.innerHTML = `${refText} `; + list.appendChild(li); + }); + + // Style the container + endnoteContainer.style.display = 'block'; + endnoteContainer.style.marginTop = '1rem'; + endnoteContainer.style.borderTop = '1px solid var(--rt-surface-3)'; + endnoteContainer.style.paddingTop = '1rem'; +}; diff --git a/developer/authored/Manuscript.copy/Element/math.js b/developer/authored/Manuscript.copy/Element/math.js new file mode 100644 index 0000000..51d86a7 --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/math.js @@ -0,0 +1,35 @@ +/* + Processes tags. + JavaScript: math() + HTML Tag: (parsed as rt-math) +*/ +function math(){ + // querySelector treats 'rt-math' as case-insensitive for the tag + document.querySelectorAll('rt-math').forEach(el => { + if (el.textContent.startsWith('$')) return; + + const is_block = el.parentElement.tagName === 'DIV' || + el.textContent.includes('\n') || + el.parentElement.childNodes.length === 1; + + const delimiter = is_block ? '$$' : '$'; + el.style.display = is_block ? 'block' : 'inline'; + el.textContent = `${delimiter}${el.textContent.trim()}${delimiter}`; + }); + + // MathJax must find its config at window.MathJax + window.MathJax = { + tex: { + inlineMath: [['$', '$']], + displayMath: [['$$', '$$']] + } + }; + + const script = document.createElement('script'); + script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'; + script.async = true; + document.head.appendChild(script); +} + +window.RT = window.RT || {}; +window.RT.math = math; diff --git a/developer/authored/Manuscript.copy/Element/symbol.js b/developer/authored/Manuscript.copy/Element/symbol.js new file mode 100644 index 0000000..7199fda --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/symbol.js @@ -0,0 +1,10 @@ +// developer/authored/RT/element/symbol.js +window.RT = window.RT || {}; + +window.RT.symbol = function(){ + document.querySelectorAll('rt-symbol').forEach( (el) => { + el.style.fontFamily = '"Courier New", Courier, monospace'; + el.style.fontWeight = '600'; + el.style.padding = '0 0.1em'; + }); +}; diff --git a/developer/authored/Manuscript.copy/Element/term.js b/developer/authored/Manuscript.copy/Element/term.js new file mode 100644 index 0000000..1cc779c --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/term.js @@ -0,0 +1,107 @@ +/* + Processes and tags. + - Styles only the first occurrence of a unique term/neologism. + - The "-em" variants (e.g., ) are always styled. + - Automatically generates IDs for first occurrences for future indexing. +*/ + +window.RT = window.RT || {}; + +window.RT.term = function() { + const RT = window.RT; + + const debug = RT.debug || { + log: function() {} + ,warn: function() {} + ,error: function() {} + }; + + const DEBUG_TOKEN_S = 'term'; + + try { + // Track seen terms so only the first occurrence is decorated + const seen_terms_dpa = new Set(); + + const apply_style = (el, is_neologism_b) => { + el.style.fontStyle = 'italic'; + el.style.fontWeight = is_neologism_b ? '600' : '500'; + el.style.color = is_neologism_b + ? 'var(--rt-brand-secondary)' + : 'var(--rt-brand-primary)'; + el.style.paddingRight = '0.1em'; // Compensation for italic slant + el.style.display = 'inline'; + }; + + const clear_style = (el) => { + el.style.fontStyle = 'normal'; + el.style.color = 'inherit'; + el.style.fontWeight = 'inherit'; + el.style.paddingRight = ''; + el.style.display = ''; + }; + + const selector_s = [ + 'rt-term' + ,'rt-term-em' + ,'rt-neologism' + ,'rt-neologism-em' + ].join(','); + + const tags_dpa = document.querySelectorAll(selector_s); + + debug.log(DEBUG_TOKEN_S, `Scanning ${tags_dpa.length} term tags`); + + tags_dpa.forEach(el => { + const tag_name_s = el.tagName.toLowerCase(); + const is_neologism_b = tag_name_s.includes('neologism'); + const is_explicit_em_b = tag_name_s.endsWith('-em'); + + const term_text_raw_s = (el.textContent || '').trim(); + if (!term_text_raw_s.length) { + debug.warn(DEBUG_TOKEN_S, `Empty term tag encountered: <${tag_name_s}>`); + return; + } + + // Normalize text for uniqueness tracking + const term_norm_s = term_text_raw_s.toLowerCase(); + + // Slug for ID generation (simple + stable) + const slug_s = term_norm_s.replace(/\s+/g, '-'); + + const is_first_occurrence_b = !seen_terms_dpa.has(term_norm_s); + + if (is_explicit_em_b || is_first_occurrence_b) { + apply_style(el, is_neologism_b); + + if (!is_explicit_em_b && is_first_occurrence_b) { + seen_terms_dpa.add(term_norm_s); + + if (!el.id) { + el.id = `def-${is_neologism_b ? 'neo-' : ''}${slug_s}`; + debug.log( + DEBUG_TOKEN_S + ,`First occurrence: "${term_norm_s}" -> id="${el.id}"` + ); + } else { + debug.log( + DEBUG_TOKEN_S + ,`First occurrence: "${term_norm_s}" (existing id="${el.id}")` + ); + } + } else if (is_explicit_em_b) { + debug.log( + DEBUG_TOKEN_S + ,`Emphasized occurrence: "${term_norm_s}" (<${tag_name_s}>)` + ); + } + } else { + // Subsequent mentions render as normal prose + clear_style(el); + } + }); + + debug.log(DEBUG_TOKEN_S, `Unique terms defined: ${seen_terms_dpa.size}`); + } catch (e) { + debug.error('error', `term failed: ${e && e.message ? e.message : String(e)}`); + } +}; diff --git a/developer/authored/Manuscript.copy/Element/theme_selector.js b/developer/authored/Manuscript.copy/Element/theme_selector.js new file mode 100644 index 0000000..05759d2 --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/theme_selector.js @@ -0,0 +1,27 @@ +class ThemeSelector extends HTMLElement{ + connectedCallback(){ + let current_theme = localStorage.getItem('RT_theme_preference'); + if(!current_theme){ + current_theme = 'dark_gold'; + } + + this.innerHTML = ` +
          + Theme Selection
          +
          + +
          + `; + + this.addEventListener( 'change' ,(e) => { + localStorage.setItem('RT_theme_preference' ,e.target.value); + location.reload(); + } ); + } +} + +customElements.define('rt-theme-selector' ,ThemeSelector); diff --git a/developer/authored/Manuscript.copy/Element/title.js b/developer/authored/Manuscript.copy/Element/title.js new file mode 100644 index 0000000..bfb8d4e --- /dev/null +++ b/developer/authored/Manuscript.copy/Element/title.js @@ -0,0 +1,72 @@ +/* + Processes tags. + Generates a standard document header block. + + Usage: + +*/ +window.RT = window.RT || {}; + +window.RT.title = function() { + const debug = window.RT.debug || { log: function(){} }; + + document.querySelectorAll('rt-title').forEach(el => { + const title = el.getAttribute('title') || 'Untitled Document'; + const author = el.getAttribute('author'); + const date = el.getAttribute('date'); + const copyright = el.getAttribute('copyright'); + + if (debug.log) debug.log('title', `Generating title block: ${title}`); + + // Container + const container = document.createElement('div'); + container.style.textAlign = 'center'; + container.style.marginBottom = '3rem'; + container.style.marginTop = '2rem'; + container.style.borderBottom = '1px solid var(--rt-border-default)'; + container.style.paddingBottom = '1.5rem'; + + // Main Title (H1) + const h1 = document.createElement('h1'); + h1.textContent = title; + h1.style.margin = '0 0 0.8rem 0'; + h1.style.border = 'none'; // Override standard H1 border + h1.style.padding = '0'; + h1.style.color = 'var(--rt-brand-primary)'; + h1.style.fontSize = '2.5em'; + h1.style.lineHeight = '1.1'; + h1.style.letterSpacing = '-0.03em'; + + container.appendChild(h1); + + // Metadata Row (Author | Date) + if (author || date) { + const meta = document.createElement('div'); + meta.style.color = 'var(--rt-content-muted)'; + meta.style.fontStyle = 'italic'; + meta.style.fontSize = '1.1em'; + meta.style.fontFamily = '"Georgia", "Times New Roman", serif'; // Classy serif + + const parts = []; + if (author) parts.push(`${author}`); + if (date) parts.push(date); + + meta.innerHTML = parts.join('  —  '); + container.appendChild(meta); + } + + // Copyright Row + if (copyright) { + const copy_div = document.createElement('div'); + copy_div.style.color = 'var(--rt-content-muted)'; + copy_div.style.fontSize = '0.9em'; + copy_div.style.marginTop = '0.5rem'; + // Automatically injects the copyright symbol + copy_div.innerHTML = `© ${copyright}`; + container.appendChild(copy_div); + } + + // Replace the raw tag with the generated block + el.replaceWith(container); + }); +}; diff --git a/developer/authored/Manuscript.copy/Layout/article_tech_ref.js b/developer/authored/Manuscript.copy/Layout/article_tech_ref.js new file mode 100644 index 0000000..9da5d5d --- /dev/null +++ b/developer/authored/Manuscript.copy/Layout/article_tech_ref.js @@ -0,0 +1,294 @@ +// debug messages don't work here, because core/utility isn't loaded until after the function runs. +(function(){ + const RT = window.RT = window.RT || {}; + const debug = RT.debug || { log: function(){} }; + + debug.log('scroll', "1. Initializing script."); + + // 1. Intercept native history restoration immediately + if ('scrollRestoration' in history) { + history.scrollRestoration = 'manual'; + debug.log('scroll', "2. history.scrollRestoration set to manual."); + } + + // 2. Read coordinate from memory before any layout shifts occur + const raw_target = sessionStorage.getItem('RT_saved_y'); + const target_y = raw_target !== null ? parseInt(raw_target, 10) : 0; + + // 3. Determine if the execution is a page reload + let is_reload = false; + if (window.performance) { + const nav_entries = performance.getEntriesByType("navigation"); + if (nav_entries.length > 0) { + is_reload = (nav_entries[0].type === "reload"); + } else if (performance.navigation) { + is_reload = (performance.navigation.type === 1); + } + } + + debug.log('scroll', `3. Target Y: ${target_y} | Is Reload: ${is_reload}`); + + // 4. The Lock + let is_layout_locked = true; + + // Helper to ensure we only signal completion once + function unlock_layout() { + if (!is_layout_locked) return; + is_layout_locked = false; + debug.log('scroll', "10. Layout fully unlocked. Emitting completion signal."); + document.dispatchEvent(new Event("RT_layout_complete")); + } + + // 5. Declare Dependencies + RT.load('Element/chapter'); + RT.load('Element/endnote'); + RT.load('Element/math'); + RT.load('Element/code'); + RT.load('Element/term'); + RT.load('Element/TOC'); + RT.load('Element/title'); + RT.load('Element/symbol'); + RT.load('Element/constraint'); + RT.load('Element/crossref'); + + RT.load('Layout/paginate_by_element'); + RT.load('Layout/page_fixed_glow'); + + // 6. The Typography Layout + RT.article = function(){ + RT.config = RT.config || {}; + RT.config.article = { + font_family: '"Noto Sans", "Segoe UI", "Helvetica Neue", sans-serif' + ,line_height: "1.8" + ,font_size: "16px" + ,font_weight: "400" + ,max_width: "820px" + ,margin: "0 auto" + }; + + if( RT.config.theme && RT.config.theme.meta_is_dark === false ){ + RT.config.article.font_weight = "600"; + } + + const conf = RT.config.article; + const article_seq = document.querySelectorAll("RT-article"); + + if(article_seq.length === 0) return; + + for(let i = 0; i < article_seq.length; i++){ + let style = article_seq[i].style; + style.display = "block"; + style.fontFamily = conf.font_family; + style.fontSize = conf.font_size; + style.lineHeight = conf.line_height; + style.fontWeight = conf.font_weight; + style.maxWidth = conf.max_width; + style.margin = conf.margin; + style.padding = "0 20px"; + style.color = "var(--rt-content-main)"; + } + + window.RT = window.RT || {}; + window.RT.config = window.RT.config || {}; + window.RT.config.page = window.RT.config.page || {}; + window.RT.config.page.height_limit = 900; + + const style_node = document.createElement("style"); + style_node.innerHTML = ` + body, html, rt-article { + overflow-anchor: none !important; + } + + rt-article { + font-family: 'Noto Sans JP', Arial, sans-serif; + background-color: var(--rt-surface-0); + color: var(--rt-content-main); + max-width: 46.875rem !important; + box-sizing: border-box !important; + } + + rt-article:not(:has(rt-page)) { + padding: 3rem !important; + } + + rt-article:has(rt-page) { + padding: 0 !important; + } + + rt-article rt-page { + position: relative; + display: block; + padding: 3rem; + margin: 1.25rem auto; + background-color: var(--rt-surface-0); + box-shadow: 0 0 0.625rem var(--rt-brand-primary); + } + + rt-article h1 { + font-size: 1.5rem; + text-align: center; + color: var(--rt-brand-primary); + font-weight: 500; + margin-top: 1.5rem; + line-height: 1.15; + } + rt-article h2 { + font-size: 1.25rem; + color: var(--rt-brand-secondary); + text-align: left; + margin-top: 2rem; + margin-left: 0; + } + rt-article h3 { + font-size: 1.125rem; + color: var(--rt-brand-tertiary); + text-align: left; + margin-top: 1.5rem; + margin-left: 4ch; + } + rt-article h4 { + font-size: 1.05rem; + color: var(--rt-content-main); + font-weight: 600; + text-align: left; + margin-top: 1.25rem; + margin-left: 8ch; + } + + rt-article p, + rt-article ul, + rt-article ol { + color: var(--rt-content-main); + text-align: justify; + margin-bottom: 1rem; + margin-left: 0; + } + rt-article li { + margin-bottom: 0.5rem; + } + + rt-article rt-code { + font-family: 'Courier New', Courier, monospace; + background-color: var(--rt-surface-code); + padding: 0.125rem 0.25rem; + color: var(--rt-content-main); + } + + rt-article img { + max-width: 100%; + height: auto; + display: block; + margin: 1.5rem auto; + } + `; + document.head.appendChild(style_node); + }; + + // 7. The Execution Sequence + function run_semantics(){ + debug.log('scroll' ,`4. run_semantics starting.`); + if(RT.theme) RT.theme(); + if(RT.endnote) RT.endnote(); + RT.article(); + if(RT.title) RT.title(); + if(RT.term) RT.term(); + if(RT.math) RT.math(); + if(RT.code) RT.code(); + if(RT.symbol) RT.symbol(); + if(RT.constraint) RT.constraint(); + if(RT.crossref) RT.crossref(); + + if( window.MathJax && MathJax.Hub && MathJax.Hub.Queue ){ + MathJax.Hub.Queue( ["Typeset" ,MathJax.Hub] ,run_layout ); + }else{ + run_layout(); + } + } + + function run_layout() { + debug.log('scroll', `5. run_layout starting.`); + + if(RT.chapter) RT.chapter(); + if(RT.TOC) RT.TOC(); + if(RT.paginate_by_element) RT.paginate_by_element(); + if(RT.page) RT.page(); + + debug.log('scroll', `6. Pagination complete.`); + + let final_target = target_y; + let use_hash = false; + + if (window.location.hash && !is_reload) { + const hash_target = document.getElementById(window.location.hash.substring(1)); + if (hash_target) { + use_hash = true; + } + } + + debug.log('scroll', `7. Commencing viewport enforce loop. Mode: ${use_hash ? 'HASH' : 'Y-COORDINATE'}`); + enforce_scroll(final_target, use_hash, 0); + } + + // 8. The Enforcer Logic + function enforce_scroll(target, use_hash, attempts) { + if (attempts > 15) { + debug.log('scroll', "8. Scroll enforcement timed out. Unlocking."); + unlock_layout(); + return; + } + + if (use_hash) { + const hash_target = document.getElementById(window.location.hash.substring(1)); + if (hash_target) { + hash_target.scrollIntoView(); + debug.log('scroll', `8a. Attempt ${attempts}: Scrolled to Hash Target. Y is now ${window.scrollY}`); + } + } else { + window.scrollTo(0, target); + debug.log('scroll', `8b. Attempt ${attempts}: Scrolled to Y=${target}. Current Y is ${window.scrollY}`); + } + + let is_successful = false; + if (use_hash) { + is_successful = true; + } else { + is_successful = (Math.abs(window.scrollY - target) < 5 || target === 0); + } + + if (is_successful && document.body.scrollHeight > 1000) { + debug.log('scroll', `9. Viewport anchored successfully.`); + + setTimeout(() => { + if (!use_hash && Math.abs(window.scrollY - target) >= 5) { + debug.log('scroll', `9a. Browser late-stage rebellion detected. Re-enforcing.`); + enforce_scroll(target, use_hash, attempts + 1); + } else { + unlock_layout(); + } + }, 100); + } else { + setTimeout(() => enforce_scroll(target, use_hash, attempts + 1), 50); + } + } + + // 9. The Ledger + let scroll_timer; + window.addEventListener('scroll', () => { + if (is_layout_locked) return; + clearTimeout(scroll_timer); + scroll_timer = setTimeout(() => { + sessionStorage.setItem('RT_saved_y', window.scrollY); + debug.log('scroll', `X. User stopped scrolling. Saved Y: ${window.scrollY}`); + }, 200); + }, { passive: true }); + + window.addEventListener('beforeunload', () => { + is_layout_locked = true; + debug.log('scroll', "Y. Page unloading. Scroll listener locked."); + }); + + // 10. Bind to DOM Ready + document.addEventListener('DOMContentLoaded', run_semantics); + +})(); + diff --git a/developer/authored/Manuscript.copy/Layout/memo_State.js b/developer/authored/Manuscript.copy/Layout/memo_State.js new file mode 100644 index 0000000..51a178e --- /dev/null +++ b/developer/authored/Manuscript.copy/Layout/memo_State.js @@ -0,0 +1,70 @@ +/* + + + + + + + +*/ + +(function(){ + const RT = window.RT = window.RT || {}; + + // 1. Declare Dependencies + RT.load('Core/utility'); + RT.load('Element/title'); + RT.load('Element/term'); + RT.load('Element/TOC'); + RT.load('Core/body_visibility_visible'); + + // 2. The Typography Layout + RT.memo_state_dept = function(){ + const body = document.body; + const html = document.documentElement; + + // Force strict print colors regardless of user system settings + html.style.backgroundColor = "white"; + body.style.backgroundColor = "white"; + body.style.color = "black"; + + // Target the new semantic tag + const memo_seq = document.querySelectorAll("RT-memo"); + if(memo_seq.length === 0) return; + + for(let i = 0; i < memo_seq.length; i++){ + let style = memo_seq[i].style; + style.display = "block"; + style.fontFamily = '"Times New Roman", Times, serif'; + style.fontSize = "12pt"; + style.lineHeight = "1.15"; + // 8.5 inch standard width minus 1-inch margins on each side + style.maxWidth = "6.5in"; + style.margin = "1in auto"; + style.padding = "0"; + style.textAlign = "left"; + style.color = "black"; + } + }; + + // 3. The Execution Sequence + const run_semantics = function(){ + RT.memo_state_dept(); + + if(RT.title) RT.title(); + if(RT.term) RT.term(); + if(RT.TOC) RT.TOC(); + + run_layout(); + }; + + const run_layout = function(){ + if(RT.body_visibility_visible) RT.body_visibility_visible(); + }; + + // 4. Bind to DOM Ready + document.addEventListener('DOMContentLoaded' ,run_semantics); + +})(); diff --git a/developer/authored/Manuscript.copy/Layout/page_fixed_glow.js b/developer/authored/Manuscript.copy/Layout/page_fixed_glow.js new file mode 100644 index 0000000..6ef8819 --- /dev/null +++ b/developer/authored/Manuscript.copy/Layout/page_fixed_glow.js @@ -0,0 +1,83 @@ +/* + Page Layout: Fixed Glow + Standard: Theme 1.0 + Description: A variable-height container with a glowing border effect that matches the active theme. +*/ +(function(){ + const RT = window.RT = window.RT || {}; + + RT.page = function() { + RT.config = RT.config || {}; + + // Default Configuration + const defaults = { + width: "100%" + ,min_height: "15rem" // Replaces fixed height + ,padding: "3rem" + ,margin: "4rem auto" + + ,bg_color: "var(--rt-surface-0)" + ,border_color: "var(--rt-brand-primary)" + ,text_color: "var(--rt-brand-primary)" + + ,shadow: "drop-shadow(0px 0px 15px var(--rt-brand-primary))" + }; + + RT.config.page = Object.assign({}, defaults, RT.config.page || {}); + + const conf = RT.config.page; + const style_id = 'rt-page-fixed-glow'; + + if (!document.getElementById(style_id)) { + const style_el = document.createElement('style'); + style_el.id = style_id; + + style_el.textContent = ` + /* Reset page counter on the article container */ + rt-article { + counter-reset: rt-page-counter; + } + + rt-page { + display: block; + position: relative; + box-sizing: border-box; + overflow: hidden; + + /* Dimensions */ + width: ${conf.width}; + min-height: ${conf.min_height}; + margin: ${conf.margin}; + padding: ${conf.padding}; + + /* Theming */ + background-color: ${conf.bg_color}; + border: 1px solid ${conf.border_color}; + + /* The "Glow" Effect */ + filter: ${conf.shadow}; + + /* Counter Increment */ + counter-increment: rt-page-counter; + } + + /* Page Numbering */ + rt-page::after { + content: "Page " counter(rt-page-counter); + position: absolute; + bottom: 1.5rem; + right: 3rem; + + font-family: "Noto Sans", sans-serif; + font-size: 0.9rem; + font-weight: bold; + + color: ${conf.text_color}; + opacity: 0.8; + pointer-events: none; + } + `; + document.head.appendChild(style_el); + } + }; +})(); diff --git a/developer/authored/Manuscript.copy/Layout/paginate_by_element.js b/developer/authored/Manuscript.copy/Layout/paginate_by_element.js new file mode 100644 index 0000000..aca2122 --- /dev/null +++ b/developer/authored/Manuscript.copy/Layout/paginate_by_element.js @@ -0,0 +1,399 @@ +window.RT.paginate_by_element = function () { + const RT = window.RT; + const debug = RT.debug || { log: function(){}, error: function(){} }; + const page_conf = (RT.config && RT.config.page) ? RT.config.page : {}; + const page_height_limit = page_conf.height_limit || 1000; + + let measureContainer = null; + + // ========================================================= + // 1. DOM Measurement Utilities + // ========================================================= + function getElHeight(el) { + const wasInDOM = el.parentNode !== null; + if (!wasInDOM) document.body.appendChild(el); + const rect = el.getBoundingClientRect(); + const style = window.getComputedStyle(el); + const margin = parseFloat(style.marginTop) + parseFloat(style.marginBottom); + if (!wasInDOM) el.remove(); + return (rect.height || 0) + (margin || 0); + } + + function getMeasureContainer() { + if (measureContainer && measureContainer.parentNode) return measureContainer; + const article = document.querySelector('RT-article'); + if (!article) { + const temp = document.createElement('div'); + temp.style.visibility = 'hidden'; + temp.style.position = 'absolute'; + temp.style.width = '100%'; + document.body.appendChild(temp); + measureContainer = temp; + return temp; + } + const container = document.createElement('div'); + const articleStyle = window.getComputedStyle(article); + container.style.visibility = 'hidden'; + container.style.position = 'absolute'; + container.style.width = articleStyle.width; + container.style.fontFamily = articleStyle.fontFamily; + container.style.fontSize = articleStyle.fontSize; + container.style.lineHeight = articleStyle.lineHeight; + container.style.fontWeight = articleStyle.fontWeight; + document.body.appendChild(container); + measureContainer = container; + return container; + } + + function measureFragment(frag) { + const container = getMeasureContainer(); + container.appendChild(frag); + const h = getElHeight(frag); + container.removeChild(frag); + return h; + } + + // ========================================================= + // STEP 1: PREPARE FOOTNOTES (Strip and tag) + // ========================================================= + const article_seq = document.querySelectorAll('RT-article'); + if (article_seq.length === 0) { + debug.error('pagination', 'No elements found. Pagination aborted.'); + return; + } + + const footnote_registry = {}; + let footnote_counter = 1; + + Array.from(article_seq).forEach(article => { + // Bulletproof extraction: immune to XML/HTML case-sensitivity parsing quirks + const all_nodes = Array.from(article.querySelectorAll('*')); + const raw_footnotes = all_nodes.filter(node => node.tagName.toLowerCase() === 'rt-footnote'); + + raw_footnotes.forEach(fn => { + const id = footnote_counter++; + footnote_registry[id] = fn.innerHTML; // Save the payload + + // Trim any standard HTML whitespace immediately preceding the tag + const prev = fn.previousSibling; + if (prev && prev.nodeType === Node.TEXT_NODE) { + prev.textContent = prev.textContent.replace(/\s+$/, ''); + } + + // Replace with a zero-height marker that rides along with the text + const marker = document.createElement('rt-fn-marker'); + marker.setAttribute('data-id', id); + + if (fn.parentNode) { + fn.parentNode.replaceChild(marker, fn); + } + }); + }); + + // ========================================================= + // Splitting Logic (Clean and undisturbed) + // ========================================================= + function isSplittable(el) { + const tag = el.tagName; + if (tag === 'UL' || tag === 'OL') { + const items = Array.from(el.children).filter(c => c.tagName === 'LI'); + if (items.length === 0) return null; + + const itemHeights = items.map(li => getElHeight(li)); + const emptyClone = el.cloneNode(false); + const overhead = getElHeight(emptyClone); + + el._splitInfo = { type: 'list', itemHeights, overhead, offset: 0 }; + return makeListSplitter(el, el._splitInfo); + } + + if (tag === 'TABLE') { + const thead = el.querySelector('thead'); + const tbody = el.querySelector('tbody'); + const rows = tbody ? Array.from(tbody.rows) : Array.from(el.rows); + if (rows.length === 0) return null; + + const theadHeight = thead ? getElHeight(thead) : 0; + const rowHeights = rows.map(row => getElHeight(row)); + + const emptyClone = el.cloneNode(false); + if (thead) emptyClone.appendChild(thead.cloneNode(true)); + emptyClone.appendChild(document.createElement('tbody')); + const overhead = getElHeight(emptyClone) - theadHeight; + + el._splitInfo = { type: 'table', rowHeights, overhead, theadHeight, offset: 0 }; + return makeTableSplitter(el, el._splitInfo); + } + return null; + } + + function makeListSplitter(el, info) { + return (remaining) => { + const children = Array.from(el.children).filter(c => c.tagName === 'LI'); + const start = info.offset; + + let bestCount = 0; + let bestHeight = 0; + const tempList = el.cloneNode(false); + + for (let i = 0; i < children.length; i++) { + const itemClone = children[i].cloneNode(true); + tempList.appendChild(itemClone); + const fragHeight = measureFragment(tempList); + if (fragHeight <= remaining) { + bestCount = i + 1; + bestHeight = fragHeight; + } else { + tempList.removeChild(itemClone); + break; + } + } + + if (bestCount === 0) return { first: null, rest: el, firstHeight: 0 }; + + const first = el.cloneNode(false); + for (let i = 0; i < bestCount; i++) { + first.appendChild(children[i].cloneNode(true)); + } + + let rest = null; + if (bestCount < children.length) { + rest = el.cloneNode(false); + for (let i = bestCount; i < children.length; i++) { + rest.appendChild(children[i].cloneNode(true)); + } + + if (el.tagName === 'OL') { + const currentStart = parseInt(el.getAttribute('start'), 10) || 1; + rest.setAttribute('start', currentStart + bestCount); + } + + rest._splitInfo = { + type: 'list', + itemHeights: info.itemHeights, + overhead: info.overhead, + offset: start + bestCount + }; + } + + return { first, rest, firstHeight: bestHeight }; + }; + } + + function makeTableSplitter(el, info) { + const thead = el.querySelector('thead'); + const createShell = () => { + const shell = el.cloneNode(false); + if (thead) shell.appendChild(thead.cloneNode(true)); + const newTbody = document.createElement('tbody'); + shell.appendChild(newTbody); + return shell; + }; + + return (remaining) => { + const tbody = el.querySelector('tbody'); + const rows = tbody ? Array.from(tbody.rows) : Array.from(el.rows); + const start = info.offset; + + let bestCount = 0; + let bestHeight = 0; + const tempTable = createShell(); + const tempBody = tempTable.querySelector('tbody'); + + for (let i = 0; i < rows.length; i++) { + tempBody.appendChild(rows[i].cloneNode(true)); + const h = measureFragment(tempTable); + if (h <= remaining) { + bestCount = i + 1; + bestHeight = h; + } else { + tempBody.removeChild(tempBody.lastChild); + break; + } + } + + if (bestCount === 0) return { first: null, rest: el, firstHeight: 0 }; + + const first = createShell(); + const firstBody = first.querySelector('tbody'); + for (let i = 0; i < bestCount; i++) { + firstBody.appendChild(rows[i].cloneNode(true)); + } + + let rest = null; + if (bestCount < rows.length) { + rest = createShell(); + const restBody = rest.querySelector('tbody'); + for (let i = bestCount; i < rows.length; i++) { + restBody.appendChild(rows[i].cloneNode(true)); + } + + rest._splitInfo = { + type: 'table', + rowHeights: info.rowHeights, + overhead: info.overhead, + theadHeight: info.theadHeight, + offset: start + bestCount + }; + } + + return { first, rest, firstHeight: bestHeight }; + }; + } + + // ========================================================= + // STEP 2: NORMAL PAGINATOR + // ========================================================= + function paginateArticle(article) { + const raw_element_seq = Array.from(article.children).filter(el => + !['SCRIPT', 'STYLE', 'RT-PAGE'].includes(el.tagName) + ); + + if (raw_element_seq.length === 0) return; + + const page_seq = []; + let current_batch_seq = []; + let current_h = 0; + let i = 0; + + while (i < raw_element_seq.length) { + const el = raw_element_seq[i]; + const splitter = isSplittable(el); + + if (splitter) { + const remaining = page_height_limit - current_h; + const { first, rest, firstHeight } = splitter(remaining); + + if (first) { + current_batch_seq.push(first); + current_h += firstHeight; + + if (rest) { + raw_element_seq.splice(i, 1, rest); + } else { + raw_element_seq.splice(i, 1); + } + } else { + if (current_batch_seq.length === 0) { + 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.push(frame); + i++; + } else { + page_seq.push(current_batch_seq); + current_batch_seq = []; + current_h = 0; + raw_element_seq[i] = rest || el; + } + } + continue; + } + + + // --- Ordinary (non-splittable) element --- + 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 ){ + 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; + 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; + } else { + page_seq.push(backtrack_seq); + current_batch_seq = []; + current_h = 0; + } + } + + current_batch_seq.push(el); + current_h += h; + i++; + } + + if (current_batch_seq.length > 0) { + page_seq.push(current_batch_seq); + } + + // Rebuild article with wrappers + article.innerHTML = ''; + let p = 0; + while (p < page_seq.length) { + const batch = page_seq[p]; + const page_el = document.createElement('rt-page'); + page_el.id = `page-${p + 1}`; + batch.forEach(item => page_el.appendChild(item)); + article.appendChild(page_el); + p++; + } + } + + // Execute pagination + Array.from(article_seq).forEach(article => paginateArticle(article)); + + // ========================================================= + // STEP 3: RESOLVE FOOTNOTES & EXPAND PAGES + // ========================================================= + Array.from(article_seq).forEach(article => { + const rendered_pages = article.querySelectorAll('rt-page'); + + Array.from(rendered_pages).forEach(page => { + // Bulletproof extraction for the markers + const all_page_nodes = Array.from(page.querySelectorAll('*')); + const markers = all_page_nodes.filter(node => node.tagName.toLowerCase() === 'rt-fn-marker'); + + if (markers.length === 0) return; + + // Construct the footer block for this page + const fn_container = document.createElement('div'); + fn_container.className = 'rt-footnote-container'; + fn_container.style.borderTop = '1px solid var(--rt-border-default)'; + fn_container.style.marginTop = '2rem'; + fn_container.style.paddingTop = '1rem'; + fn_container.style.fontSize = '0.9em'; + + markers.forEach(marker => { + const id = marker.getAttribute('data-id'); + const html = footnote_registry[id]; + + // Replace the invisible marker with the visible naked superscript link + const sup = document.createElement('sup'); + sup.innerHTML = `${id}`; + + if (marker.parentNode) { + marker.parentNode.replaceChild(sup, marker); + } + + // Append the actual text to the footer with a clean, print-ready number format + const fn_line = document.createElement('div'); + fn_line.id = `fn-${id}`; + fn_line.style.marginBottom = '0.5rem'; + fn_line.innerHTML = `${id}.${html}`; + fn_container.appendChild(fn_line); + }); + + // Attach the footer. The page organically stretches to fit. + page.appendChild(fn_container); + }); + }); + + // Cleanup + if (measureContainer && measureContainer.parentNode) { + measureContainer.remove(); + measureContainer = null; + } +}; diff --git a/developer/authored/Manuscript.copy/Theme/dark_gold.js b/developer/authored/Manuscript.copy/Theme/dark_gold.js new file mode 100644 index 0000000..9550a98 --- /dev/null +++ b/developer/authored/Manuscript.copy/Theme/dark_gold.js @@ -0,0 +1,115 @@ +/* + Theme: Inverse Wheat (Dark) + Standard: Theme 1.0 + Description: High contrast Amber on Deep Charcoal. +*/ +( function(){ + const RT = window.RT = window.RT || {}; + + RT.theme = function(){ + RT.config = RT.config || {}; + + // THEME 1.0 DATA CONTRACT + RT.config.theme = { + meta_is_dark: true + ,meta_name: "Inverse Wheat" + + // --- SURFACES (Depth & Container Hierarchy) --- + ,surface_0: "hsl(0, 0%, 5%)" // App Background (Deepest) + ,surface_1: "hsl(0, 0%, 10%)" // Sidebar / Nav / Panels + ,surface_2: "hsl(0, 0%, 14%)" // Cards / Floating Elements + ,surface_3: "hsl(0, 0%, 18%)" // Modals / Dropdowns / Popovers + ,surface_input: "hsl(0, 0%, 12%)" // Form Inputs + ,surface_code: "hsl(0, 0%, 11%)" // Code Block Background + ,surface_select: "hsl(45, 100%, 15%)" // Text Selection Highlight + + // --- CONTENT (Text & Icons) --- + ,content_main: "hsl(50, 60%, 85%)" // Primary Reading Text + ,content_muted: "hsl(36, 15%, 60%)" // Metadata, subtitles + ,content_subtle: "hsl(36, 10%, 40%)" // Placeholders, disabled states + ,content_inverse: "hsl(0, 0%, 5%)" // Text on high-contrast buttons + + // --- BRAND & ACTION (The "Wheat" Identity) --- + ,brand_primary: "hsl(45, 100%, 50%)" // Main Action / H1 / Focus Ring + ,brand_secondary: "hsl(38, 90%, 65%)" // Secondary Buttons / H2 + ,brand_tertiary: "hsl(30, 60%, 70%)" // Accents / H3 + ,brand_link: "hsl(48, 100%, 50%)" // Hyperlinks (High Visibility) + + // --- BORDERS & DIVIDERS --- + ,border_faint: "hsl(36, 20%, 15%)" // Subtle separation + ,border_default: "hsl(36, 20%, 25%)" // Standard Card Borders + ,border_strong: "hsl(36, 20%, 40%)" // Active states / Inputs + + // --- STATE & FEEDBACK (Earth Tones) --- + ,state_success: "hsl(100, 50%, 45%)" // Olive Green + ,state_warning: "hsl(35, 90%, 55%)" // Burnt Orange + ,state_error: "hsl(0, 60%, 55%)" // Brick Red + ,state_info: "hsl(200, 40%, 55%)" // Slate Blue + + // --- SYNTAX HIGHLIGHTING (For Code) --- + ,syntax_keyword: "hsl(35, 100%, 65%)" // Orange + ,syntax_string: "hsl(75, 50%, 60%)" // Sage Green + ,syntax_func: "hsl(45, 90%, 70%)" // Light Gold + ,syntax_comment: "hsl(36, 15%, 45%)" // Brown/Gray + }; + + // --- APPLY THEME --- + const palette = RT.config.theme; + const body = document.body; + const html = document.documentElement; + + // 1. Paint Base + html.style.backgroundColor = palette.surface_0; + body.style.backgroundColor = palette.surface_0; + body.style.color = palette.content_main; + + // 2. Export Variables (Standardization) + const s = body.style; + for (const [key, value] of Object.entries(palette)) { + s.setProperty(`--rt-${key.replace(/_/g, '-')}`, value); + } + + + // 3. Global Overrides + const style_id = 'rt-global-overrides'; + if (!document.getElementById(style_id)) { + const style = document.createElement('style'); + style.id = style_id; + style.textContent = ` + ::selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } + ::-moz-selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } + + ::-webkit-scrollbar { width: 12px; } + ::-webkit-scrollbar-track { background: var(--rt-surface-0); } + ::-webkit-scrollbar-thumb { + background: var(--rt-border-default); + border: 2px solid var(--rt-surface-0); + border-radius: 8px; + } + ::-webkit-scrollbar-thumb:hover { background: var(--rt-brand-secondary); } + + /* --- Citation & Endnote Styling --- */ + rt-cite a, .rt-inline-cite a, rt-endnotes a { + color: var(--rt-brand-link); + text-decoration: none; + } + rt-cite a:hover, .rt-inline-cite a:hover, rt-endnotes a:hover { + text-decoration: underline; + } + rt-cite, .rt-inline-cite { + font-size: 1em; + vertical-align: baseline; + padding: 0 0.15em; + } + + /* --- Image Inversion for Diagrams --- */ + img.rt-diagram { + filter: invert(1) hue-rotate(180deg); + } + `; + + document.head.appendChild(style); + } + }; + +} )(); diff --git a/developer/authored/Manuscript.copy/Theme/light.js b/developer/authored/Manuscript.copy/Theme/light.js new file mode 100644 index 0000000..d0e80eb --- /dev/null +++ b/developer/authored/Manuscript.copy/Theme/light.js @@ -0,0 +1,70 @@ +/* + Theme: Classic Wheat (Light) + Standard: Theme 1.0 + Description: Warm paper tones with Burnt Orange accents. +*/ +( function(){ + const RT = window.RT = window.RT || {}; + + RT.theme_light = function(){ + RT.config = RT.config || {}; + + // THEME 1.0 DATA CONTRACT + RT.config.theme = { + meta_is_dark: false + ,meta_name: "Classic Wheat" + + // --- SURFACES --- + ,surface_0: "hsl(40, 30%, 94%)" // App Background (Cream/Linen) + ,surface_1: "hsl(40, 25%, 90%)" // Sidebar (Slightly darker beige) + ,surface_2: "hsl(40, 20%, 98%)" // Cards (Lighter, almost white) + ,surface_3: "hsl(0, 0%, 100%)" // Modals (Pure White) + ,surface_input: "hsl(40, 20%, 98%)" // Form Inputs + ,surface_code: "hsl(40, 15%, 90%)" // Code Block Background + ,surface_select: "hsl(45, 100%, 85%)" // Text Selection Highlight + + // --- CONTENT --- + ,content_main: "hsl(30, 20%, 20%)" // Deep Umber (Not Black) + ,content_muted: "hsl(30, 15%, 45%)" // Medium Brown + ,content_subtle: "hsl(30, 10%, 65%)" // Light Brown/Gray + ,content_inverse: "hsl(40, 30%, 94%)" // Text on dark buttons + + // --- BRAND & ACTION --- + ,brand_primary: "hsl(30, 90%, 35%)" // Burnt Orange (Action) + ,brand_secondary: "hsl(35, 70%, 45%)" // Rust / Gold + ,brand_tertiary: "hsl(25, 60%, 55%)" // Copper + ,brand_link: "hsl(30, 100%, 35%)" // Link Color + + // --- BORDERS --- + ,border_faint: "hsl(35, 20%, 85%)" + ,border_default: "hsl(35, 20%, 75%)" + ,border_strong: "hsl(35, 20%, 55%)" + + // --- STATE & FEEDBACK --- + ,state_success: "hsl(100, 40%, 40%)" // Forest Green + ,state_warning: "hsl(30, 90%, 50%)" // Persimmon + ,state_error: "hsl(0, 60%, 45%)" // Crimson + ,state_info: "hsl(200, 50%, 45%)" // Navy Blue + + // --- SYNTAX --- + ,syntax_keyword: "hsl(20, 90%, 45%)" // Rust + ,syntax_string: "hsl(100, 35%, 35%)" // Ivy Green + ,syntax_func: "hsl(300, 30%, 40%)" // Muted Purple + ,syntax_comment: "hsl(35, 10%, 60%)" // Light Brown + }; + + // --- APPLY THEME --- + const palette = RT.config.theme; + const body = document.body; + const html = document.documentElement; + + html.style.backgroundColor = palette.surface_0; + body.style.backgroundColor = palette.surface_0; + body.style.color = palette.content_main; + + const s = body.style; + for (const [key, value] of Object.entries(palette)) { + s.setProperty(`--rt-${key.replace(/_/g, '-')}`, value); + } + }; +} )(); diff --git a/developer/authored/Manuscript.copy/Theme/light_gold.js b/developer/authored/Manuscript.copy/Theme/light_gold.js new file mode 100644 index 0000000..3136934 --- /dev/null +++ b/developer/authored/Manuscript.copy/Theme/light_gold.js @@ -0,0 +1,103 @@ +/* + Theme: Golden Wheat (Light) - "Spanish Gold Edition" + File: style/theme-light-gold.js + Standard: Theme 1.0 + Description: Light Parchment background with Oxblood Red ink. +*/ +( function(){ + const RT = window.RT = window.RT || {}; + + RT.theme = function(){ + RT.config = RT.config || {}; + + RT.config.theme = { + meta_is_dark: false + ,meta_name: "Golden Wheat (Yellow)" + + // --- SURFACES (Light Parchment) --- + // Shifted lightness up to 94% for a "whiter" feel that still holds the yellow tint. + ,surface_0: "hsl(48, 50%, 94%)" // Main Page: Fine Parchment + ,surface_1: "hsl(48, 40%, 90%)" // Panels: Slightly darker + ,surface_2: "hsl(48, 30%, 97%)" // Cards: Very light + ,surface_3: "hsl(0, 0%, 100%)" // Popups + ,surface_input: "hsl(48, 20%, 96%)" + ,surface_code: "hsl(48, 25%, 88%)" // Distinct Code BG + ,surface_select: "hsl(10, 70%, 85%)" // Red Highlight + + // --- CONTENT (Deep Ink) --- + ,content_main: "hsl(10, 25%, 7%)" // Deep Warm Black (Ink) + ,content_muted: "hsl(10, 15%, 35%)" // Dark Grey-Red + ,content_subtle: "hsl(10, 10%, 55%)" + ,content_inverse: "hsl(48, 50%, 90%)" + + // --- BRAND & ACTION (The Red Spectrum) --- + ,brand_primary: "hsl(12, 85%, 30%)" // H1 (Deep Oxblood) + ,brand_secondary: "hsl(10, 80%, 35%)" // H2 (Garnet) + ,brand_tertiary: "hsl(8, 70%, 40%)" // H3 (Brick) + ,brand_link: "hsl(12, 90%, 35%)" // Link + + // --- BORDERS --- + ,border_faint: "hsl(45, 30%, 80%)" + ,border_default: "hsl(45, 30%, 70%)" // Pencil Grey + ,border_strong: "hsl(12, 50%, 40%)" + + // --- STATE --- + ,state_success: "hsl(120, 40%, 30%)" + ,state_warning: "hsl(25, 90%, 45%)" + ,state_error: "hsl(0, 75%, 35%)" + ,state_info: "hsl(210, 60%, 40%)" + + // --- SYNTAX --- + ,syntax_keyword: "hsl(0, 75%, 35%)" + ,syntax_string: "hsl(100, 35%, 25%)" + ,syntax_func: "hsl(15, 85%, 35%)" + ,syntax_comment: "hsl(45, 20%, 50%)" + }; + + // --- APPLY THEME --- + const palette = RT.config.theme; + const body = document.body; + const html = document.documentElement; + + html.style.backgroundColor = palette.surface_0; + body.style.backgroundColor = palette.surface_0; + body.style.color = palette.content_main; + + const s = body.style; + for (const [key, value] of Object.entries(palette)) { + s.setProperty(`--rt-${key.replace(/_/g, '-')}`, value); + } + + // Global overrides + const style_id = 'rt-global-overrides'; + if (!document.getElementById(style_id)) { + const style = document.createElement('style'); + style.id = style_id; + style.textContent = ` + ::selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } + ::-moz-selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } + + ::-webkit-scrollbar { width: 12px; } + ::-webkit-scrollbar-track { background: var(--rt-surface-0); } + ::-webkit-scrollbar-thumb { + background: var(--rt-border-default); + border: 2px solid var(--rt-surface-0); + border-radius: 8px; + } + ::-webkit-scrollbar-thumb:hover { background: var(--rt-brand-secondary); } + + rt-article p, rt-article li { + text-shadow: 0px 0px 0.5px rgba(0,0,0, 0.2); + } + + .MathJax, .MathJax_Display, .mjx-chtml { + color: var(--rt-content-main) !important; + fill: var(--rt-content-main) !important; + stroke: var(--rt-content-main) !important; + } + `; + document.head.appendChild(style); + } + }; + +} )(); diff --git a/developer/authored/Manuscript.copy/Tool/to_pdf.py b/developer/authored/Manuscript.copy/Tool/to_pdf.py new file mode 100644 index 0000000..177f7bd --- /dev/null +++ b/developer/authored/Manuscript.copy/Tool/to_pdf.py @@ -0,0 +1,167 @@ +import os +import glob +import base64 +import re +from weasyprint import HTML + +# Find the image file +img_path = None +for search_dir in ['/mnt/data', '/tmp', '.']: + for root, dirs, files in os.walk(search_dir): + if 'money_circle.jpeg' in files: + img_path = os.path.join(root, 'money_circle.jpeg') + break + if img_path: + break + +img_b64 = "" +if img_path: + with open(img_path, "rb") as f: + img_b64 = base64.b64encode(f.read()).decode('utf-8') + +html_content = """ + + + + + On Cybersecurity and Commonsense + + + + +""" + +# String replacements (hyphens, 'may', 'just') +html_content = html_content.replace('—', '-') +html_content = re.sub(r'\bmay\b', 'can', html_content) +html_content = re.sub(r'\bMay\b', 'Can', html_content) +html_content = re.sub(r'\bjust\b', 'merely', html_content) +html_content = re.sub(r'\bJust\b', 'Merely', html_content) + +# Title block replacement +title_match = re.search(r'\s*', html_content, re.IGNORECASE | re.DOTALL) +if title_match: + title, author, date, copyright_text = title_match.groups() + if not copyright_text.startswith('©') and not copyright_text.startswith('©'): + copyright_text = f"© {copyright_text}" + + title_html = f''' +
          +

          {title}

          +

          {author}

          +

          {date}

          + +
          + ''' + html_content = html_content[:title_match.start()] + title_html + html_content[title_match.end():] + +# TOC replacement +headings = re.findall(r'(.*?)', html_content, re.IGNORECASE) +toc_html = '

          Table of Contents

            ' +for idx, (level, _, id_val, text) in enumerate(headings): + if not id_val: + id_val = f"heading-{idx}" + html_content = re.sub(f'{text}', f'{text}', html_content, count=1) + toc_html += f'
          • {text}
          • ' +toc_html += '
          ' + +html_content = re.sub(r']*>', toc_html, html_content, flags=re.IGNORECASE) + +# Image replacement +if img_b64: + html_content = re.sub(r'src="money_circle\.jpeg"', f'src="data:image/jpeg;base64,{img_b64}" class="content-image"', html_content) + +# Custom tags +html_content = re.sub(r'', '
          ', html_content, flags=re.IGNORECASE) +html_content = re.sub(r'', '
          ', html_content, flags=re.IGNORECASE) +html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) +html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) +html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) +html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) +html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) +html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) + +def replace_rt_math(m): + content = m.group(1) + if '\n' in content: + return f'
          {content}
          ' + return f'{content}' + +def replace_rt_code(m): + content = m.group(1) + if '\n' in content: + return f'
          {content}
          ' + return f'{content}' + +html_content = re.sub(r'(.*?)', replace_rt_math, html_content, flags=re.IGNORECASE | re.DOTALL) +html_content = re.sub(r'(.*?)', replace_rt_code, html_content, flags=re.IGNORECASE | re.DOTALL) + +css_styles = """ + @page { + size: letter; + margin: 25mm 20mm; + background-color: #FAFAFA; + @bottom-center { + content: counter(page); + font-family: 'Georgia', serif; + font-size: 10pt; + color: #555; + } + } + body { + margin: 0; + padding: 0; + font-family: 'Georgia', serif; + font-size: 11pt; + line-height: 1.6; + color: #2c3e50; + background-color: #FAFAFA; + } + *, *::before, *::after { box-sizing: border-box; } + + h1, h2, h3, h4 { + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #1A365D; + page-break-after: avoid; + } + h1 { font-size: 20pt; margin-top: 1.5em; margin-bottom: 0.5em; border-bottom: 2px solid #E2E8F0; padding-bottom: 0.2em; } + h2 { font-size: 16pt; margin-top: 1.5em; margin-bottom: 0.5em; } + p { margin-bottom: 1em; text-align: justify; } + ul, ol { margin-bottom: 1em; padding-left: 2em; } + li { margin-bottom: 0.5em; } + + .title-block { text-align: center; margin-bottom: 4em; padding: 2em 0; border-bottom: 3px solid #1A365D; } + .title-block h1 { font-size: 26pt; border: none; margin-top: 0; margin-bottom: 0.5em; color: #0F2040; } + .title-block .meta-author { font-size: 14pt; font-weight: bold; margin: 0.2em 0; } + .title-block .meta-date { font-size: 12pt; color: #555; font-style: italic; margin: 0.2em 0; } + .title-block .meta-copyright { font-size: 10pt; color: #777; margin-top: 1em; } + + .toc-block { background-color: #F0F4F8; padding: 20px; border-radius: 5px; margin-bottom: 3em; page-break-after: always; } + .toc-block h2 { margin-top: 0; border: none; } + .toc-block ul { list-style-type: none; padding-left: 0; } + .toc-h1 { font-weight: bold; margin-top: 0.8em; } + .toc-h2 { padding-left: 1.5em; font-size: 0.95em; } + .toc-block a { text-decoration: none; color: #2c3e50; } + + .rt-term { font-weight: bold; color: #2980B9; } + .rt-term-em { font-weight: bold; font-style: italic; color: #2980B9; } + .rt-neologism { font-variant: small-caps; font-weight: bold; color: #C0392B; } + .rt-code-inline { font-family: 'Courier New', Courier, monospace; background-color: #EAECEE; padding: 2px 4px; border-radius: 3px; font-size: 0.9em; } + .rt-code-block { font-family: 'Courier New', Courier, monospace; background-color: #F4F6F7; padding: 15px; border-left: 4px solid #7F8C8D; border-radius: 3px; font-size: 0.9em; overflow-x: auto; white-space: pre-wrap; } + + .math { font-family: 'Times New Roman', serif; font-style: italic; font-weight: bold; color: #2C3E50; } + .math-block { text-align: center; margin: 1.5em 0; font-size: 1.2em; background-color: #F9EBEA; padding: 10px; border-radius: 5px; } + .math-inline { font-size: 1.05em; } + + table { width: 100%; border-collapse: collapse; margin: 2em 0; } + th, td { padding: 10px; text-align: left; vertical-align: top; } + th { background-color: #1A365D; color: white; font-weight: bold; } + tr { border-bottom: 1px solid #ddd; } + hr { border: 0; border-top: 1px solid #eee; } + + .content-image { display: block; max-width: 90%; margin: 2em auto; border: 1px solid #ccc; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } +""" + +final_html = f"{html_content}" +HTML(string=final_html).write_pdf("White_Paper_Cybersecurity_Legislation.pdf") +print("Success") diff --git a/developer/authored/Manuscript.copy/Tool/to_pdf2.py b/developer/authored/Manuscript.copy/Tool/to_pdf2.py new file mode 100644 index 0000000..a493d27 --- /dev/null +++ b/developer/authored/Manuscript.copy/Tool/to_pdf2.py @@ -0,0 +1,479 @@ +import re +import os +import glob +from weasyprint import HTML + +def process_rt_html(html_str, out_file): + # Fix escaped dollar signs + html_str = html_str.replace('\\$', '$') + + # Remove hardcoded page breaks that cause blank pages + html_str = re.sub(r']*["\']>\s*', '', html_str, flags=re.IGNORECASE) + + css = """ + + """ + + # Inject CSS + html_str = html_str.replace("", css + "") + + # Process Title Block + title_match = re.search(r']+)>(.*?)', html_str, re.DOTALL | re.IGNORECASE) + if title_match: + attrs = title_match.group(1) + title = re.search(r'title="(.*?)"', attrs).group(1) if 'title="' in attrs else 'Document' + author = re.search(r'author="(.*?)"', attrs).group(1) if 'author="' in attrs else '' + date = re.search(r'date="(.*?)"', attrs).group(1) if 'date="' in attrs else '' + copyright_txt = re.search(r'copyright="(.*?)"', attrs).group(1) if 'copyright="' in attrs else '' + + title_block = f''' +
          +

          {title}

          +
          {author} | {date}
          + +
          + ''' + html_str = html_str[:title_match.start()] + title_block + html_str[title_match.end():] + + # Process TOC + toc_match = re.search(r'', html_str, re.IGNORECASE) + if toc_match: + level = toc_match.group(1) + headings = [] + if '-' in level: + headings = re.findall(r'(.*?)', html_str, re.IGNORECASE) + else: + headings = re.findall(rf'(.*?)', html_str, re.IGNORECASE) + + toc_html = '
          Table of Contents
            ' + for lvl, text in headings: + # exclude COVER SHEET from TOC + if "COVER SHEET" in text: + continue + toc_html += f'
          • {text}
          • ' + toc_html += '
          ' + + html_str = html_str[:toc_match.start()] + toc_html + html_str[toc_match.end():] + + # Term Replacement (First occurrence) + seen_terms = set() + def term_replace(match): + text = match.group(1) + l_text = text.lower() + if l_text not in seen_terms: + seen_terms.add(l_text) + return f'{text}' + else: + return f'{text}' + + html_str = re.sub(r'(.*?)', term_replace, html_str) + + # Neologism Replacement (First occurrence) + seen_neos = set() + def neo_replace(match): + text = match.group(1) + l_text = text.lower() + if l_text not in seen_neos: + seen_neos.add(l_text) + return f'{text}' + else: + return f'{text}' + + html_str = re.sub(r'(.*?)', neo_replace, html_str) + + HTML(string=html_str).write_pdf(out_file) + +# Locate the uploaded file +uploaded_files = glob.glob('/mnt/data/user_uploads/*abstract.html') +if not uploaded_files: + uploaded_files = glob.glob('/mnt/data/uploads/*abstract.html') +if not uploaded_files: + # Look for it anywhere under /mnt/data + for root, dirs, files in os.walk('/mnt/data'): + for file in files: + if file == 'abstract.html': + uploaded_files.append(os.path.join(root, file)) + +if uploaded_files: + filepath = uploaded_files[0] + with open(filepath, 'r', encoding='utf-8') as f: + html_content = f.read() + process_rt_html(html_content, 'abstract.pdf') + print("PDF successfully generated.") +else: + print("Could not find abstract.html in the data directory.") + +Code output +Traceback (most recent call last): + File "", line 1, in + import bs4 +ModuleNotFoundError: No module named 'bs4' + +Python +import re +import os +import glob +from weasyprint import HTML + +def process_rt_html(html_str, out_file): + html_str = html_str.replace('\\$', '$') + html_str = re.sub(r']*["\']>\s*', '', html_str, flags=re.IGNORECASE) + + css = """ + + """ + + html_str = html_str.replace("", css + "") + + title_match = re.search(r']+)>(.*?)', html_str, re.DOTALL | re.IGNORECASE) + if title_match: + attrs = title_match.group(1) + title = re.search(r'title="(.*?)"', attrs).group(1) if 'title="' in attrs else 'Document' + author = re.search(r'author="(.*?)"', attrs).group(1) if 'author="' in attrs else '' + date = re.search(r'date="(.*?)"', attrs).group(1) if 'date="' in attrs else '' + copyright_txt = re.search(r'copyright="(.*?)"', attrs).group(1) if 'copyright="' in attrs else '' + + title_block = f''' +
          +

          {title}

          +
          {author} | {date}
          + +
          + ''' + html_str = html_str[:title_match.start()] + title_block + html_str[title_match.end():] + + toc_match = re.search(r'', html_str, re.IGNORECASE) + if toc_match: + level = toc_match.group(1) + headings = [] + if '-' in level: + headings = re.findall(r'(.*?)', html_str, re.IGNORECASE) + else: + headings = re.findall(rf'(.*?)', html_str, re.IGNORECASE) + + toc_html = '
          Table of Contents
            ' + for lvl, text in headings: + if "COVER SHEET" in text: + continue + toc_html += f'
          • {text}
          • ' + toc_html += '
          ' + + # Add page break AFTER the TOC instead of before it + toc_html += '
          ' + + html_str = html_str[:toc_match.start()] + toc_html + html_str[toc_match.end():] + + seen_terms = set() + def term_replace(match): + text = match.group(1) + l_text = text.lower() + if l_text not in seen_terms: + seen_terms.add(l_text) + return f'{text}' + else: + return f'{text}' + + html_str = re.sub(r'(.*?)', term_replace, html_str) + + seen_neos = set() + def neo_replace(match): + text = match.group(1) + l_text = text.lower() + if l_text not in seen_neos: + seen_neos.add(l_text) + return f'{text}' + else: + return f'{text}' + + html_str = re.sub(r'(.*?)', neo_replace, html_str) + + HTML(string=html_str).write_pdf(out_file) + +uploaded_files = glob.glob('/mnt/data/user_uploads/*abstract.html') +if not uploaded_files: + uploaded_files = glob.glob('/mnt/data/uploads/*abstract.html') +if not uploaded_files: + for root, dirs, files in os.walk('/mnt/data'): + for file in files: + if file == 'abstract.html': + uploaded_files.append(os.path.join(root, file)) + +if uploaded_files: + filepath = uploaded_files[0] + with open(filepath, 'r', encoding='utf-8') as f: + html_content = f.read() + + # One last aggressive check to ensure we absolutely strip ANY style="page-break..." strings + # in case the earlier regex missed a specific formatting + html_content = re.sub(r'style="[^"]*page-break-after:\s*always;?[^"]*"', '', html_content, flags=re.IGNORECASE) + + process_rt_html(html_content, 'abstract_no_gap.pdf') + print("PDF successfully generated.") +else: + print("Could not find abstract.html in the data directory.") diff --git a/developer/authored/RT_Formatter.copy/RT-formatter b/developer/authored/RT_Formatter.copy/RT-formatter new file mode 100755 index 0000000..09ee7a5 --- /dev/null +++ b/developer/authored/RT_Formatter.copy/RT-formatter @@ -0,0 +1,331 @@ +#!/usr/bin/env -S python3 -B +# -*- mode: python; coding: utf-8; python-indent-offset: 2; indent-tabs-mode: nil -*- +""" +RTfmt — Reasoning Technology code formatter (Predicate Tokenizer) + +Commands: + RTfmt write [--lisp] Format files in place (rewrite originals) + RTfmt copy [--lisp] Save backups as ~ then format originals + RT-formatter pipe [--lisp] Read from stdin, write to stdout + RTfmt self_test Run built-in tests + RTfmt version Show tool version + RTfmt help | --help Show usage +""" + +import sys ,re ,shutil ,os +from typing import List ,Tuple ,Optional ,TextIO + +RTF_VERSION = "0.5.0-predicate" + +def get_usage() -> str: + prog_name = os.path.basename(sys.argv[0]) + return f"""\ +Usage: + {prog_name} write [--lisp] + {prog_name} copy [--lisp] + {prog_name} pipe [--lisp] + {prog_name} self_test + {prog_name} version + {prog_name} help | --help +""" + +# Removed < and > so they are treated as standard CODE operators +BR_OPEN = "([{" +BR_CLOSE = ")]}" +PAIR = dict( zip(BR_OPEN ,BR_CLOSE) ) +REV = dict( zip(BR_CLOSE ,BR_OPEN) ) + +# --------------- Lexer ---------------- + +class RT_Token: + def __init__(self ,kind: str ,text: str): + self.kind = kind + self.text = text + + def __repr__(self): + return f"<{self.kind}:{repr(self.text)}>" + +TOKEN_REGEX = re.compile( + r'(?P//[^\n]*|#[^\n]*|(?s:/\*.*?\*/))' + r'|(?P"""[\s\S]*?"""|\'\'\'[\s\S]*?\'\'\'|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\')' + r'|(?P[ \t]+)' + r'|(?P\n)' + r'|(?P,)' + r'|(?P[\[\(\{])' + r'|(?P[\]\)\}])' + r'|(?P[^ \t\n,\[\(\{\]\)\}"\'#/]+|/)' +) + +def tokenize(text: str) -> List[RT_Token]: + tokens = [] + for TM_match in TOKEN_REGEX.finditer(text): + kind = TM_match.lastgroup + text_val = TM_match.group(kind) + tokens.append( RT_Token(kind ,text_val) ) + return tokens + +# --------------- Intelligence API ---------------- + +class TokenStream: + def __init__(self ,tokens: List[RT_Token]): + self.tokens = tokens + + def get_token(self ,index: int) -> Optional[RT_Token]: + if 0 <= index < len(self.tokens): + return self.tokens[index] + return None + + def next_sig_index(self ,index: int) -> Optional[int]: + for TM_i in range(index + 1 ,len(self.tokens)): + if self.tokens[TM_i].kind not in ("SPACE" ,"NEWLINE" ,"COMMENT"): + return TM_i + return None + + def is_first_on_line(self ,index: int) -> bool: + for TM_i in range(index - 1 ,-1 ,-1): + k = self.tokens[TM_i].kind + if k == "NEWLINE": + return True + if k != "SPACE": + return False + return True # Start of file + + def indent_of_line(self ,index: int) -> str: + for TM_i in range(index ,-1 ,-1): + if self.tokens[TM_i].kind == "NEWLINE": + if TM_i + 1 < len(self.tokens) and self.tokens[TM_i + 1].kind == "SPACE": + return self.tokens[TM_i + 1].text + return "" + if self.tokens and self.tokens[0].kind == "SPACE": + return self.tokens[0].text + return "" + + def indent_of_left_match(self ,index: int) -> Optional[str]: + tok = self.get_token(index) + if not tok or tok.kind != "BR_CLOSE": + return None + target_opener = REV[tok.text] + depth = 0 + for TM_i in range(index - 1 ,-1 ,-1): + t = self.tokens[TM_i] + if t.kind == "BR_CLOSE": + depth += 1 + elif t.kind == "BR_OPEN": + if depth > 0: + depth -= 1 + elif t.text == target_opener: + return self.indent_of_line(TM_i) + return None + +# --------------- Rule Engine ---------------- + +def rule_migrate_vertical_commas(stream: TokenStream): + TM_i = 0 + while TM_i < len(stream.tokens): + if stream.tokens[TM_i].kind == "COMMA": + is_trailing = False + next_sig = stream.next_sig_index(TM_i) + if next_sig is not None: + for TM_j in range(TM_i + 1 ,next_sig): + if stream.tokens[TM_j].kind == "NEWLINE": + is_trailing = True + break + + if is_trailing: + comma_tok = stream.tokens.pop(TM_i) + next_sig -= 1 # Shifted because of pop + stream.tokens.insert(next_sig ,comma_tok) + continue + TM_i += 1 + +def rule_format_horizontal_commas(stream: TokenStream): + for TM_i in range(len(stream.tokens) - 1 ,-1 ,-1): + if stream.tokens[TM_i].kind == "COMMA": + if stream.is_first_on_line(TM_i): + continue + + next_tok = stream.get_token(TM_i + 1) + if next_tok and next_tok.kind == "SPACE": + stream.tokens.pop(TM_i + 1) + + prev_tok = stream.get_token(TM_i - 1) + if prev_tok and prev_tok.kind == "SPACE": + if prev_tok.text != " ": + prev_tok.text = " " + else: + stream.tokens.insert(TM_i ,RT_Token("SPACE" ," ")) + +def rule_fix_closing_indent(stream: TokenStream): + for TM_i in range(len(stream.tokens) - 1 ,-1 ,-1): + if stream.tokens[TM_i].kind == "BR_CLOSE" and stream.is_first_on_line(TM_i): + target_indent = stream.indent_of_left_match(TM_i) + if target_indent is not None: + prev = stream.get_token(TM_i - 1) + if prev and prev.kind == "SPACE": + prev.text = target_indent + else: + stream.tokens.insert(TM_i ,RT_Token("SPACE" ,target_indent)) + +def rule_tighten_brackets(stream: TokenStream): + for TM_i in range(len(stream.tokens) - 1 ,-1 ,-1): + if stream.tokens[TM_i].kind == "SPACE" and not stream.is_first_on_line(TM_i): + prev_t = stream.get_token(TM_i - 1) + next_t = stream.get_token(TM_i + 1) + if (prev_t and prev_t.kind == "BR_OPEN") or (next_t and next_t.kind == "BR_CLOSE"): + stream.tokens.pop(TM_i) + +def get_bracket_spans(stream: TokenStream) -> List[Tuple[int ,int]]: + stack = [] + spans = [] + for TM_i ,tok in enumerate(stream.tokens): + if tok.kind == "BR_OPEN": + stack.append( (tok.text ,TM_i) ) + elif tok.kind == "BR_CLOSE": + if stack and REV[tok.text] == stack[-1][0]: + _ ,pos = stack.pop() + if not stack: + spans.append( (pos ,TM_i) ) + return spans + +def rule_pad_outermost(stream: TokenStream ,is_lisp: bool): + if is_lisp: + return + while True: + spans = get_bracket_spans(stream) + changed = False + for TM_start ,TM_end in reversed(spans): + has_inner = False + for TM_k in range(TM_start + 1 ,TM_end): + if stream.tokens[TM_k].kind in ("BR_OPEN" ,"BR_CLOSE"): + has_inner = True + break + + if has_inner: + left_has = (TM_start + 1 < len(stream.tokens)) and stream.tokens[TM_start + 1].kind == "SPACE" + right_has = (TM_end - 1 >= 0) and stream.tokens[TM_end - 1].kind == "SPACE" + if not left_has or not right_has: + if not right_has: + stream.tokens.insert(TM_end ,RT_Token("SPACE" ," ")) + if not left_has: + stream.tokens.insert(TM_start + 1 ,RT_Token("SPACE" ," ")) + changed = True + break + if not changed: + break + +# --------------- Public API ---------------- + +def format_tokens(tokens: List[RT_Token] ,is_lisp: bool) -> str: + stream = TokenStream(tokens) + + rule_migrate_vertical_commas(stream) + rule_format_horizontal_commas(stream) + rule_tighten_brackets(stream) + rule_fix_closing_indent(stream) + rule_pad_outermost(stream ,is_lisp) + + return "".join(t.text for t in stream.tokens) + +def rt_format_text(text: str ,is_lisp: bool) -> str: + tokens = tokenize(text) + return format_tokens(tokens ,is_lisp) + +def rt_format_stream(inp: TextIO ,out: TextIO ,is_lisp: bool) -> None: + text = inp.read() + out.write( rt_format_text(text ,is_lisp) ) + +# --------------- Self-test ---------------- + +def run_self_test() -> bool: + ok = True + def chk(src ,exp): + nonlocal ok + got = rt_format_text(src ,False) + if got != exp: + print("FAIL:\n" + src + "\n=>\n" + got + "\nexpected:\n" + exp) + ok = False + + chk("a,b,c" ,"a ,b ,c") + chk("a , b , c" ,"a ,b ,c") + chk(" ,vertical_arg" ," ,vertical_arg") + + chk("int a=0,\n b=1,\n c=2;" ,"int a=0\n ,b=1\n ,c=2;") + + chk("f ( x )" ,"f(x)") + chk("f(x) + g(y)" ,"f(x) + g(y)") + chk(" {" ," {") + + src = "int g(){int a=0,b=1,c=2; return h(a,b,c);}" + exp = "int g(){ int a=0 ,b=1 ,c=2; return h(a ,b ,c); }" + chk(src ,exp) + + chk("outer( inner(a,b) )" ,"outer( inner(a ,b) )") + + # Operator protection check + chk("for(int TM = 0; TM < count; ++TM)" ,"for(int TM = 0; TM < count; ++TM)") + + print("SELFTEST OK" if ok else "SELFTEST FAILED") + return ok + +# --------------- CLI ---------------- +def write_files(paths: List[str] ,is_lisp: bool) -> int: + for TM_path in paths: + with open(TM_path ,"r" ,encoding="utf-8") as f: + data = f.read() + + formatted = rt_format_text(data ,is_lisp) + + # Only touch the file if the content actually changed + if data != formatted: + with open(TM_path ,"w" ,encoding="utf-8") as f: + f.write(formatted) + print(f"Formatted: {TM_path}") + return 0 + +def copy_files(paths: List[str] ,is_lisp: bool) -> int: + for TM_path in paths: + shutil.copy2(TM_path ,TM_path + "~") + return write_files(paths ,is_lisp) + +def CLI(argv=None) -> int: + args = list(sys.argv[1:] if argv is None else argv) + usage_text = get_usage() + + if not args or args[0] in {"help" ,"--help" ,"-h"}: + print(usage_text) + return 0 + + is_lisp = "--lisp" in args + args = [TM_a for TM_a in args if TM_a != "--lisp"] + + if not args: + return 0 + + cmd = args[0] + rest = args[1:] + + if cmd == "version": + print(RTF_VERSION) + return 0 + if cmd == "self_test": + ok = run_self_test() + return 0 if ok else 1 + if cmd == "pipe": + rt_format_stream(sys.stdin ,sys.stdout ,is_lisp) + return 0 + if cmd == "write": + if not rest: + print("write: missing \n" + usage_text) + return 2 + return write_files(rest ,is_lisp) + if cmd == "copy": + if not rest: + print("copy: missing \n" + usage_text) + return 2 + return copy_files(rest ,is_lisp) + + print(f"Unknown command: {cmd}\n" + usage_text) + return 2 + +if __name__ == "__main__": + sys.exit( CLI() ) diff --git a/developer/authored/RT_Formatter.copy/RT-formatter.el b/developer/authored/RT_Formatter.copy/RT-formatter.el new file mode 100644 index 0000000..36213ae --- /dev/null +++ b/developer/authored/RT_Formatter.copy/RT-formatter.el @@ -0,0 +1,23 @@ +(defun RT-formatter-buffer () + "Format the current buffer using RTfmt." + (interactive) + (if (not (executable-find "RT-formatter")) + (message "Error: RTfmt executable not found in PATH.") + (let ((temp-buffer (generate-new-buffer " *RTfmt*")) + (args (list "pipe"))) + (when (derived-mode-p 'emacs-lisp-mode 'lisp-mode) + (setq args (append args (list "--lisp")))) + (unwind-protect + (let ((exit-code (apply #'call-process-region + (point-min) (point-max) + "RT-formatter" + nil temp-buffer nil + args))) + (if (zerop exit-code) + ;; Check if the formatted text is actually different + (if (= (compare-buffer-substrings nil nil nil temp-buffer nil nil) 0) + (message "RTfmt: Already perfectly formatted.") + (replace-buffer-contents temp-buffer) + (message "RT-formatter formatting successful.")) + (message "RT-formatter failed with exit code %s. Buffer unchanged." exit-code))) + (kill-buffer temp-buffer))))) diff --git a/developer/authored/RT_Formatter.copy/data_test-0.c b/developer/authored/RT_Formatter.copy/data_test-0.c new file mode 100644 index 0000000..c877406 --- /dev/null +++ b/developer/authored/RT_Formatter.copy/data_test-0.c @@ -0,0 +1,20 @@ +// commas and simple tight brackets +int g(){ + int a=0 , + b=1 , + c=2; + return h(a ,b ,c); +} + +// balanced outermost-with-nesting -> pad inside outer () +int f(){ return outer(inner(a ,b)); } + +// strings and comments must be unchanged +int s(){ printf("x ,y ,z (still a string)"); /* a ,b ,c */ return 1; } + +// unbalanced open-right with nesting -> pad after first unmatched '(' +int u(){if(doit(foo(1 ,2) // missing )) + return 0;} + +// arrays / subscripts stay tight; commas still RT-style +int a(int i ,int j){ return M[i ,j] + V[i] + W[j]; } diff --git a/developer/authored/RT_Formatter.copy/data_test-1.py b/developer/authored/RT_Formatter.copy/data_test-1.py new file mode 100644 index 0000000..9b2fa87 --- /dev/null +++ b/developer/authored/RT_Formatter.copy/data_test-1.py @@ -0,0 +1,16 @@ +# commas and spacing in defs / calls +def f ( x , y , z ): + return dict( a =1 , b= 2 ), [ 1, 2 ,3 ], ( (1,2) ) + +# outermost-with-nesting -> pad inside outer () +val = outer( inner( a,b ) ) + +# strings/comments untouched +s = "text, with , commas ( not to touch )" # a ,b ,c + +# unbalanced: open-left (closing without opener) -> no padding unless inner bracket before it +def g(): + return result) # likely unchanged + +# unbalanced: open-right (first unmatched opener) with inner bracket following +k = compute(x, f(y diff --git a/developer/authored/Theme.copy/dark_gold.js b/developer/authored/Theme.copy/dark_gold.js deleted file mode 100644 index 9550a98..0000000 --- a/developer/authored/Theme.copy/dark_gold.js +++ /dev/null @@ -1,115 +0,0 @@ -/* - Theme: Inverse Wheat (Dark) - Standard: Theme 1.0 - Description: High contrast Amber on Deep Charcoal. -*/ -( function(){ - const RT = window.RT = window.RT || {}; - - RT.theme = function(){ - RT.config = RT.config || {}; - - // THEME 1.0 DATA CONTRACT - RT.config.theme = { - meta_is_dark: true - ,meta_name: "Inverse Wheat" - - // --- SURFACES (Depth & Container Hierarchy) --- - ,surface_0: "hsl(0, 0%, 5%)" // App Background (Deepest) - ,surface_1: "hsl(0, 0%, 10%)" // Sidebar / Nav / Panels - ,surface_2: "hsl(0, 0%, 14%)" // Cards / Floating Elements - ,surface_3: "hsl(0, 0%, 18%)" // Modals / Dropdowns / Popovers - ,surface_input: "hsl(0, 0%, 12%)" // Form Inputs - ,surface_code: "hsl(0, 0%, 11%)" // Code Block Background - ,surface_select: "hsl(45, 100%, 15%)" // Text Selection Highlight - - // --- CONTENT (Text & Icons) --- - ,content_main: "hsl(50, 60%, 85%)" // Primary Reading Text - ,content_muted: "hsl(36, 15%, 60%)" // Metadata, subtitles - ,content_subtle: "hsl(36, 10%, 40%)" // Placeholders, disabled states - ,content_inverse: "hsl(0, 0%, 5%)" // Text on high-contrast buttons - - // --- BRAND & ACTION (The "Wheat" Identity) --- - ,brand_primary: "hsl(45, 100%, 50%)" // Main Action / H1 / Focus Ring - ,brand_secondary: "hsl(38, 90%, 65%)" // Secondary Buttons / H2 - ,brand_tertiary: "hsl(30, 60%, 70%)" // Accents / H3 - ,brand_link: "hsl(48, 100%, 50%)" // Hyperlinks (High Visibility) - - // --- BORDERS & DIVIDERS --- - ,border_faint: "hsl(36, 20%, 15%)" // Subtle separation - ,border_default: "hsl(36, 20%, 25%)" // Standard Card Borders - ,border_strong: "hsl(36, 20%, 40%)" // Active states / Inputs - - // --- STATE & FEEDBACK (Earth Tones) --- - ,state_success: "hsl(100, 50%, 45%)" // Olive Green - ,state_warning: "hsl(35, 90%, 55%)" // Burnt Orange - ,state_error: "hsl(0, 60%, 55%)" // Brick Red - ,state_info: "hsl(200, 40%, 55%)" // Slate Blue - - // --- SYNTAX HIGHLIGHTING (For Code) --- - ,syntax_keyword: "hsl(35, 100%, 65%)" // Orange - ,syntax_string: "hsl(75, 50%, 60%)" // Sage Green - ,syntax_func: "hsl(45, 90%, 70%)" // Light Gold - ,syntax_comment: "hsl(36, 15%, 45%)" // Brown/Gray - }; - - // --- APPLY THEME --- - const palette = RT.config.theme; - const body = document.body; - const html = document.documentElement; - - // 1. Paint Base - html.style.backgroundColor = palette.surface_0; - body.style.backgroundColor = palette.surface_0; - body.style.color = palette.content_main; - - // 2. Export Variables (Standardization) - const s = body.style; - for (const [key, value] of Object.entries(palette)) { - s.setProperty(`--rt-${key.replace(/_/g, '-')}`, value); - } - - - // 3. Global Overrides - const style_id = 'rt-global-overrides'; - if (!document.getElementById(style_id)) { - const style = document.createElement('style'); - style.id = style_id; - style.textContent = ` - ::selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } - ::-moz-selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } - - ::-webkit-scrollbar { width: 12px; } - ::-webkit-scrollbar-track { background: var(--rt-surface-0); } - ::-webkit-scrollbar-thumb { - background: var(--rt-border-default); - border: 2px solid var(--rt-surface-0); - border-radius: 8px; - } - ::-webkit-scrollbar-thumb:hover { background: var(--rt-brand-secondary); } - - /* --- Citation & Endnote Styling --- */ - rt-cite a, .rt-inline-cite a, rt-endnotes a { - color: var(--rt-brand-link); - text-decoration: none; - } - rt-cite a:hover, .rt-inline-cite a:hover, rt-endnotes a:hover { - text-decoration: underline; - } - rt-cite, .rt-inline-cite { - font-size: 1em; - vertical-align: baseline; - padding: 0 0.15em; - } - - /* --- Image Inversion for Diagrams --- */ - img.rt-diagram { - filter: invert(1) hue-rotate(180deg); - } - `; - - document.head.appendChild(style); - } - }; - -} )(); diff --git a/developer/authored/Theme.copy/light.js b/developer/authored/Theme.copy/light.js deleted file mode 100644 index d0e80eb..0000000 --- a/developer/authored/Theme.copy/light.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - Theme: Classic Wheat (Light) - Standard: Theme 1.0 - Description: Warm paper tones with Burnt Orange accents. -*/ -( function(){ - const RT = window.RT = window.RT || {}; - - RT.theme_light = function(){ - RT.config = RT.config || {}; - - // THEME 1.0 DATA CONTRACT - RT.config.theme = { - meta_is_dark: false - ,meta_name: "Classic Wheat" - - // --- SURFACES --- - ,surface_0: "hsl(40, 30%, 94%)" // App Background (Cream/Linen) - ,surface_1: "hsl(40, 25%, 90%)" // Sidebar (Slightly darker beige) - ,surface_2: "hsl(40, 20%, 98%)" // Cards (Lighter, almost white) - ,surface_3: "hsl(0, 0%, 100%)" // Modals (Pure White) - ,surface_input: "hsl(40, 20%, 98%)" // Form Inputs - ,surface_code: "hsl(40, 15%, 90%)" // Code Block Background - ,surface_select: "hsl(45, 100%, 85%)" // Text Selection Highlight - - // --- CONTENT --- - ,content_main: "hsl(30, 20%, 20%)" // Deep Umber (Not Black) - ,content_muted: "hsl(30, 15%, 45%)" // Medium Brown - ,content_subtle: "hsl(30, 10%, 65%)" // Light Brown/Gray - ,content_inverse: "hsl(40, 30%, 94%)" // Text on dark buttons - - // --- BRAND & ACTION --- - ,brand_primary: "hsl(30, 90%, 35%)" // Burnt Orange (Action) - ,brand_secondary: "hsl(35, 70%, 45%)" // Rust / Gold - ,brand_tertiary: "hsl(25, 60%, 55%)" // Copper - ,brand_link: "hsl(30, 100%, 35%)" // Link Color - - // --- BORDERS --- - ,border_faint: "hsl(35, 20%, 85%)" - ,border_default: "hsl(35, 20%, 75%)" - ,border_strong: "hsl(35, 20%, 55%)" - - // --- STATE & FEEDBACK --- - ,state_success: "hsl(100, 40%, 40%)" // Forest Green - ,state_warning: "hsl(30, 90%, 50%)" // Persimmon - ,state_error: "hsl(0, 60%, 45%)" // Crimson - ,state_info: "hsl(200, 50%, 45%)" // Navy Blue - - // --- SYNTAX --- - ,syntax_keyword: "hsl(20, 90%, 45%)" // Rust - ,syntax_string: "hsl(100, 35%, 35%)" // Ivy Green - ,syntax_func: "hsl(300, 30%, 40%)" // Muted Purple - ,syntax_comment: "hsl(35, 10%, 60%)" // Light Brown - }; - - // --- APPLY THEME --- - const palette = RT.config.theme; - const body = document.body; - const html = document.documentElement; - - html.style.backgroundColor = palette.surface_0; - body.style.backgroundColor = palette.surface_0; - body.style.color = palette.content_main; - - const s = body.style; - for (const [key, value] of Object.entries(palette)) { - s.setProperty(`--rt-${key.replace(/_/g, '-')}`, value); - } - }; -} )(); diff --git a/developer/authored/Theme.copy/light_gold.js b/developer/authored/Theme.copy/light_gold.js deleted file mode 100644 index 3136934..0000000 --- a/developer/authored/Theme.copy/light_gold.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - Theme: Golden Wheat (Light) - "Spanish Gold Edition" - File: style/theme-light-gold.js - Standard: Theme 1.0 - Description: Light Parchment background with Oxblood Red ink. -*/ -( function(){ - const RT = window.RT = window.RT || {}; - - RT.theme = function(){ - RT.config = RT.config || {}; - - RT.config.theme = { - meta_is_dark: false - ,meta_name: "Golden Wheat (Yellow)" - - // --- SURFACES (Light Parchment) --- - // Shifted lightness up to 94% for a "whiter" feel that still holds the yellow tint. - ,surface_0: "hsl(48, 50%, 94%)" // Main Page: Fine Parchment - ,surface_1: "hsl(48, 40%, 90%)" // Panels: Slightly darker - ,surface_2: "hsl(48, 30%, 97%)" // Cards: Very light - ,surface_3: "hsl(0, 0%, 100%)" // Popups - ,surface_input: "hsl(48, 20%, 96%)" - ,surface_code: "hsl(48, 25%, 88%)" // Distinct Code BG - ,surface_select: "hsl(10, 70%, 85%)" // Red Highlight - - // --- CONTENT (Deep Ink) --- - ,content_main: "hsl(10, 25%, 7%)" // Deep Warm Black (Ink) - ,content_muted: "hsl(10, 15%, 35%)" // Dark Grey-Red - ,content_subtle: "hsl(10, 10%, 55%)" - ,content_inverse: "hsl(48, 50%, 90%)" - - // --- BRAND & ACTION (The Red Spectrum) --- - ,brand_primary: "hsl(12, 85%, 30%)" // H1 (Deep Oxblood) - ,brand_secondary: "hsl(10, 80%, 35%)" // H2 (Garnet) - ,brand_tertiary: "hsl(8, 70%, 40%)" // H3 (Brick) - ,brand_link: "hsl(12, 90%, 35%)" // Link - - // --- BORDERS --- - ,border_faint: "hsl(45, 30%, 80%)" - ,border_default: "hsl(45, 30%, 70%)" // Pencil Grey - ,border_strong: "hsl(12, 50%, 40%)" - - // --- STATE --- - ,state_success: "hsl(120, 40%, 30%)" - ,state_warning: "hsl(25, 90%, 45%)" - ,state_error: "hsl(0, 75%, 35%)" - ,state_info: "hsl(210, 60%, 40%)" - - // --- SYNTAX --- - ,syntax_keyword: "hsl(0, 75%, 35%)" - ,syntax_string: "hsl(100, 35%, 25%)" - ,syntax_func: "hsl(15, 85%, 35%)" - ,syntax_comment: "hsl(45, 20%, 50%)" - }; - - // --- APPLY THEME --- - const palette = RT.config.theme; - const body = document.body; - const html = document.documentElement; - - html.style.backgroundColor = palette.surface_0; - body.style.backgroundColor = palette.surface_0; - body.style.color = palette.content_main; - - const s = body.style; - for (const [key, value] of Object.entries(palette)) { - s.setProperty(`--rt-${key.replace(/_/g, '-')}`, value); - } - - // Global overrides - const style_id = 'rt-global-overrides'; - if (!document.getElementById(style_id)) { - const style = document.createElement('style'); - style.id = style_id; - style.textContent = ` - ::selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } - ::-moz-selection { background: var(--rt-surface-select); color: var(--rt-brand-primary); } - - ::-webkit-scrollbar { width: 12px; } - ::-webkit-scrollbar-track { background: var(--rt-surface-0); } - ::-webkit-scrollbar-thumb { - background: var(--rt-border-default); - border: 2px solid var(--rt-surface-0); - border-radius: 8px; - } - ::-webkit-scrollbar-thumb:hover { background: var(--rt-brand-secondary); } - - rt-article p, rt-article li { - text-shadow: 0px 0px 0.5px rgba(0,0,0, 0.2); - } - - .MathJax, .MathJax_Display, .mjx-chtml { - color: var(--rt-content-main) !important; - fill: var(--rt-content-main) !important; - stroke: var(--rt-content-main) !important; - } - `; - document.head.appendChild(style); - } - }; - -} )(); diff --git a/developer/authored/Tool.copy/to_pdf.py b/developer/authored/Tool.copy/to_pdf.py deleted file mode 100644 index 177f7bd..0000000 --- a/developer/authored/Tool.copy/to_pdf.py +++ /dev/null @@ -1,167 +0,0 @@ -import os -import glob -import base64 -import re -from weasyprint import HTML - -# Find the image file -img_path = None -for search_dir in ['/mnt/data', '/tmp', '.']: - for root, dirs, files in os.walk(search_dir): - if 'money_circle.jpeg' in files: - img_path = os.path.join(root, 'money_circle.jpeg') - break - if img_path: - break - -img_b64 = "" -if img_path: - with open(img_path, "rb") as f: - img_b64 = base64.b64encode(f.read()).decode('utf-8') - -html_content = """ - - - - - On Cybersecurity and Commonsense - - - - -""" - -# String replacements (hyphens, 'may', 'just') -html_content = html_content.replace('—', '-') -html_content = re.sub(r'\bmay\b', 'can', html_content) -html_content = re.sub(r'\bMay\b', 'Can', html_content) -html_content = re.sub(r'\bjust\b', 'merely', html_content) -html_content = re.sub(r'\bJust\b', 'Merely', html_content) - -# Title block replacement -title_match = re.search(r'\s*', html_content, re.IGNORECASE | re.DOTALL) -if title_match: - title, author, date, copyright_text = title_match.groups() - if not copyright_text.startswith('©') and not copyright_text.startswith('©'): - copyright_text = f"© {copyright_text}" - - title_html = f''' -
          -

          {title}

          -

          {author}

          -

          {date}

          - -
          - ''' - html_content = html_content[:title_match.start()] + title_html + html_content[title_match.end():] - -# TOC replacement -headings = re.findall(r'(.*?)', html_content, re.IGNORECASE) -toc_html = '

          Table of Contents

            ' -for idx, (level, _, id_val, text) in enumerate(headings): - if not id_val: - id_val = f"heading-{idx}" - html_content = re.sub(f'{text}', f'{text}', html_content, count=1) - toc_html += f'
          • {text}
          • ' -toc_html += '
          ' - -html_content = re.sub(r']*>', toc_html, html_content, flags=re.IGNORECASE) - -# Image replacement -if img_b64: - html_content = re.sub(r'src="money_circle\.jpeg"', f'src="data:image/jpeg;base64,{img_b64}" class="content-image"', html_content) - -# Custom tags -html_content = re.sub(r'', '
          ', html_content, flags=re.IGNORECASE) -html_content = re.sub(r'', '
          ', html_content, flags=re.IGNORECASE) -html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) -html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) -html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) -html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) -html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) -html_content = re.sub(r'', '', html_content, flags=re.IGNORECASE) - -def replace_rt_math(m): - content = m.group(1) - if '\n' in content: - return f'
          {content}
          ' - return f'{content}' - -def replace_rt_code(m): - content = m.group(1) - if '\n' in content: - return f'
          {content}
          ' - return f'{content}' - -html_content = re.sub(r'(.*?)', replace_rt_math, html_content, flags=re.IGNORECASE | re.DOTALL) -html_content = re.sub(r'(.*?)', replace_rt_code, html_content, flags=re.IGNORECASE | re.DOTALL) - -css_styles = """ - @page { - size: letter; - margin: 25mm 20mm; - background-color: #FAFAFA; - @bottom-center { - content: counter(page); - font-family: 'Georgia', serif; - font-size: 10pt; - color: #555; - } - } - body { - margin: 0; - padding: 0; - font-family: 'Georgia', serif; - font-size: 11pt; - line-height: 1.6; - color: #2c3e50; - background-color: #FAFAFA; - } - *, *::before, *::after { box-sizing: border-box; } - - h1, h2, h3, h4 { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #1A365D; - page-break-after: avoid; - } - h1 { font-size: 20pt; margin-top: 1.5em; margin-bottom: 0.5em; border-bottom: 2px solid #E2E8F0; padding-bottom: 0.2em; } - h2 { font-size: 16pt; margin-top: 1.5em; margin-bottom: 0.5em; } - p { margin-bottom: 1em; text-align: justify; } - ul, ol { margin-bottom: 1em; padding-left: 2em; } - li { margin-bottom: 0.5em; } - - .title-block { text-align: center; margin-bottom: 4em; padding: 2em 0; border-bottom: 3px solid #1A365D; } - .title-block h1 { font-size: 26pt; border: none; margin-top: 0; margin-bottom: 0.5em; color: #0F2040; } - .title-block .meta-author { font-size: 14pt; font-weight: bold; margin: 0.2em 0; } - .title-block .meta-date { font-size: 12pt; color: #555; font-style: italic; margin: 0.2em 0; } - .title-block .meta-copyright { font-size: 10pt; color: #777; margin-top: 1em; } - - .toc-block { background-color: #F0F4F8; padding: 20px; border-radius: 5px; margin-bottom: 3em; page-break-after: always; } - .toc-block h2 { margin-top: 0; border: none; } - .toc-block ul { list-style-type: none; padding-left: 0; } - .toc-h1 { font-weight: bold; margin-top: 0.8em; } - .toc-h2 { padding-left: 1.5em; font-size: 0.95em; } - .toc-block a { text-decoration: none; color: #2c3e50; } - - .rt-term { font-weight: bold; color: #2980B9; } - .rt-term-em { font-weight: bold; font-style: italic; color: #2980B9; } - .rt-neologism { font-variant: small-caps; font-weight: bold; color: #C0392B; } - .rt-code-inline { font-family: 'Courier New', Courier, monospace; background-color: #EAECEE; padding: 2px 4px; border-radius: 3px; font-size: 0.9em; } - .rt-code-block { font-family: 'Courier New', Courier, monospace; background-color: #F4F6F7; padding: 15px; border-left: 4px solid #7F8C8D; border-radius: 3px; font-size: 0.9em; overflow-x: auto; white-space: pre-wrap; } - - .math { font-family: 'Times New Roman', serif; font-style: italic; font-weight: bold; color: #2C3E50; } - .math-block { text-align: center; margin: 1.5em 0; font-size: 1.2em; background-color: #F9EBEA; padding: 10px; border-radius: 5px; } - .math-inline { font-size: 1.05em; } - - table { width: 100%; border-collapse: collapse; margin: 2em 0; } - th, td { padding: 10px; text-align: left; vertical-align: top; } - th { background-color: #1A365D; color: white; font-weight: bold; } - tr { border-bottom: 1px solid #ddd; } - hr { border: 0; border-top: 1px solid #eee; } - - .content-image { display: block; max-width: 90%; margin: 2em auto; border: 1px solid #ccc; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } -""" - -final_html = f"{html_content}" -HTML(string=final_html).write_pdf("White_Paper_Cybersecurity_Legislation.pdf") -print("Success") diff --git a/developer/authored/Tool.copy/to_pdf2.py b/developer/authored/Tool.copy/to_pdf2.py deleted file mode 100644 index a493d27..0000000 --- a/developer/authored/Tool.copy/to_pdf2.py +++ /dev/null @@ -1,479 +0,0 @@ -import re -import os -import glob -from weasyprint import HTML - -def process_rt_html(html_str, out_file): - # Fix escaped dollar signs - html_str = html_str.replace('\\$', '$') - - # Remove hardcoded page breaks that cause blank pages - html_str = re.sub(r']*["\']>\s*', '', html_str, flags=re.IGNORECASE) - - css = """ - - """ - - # Inject CSS - html_str = html_str.replace("", css + "") - - # Process Title Block - title_match = re.search(r']+)>(.*?)', html_str, re.DOTALL | re.IGNORECASE) - if title_match: - attrs = title_match.group(1) - title = re.search(r'title="(.*?)"', attrs).group(1) if 'title="' in attrs else 'Document' - author = re.search(r'author="(.*?)"', attrs).group(1) if 'author="' in attrs else '' - date = re.search(r'date="(.*?)"', attrs).group(1) if 'date="' in attrs else '' - copyright_txt = re.search(r'copyright="(.*?)"', attrs).group(1) if 'copyright="' in attrs else '' - - title_block = f''' -
          -

          {title}

          -
          {author} | {date}
          - -
          - ''' - html_str = html_str[:title_match.start()] + title_block + html_str[title_match.end():] - - # Process TOC - toc_match = re.search(r'', html_str, re.IGNORECASE) - if toc_match: - level = toc_match.group(1) - headings = [] - if '-' in level: - headings = re.findall(r'(.*?)', html_str, re.IGNORECASE) - else: - headings = re.findall(rf'(.*?)', html_str, re.IGNORECASE) - - toc_html = '
          Table of Contents
            ' - for lvl, text in headings: - # exclude COVER SHEET from TOC - if "COVER SHEET" in text: - continue - toc_html += f'
          • {text}
          • ' - toc_html += '
          ' - - html_str = html_str[:toc_match.start()] + toc_html + html_str[toc_match.end():] - - # Term Replacement (First occurrence) - seen_terms = set() - def term_replace(match): - text = match.group(1) - l_text = text.lower() - if l_text not in seen_terms: - seen_terms.add(l_text) - return f'{text}' - else: - return f'{text}' - - html_str = re.sub(r'(.*?)', term_replace, html_str) - - # Neologism Replacement (First occurrence) - seen_neos = set() - def neo_replace(match): - text = match.group(1) - l_text = text.lower() - if l_text not in seen_neos: - seen_neos.add(l_text) - return f'{text}' - else: - return f'{text}' - - html_str = re.sub(r'(.*?)', neo_replace, html_str) - - HTML(string=html_str).write_pdf(out_file) - -# Locate the uploaded file -uploaded_files = glob.glob('/mnt/data/user_uploads/*abstract.html') -if not uploaded_files: - uploaded_files = glob.glob('/mnt/data/uploads/*abstract.html') -if not uploaded_files: - # Look for it anywhere under /mnt/data - for root, dirs, files in os.walk('/mnt/data'): - for file in files: - if file == 'abstract.html': - uploaded_files.append(os.path.join(root, file)) - -if uploaded_files: - filepath = uploaded_files[0] - with open(filepath, 'r', encoding='utf-8') as f: - html_content = f.read() - process_rt_html(html_content, 'abstract.pdf') - print("PDF successfully generated.") -else: - print("Could not find abstract.html in the data directory.") - -Code output -Traceback (most recent call last): - File "", line 1, in - import bs4 -ModuleNotFoundError: No module named 'bs4' - -Python -import re -import os -import glob -from weasyprint import HTML - -def process_rt_html(html_str, out_file): - html_str = html_str.replace('\\$', '$') - html_str = re.sub(r']*["\']>\s*', '', html_str, flags=re.IGNORECASE) - - css = """ - - """ - - html_str = html_str.replace("", css + "") - - title_match = re.search(r']+)>(.*?)', html_str, re.DOTALL | re.IGNORECASE) - if title_match: - attrs = title_match.group(1) - title = re.search(r'title="(.*?)"', attrs).group(1) if 'title="' in attrs else 'Document' - author = re.search(r'author="(.*?)"', attrs).group(1) if 'author="' in attrs else '' - date = re.search(r'date="(.*?)"', attrs).group(1) if 'date="' in attrs else '' - copyright_txt = re.search(r'copyright="(.*?)"', attrs).group(1) if 'copyright="' in attrs else '' - - title_block = f''' -
          -

          {title}

          -
          {author} | {date}
          - -
          - ''' - html_str = html_str[:title_match.start()] + title_block + html_str[title_match.end():] - - toc_match = re.search(r'', html_str, re.IGNORECASE) - if toc_match: - level = toc_match.group(1) - headings = [] - if '-' in level: - headings = re.findall(r'(.*?)', html_str, re.IGNORECASE) - else: - headings = re.findall(rf'(.*?)', html_str, re.IGNORECASE) - - toc_html = '
          Table of Contents
            ' - for lvl, text in headings: - if "COVER SHEET" in text: - continue - toc_html += f'
          • {text}
          • ' - toc_html += '
          ' - - # Add page break AFTER the TOC instead of before it - toc_html += '
          ' - - html_str = html_str[:toc_match.start()] + toc_html + html_str[toc_match.end():] - - seen_terms = set() - def term_replace(match): - text = match.group(1) - l_text = text.lower() - if l_text not in seen_terms: - seen_terms.add(l_text) - return f'{text}' - else: - return f'{text}' - - html_str = re.sub(r'(.*?)', term_replace, html_str) - - seen_neos = set() - def neo_replace(match): - text = match.group(1) - l_text = text.lower() - if l_text not in seen_neos: - seen_neos.add(l_text) - return f'{text}' - else: - return f'{text}' - - html_str = re.sub(r'(.*?)', neo_replace, html_str) - - HTML(string=html_str).write_pdf(out_file) - -uploaded_files = glob.glob('/mnt/data/user_uploads/*abstract.html') -if not uploaded_files: - uploaded_files = glob.glob('/mnt/data/uploads/*abstract.html') -if not uploaded_files: - for root, dirs, files in os.walk('/mnt/data'): - for file in files: - if file == 'abstract.html': - uploaded_files.append(os.path.join(root, file)) - -if uploaded_files: - filepath = uploaded_files[0] - with open(filepath, 'r', encoding='utf-8') as f: - html_content = f.read() - - # One last aggressive check to ensure we absolutely strip ANY style="page-break..." strings - # in case the earlier regex missed a specific formatting - html_content = re.sub(r'style="[^"]*page-break-after:\s*always;?[^"]*"', '', html_content, flags=re.IGNORECASE) - - process_rt_html(html_content, 'abstract_no_gap.pdf') - print("PDF successfully generated.") -else: - print("Could not find abstract.html in the data directory.") diff --git a/developer/document/RT-code-format-Lisp.html b/developer/document/RT-code-format-Lisp.html index 917b4db..61730d3 100644 --- a/developer/document/RT-code-format-Lisp.html +++ b/developer/document/RT-code-format-Lisp.html @@ -3,16 +3,9 @@ RT Code Format: Lisp Addendum + - diff --git a/developer/document/RT-code-format.html b/developer/document/RT-code-format.html index 4a8bbb6..a162364 100644 --- a/developer/document/RT-code-format.html +++ b/developer/document/RT-code-format.html @@ -3,16 +3,9 @@ RT code format conventions + - diff --git a/developer/document/RT-style.js b/developer/document/RT-style.js new file mode 100644 index 0000000..34cfb22 --- /dev/null +++ b/developer/document/RT-style.js @@ -0,0 +1,28 @@ +// RT-style.js (Internal RT-style project router) +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/made/Manuscript"; + } else { + // Fallback for when served via local Python HTTP daemon from the project root + window.RT.dirpr_library = "../consumer/made/Manuscript"; + } + + document.write(' - diff --git a/developer/document/single-file_C-module-and-namespace.html b/developer/document/single-file_C-module-and-namespace.html index 3109daa..db0e657 100644 --- a/developer/document/single-file_C-module-and-namespace.html +++ b/developer/document/single-file_C-module-and-namespace.html @@ -3,16 +3,9 @@ C modules, namespaces, and the build lifecycle + - diff --git a/document/RT-style-HTML.html b/document/RT-style-HTML.html index 15fb720..1ed8fed 100644 --- a/document/RT-style-HTML.html +++ b/document/RT-style-HTML.html @@ -3,16 +3,9 @@ RT semantic HTML tags + - @@ -419,11 +412,6 @@ 9. page_fixed_glow.js (Visual page container)
          - - -

          RT conventions

          Headings are first letter capitalized. Remaining words are as they would be in English prose.

          diff --git a/document/RT-style.js b/document/RT-style.js new file mode 100644 index 0000000..34cfb22 --- /dev/null +++ b/document/RT-style.js @@ -0,0 +1,28 @@ +// RT-style.js (Internal RT-style project router) +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/made/Manuscript"; + } else { + // Fallback for when served via local Python HTTP daemon from the project root + window.RT.dirpr_library = "../consumer/made/Manuscript"; + } + + document.write(' - diff --git a/document/role-and-workflow_product-development.html b/document/role-and-workflow_product-development.html index 57adde1..47c5b2a 100644 --- a/document/role-and-workflow_product-development.html +++ b/document/role-and-workflow_product-development.html @@ -3,16 +3,9 @@ Product development roles and workflow + - diff --git a/document/role-and-workflow_product-maintenance.html b/document/role-and-workflow_product-maintenance.html index 5cccbbd..e2c59db 100644 --- a/document/role-and-workflow_product-maintenance.html +++ b/document/role-and-workflow_product-maintenance.html @@ -3,16 +3,9 @@ Product maintenance roles and workflow + - diff --git a/shared/document/.gitkeep b/shared/document/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/shared/document/RT-style.js b/shared/document/RT-style.js new file mode 100644 index 0000000..34cfb22 --- /dev/null +++ b/shared/document/RT-style.js @@ -0,0 +1,28 @@ +// RT-style.js (Internal RT-style project router) +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/made/Manuscript"; + } else { + // Fallback for when served via local Python HTTP daemon from the project root + window.RT.dirpr_library = "../consumer/made/Manuscript"; + } + + document.write('