Default the public catalog to colored PDFs
Some checks are pending
offline / test (push) Waiting to run
Some checks are pending
offline / test (push) Waiting to run
Render published markdown with pandoc + WeasyPrint (indigo tables, dark code). Home page links to PDFs with a top-right switch to Markdown indexes. Serve CONSOLE.pdf from the operator console.
This commit is contained in:
parent
cf4ef9e3af
commit
5ad3222def
9 changed files with 957 additions and 182 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
# Documentation index
|
# Documentation index
|
||||||
|
|
||||||
Read **high-level first**, then **architecture**, then the rest. Live catalog: https://zapier.georgelambert.org/
|
Read **high-level first**, then **architecture**, then the rest. Live catalog (PDF by default): https://zapier.georgelambert.org/ — [Markdown indexes](https://zapier.georgelambert.org/index-md.html)
|
||||||
|
|
||||||
Operator console (loopback): http://127.0.0.1:3850/
|
Operator console (loopback): http://127.0.0.1:3850/ · [CONSOLE.pdf](https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf)
|
||||||
|
|
||||||
## 1. High-level (non-technical)
|
## 1. High-level (non-technical)
|
||||||
|
|
||||||
|
|
@ -24,25 +24,25 @@ Operator console (loopback): http://127.0.0.1:3850/
|
||||||
| Address routing | [06-address-routing.md](06-address-routing.md) |
|
| Address routing | [06-address-routing.md](06-address-routing.md) |
|
||||||
| External resources | [07-external-resources.md](07-external-resources.md) |
|
| External resources | [07-external-resources.md](07-external-resources.md) |
|
||||||
| Diagrams | [08-diagrams.md](08-diagrams.md) |
|
| Diagrams | [08-diagrams.md](08-diagrams.md) |
|
||||||
| Catalog home | https://zapier.georgelambert.org/ |
|
| Catalog home | https://zapier.georgelambert.org/ (PDF) · [Markdown indexes](https://zapier.georgelambert.org/index-md.html) |
|
||||||
| Composition | https://zapier.georgelambert.org/docs/02-architecture/composition.html |
|
| Composition | https://zapier.georgelambert.org/docs/02-architecture/composition.pdf |
|
||||||
| NATS gateway | https://zapier.georgelambert.org/docs/02-architecture/nats-gateway.html |
|
| NATS gateway | https://zapier.georgelambert.org/docs/02-architecture/nats-gateway.pdf |
|
||||||
| NATS subjects | https://zapier.georgelambert.org/docs/02-architecture/nats-subjects.html |
|
| NATS subjects | https://zapier.georgelambert.org/docs/02-architecture/nats-subjects.pdf |
|
||||||
| Archive / bloom | https://zapier.georgelambert.org/docs/02-architecture/archive-nats.html |
|
| Archive / bloom | https://zapier.georgelambert.org/docs/02-architecture/archive-nats.pdf |
|
||||||
| Module NATS map | https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.html |
|
| Module NATS map | https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.pdf |
|
||||||
| Tree nodes | https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.html |
|
| Tree nodes | https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.pdf |
|
||||||
| Fleet | https://zapier.georgelambert.org/docs/02-architecture/fleet.html |
|
| Fleet | https://zapier.georgelambert.org/docs/02-architecture/fleet.pdf |
|
||||||
|
|
||||||
## 3. Remaining documentation
|
## 3. Remaining documentation
|
||||||
|
|
||||||
| Document | URL |
|
| Document | URL |
|
||||||
|----------|-----|
|
|----------|-----|
|
||||||
| Expansion template | [09-expansion-template.md](09-expansion-template.md) |
|
| Expansion template | [09-expansion-template.md](09-expansion-template.md) |
|
||||||
| Operator console | https://git.georgelambert.org/marchon/verae-fleet/src/branch/main/docs/CONSOLE.md |
|
| Operator console | https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf |
|
||||||
| User guide | https://zapier.georgelambert.org/user-docs/README.md |
|
| User guide | https://zapier.georgelambert.org/user-docs/README.pdf |
|
||||||
| Tree-node lookup (users) | https://zapier.georgelambert.org/packages/zapier-user-docs/09-lookup-tree-nodes.html |
|
| Tree-node lookup (users) | https://zapier.georgelambert.org/packages/zapier-user-docs/09-lookup-tree-nodes.pdf |
|
||||||
| Zapier developer setup | https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.html |
|
| Zapier developer setup | https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf |
|
||||||
| docs-master | https://zapier.georgelambert.org/docs-master/README.md |
|
| docs-master | https://zapier.georgelambert.org/docs-master/README.pdf |
|
||||||
|
|
||||||
## Independent git repositories
|
## Independent git repositories
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
High-level description of the whole system: what it is, which **independent git repositories** implement it, how it stays up, how it behaves when the local network fails, and how it talks to the **central Verae NATS.IO 3-server cluster**. New work is added by **new address routing**, not by teaching Zapier about NATS.
|
High-level description of the whole system: what it is, which **independent git repositories** implement it, how it stays up, how it behaves when the local network fails, and how it talks to the **central Verae NATS.IO 3-server cluster**. New work is added by **new address routing**, not by teaching Zapier about NATS.
|
||||||
|
|
||||||
**This repo:** https://git.georgelambert.org/marchon/overview
|
**This repo:** https://git.georgelambert.org/marchon/overview
|
||||||
**Live catalog:** https://zapier.georgelambert.org/
|
**Live catalog (PDF by default):** https://zapier.georgelambert.org/ · [Markdown indexes](https://zapier.georgelambert.org/index-md.html)
|
||||||
**Clone:** `ssh://git@git.georgelambert.org:2223/marchon/overview.git`
|
**Clone:** `ssh://git@git.georgelambert.org:2223/marchon/overview.git`
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
@ -49,7 +49,7 @@ Clone any of them: `git clone ssh://git@git.georgelambert.org:2223/marchon/<name
|
||||||
|
|
||||||
## Operator console (loopback)
|
## Operator console (loopback)
|
||||||
|
|
||||||
Fleet, message **Trace**, and **Docs** share one shell at http://127.0.0.1:3850/ (`verae-fleet`). Not public. See [verae-fleet CONSOLE.md](https://git.georgelambert.org/marchon/verae-fleet/src/branch/main/docs/CONSOLE.md).
|
Fleet, message **Trace**, and **Docs** share one shell at http://127.0.0.1:3850/ (`verae-fleet`). Not public. See [CONSOLE.pdf](https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
@ -80,11 +80,11 @@ Start at the top. Architecture is second. Everything else is reference.
|
||||||
| [Address routing](06-address-routing.md) | Unplanned functions as new subjects |
|
| [Address routing](06-address-routing.md) | Unplanned functions as new subjects |
|
||||||
| [External resources](07-external-resources.md) | Chain, WORM, tree-node search |
|
| [External resources](07-external-resources.md) | Chain, WORM, tree-node search |
|
||||||
| [Diagrams](08-diagrams.md) | SVG + mermaid |
|
| [Diagrams](08-diagrams.md) | SVG + mermaid |
|
||||||
| [Fleet](https://zapier.georgelambert.org/docs/02-architecture/fleet.html) | Operator replica control |
|
| [Fleet](https://zapier.georgelambert.org/docs/02-architecture/fleet.pdf) | Operator replica control |
|
||||||
| [Module NATS map](https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.html) | Address table |
|
| [Module NATS map](https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.pdf) | Address table |
|
||||||
| [Archive / bloom](https://zapier.georgelambert.org/docs/02-architecture/archive-nats.html) | Multipart and multi-receipt |
|
| [Archive / bloom](https://zapier.georgelambert.org/docs/02-architecture/archive-nats.pdf) | Multipart and multi-receipt |
|
||||||
| [Tree nodes](https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.html) | Bulk Merkle leaves |
|
| [Tree nodes](https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.pdf) | Bulk Merkle leaves |
|
||||||
| [Composition](https://zapier.georgelambert.org/docs/02-architecture/composition.html) | zappier + middleware HTTPS |
|
| [Composition](https://zapier.georgelambert.org/docs/02-architecture/composition.pdf) | zappier + middleware HTTPS |
|
||||||
|
|
||||||
### 3. Remaining documentation
|
### 3. Remaining documentation
|
||||||
|
|
||||||
|
|
@ -92,10 +92,10 @@ Start at the top. Architecture is second. Everything else is reference.
|
||||||
|----------|------------|
|
|----------|------------|
|
||||||
| [Documentation index](INDEX.md) | A–Z and catalog URLs |
|
| [Documentation index](INDEX.md) | A–Z and catalog URLs |
|
||||||
| [Expansion template](09-expansion-template.md) / [verae-nats-process](https://git.georgelambert.org/marchon/verae-nats-process) | Copy this to add an address |
|
| [Expansion template](09-expansion-template.md) / [verae-nats-process](https://git.georgelambert.org/marchon/verae-nats-process) | Copy this to add an address |
|
||||||
| [Operator console](https://git.georgelambert.org/marchon/verae-fleet/src/branch/main/docs/CONSOLE.md) | Screenshots of Fleet / Trace / Docs |
|
| [Operator console](https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf) | Screenshots of Fleet / Trace / Docs |
|
||||||
| [Simulator](https://git.georgelambert.org/marchon/verae-zapier-simulator) | Standalone trace (also inside the console) |
|
| [Simulator](https://git.georgelambert.org/marchon/verae-zapier-simulator) | Standalone trace (also inside the console) |
|
||||||
| [Zapier developer setup](https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.html) | CLI / login / push |
|
| [Zapier developer setup](https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf) | CLI / login / push |
|
||||||
| Live catalog | https://zapier.georgelambert.org/ |
|
| Live catalog | https://zapier.georgelambert.org/ (PDF) · [Markdown indexes](https://zapier.georgelambert.org/index-md.html) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ node src/cli.js ssh-check ns1 # marchon@70.88.205.138 with ~/.ssh/id_ed25519
|
||||||
|
|
||||||
Private keys stay on disk (`~/.ssh/id_ed25519`); git stores only the path. Optional overrides: `machines.secrets.json` (gitignored).
|
Private keys stay on disk (`~/.ssh/id_ed25519`); git stores only the path. Optional overrides: `machines.secrets.json` (gitignored).
|
||||||
|
|
||||||
Operator console (Fleet · Trace · Docs) at http://127.0.0.1:3850/ — see [docs/CONSOLE.md](docs/CONSOLE.md). Message-processing **min / avg / p50 / p90** RTT is on the Fleet tab.
|
Operator console (Fleet · Trace · Docs) at http://127.0.0.1:3850/ — [docs/CONSOLE.md](docs/CONSOLE.md) · [CONSOLE.pdf](docs/CONSOLE.pdf) (also https://zapier.georgelambert.org/packages/verae-fleet/docs/CONSOLE.pdf). Message-processing **min / avg / p50 / p90** RTT is on the Fleet tab.
|
||||||
|
|
||||||
Zapier cloud apps are listed but **not spawned**. NATS on NS1 is **monitored only** (loopback `:4222`, never a public bind).
|
Zapier cloud apps are listed but **not spawned**. NATS on NS1 is **monitored only** (loopback `:4222`, never a public bind).
|
||||||
|
|
||||||
|
|
|
||||||
426
packages/verae-fleet/docs/CONSOLE.html
Normal file
426
packages/verae-fleet/docs/CONSOLE.html
Normal file
|
|
@ -0,0 +1,426 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="generator" content="pandoc" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||||
|
<title>Operator console</title>
|
||||||
|
<style>
|
||||||
|
/* Default styles provided by pandoc.
|
||||||
|
** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
|
||||||
|
*/
|
||||||
|
html {
|
||||||
|
color: #1a1a1a;
|
||||||
|
background-color: #fdfdfd;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 36em;
|
||||||
|
padding-left: 50px;
|
||||||
|
padding-right: 50px;
|
||||||
|
padding-top: 50px;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
hyphens: auto;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
font-kerning: normal;
|
||||||
|
}
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
body {
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 1.8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
html {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: transparent;
|
||||||
|
color: black;
|
||||||
|
font-size: 12pt;
|
||||||
|
}
|
||||||
|
p, h2, h3 {
|
||||||
|
orphans: 3;
|
||||||
|
widows: 3;
|
||||||
|
}
|
||||||
|
h2, h3, h4 {
|
||||||
|
page-break-after: avoid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
a:visited {
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
height: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin-top: 1.4em;
|
||||||
|
}
|
||||||
|
h5, h6 {
|
||||||
|
font-size: 1em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
ol, ul {
|
||||||
|
padding-left: 1.7em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
li > ol, li > ul {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
margin: 1em 0 1em 1.7em;
|
||||||
|
padding-left: 1em;
|
||||||
|
border-left: 2px solid #e6e6e6;
|
||||||
|
color: #606060;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||||
|
font-size: 85%;
|
||||||
|
margin: 0;
|
||||||
|
hyphens: manual;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
margin: 1em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
padding: 0;
|
||||||
|
overflow: visible;
|
||||||
|
overflow-wrap: normal;
|
||||||
|
}
|
||||||
|
.sourceCode {
|
||||||
|
background-color: transparent;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid #1a1a1a;
|
||||||
|
height: 1px;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
margin: 1em 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
display: block;
|
||||||
|
font-variant-numeric: lining-nums tabular-nums;
|
||||||
|
}
|
||||||
|
table caption {
|
||||||
|
margin-bottom: 0.75em;
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
border-top: 1px solid #1a1a1a;
|
||||||
|
border-bottom: 1px solid #1a1a1a;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
border-top: 1px solid #1a1a1a;
|
||||||
|
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
margin-bottom: 4em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#TOC li {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
#TOC ul {
|
||||||
|
padding-left: 1.3em;
|
||||||
|
}
|
||||||
|
#TOC > ul {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
#TOC a:not(:hover) {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
code{white-space: pre-wrap;}
|
||||||
|
span.smallcaps{font-variant: small-caps;}
|
||||||
|
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||||
|
div.column{flex: auto; overflow-x: auto;}
|
||||||
|
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||||
|
/* The extra [class] is a hack that increases specificity enough to
|
||||||
|
override a similar rule in reveal.js */
|
||||||
|
ul.task-list[class]{list-style: none;}
|
||||||
|
ul.task-list li input[type="checkbox"] {
|
||||||
|
font-size: inherit;
|
||||||
|
width: 0.8em;
|
||||||
|
margin: 0 0.8em 0.2em -1.6em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||||
|
/* CSS for syntax highlighting */
|
||||||
|
html { -webkit-text-size-adjust: 100%; }
|
||||||
|
pre > code.sourceCode { white-space: pre; position: relative; }
|
||||||
|
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
||||||
|
pre > code.sourceCode > span:empty { height: 1.2em; }
|
||||||
|
.sourceCode { overflow: visible; }
|
||||||
|
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
||||||
|
div.sourceCode { margin: 1em 0; }
|
||||||
|
pre.sourceCode { margin: 0; }
|
||||||
|
@media screen {
|
||||||
|
div.sourceCode { overflow: auto; }
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
pre > code.sourceCode { white-space: pre-wrap; }
|
||||||
|
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
||||||
|
}
|
||||||
|
pre.numberSource code
|
||||||
|
{ counter-reset: source-line 0; }
|
||||||
|
pre.numberSource code > span
|
||||||
|
{ position: relative; left: -4em; counter-increment: source-line; }
|
||||||
|
pre.numberSource code > span > a:first-child::before
|
||||||
|
{ content: counter(source-line);
|
||||||
|
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
||||||
|
border: none; display: inline-block;
|
||||||
|
-webkit-touch-callout: none; -webkit-user-select: none;
|
||||||
|
-khtml-user-select: none; -moz-user-select: none;
|
||||||
|
-ms-user-select: none; user-select: none;
|
||||||
|
padding: 0 4px; width: 4em;
|
||||||
|
background-color: #232629;
|
||||||
|
color: #7a7c7d;
|
||||||
|
}
|
||||||
|
pre.numberSource { margin-left: 3em; border-left: 1px solid #7a7c7d; padding-left: 4px; }
|
||||||
|
div.sourceCode
|
||||||
|
{ color: #cfcfc2; background-color: #232629; }
|
||||||
|
@media screen {
|
||||||
|
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||||||
|
}
|
||||||
|
code span { color: #cfcfc2; } /* Normal */
|
||||||
|
code span.al { color: #95da4c; background-color: #4d1f24; font-weight: bold; } /* Alert */
|
||||||
|
code span.an { color: #3f8058; } /* Annotation */
|
||||||
|
code span.at { color: #2980b9; } /* Attribute */
|
||||||
|
code span.bn { color: #f67400; } /* BaseN */
|
||||||
|
code span.bu { color: #7f8c8d; } /* BuiltIn */
|
||||||
|
code span.cf { color: #fdbc4b; font-weight: bold; } /* ControlFlow */
|
||||||
|
code span.ch { color: #3daee9; } /* Char */
|
||||||
|
code span.cn { color: #27aeae; font-weight: bold; } /* Constant */
|
||||||
|
code span.co { color: #7a7c7d; } /* Comment */
|
||||||
|
code span.cv { color: #7f8c8d; } /* CommentVar */
|
||||||
|
code span.do { color: #a43340; } /* Documentation */
|
||||||
|
code span.dt { color: #2980b9; } /* DataType */
|
||||||
|
code span.dv { color: #f67400; } /* DecVal */
|
||||||
|
code span.er { color: #da4453; text-decoration: underline; } /* Error */
|
||||||
|
code span.ex { color: #0099ff; font-weight: bold; } /* Extension */
|
||||||
|
code span.fl { color: #f67400; } /* Float */
|
||||||
|
code span.fu { color: #8e44ad; } /* Function */
|
||||||
|
code span.im { color: #27ae60; } /* Import */
|
||||||
|
code span.in { color: #c45b00; } /* Information */
|
||||||
|
code span.kw { color: #cfcfc2; font-weight: bold; } /* Keyword */
|
||||||
|
code span.op { color: #cfcfc2; } /* Operator */
|
||||||
|
code span.ot { color: #27ae60; } /* Other */
|
||||||
|
code span.pp { color: #27ae60; } /* Preprocessor */
|
||||||
|
code span.re { color: #2980b9; background-color: #153042; } /* RegionMarker */
|
||||||
|
code span.sc { color: #3daee9; } /* SpecialChar */
|
||||||
|
code span.ss { color: #da4453; } /* SpecialString */
|
||||||
|
code span.st { color: #f44f4f; } /* String */
|
||||||
|
code span.va { color: #27aeae; } /* Variable */
|
||||||
|
code span.vs { color: #da4453; } /* VerbatimString */
|
||||||
|
code span.wa { color: #da4453; } /* Warning */
|
||||||
|
</style>
|
||||||
|
<style>/* Colored print + screen stylesheet for zapier.georgelambert.org */
|
||||||
|
:root {
|
||||||
|
--ink: #171a26;
|
||||||
|
--muted: #5b6178;
|
||||||
|
--line: #d9dce8;
|
||||||
|
--bg: #f4f5fb;
|
||||||
|
--paper: #ffffff;
|
||||||
|
--accent: #4f46e5;
|
||||||
|
--accent-deep: #312e81;
|
||||||
|
--accent-soft: #eef0fe;
|
||||||
|
--ok: #047857;
|
||||||
|
--warn: #8a5a00;
|
||||||
|
--code-bg: #1b1f33;
|
||||||
|
--code-fg: #e8ecff;
|
||||||
|
}
|
||||||
|
html { background: var(--bg); }
|
||||||
|
body {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1.5rem 1.25rem 3rem;
|
||||||
|
max-width: 48rem;
|
||||||
|
font: 15px/1.55 -apple-system, "Segoe UI", Georgia, serif;
|
||||||
|
color: var(--ink);
|
||||||
|
background: var(--paper);
|
||||||
|
}
|
||||||
|
.doc-banner {
|
||||||
|
background: linear-gradient(160deg, #312e81 0%, #4f46e5 60%, #7c74f0 100%);
|
||||||
|
color: #eef0fe;
|
||||||
|
margin: -1.5rem -1.25rem 1.5rem;
|
||||||
|
padding: 1.1rem 1.25rem 1rem;
|
||||||
|
}
|
||||||
|
.doc-banner a { color: #fff; }
|
||||||
|
.doc-banner .kicker {
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font: 700 10px system-ui, sans-serif;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.doc-banner h1 { margin: 0.25rem 0 0; font-size: 1.45rem; color: #fff; }
|
||||||
|
h1, h2, h3, h4 { color: var(--accent-deep); page-break-after: avoid; }
|
||||||
|
h1 { font-size: 1.7rem; }
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
border-bottom: 2px solid var(--accent);
|
||||||
|
padding-bottom: 0.2rem;
|
||||||
|
margin-top: 1.6rem;
|
||||||
|
}
|
||||||
|
h3 { font-size: 1.05rem; color: var(--accent); }
|
||||||
|
a { color: var(--accent); }
|
||||||
|
p, li { orphans: 3; widows: 3; }
|
||||||
|
code {
|
||||||
|
font-family: ui-monospace, Menlo, Consolas, monospace;
|
||||||
|
font-size: 0.86em;
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--accent-deep);
|
||||||
|
padding: 0.08em 0.28em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
pre, div.sourceCode, div.sourceCode pre {
|
||||||
|
background: var(--code-bg) !important;
|
||||||
|
color: var(--code-fg) !important;
|
||||||
|
padding: 0.85rem 1rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: auto;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
pre code { background: transparent; color: inherit; padding: 0; }
|
||||||
|
#title-block-header, header#title-block-header, h1.title { display: none; }
|
||||||
|
.doc-banner + h1 { display: none; }
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0.8rem 0 1.2rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
th, td { border: 1px solid var(--line); padding: 0.38rem 0.55rem; text-align: left; vertical-align: top; }
|
||||||
|
th {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
font: 650 12px system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
tr:nth-child(even) td { background: var(--accent-soft); }
|
||||||
|
blockquote {
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding: 0.4rem 0.9rem;
|
||||||
|
border-left: 4px solid var(--accent);
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--accent-deep);
|
||||||
|
}
|
||||||
|
img { max-width: 100%; height: auto; border-radius: 8px; page-break-inside: avoid; }
|
||||||
|
hr { border: 0; border-top: 1px solid var(--line); }
|
||||||
|
ul, ol { padding-left: 1.25rem; }
|
||||||
|
nav.site { font: 13px system-ui, sans-serif; margin-bottom: 0.4rem; }
|
||||||
|
.source-path { font: 11px ui-monospace, Menlo, monospace; color: var(--muted); }
|
||||||
|
|
||||||
|
@page {
|
||||||
|
size: letter;
|
||||||
|
margin: 0.65in 0.7in 0.8in 0.7in;
|
||||||
|
@top-left {
|
||||||
|
content: "Verae Time × Zapier";
|
||||||
|
font: 700 8pt system-ui, sans-serif;
|
||||||
|
color: #4f46e5;
|
||||||
|
}
|
||||||
|
@top-right {
|
||||||
|
content: "zapier.georgelambert.org";
|
||||||
|
font: 8pt system-ui, sans-serif;
|
||||||
|
color: #6b7186;
|
||||||
|
}
|
||||||
|
@bottom-center {
|
||||||
|
content: counter(page) " / " counter(pages);
|
||||||
|
font: 8pt system-ui, sans-serif;
|
||||||
|
color: #6b7186;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
html, body { background: #fff; max-width: none; padding: 0; }
|
||||||
|
.doc-banner { margin: 0 0 1rem; border-radius: 8px; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||||
|
a { text-decoration: none; }
|
||||||
|
th, tr:nth-child(even) td, pre, blockquote, code { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="doc-banner"><nav class="site"><a href="/">zapier.georgelambert.org</a> · <a href="/index-md.html">Markdown indexes</a></nav><div class="kicker">Verae Time × Zapier</div><h1>Operator console</h1><div class="source-path">packages/verae-fleet/docs/CONSOLE.md</div></div>
|
||||||
|
<header id="title-block-header">
|
||||||
|
<h1 class="title">Operator console</h1>
|
||||||
|
</header>
|
||||||
|
<h1 id="operator-console">Operator console</h1>
|
||||||
|
<p>Loopback UI at <strong>http://127.0.0.1:3850/</strong> — Fleet, Trace
|
||||||
|
(simulator), and Docs in one shell. Not a public site. NATS stays
|
||||||
|
private; SSH identity files stay on disk.</p>
|
||||||
|
<div class="sourceCode" id="cb1"><pre
|
||||||
|
class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> packages/verae-fleet</span>
|
||||||
|
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">node</span> src/cli.js serve</span></code></pre></div>
|
||||||
|
<h2 id="tabs">Tabs</h2>
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 35%" />
|
||||||
|
<col style="width: 64%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Tab</th>
|
||||||
|
<th>Purpose</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Fleet</strong></td>
|
||||||
|
<td>Machines (SSH/local), replica floors, green/yellow/red, RTT
|
||||||
|
min/avg/p50/p90 spark, pause/restart/off with confirm, ssh-check
|
||||||
|
toast</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Trace</strong></td>
|
||||||
|
<td>In-process Zapier simulator: run a step, hop log,
|
||||||
|
monitors/suggestions</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Docs</strong></td>
|
||||||
|
<td>Reading order: overview → module summaries → architecture →
|
||||||
|
remaining docs</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h2 id="screenshots">Screenshots</h2>
|
||||||
|
<figure>
|
||||||
|
<img src="screenshots/console-fleet.png" alt="Fleet" />
|
||||||
|
<figcaption aria-hidden="true">Fleet</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<img src="screenshots/console-trace.png" alt="Trace" />
|
||||||
|
<figcaption aria-hidden="true">Trace</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<img src="screenshots/console-docs.png" alt="Docs" />
|
||||||
|
<figcaption aria-hidden="true">Docs</figcaption>
|
||||||
|
</figure>
|
||||||
|
<p>Design tokens match the zappier portal/admin (indigo shell). Customer
|
||||||
|
portal is unchanged.</p>
|
||||||
|
<p>See <a
|
||||||
|
href="https://git.georgelambert.org/marchon/overview">overview</a>.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
packages/verae-fleet/docs/CONSOLE.pdf
Normal file
BIN
packages/verae-fleet/docs/CONSOLE.pdf
Normal file
Binary file not shown.
|
|
@ -44,8 +44,8 @@
|
||||||
.pill.good { background:#c8efd4; color:var(--ok); }
|
.pill.good { background:#c8efd4; color:var(--ok); }
|
||||||
.pill.warn { background:#ffe08a; color:var(--warn); }
|
.pill.warn { background:#ffe08a; color:var(--warn); }
|
||||||
.pill.bad { background:#f3c0c0; color:var(--err); }
|
.pill.bad { background:#f3c0c0; color:var(--err); }
|
||||||
button.act { margin:.15rem .2rem 0 0; border:1px solid var(--line); background:#fff; border-radius:8px; padding:.28rem .5rem; font:650 12px system-ui; cursor:pointer; }
|
button.act, a.act { margin:.15rem .2rem 0 0; border:1px solid var(--line); background:#fff; border-radius:8px; padding:.28rem .5rem; font:650 12px system-ui; cursor:pointer; text-decoration:none; color:var(--ink); display:inline-block; }
|
||||||
button.act.primary { background:var(--accent); color:#fff; border:0; }
|
button.act.primary, a.act.primary { background:var(--accent); color:#fff; border:0; }
|
||||||
button.act.danger { color:var(--err); }
|
button.act.danger { color:var(--err); }
|
||||||
table { width:100%; border-collapse:collapse; background:var(--panel); border-radius:var(--radius); overflow:hidden; box-shadow:var(--shadow); }
|
table { width:100%; border-collapse:collapse; background:var(--panel); border-radius:var(--radius); overflow:hidden; box-shadow:var(--shadow); }
|
||||||
th,td { text-align:left; padding:.45rem .6rem; border-bottom:1px solid var(--line); font-size:13px; vertical-align:top; }
|
th,td { text-align:left; padding:.45rem .6rem; border-bottom:1px solid var(--line); font-size:13px; vertical-align:top; }
|
||||||
|
|
@ -150,33 +150,36 @@ invoice-1003</textarea>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="docs" class="panel docs">
|
<section id="docs" class="panel docs">
|
||||||
<p class="muted">Reading order: high-level first, then architecture, then the rest. Operator console is loopback only.</p>
|
<p class="muted">Reading order: high-level first, then architecture, then the rest. Catalog defaults to colored PDFs. Operator console is loopback only.</p>
|
||||||
|
<p><a class="act primary" href="/docs/CONSOLE.pdf" target="_blank" rel="noopener">Open CONSOLE.pdf</a>
|
||||||
|
· <a href="https://zapier.georgelambert.org/">PDF catalog</a>
|
||||||
|
· <a href="https://zapier.georgelambert.org/index-md.html">Markdown indexes</a></p>
|
||||||
<h2>High-level (start here)</h2>
|
<h2>High-level (start here)</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/README.md">Overview</a> — whole system in plain language</li>
|
<li><a href="https://zapier.georgelambert.org/overview/README.pdf">Overview</a> — whole system in plain language</li>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/02-modules-and-repos.md">Modules and repositories</a> — short names of every independent repo</li>
|
<li><a href="https://zapier.georgelambert.org/overview/02-modules-and-repos.pdf">Modules and repositories</a> — short names of every independent repo</li>
|
||||||
<li><a href="https://zapier.georgelambert.org/docs-master/README.md">docs-master</a> — one-line SUMMARY + NATS for each module</li>
|
<li><a href="https://zapier.georgelambert.org/docs-master/README.pdf">docs-master</a> — one-line SUMMARY + NATS for each module</li>
|
||||||
<li><a href="https://zapier.georgelambert.org/user-docs/README.md">User guide</a> — signup → register → lookup (non-operator)</li>
|
<li><a href="https://zapier.georgelambert.org/user-docs/README.pdf">User guide</a> — signup → register → lookup (non-operator)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Architecture</h2>
|
<h2>Architecture</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/03-nats-cluster.md">NATS.IO 3-server cluster</a></li>
|
<li><a href="https://zapier.georgelambert.org/overview/03-nats-cluster.pdf">NATS.IO 3-server cluster</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/04-uptime.md">Uptime / replica floors</a></li>
|
<li><a href="https://zapier.georgelambert.org/overview/04-uptime.pdf">Uptime / replica floors</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/05-network-failures.md">Local network failures</a></li>
|
<li><a href="https://zapier.georgelambert.org/overview/05-network-failures.pdf">Local network failures</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/06-address-routing.md">Address routing</a></li>
|
<li><a href="https://zapier.georgelambert.org/overview/06-address-routing.pdf">Address routing</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/08-diagrams.md">Diagrams</a> · <a href="https://zapier.georgelambert.org/overview/diagrams/system.svg">system.svg</a></li>
|
<li><a href="https://zapier.georgelambert.org/overview/08-diagrams.pdf">Diagrams</a> · <a href="https://zapier.georgelambert.org/overview/diagrams/system.svg">system.svg</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/composition.html">Composition</a></li>
|
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/composition.pdf">Composition</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.html">Module NATS map</a></li>
|
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/modules-and-nats.pdf">Module NATS map</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/archive-nats.html">Archive / bloom</a></li>
|
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/archive-nats.pdf">Archive / bloom</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.html">Tree nodes</a></li>
|
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/tree-nodes.pdf">Tree nodes</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/fleet.html">Fleet</a></li>
|
<li><a href="https://zapier.georgelambert.org/docs/02-architecture/fleet.pdf">Fleet</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Remaining documentation</h2>
|
<h2>Remaining documentation</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/INDEX.md">Full documentation index</a></li>
|
<li><a href="https://zapier.georgelambert.org/overview/INDEX.pdf">Full documentation index</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/overview/09-expansion-template.md">Expansion template</a> · <a href="https://git.georgelambert.org/marchon/verae-nats-process">verae-nats-process</a></li>
|
<li><a href="https://zapier.georgelambert.org/overview/09-expansion-template.pdf">Expansion template</a> · <a href="https://git.georgelambert.org/marchon/verae-nats-process">verae-nats-process</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.html">Zapier developer setup</a></li>
|
<li><a href="https://zapier.georgelambert.org/docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf">Zapier developer setup</a></li>
|
||||||
<li><a href="https://zapier.georgelambert.org/packages/verae-zapier-simulator/README.md">Simulator README</a></li>
|
<li><a href="https://zapier.georgelambert.org/packages/verae-zapier-simulator/README.pdf">Simulator README</a></li>
|
||||||
<li><a href="https://git.georgelambert.org/marchon/verae-fleet">verae-fleet repo</a></li>
|
<li><a href="https://git.georgelambert.org/marchon/verae-fleet">verae-fleet repo</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -108,11 +108,27 @@ export function startControlServer(sup, mon) {
|
||||||
fs.createReadStream(dest).pipe(res);
|
fs.createReadStream(dest).pipe(res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (req.method === 'GET' && url.pathname.startsWith('/docs/screenshots/')) {
|
if (req.method === 'GET' && url.pathname.startsWith('/docs/')) {
|
||||||
const dest = path.normalize(path.join(PUBLIC, '..', url.pathname));
|
const dest = path.normalize(path.join(PUBLIC, '..', url.pathname));
|
||||||
const root = path.normalize(path.join(PUBLIC, '..'));
|
const root = path.normalize(path.join(PUBLIC, '..', 'docs'));
|
||||||
if (!dest.startsWith(root) || !fs.existsSync(dest)) return json(res, 404, { error: 'not found' });
|
if (
|
||||||
res.writeHead(200, { 'content-type': 'image/png' });
|
!(dest === root || dest.startsWith(root + path.sep)) ||
|
||||||
|
!fs.existsSync(dest) ||
|
||||||
|
!fs.statSync(dest).isFile()
|
||||||
|
) {
|
||||||
|
return json(res, 404, { error: 'not found' });
|
||||||
|
}
|
||||||
|
const ext = path.extname(dest).toLowerCase();
|
||||||
|
const types = {
|
||||||
|
'.png': 'image/png',
|
||||||
|
'.jpg': 'image/jpeg',
|
||||||
|
'.jpeg': 'image/jpeg',
|
||||||
|
'.svg': 'image/svg+xml',
|
||||||
|
'.pdf': 'application/pdf',
|
||||||
|
'.md': 'text/markdown; charset=utf-8',
|
||||||
|
'.html': 'text/html; charset=utf-8',
|
||||||
|
};
|
||||||
|
res.writeHead(200, { 'content-type': types[ext] || 'application/octet-stream' });
|
||||||
fs.createReadStream(dest).pipe(res);
|
fs.createReadStream(dest).pipe(res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,30 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Build static documentation site into ./site for zapier.georgelambert.org."""
|
"""Build static documentation site into ./site for zapier.georgelambert.org.
|
||||||
|
|
||||||
|
Markdown is rendered to colored HTML *and* PDF. The home page (index.html)
|
||||||
|
defaults to PDF links; index-md.html is the Markdown/HTML index.
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
SITE = ROOT / "site"
|
SITE = ROOT / "site"
|
||||||
|
CSS = ROOT / "scripts" / "docs-print.css"
|
||||||
|
|
||||||
SECTIONS = [
|
SECTIONS = [
|
||||||
(
|
(
|
||||||
"Start here",
|
"Start here",
|
||||||
[
|
[
|
||||||
|
("packages/overview/README.md", "System overview (plain language)"),
|
||||||
|
("packages/overview/INDEX.md", "Documentation index"),
|
||||||
|
("packages/verae-fleet/docs/CONSOLE.md", "Operator console (Fleet · Trace · Docs)"),
|
||||||
("README.md", "Workspace README"),
|
("README.md", "Workspace README"),
|
||||||
("docs/04-activate/SETUP-ZAPIER-DEVELOPER.html", "Zapier developer setup (HTML)"),
|
|
||||||
("docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf", "Zapier developer setup (PDF)"),
|
("docs/04-activate/SETUP-ZAPIER-DEVELOPER.pdf", "Zapier developer setup (PDF)"),
|
||||||
("docs/OPEN.md", "Still open"),
|
("docs/OPEN.md", "Still open"),
|
||||||
("TODO.md", "Implementation TODO / gates"),
|
("TODO.md", "Implementation TODO / gates"),
|
||||||
|
|
@ -33,8 +41,11 @@ SECTIONS = [
|
||||||
("docs/02-architecture/modules-and-nats.md", "Module catalog and NATS addresses"),
|
("docs/02-architecture/modules-and-nats.md", "Module catalog and NATS addresses"),
|
||||||
("docs/02-architecture/tree-nodes.md", "Tree nodes and bulk Merkle summaries"),
|
("docs/02-architecture/tree-nodes.md", "Tree nodes and bulk Merkle summaries"),
|
||||||
("docs/02-architecture/fleet.md", "Fleet replica floors and monitor"),
|
("docs/02-architecture/fleet.md", "Fleet replica floors and monitor"),
|
||||||
("packages/overview/README.md", "System overview (TOC)"),
|
("packages/overview/03-nats-cluster.md", "NATS.IO 3-server cluster"),
|
||||||
("packages/overview/INDEX.md", "Documentation index"),
|
("packages/overview/04-uptime.md", "Uptime / replica floors"),
|
||||||
|
("packages/overview/05-network-failures.md", "Local network failures"),
|
||||||
|
("packages/overview/06-address-routing.md", "Address routing"),
|
||||||
|
("packages/overview/08-diagrams.md", "Architectural diagrams"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
@ -82,44 +93,162 @@ def copy_tree(src: Path, dest: Path, ignore=None) -> None:
|
||||||
shutil.copytree(src, dest, dirs_exist_ok=True, ignore=ignore)
|
shutil.copytree(src, dest, dirs_exist_ok=True, ignore=ignore)
|
||||||
|
|
||||||
|
|
||||||
def pandoc_md(src: Path, dest: Path, title: str) -> None:
|
def site_href_for(path: str, src: Path) -> tuple[str, str]:
|
||||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
"""Return (pdf_or_native_href, md_or_html_href) relative to SITE."""
|
||||||
css = """
|
suffix = src.suffix.lower()
|
||||||
body{font:16px/1.5 Georgia,serif;max-width:48rem;margin:2rem auto;padding:0 1rem;color:#122}
|
if suffix == ".md":
|
||||||
a{color:#0b4f8a} code,pre{font-family:ui-monospace,Menlo,monospace;font-size:0.88rem}
|
pdf = Path(path).with_suffix(".pdf").as_posix()
|
||||||
pre{background:#1b2833;color:#eef;padding:0.8rem;overflow:auto}
|
html = Path(path).with_suffix(".html").as_posix()
|
||||||
table{border-collapse:collapse} td,th{border:1px solid #ccc;padding:0.35rem 0.5rem}
|
return pdf, html
|
||||||
nav{font:14px system-ui;margin-bottom:1.5rem}
|
return path, path
|
||||||
"""
|
|
||||||
header = dest.with_suffix(".hdr.html")
|
|
||||||
header.write_text(
|
def render_md(src: Path, html_dest: Path, pdf_dest: Path, title: str) -> str:
|
||||||
f"<nav><a href=\"/\">zapier.georgelambert.org</a></nav>\n<style>{css}</style>\n",
|
"""Pandoc markdown → colored HTML + WeasyPrint PDF. Returns '' on success."""
|
||||||
|
html_dest.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
pdf_dest.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
header = html_dest.with_suffix(".hdr.html")
|
||||||
|
banner = html_dest.with_suffix(".ban.html")
|
||||||
|
rel_src = src.relative_to(ROOT).as_posix() if src.is_relative_to(ROOT) else src.name
|
||||||
|
css_text = CSS.read_text(encoding="utf-8")
|
||||||
|
header.write_text(f"<style>{css_text}</style>\n", encoding="utf-8")
|
||||||
|
banner.write_text(
|
||||||
|
f'<div class="doc-banner">'
|
||||||
|
f'<nav class="site"><a href="/">zapier.georgelambert.org</a>'
|
||||||
|
f' · <a href="/index-md.html">Markdown indexes</a></nav>'
|
||||||
|
f'<div class="kicker">Verae Time × Zapier</div>'
|
||||||
|
f"<h1>{title}</h1>"
|
||||||
|
f'<div class="source-path">{rel_src}</div>'
|
||||||
|
f"</div>\n",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
subprocess.run(
|
resource = str(src.parent)
|
||||||
|
r = subprocess.run(
|
||||||
[
|
[
|
||||||
"pandoc",
|
"pandoc",
|
||||||
str(src),
|
str(src),
|
||||||
"-o",
|
"-o",
|
||||||
str(dest),
|
str(html_dest),
|
||||||
"--standalone",
|
"--standalone",
|
||||||
|
f"--resource-path={resource}",
|
||||||
|
"--highlight-style=breezedark",
|
||||||
f"--metadata=title={title}",
|
f"--metadata=title={title}",
|
||||||
f"--include-in-header={header}",
|
f"--include-in-header={header}",
|
||||||
|
f"--include-before-body={banner}",
|
||||||
],
|
],
|
||||||
check=False,
|
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
)
|
)
|
||||||
header.unlink(missing_ok=True)
|
header.unlink(missing_ok=True)
|
||||||
|
banner.unlink(missing_ok=True)
|
||||||
|
if r.returncode != 0:
|
||||||
|
return f"pandoc {src}: {r.stderr[-400:]}"
|
||||||
|
w = subprocess.run(
|
||||||
|
["weasyprint", str(html_dest), str(pdf_dest)],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
if w.returncode != 0:
|
||||||
|
return f"weasyprint {src}: {w.stderr[-400:]}"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def walk_md_pdf(prefix: Path) -> list[tuple[str, str]]:
|
def convert_all_markdown(copied: list[tuple[Path, Path, str]]) -> list[str]:
|
||||||
items = []
|
errors = []
|
||||||
if not prefix.exists():
|
n = len(copied)
|
||||||
return items
|
print(f"rendering {n} markdown files to HTML + PDF…")
|
||||||
for p in sorted(prefix.rglob("*")):
|
with ThreadPoolExecutor(max_workers=6) as pool:
|
||||||
if p.suffix.lower() in {".md", ".pdf", ".html", ".yaml", ".yml", ".svg"} and p.is_file():
|
futs = {
|
||||||
items.append((rel(p), p.name))
|
pool.submit(render_md, src, html, pdf, title): src
|
||||||
return items
|
for src, html, pdf, title in (
|
||||||
|
(
|
||||||
|
src,
|
||||||
|
dest.with_suffix(".html"),
|
||||||
|
dest.with_suffix(".pdf"),
|
||||||
|
title,
|
||||||
|
)
|
||||||
|
for src, dest, title in copied
|
||||||
|
)
|
||||||
|
}
|
||||||
|
done = 0
|
||||||
|
for fut in as_completed(futs):
|
||||||
|
err = fut.result()
|
||||||
|
done += 1
|
||||||
|
if err:
|
||||||
|
errors.append(err)
|
||||||
|
print(f" [{done}/{n}] FAIL {futs[fut].name}")
|
||||||
|
elif done % 25 == 0 or done == n:
|
||||||
|
print(f" [{done}/{n}]")
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def format_switch(to_md: bool) -> str:
|
||||||
|
if to_md:
|
||||||
|
href, label = "/index-md.html", "Markdown indexes"
|
||||||
|
else:
|
||||||
|
href, label = "/", "PDF catalog"
|
||||||
|
return (
|
||||||
|
f'<a class="format-switch" href="{href}">{label}</a>'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def page_shell(now: str, body: str, switch_to_md: bool, title: str) -> str:
|
||||||
|
switch = format_switch(switch_to_md)
|
||||||
|
return f"""<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
<title>{title}</title>
|
||||||
|
<style>
|
||||||
|
:root {{ --ink:#171a26; --muted:#5b6178; --line:#d9dce8; --bg:#f4f5fb; --accent:#4f46e5; --accent-deep:#312e81; --soft:#eef0fe; }}
|
||||||
|
body {{ margin:0; font:16px/1.5 Georgia, serif; color:var(--ink); background:var(--bg); }}
|
||||||
|
header {{ background:linear-gradient(160deg,#312e81 0%,#4f46e5 60%,#7c74f0 100%); color:#eef0fe; padding:2rem 1.5rem 1.4rem; position:relative; }}
|
||||||
|
header p {{ max-width:44rem; color:#e4e7ff; }}
|
||||||
|
.kicker {{ letter-spacing:.12em; text-transform:uppercase; font:700 11px system-ui; opacity:.75; }}
|
||||||
|
.format-switch {{
|
||||||
|
position:absolute; top:1.25rem; right:1.5rem;
|
||||||
|
font:650 13px system-ui, sans-serif; color:#fff; text-decoration:none;
|
||||||
|
background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.35);
|
||||||
|
padding:.4rem .75rem; border-radius:999px;
|
||||||
|
}}
|
||||||
|
.format-switch:hover {{ background:rgba(255,255,255,.28); }}
|
||||||
|
main {{ max-width:52rem; margin:0 auto; padding:1.5rem 1.25rem 3rem; }}
|
||||||
|
h1 {{ margin:.4rem 0 .6rem; font-size:1.85rem; }}
|
||||||
|
h2 {{ border-top:1px solid var(--line); padding-top:.8rem; margin-top:1.8rem; color:var(--accent-deep); }}
|
||||||
|
ul {{ padding-left:1.2rem; }}
|
||||||
|
li {{ margin:.35rem 0; }}
|
||||||
|
a {{ color:var(--accent); }}
|
||||||
|
.path {{ color:var(--muted); font:12px ui-monospace, Menlo, monospace; margin-left:.4rem; }}
|
||||||
|
.badge {{ font:700 10px system-ui; letter-spacing:.04em; text-transform:uppercase;
|
||||||
|
background:var(--soft); color:var(--accent); padding:.1rem .35rem; border-radius:4px; margin-left:.25rem; }}
|
||||||
|
input {{ width:100%; padding:.55rem .7rem; font:16px system-ui; border:1px solid var(--line); border-radius:6px; }}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
{switch}
|
||||||
|
<div class="kicker">zapier.georgelambert.org</div>
|
||||||
|
<h1>Verae Time × Zapier documentation</h1>
|
||||||
|
<p>Project reference: setup, architecture, NATS, module APIs, user guide, and operator console.
|
||||||
|
Catalog defaults to <strong>colored PDFs</strong>. Generated {now}.</p>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<p><input id="q" type="search" placeholder="Filter links…" /></p>
|
||||||
|
{body}
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
const q = document.getElementById('q');
|
||||||
|
q.addEventListener('input', () => {{
|
||||||
|
const v = q.value.toLowerCase();
|
||||||
|
document.querySelectorAll('li').forEach(li => {{
|
||||||
|
li.style.display = li.textContent.toLowerCase().includes(v) ? '' : 'none';
|
||||||
|
}});
|
||||||
|
}});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|
@ -147,12 +276,37 @@ def main() -> None:
|
||||||
"verae-nats-process",
|
"verae-nats-process",
|
||||||
"docs-master",
|
"docs-master",
|
||||||
):
|
):
|
||||||
readme = ROOT / "packages" / pkg / "README.md"
|
pkg_root = ROOT / "packages" / pkg
|
||||||
if readme.exists():
|
if pkg in {"zapier-user-docs", "overview", "docs-master"}:
|
||||||
copy_tree(readme, SITE / "packages" / pkg / "README.md")
|
copy_tree(
|
||||||
|
pkg_root,
|
||||||
|
SITE / "packages" / pkg,
|
||||||
|
ignore=shutil.ignore_patterns("node_modules", ".git", "src", "test", "data"),
|
||||||
|
)
|
||||||
|
elif pkg == "verae-fleet":
|
||||||
|
for name in ("README.md", "SUMMARY.md", "NATS.md", "SERVICES.md"):
|
||||||
|
p = pkg_root / name
|
||||||
|
if p.exists():
|
||||||
|
copy_tree(p, SITE / "packages" / pkg / name)
|
||||||
|
copy_tree(
|
||||||
|
pkg_root / "docs",
|
||||||
|
SITE / "packages" / pkg / "docs",
|
||||||
|
ignore=shutil.ignore_patterns("node_modules"),
|
||||||
|
)
|
||||||
|
elif pkg == "verae-nats-process":
|
||||||
|
for p in pkg_root.glob("*.md"):
|
||||||
|
copy_tree(p, SITE / "packages" / pkg / p.name)
|
||||||
|
else:
|
||||||
|
readme = pkg_root / "README.md"
|
||||||
|
if readme.exists():
|
||||||
|
copy_tree(readme, SITE / "packages" / pkg / "README.md")
|
||||||
zdocs = ROOT / "packages" / "zappier" / "docs"
|
zdocs = ROOT / "packages" / "zappier" / "docs"
|
||||||
if zdocs.exists():
|
if zdocs.exists():
|
||||||
copy_tree(zdocs, SITE / "packages" / "zappier" / "docs", ignore=shutil.ignore_patterns("screenshots", "walkthrough", "superpowers"))
|
copy_tree(
|
||||||
|
zdocs,
|
||||||
|
SITE / "packages" / "zappier" / "docs",
|
||||||
|
ignore=shutil.ignore_patterns("screenshots", "walkthrough", "superpowers"),
|
||||||
|
)
|
||||||
for name in ("README.md", "TODO.md", "OPEN.md"):
|
for name in ("README.md", "TODO.md", "OPEN.md"):
|
||||||
src = ROOT / name
|
src = ROOT / name
|
||||||
if not src.exists() and name == "OPEN.md":
|
if not src.exists() and name == "OPEN.md":
|
||||||
|
|
@ -163,11 +317,15 @@ def main() -> None:
|
||||||
copy_tree(ROOT / "packages" / "docs-master", SITE / "docs-master")
|
copy_tree(ROOT / "packages" / "docs-master", SITE / "docs-master")
|
||||||
copy_tree(ROOT / "packages" / "overview", SITE / "overview")
|
copy_tree(ROOT / "packages" / "overview", SITE / "overview")
|
||||||
copy_tree(ROOT / "packages" / "zapier-user-docs", SITE / "user-docs", ignore=shutil.ignore_patterns("node_modules"))
|
copy_tree(ROOT / "packages" / "zapier-user-docs", SITE / "user-docs", ignore=shutil.ignore_patterns("node_modules"))
|
||||||
|
copy_tree(
|
||||||
|
ROOT / "packages" / "verae-fleet" / "docs",
|
||||||
|
SITE / "packages" / "verae-fleet" / "docs",
|
||||||
|
ignore=shutil.ignore_patterns("node_modules"),
|
||||||
|
)
|
||||||
sim_pub = ROOT / "packages" / "verae-zapier-simulator" / "public" / "index.html"
|
sim_pub = ROOT / "packages" / "verae-zapier-simulator" / "public" / "index.html"
|
||||||
if sim_pub.exists():
|
if sim_pub.exists():
|
||||||
copy_tree(sim_pub, SITE / "simulator" / "index.html")
|
copy_tree(sim_pub, SITE / "simulator" / "index.html")
|
||||||
|
|
||||||
# research markdown + diagrams only
|
|
||||||
r = ROOT / "research" / "zapier"
|
r = ROOT / "research" / "zapier"
|
||||||
if r.exists():
|
if r.exists():
|
||||||
for fname in (
|
for fname in (
|
||||||
|
|
@ -186,45 +344,73 @@ def main() -> None:
|
||||||
if diagrams.exists():
|
if diagrams.exists():
|
||||||
copy_tree(diagrams, SITE / "research" / "docs" / "diagrams")
|
copy_tree(diagrams, SITE / "research" / "docs" / "diagrams")
|
||||||
|
|
||||||
# HTML versions of markdown for the catalog entries
|
# Render every published .md from the site copy so relative images resolve.
|
||||||
html_pairs = []
|
to_render: list[tuple[Path, Path, str]] = []
|
||||||
for _title, links in SECTIONS:
|
seen: set[Path] = set()
|
||||||
|
for md in SITE.rglob("*.md"):
|
||||||
|
if not md.is_file():
|
||||||
|
continue
|
||||||
|
key = md.resolve()
|
||||||
|
if key in seen:
|
||||||
|
continue
|
||||||
|
seen.add(key)
|
||||||
|
to_render.append((md, md, md.stem.replace("-", " ")))
|
||||||
|
|
||||||
|
# Prefer curated titles for catalog entries
|
||||||
|
title_map = {}
|
||||||
|
for _sec, links in SECTIONS:
|
||||||
for path, label in links:
|
for path, label in links:
|
||||||
src = ROOT / path
|
title_map[path] = label
|
||||||
if src.suffix == ".md" and src.exists():
|
labeled = []
|
||||||
dest = SITE / Path(path).with_suffix(".html")
|
for src, dest, title in to_render:
|
||||||
pandoc_md(src, dest, label)
|
try:
|
||||||
html_pairs.append((path, dest.relative_to(SITE).as_posix(), label))
|
key = dest.relative_to(SITE).as_posix()
|
||||||
|
except ValueError:
|
||||||
|
key = dest.name
|
||||||
|
# packages/overview/... also listed as packages/overview
|
||||||
|
labeled.append((src, dest, title_map.get(key, title_map.get(src.relative_to(ROOT).as_posix() if src.is_relative_to(ROOT) else key, title))))
|
||||||
|
|
||||||
|
errors = convert_all_markdown(labeled)
|
||||||
|
|
||||||
|
# Also write CONSOLE.pdf next to the markdown in the fleet package (local console)
|
||||||
|
console_md = ROOT / "packages" / "verae-fleet" / "docs" / "CONSOLE.md"
|
||||||
|
if console_md.exists():
|
||||||
|
err = render_md(
|
||||||
|
console_md,
|
||||||
|
ROOT / "packages" / "verae-fleet" / "docs" / "CONSOLE.html",
|
||||||
|
ROOT / "packages" / "verae-fleet" / "docs" / "CONSOLE.pdf",
|
||||||
|
"Operator console",
|
||||||
|
)
|
||||||
|
if err:
|
||||||
|
errors.append(err)
|
||||||
|
|
||||||
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
||||||
cards = []
|
|
||||||
for title, links in SECTIONS:
|
|
||||||
lis = []
|
|
||||||
for path, label in links:
|
|
||||||
src = ROOT / path
|
|
||||||
if not src.exists() and path == "OPEN.md":
|
|
||||||
src = ROOT / "docs" / "OPEN.md"
|
|
||||||
path = "docs/OPEN.md"
|
|
||||||
if not src.exists():
|
|
||||||
continue
|
|
||||||
href = path
|
|
||||||
html = Path(path).with_suffix(".html").as_posix()
|
|
||||||
if src.suffix == ".md" and (SITE / html).exists():
|
|
||||||
href = html
|
|
||||||
lis.append(f'<li><a href="{href}">{label}</a> <span class="path">{path}</span></li>')
|
|
||||||
cards.append(f"<section><h2>{title}</h2><ul>{''.join(lis)}</ul></section>")
|
|
||||||
|
|
||||||
extra = [
|
def cards(mode: str) -> str:
|
||||||
("docs/modules/README.md", "Module API sheets"),
|
out = []
|
||||||
("docs/models/README.md", "Data models"),
|
for title, links in SECTIONS:
|
||||||
("sphinx/index.html", "Sphinx HTML"),
|
lis = []
|
||||||
("docs/04-activate/SETUP-ZAPIER-DEVELOPER.html", "Setup HTML"),
|
for path, label in links:
|
||||||
("docs-master/README.md", "Master summaries (docs-master)"),
|
src = ROOT / path
|
||||||
("docs-master/MESSAGE-FLOWS.md", "Numbered message flows"),
|
if not src.exists() and path == "OPEN.md":
|
||||||
("docs-master/modules-and-nats.md", "NATS address table"),
|
src = ROOT / "docs" / "OPEN.md"
|
||||||
("user-docs/README.md", "User guide index"),
|
path = "docs/OPEN.md"
|
||||||
("packages/verae-zapier-simulator/README.md", "Simulator README"),
|
if not src.exists():
|
||||||
]
|
continue
|
||||||
|
pdf_href, html_href = site_href_for(path, src)
|
||||||
|
if mode == "pdf":
|
||||||
|
href = pdf_href if (SITE / pdf_href).exists() or src.suffix.lower() in {".pdf", ".yaml", ".yml"} else html_href
|
||||||
|
badge = "PDF" if href.endswith(".pdf") else src.suffix.lstrip(".").upper() or "FILE"
|
||||||
|
else:
|
||||||
|
href = html_href if (SITE / html_href).exists() else path
|
||||||
|
badge = "MD" if src.suffix.lower() == ".md" else src.suffix.lstrip(".").upper() or "FILE"
|
||||||
|
lis.append(
|
||||||
|
f'<li><a href="{href}">{label}</a>'
|
||||||
|
f'<span class="badge">{badge}</span>'
|
||||||
|
f'<span class="path">{path}</span></li>'
|
||||||
|
)
|
||||||
|
out.append(f"<section><h2>{title}</h2><ul>{''.join(lis)}</ul></section>")
|
||||||
|
return "".join(out)
|
||||||
|
|
||||||
git_repos = [
|
git_repos = [
|
||||||
("master-zapier-plan-draft", "Monorepo (this workspace)"),
|
("master-zapier-plan-draft", "Monorepo (this workspace)"),
|
||||||
|
|
@ -248,41 +434,44 @@ def main() -> None:
|
||||||
f'<span class="path">{desc}</span></li>'
|
f'<span class="path">{desc}</span></li>'
|
||||||
for name, desc in git_repos
|
for name, desc in git_repos
|
||||||
)
|
)
|
||||||
extra_lis = "".join(
|
|
||||||
f'<li><a href="{h}">{lab}</a></li>' for h, lab in extra if (SITE / h).exists() or h.startswith("sphinx")
|
|
||||||
)
|
|
||||||
|
|
||||||
index = f"""<!DOCTYPE html>
|
extra_pdf = [
|
||||||
<html lang="en">
|
("docs-master/README.pdf", "Master summaries (docs-master)"),
|
||||||
<head>
|
("docs-master/MESSAGE-FLOWS.pdf", "Numbered message flows"),
|
||||||
<meta charset="utf-8"/>
|
("docs-master/modules-and-nats.pdf", "NATS address table"),
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
("user-docs/README.pdf", "User guide index"),
|
||||||
<title>Verae Time × Zapier documentation</title>
|
("packages/verae-zapier-simulator/README.pdf", "Simulator README"),
|
||||||
<style>
|
("packages/verae-fleet/docs/CONSOLE.pdf", "Operator console"),
|
||||||
:root {{ --ink:#12202c; --muted:#52646f; --line:#d5dee4; --bg:#f6f3ee; --accent:#0f6e56; }}
|
("overview/README.pdf", "System overview"),
|
||||||
body {{ margin:0; font:16px/1.5 Georgia, serif; color:var(--ink); background:var(--bg); }}
|
("overview/INDEX.pdf", "Documentation index"),
|
||||||
header {{ background:var(--ink); color:#f6f3ee; padding:2rem 1.5rem; }}
|
("docs/modules-pdf/", "Module PDFs (book)"),
|
||||||
header p {{ max-width:44rem; color:#d9e2e8; }}
|
("docs/models-pdf/", "Model PDFs (book)"),
|
||||||
.kicker {{ letter-spacing:.12em; text-transform:uppercase; font:700 11px system-ui; opacity:.75; }}
|
("sphinx/index.html", "Sphinx HTML"),
|
||||||
main {{ max-width:52rem; margin:0 auto; padding:1.5rem 1.25rem 3rem; }}
|
]
|
||||||
h1 {{ margin:.4rem 0 .6rem; font-size:1.85rem; }}
|
extra_md = [
|
||||||
h2 {{ border-top:1px solid var(--line); padding-top:.8rem; margin-top:1.8rem; }}
|
("docs-master/README.html", "Master summaries (docs-master)"),
|
||||||
ul {{ padding-left:1.2rem; }}
|
("docs-master/MESSAGE-FLOWS.html", "Numbered message flows"),
|
||||||
li {{ margin:.35rem 0; }}
|
("docs-master/modules-and-nats.html", "NATS address table"),
|
||||||
a {{ color:#0b4f8a; }}
|
("user-docs/README.html", "User guide index"),
|
||||||
.path {{ color:var(--muted); font:12px ui-monospace, Menlo, monospace; margin-left:.4rem; }}
|
("packages/verae-zapier-simulator/README.html", "Simulator README"),
|
||||||
input {{ width:100%; padding:.55rem .7rem; font:16px system-ui; border:1px solid var(--line); border-radius:6px; }}
|
("packages/verae-fleet/docs/CONSOLE.html", "Operator console"),
|
||||||
</style>
|
("overview/README.html", "System overview"),
|
||||||
</head>
|
("overview/INDEX.html", "Documentation index"),
|
||||||
<body>
|
("docs/modules/", "All module markdown"),
|
||||||
<header>
|
("docs/models/", "All model markdown"),
|
||||||
<div class="kicker">zapier.georgelambert.org</div>
|
("sphinx/index.html", "Sphinx HTML"),
|
||||||
<h1>Verae Time × Zapier documentation</h1>
|
]
|
||||||
<p>Project reference: setup checklist, architecture (including NATS job wait and WORM archive fan-out), module API sheets, models, OpenAPI, and research notes. Generated {now}.</p>
|
|
||||||
</header>
|
def extra_section(items: list[tuple[str, str]]) -> str:
|
||||||
<main>
|
lis = "".join(
|
||||||
<p><input id="q" type="search" placeholder="Filter links…" /></p>
|
f'<li><a href="{h}">{lab}</a></li>'
|
||||||
{''.join(cards)}
|
for h, lab in items
|
||||||
|
if (SITE / h).exists() or h.endswith("/") or h.startswith("sphinx")
|
||||||
|
)
|
||||||
|
return f"<section><h2>Catalogs</h2><ul>{lis}</ul></section>"
|
||||||
|
|
||||||
|
rest_pdf = f"""
|
||||||
|
{cards("pdf")}
|
||||||
<section>
|
<section>
|
||||||
<h2>Git repositories (Forgejo)</h2>
|
<h2>Git repositories (Forgejo)</h2>
|
||||||
<p>Clone: <code>ssh://git@git.georgelambert.org:2223/marchon/<name>.git</code> (SSH port 2223). Branches <code>main</code> and <code>master</code>.</p>
|
<p>Clone: <code>ssh://git@git.georgelambert.org:2223/marchon/<name>.git</code> (SSH port 2223). Branches <code>main</code> and <code>master</code>.</p>
|
||||||
|
|
@ -291,43 +480,62 @@ def main() -> None:
|
||||||
<section>
|
<section>
|
||||||
<h2>Master module docs</h2>
|
<h2>Master module docs</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="docs-master/README.md">docs-master README</a></li>
|
<li><a href="docs-master/README.pdf">docs-master README</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="docs-master/MESSAGE-FLOWS.md">MESSAGE-FLOWS.md</a></li>
|
<li><a href="docs-master/MESSAGE-FLOWS.pdf">MESSAGE-FLOWS</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="docs-master/modules-and-nats.md">modules-and-nats.md</a></li>
|
<li><a href="docs-master/modules-and-nats.pdf">modules-and-nats</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="docs-master/archive-nats.md">archive-nats.md</a></li>
|
<li><a href="docs-master/archive-nats.pdf">archive-nats</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="docs-master/composition.md">composition.md</a></li>
|
<li><a href="docs-master/composition.pdf">composition</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="docs-master/modules/">Per-module SUMMARY.md and NATS.md</a></li>
|
<li><a href="user-docs/README.pdf">User guide (signup → tree-node lookup)</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="user-docs/README.md">User guide (signup → tree-node lookup)</a></li>
|
<li><a href="packages/verae-zapier-simulator/README.pdf">Simulator README</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="packages/verae-zapier-simulator/README.md">Simulator README</a></li>
|
<li><a href="overview/README.pdf">System overview</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="overview/README.md">System overview</a></li>
|
<li><a href="overview/INDEX.pdf">Documentation index</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="overview/INDEX.md">Documentation index</a></li>
|
<li><a href="packages/verae-fleet/docs/CONSOLE.pdf">Operator console</a><span class="badge">PDF</span></li>
|
||||||
<li><a href="overview/diagrams/system.svg">System diagram (SVG)</a></li>
|
<li><a href="overview/diagrams/system.svg">System diagram (SVG)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
{extra_section(extra_pdf)}
|
||||||
|
"""
|
||||||
|
rest_md = f"""
|
||||||
|
{cards("md")}
|
||||||
<section>
|
<section>
|
||||||
<h2>Catalogs</h2>
|
<h2>Git repositories (Forgejo)</h2>
|
||||||
<ul>{extra_lis}
|
<p>Clone: <code>ssh://git@git.georgelambert.org:2223/marchon/<name>.git</code> (SSH port 2223).</p>
|
||||||
<li><a href="docs/modules/">All module markdown</a></li>
|
<ul>{git_lis}</ul>
|
||||||
<li><a href="docs/models/">All model markdown</a></li>
|
</section>
|
||||||
<li><a href="docs/modules-pdf/">Module PDFs</a></li>
|
<section>
|
||||||
<li><a href="docs/models-pdf/">Model PDFs</a></li>
|
<h2>Master module docs (HTML / Markdown)</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="docs-master/README.html">docs-master README</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="docs-master/MESSAGE-FLOWS.html">MESSAGE-FLOWS</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="docs-master/modules-and-nats.html">modules-and-nats</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="docs-master/archive-nats.md">archive-nats.md</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="docs-master/composition.md">composition.md</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="user-docs/README.html">User guide</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="packages/verae-zapier-simulator/README.html">Simulator README</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="overview/README.html">System overview</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="overview/INDEX.html">Documentation index</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="packages/verae-fleet/docs/CONSOLE.html">Operator console</a><span class="badge">MD</span></li>
|
||||||
|
<li><a href="overview/diagrams/system.svg">System diagram (SVG)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
{extra_section(extra_md)}
|
||||||
<script>
|
|
||||||
const q = document.getElementById('q');
|
|
||||||
q.addEventListener('input', () => {{
|
|
||||||
const v = q.value.toLowerCase();
|
|
||||||
document.querySelectorAll('li').forEach(li => {{
|
|
||||||
li.style.display = li.textContent.toLowerCase().includes(v) ? '' : 'none';
|
|
||||||
}});
|
|
||||||
}});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
"""
|
||||||
(SITE / "index.html").write_text(index, encoding="utf-8")
|
|
||||||
print(f"site built at {SITE} ({sum(1 for _ in SITE.rglob('*') if _.is_file())} files)")
|
(SITE / "index.html").write_text(
|
||||||
|
page_shell(now, rest_pdf, switch_to_md=True, title="Verae Time × Zapier documentation"),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
(SITE / "index-md.html").write_text(
|
||||||
|
page_shell(now, rest_md, switch_to_md=False, title="Verae Time × Zapier — Markdown indexes"),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
nfiles = sum(1 for _ in SITE.rglob("*") if _.is_file())
|
||||||
|
npdf = sum(1 for _ in SITE.rglob("*.pdf") if _.is_file())
|
||||||
|
print(f"site built at {SITE} ({nfiles} files, {npdf} PDFs)")
|
||||||
|
if errors:
|
||||||
|
print(f"{len(errors)} render errors:")
|
||||||
|
for e in errors[:20]:
|
||||||
|
print(" ", e[:300])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
122
scripts/docs-print.css
Normal file
122
scripts/docs-print.css
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* Colored print + screen stylesheet for zapier.georgelambert.org */
|
||||||
|
:root {
|
||||||
|
--ink: #171a26;
|
||||||
|
--muted: #5b6178;
|
||||||
|
--line: #d9dce8;
|
||||||
|
--bg: #f4f5fb;
|
||||||
|
--paper: #ffffff;
|
||||||
|
--accent: #4f46e5;
|
||||||
|
--accent-deep: #312e81;
|
||||||
|
--accent-soft: #eef0fe;
|
||||||
|
--ok: #047857;
|
||||||
|
--warn: #8a5a00;
|
||||||
|
--code-bg: #1b1f33;
|
||||||
|
--code-fg: #e8ecff;
|
||||||
|
}
|
||||||
|
html { background: var(--bg); }
|
||||||
|
body {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1.5rem 1.25rem 3rem;
|
||||||
|
max-width: 48rem;
|
||||||
|
font: 15px/1.55 -apple-system, "Segoe UI", Georgia, serif;
|
||||||
|
color: var(--ink);
|
||||||
|
background: var(--paper);
|
||||||
|
}
|
||||||
|
.doc-banner {
|
||||||
|
background: linear-gradient(160deg, #312e81 0%, #4f46e5 60%, #7c74f0 100%);
|
||||||
|
color: #eef0fe;
|
||||||
|
margin: -1.5rem -1.25rem 1.5rem;
|
||||||
|
padding: 1.1rem 1.25rem 1rem;
|
||||||
|
}
|
||||||
|
.doc-banner a { color: #fff; }
|
||||||
|
.doc-banner .kicker {
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font: 700 10px system-ui, sans-serif;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.doc-banner h1 { margin: 0.25rem 0 0; font-size: 1.45rem; color: #fff; }
|
||||||
|
h1, h2, h3, h4 { color: var(--accent-deep); page-break-after: avoid; }
|
||||||
|
h1 { font-size: 1.7rem; }
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
border-bottom: 2px solid var(--accent);
|
||||||
|
padding-bottom: 0.2rem;
|
||||||
|
margin-top: 1.6rem;
|
||||||
|
}
|
||||||
|
h3 { font-size: 1.05rem; color: var(--accent); }
|
||||||
|
a { color: var(--accent); }
|
||||||
|
p, li { orphans: 3; widows: 3; }
|
||||||
|
code {
|
||||||
|
font-family: ui-monospace, Menlo, Consolas, monospace;
|
||||||
|
font-size: 0.86em;
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--accent-deep);
|
||||||
|
padding: 0.08em 0.28em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
pre, div.sourceCode, div.sourceCode pre {
|
||||||
|
background: var(--code-bg) !important;
|
||||||
|
color: var(--code-fg) !important;
|
||||||
|
padding: 0.85rem 1rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: auto;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
pre code { background: transparent; color: inherit; padding: 0; }
|
||||||
|
#title-block-header, header#title-block-header, h1.title { display: none; }
|
||||||
|
.doc-banner + h1 { display: none; }
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0.8rem 0 1.2rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
th, td { border: 1px solid var(--line); padding: 0.38rem 0.55rem; text-align: left; vertical-align: top; }
|
||||||
|
th {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
font: 650 12px system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
tr:nth-child(even) td { background: var(--accent-soft); }
|
||||||
|
blockquote {
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding: 0.4rem 0.9rem;
|
||||||
|
border-left: 4px solid var(--accent);
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--accent-deep);
|
||||||
|
}
|
||||||
|
img { max-width: 100%; height: auto; border-radius: 8px; page-break-inside: avoid; }
|
||||||
|
hr { border: 0; border-top: 1px solid var(--line); }
|
||||||
|
ul, ol { padding-left: 1.25rem; }
|
||||||
|
nav.site { font: 13px system-ui, sans-serif; margin-bottom: 0.4rem; }
|
||||||
|
.source-path { font: 11px ui-monospace, Menlo, monospace; color: var(--muted); }
|
||||||
|
|
||||||
|
@page {
|
||||||
|
size: letter;
|
||||||
|
margin: 0.65in 0.7in 0.8in 0.7in;
|
||||||
|
@top-left {
|
||||||
|
content: "Verae Time × Zapier";
|
||||||
|
font: 700 8pt system-ui, sans-serif;
|
||||||
|
color: #4f46e5;
|
||||||
|
}
|
||||||
|
@top-right {
|
||||||
|
content: "zapier.georgelambert.org";
|
||||||
|
font: 8pt system-ui, sans-serif;
|
||||||
|
color: #6b7186;
|
||||||
|
}
|
||||||
|
@bottom-center {
|
||||||
|
content: counter(page) " / " counter(pages);
|
||||||
|
font: 8pt system-ui, sans-serif;
|
||||||
|
color: #6b7186;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
html, body { background: #fff; max-width: none; padding: 0; }
|
||||||
|
.doc-banner { margin: 0 0 1rem; border-radius: 8px; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||||
|
a { text-decoration: none; }
|
||||||
|
th, tr:nth-child(even) td, pre, blockquote, code { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue