6.9 KiB
6.9 KiB
Operation Undigg — Architecture
Document-first platform: every namespace is a book, every thread is a chapter, every reply is a section. Pandoc renders 67 output formats.
Data Flow — Write Path
digraph write_path {
rankdir=LR
node [shape=box, style=rounded, fontname="sans-serif"]
edge [fontname="sans-serif", fontsize=10]
input [label="User Input\n(md, html, rst,\nmediawiki, latex,\ntextile, org, ...)", shape=note]
source_fmt [label="source_format\ndetection", shape=diamond]
pandoc_html [label="pandoc\nconvert to html5"]
pandoc_roundtrip [label="pandoc\nhtml → markdown\n(round-trip clean)"]
bleach [label="bleach\nsanitize"]
data [label="Node.data\n(raw source)", shape=cylinder]
data_html [label="Node.data_html\n(rendered)", shape=cylinder]
source_col [label="Node.source_format", shape=cylinder]
input -> source_fmt
source_fmt -> pandoc_html [label="rst, mediawiki,\nlatex, etc."]
source_fmt -> pandoc_roundtrip [label="html input"]
source_fmt -> data [label="markdown\n(direct)"]
pandoc_roundtrip -> data [label="cleaned md"]
pandoc_html -> bleach
bleach -> data_html
input -> source_col [style=dashed, label="store format"]
data -> data_html [label="markdown_to_html\n(for md input)", style=dashed]
}
Data Flow — Read / Export Path
digraph read_path {
rankdir=LR
node [shape=box, style=rounded, fontname="sans-serif"]
edge [fontname="sans-serif", fontsize=10]
tree [label="Node tree\n(adjacency list)", shape=cylinder]
renderer [label="tree-to-markdown\nrenderer"]
pandoc [label="pandoc\nconvert to\ntarget format"]
output [label="Output\n(pdf, epub, docx,\nhtml, rst, ...)", shape=note]
tree -> renderer
renderer -> pandoc [label="markdown\ndocument"]
pandoc -> output
subgraph cluster_heading_map {
label="Heading depth mapping"
style=dashed
fontname="sans-serif"
h1 [label="# Thread Title (h1)", shape=plaintext]
h2 [label="## Author Name (h2, reply)", shape=plaintext]
h3 [label="### Author Name (h3, nested)", shape=plaintext]
}
}
Export Hierarchy
digraph export_hierarchy {
rankdir=TB
node [shape=box, style=rounded, fontname="sans-serif"]
edge [fontname="sans-serif", fontsize=10]
ns [label="Namespace (book)\n/export/namespace/{name}.{fmt}"]
rootA [label="Root Node A (chapter)\n/export/threads/{id}.{fmt}"]
rootB [label="Root Node B (chapter)\n/export/threads/{id}.{fmt}"]
reply1 [label="Reply 1 (section)\n/export/nodes/{id}.{fmt}"]
reply2 [label="Reply 2 (section)\n/export/nodes/{id}.{fmt}"]
reply1_1 [label="Reply 1.1 (subsection)\n/export/nodes/{id}.{fmt}"]
ns -> rootA [label="default"]
ns -> rootB [label="default"]
rootA -> reply1 [label="on-demand"]
rootA -> reply2 [label="on-demand"]
reply1 -> reply1_1 [label="on-demand"]
}
67 output formats including: markdown, html5, pdf, epub, docx, odt, rst, latex, mediawiki, man, plain, rtf, asciidoc, textile, org, json, and more.
Wiki Mode
digraph wiki_mode {
rankdir=TB
node [shape=record, fontname="sans-serif"]
edge [fontname="sans-serif", fontsize=10]
rb_node [label="{rb_node|id\ldata\ldata_html\lsource_format\l}"]
rb_revision [label="{rb_revision|id\lnode_id (FK)\luser_id (FK)\ldata\lsource_format\lrevision_number\lcreated\l}"]
wiki_edit [label="wiki_edit()", shape=ellipse]
check [label="can_wiki_edit(node, user)?", shape=diamond]
rb_node -> wiki_edit [label="called on node"]
wiki_edit -> rb_revision [label="1. snapshot\ncurrent data"]
wiki_edit -> rb_node [label="3. overwrite\nwith new content", style=dashed]
check -> wiki_edit [label="allowed"]
subgraph cluster_perms {
label="Permission checks"
style=dashed
fontname="sans-serif"
node [shape=plaintext]
p1 [label="user.authenticated → required"]
p2 [label="namespace.can_alter_node() → owner/moderator always yes"]
p3 [label="namespace.wiki && node.is_root → wiki mode for root nodes"]
}
check -> p1 [style=invis]
}
Auto-Generated Themes
digraph themes {
rankdir=TB
node [shape=box, style=rounded, fontname="sans-serif"]
edge [fontname="sans-serif", fontsize=10]
name [label="namespace_name", shape=plaintext]
sha [label="SHA-256 hash"]
hue [label="hue (0-360)\nbits[0:8]"]
seeds [label="8 seed values\nbits[8:40]"]
palette [label="HSL color palette"]
light [label="Light mode\n:root, .theme-light\n--rb-bg, --rb-text,\n--rb-link, --rb-accent,\n--rb-border, ...", shape=note]
dark [label="Dark mode\n@media prefers-color-scheme: dark\n.theme-dark\n--rb-bg, --rb-text,\n--rb-link, --rb-accent,\n--rb-border, ...", shape=note]
css [label="GET /api/v1/themes/{ns}/css\n(1-day cache)", shape=component]
preview [label="GET /api/v1/themes/{ns}/preview\n(JSON palette)", shape=component]
name -> sha
sha -> hue
sha -> seeds
hue -> palette
seeds -> palette
palette -> light
palette -> dark
light -> css
dark -> css
palette -> preview
}
Deterministic: same namespace name always produces the same theme.
Module Map
digraph modules {
rankdir=TB
node [shape=box, fontname="monospace", fontsize=10]
edge [fontname="sans-serif", fontsize=9]
compound=true
subgraph cluster_lib {
label="remarkbox/lib/"
style=rounded
fontname="sans-serif"
pandoc_py [label="pandoc.py\nsubprocess wrapper\ntree renderer"]
theme_gen [label="theme_generator.py\ndeterministic CSS"]
}
subgraph cluster_api {
label="remarkbox/api/"
style=rounded
fontname="sans-serif"
export_py [label="export.py\n/export/ endpoints"]
wiki_py [label="wiki.py\n/wiki-edit, /revisions"]
themes_py [label="themes.py\n/themes/ endpoints"]
views_py [label="views.py\nsource_format on\ncreate/reply/edit"]
serial_py [label="serializers.py\nsource_format in JSON"]
}
subgraph cluster_models {
label="remarkbox/models/"
style=rounded
fontname="sans-serif"
node_py [label="node.py\nsource_format column\nset_data(), wiki_edit()"]
ns_py [label="namespace.py\ncan_wiki_edit()"]
rev_py [label="revision.py\nRevision model"]
}
subgraph cluster_migrations {
label="remarkbox/scripts/alembic/versions/"
style=rounded
fontname="sans-serif"
mig1 [label="d47dc908d2ea\nadd source_format"]
mig2 [label="8e3c406e4049\ncreate rb_revision"]
}
export_py -> pandoc_py
themes_py -> theme_gen
wiki_py -> rev_py
wiki_py -> node_py
views_py -> node_py
export_py -> node_py
export_py -> ns_py
node_py -> pandoc_py [style=dashed, label="non-md formats"]
mig1 -> node_py [style=dotted]
mig2 -> rev_py [style=dotted]
}