@karmaniverous/jeeves-server 3.0.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/.env.local +13 -0
  2. package/.env.local.template +13 -0
  3. package/.tsbuildinfo +1 -0
  4. package/CHANGELOG.md +450 -0
  5. package/about.md +82 -0
  6. package/client/README.md +73 -0
  7. package/client/eslint.config.js +23 -0
  8. package/client/index.html +14 -0
  9. package/client/package-lock.json +5181 -0
  10. package/client/package.json +60 -0
  11. package/client/public/vite.svg +1 -0
  12. package/client/src/App.tsx +22 -0
  13. package/client/src/components/AccountMenu.tsx +167 -0
  14. package/client/src/components/ActionDropdown.tsx +120 -0
  15. package/client/src/components/CodeEditor.tsx +143 -0
  16. package/client/src/components/CodeViewer.tsx +113 -0
  17. package/client/src/components/ConfirmDialog.tsx +32 -0
  18. package/client/src/components/DirectoryRow.tsx +62 -0
  19. package/client/src/components/DirectoryTable.tsx +42 -0
  20. package/client/src/components/DownloadDropdown.tsx +116 -0
  21. package/client/src/components/DriveList.tsx +54 -0
  22. package/client/src/components/EmbeddedDiagramPanzoom.ts +28 -0
  23. package/client/src/components/FileContentView.tsx +155 -0
  24. package/client/src/components/InlineSvgPanzoom.ts +60 -0
  25. package/client/src/components/LazyDiagram.ts +93 -0
  26. package/client/src/components/LinkDropdown.tsx +134 -0
  27. package/client/src/components/MarkdownView.tsx +115 -0
  28. package/client/src/components/MermaidViewer.tsx +21 -0
  29. package/client/src/components/PlantUmlViewer.tsx +21 -0
  30. package/client/src/components/SearchModal.tsx +424 -0
  31. package/client/src/components/SvgViewer.tsx +107 -0
  32. package/client/src/components/TabBar.tsx +96 -0
  33. package/client/src/components/layout/Header.tsx +270 -0
  34. package/client/src/components/panzoom.ts +203 -0
  35. package/client/src/components/renderableUtils.ts +15 -0
  36. package/client/src/components/runner/JobTable.tsx +153 -0
  37. package/client/src/components/runner/RunHistory.tsx +140 -0
  38. package/client/src/components/runner/StatsBar.tsx +43 -0
  39. package/client/src/components/runner/StatusPill.tsx +27 -0
  40. package/client/src/components/runner/jobTableUtils.ts +65 -0
  41. package/client/src/components/scrollUtils.ts +39 -0
  42. package/client/src/components/ui/alert-dialog.tsx +107 -0
  43. package/client/src/components/ui/button.tsx +40 -0
  44. package/client/src/components/ui/dropdown-menu.tsx +79 -0
  45. package/client/src/components/ui/input.tsx +26 -0
  46. package/client/src/components/useActionState.ts +43 -0
  47. package/client/src/hooks/useFileBrowser.ts +102 -0
  48. package/client/src/hooks/useFileData.ts +78 -0
  49. package/client/src/hooks/useScrollAnchor.ts +70 -0
  50. package/client/src/hooks/useShareSettings.ts +22 -0
  51. package/client/src/hooks/useTopBar.ts +27 -0
  52. package/client/src/index.css +281 -0
  53. package/client/src/lib/AuthContext.ts +27 -0
  54. package/client/src/lib/api.ts +239 -0
  55. package/client/src/lib/auth.tsx +50 -0
  56. package/client/src/lib/codeBlockCm6.ts +129 -0
  57. package/client/src/lib/codeBlockCopy.ts +43 -0
  58. package/client/src/lib/codemirror.ts +77 -0
  59. package/client/src/lib/runner-api.ts +172 -0
  60. package/client/src/lib/svg.ts +50 -0
  61. package/client/src/lib/theme.ts +34 -0
  62. package/client/src/lib/utils.ts +6 -0
  63. package/client/src/main.tsx +11 -0
  64. package/client/src/pages/FileBrowser.tsx +135 -0
  65. package/client/src/pages/Home.tsx +46 -0
  66. package/client/src/pages/Runner.tsx +151 -0
  67. package/client/src/pages/RunnerJob.tsx +170 -0
  68. package/client/tsconfig.app.json +32 -0
  69. package/client/tsconfig.json +7 -0
  70. package/client/tsconfig.node.json +26 -0
  71. package/client/vite.config.ts +35 -0
  72. package/content/privacy.md +61 -0
  73. package/content/terms.md +41 -0
  74. package/dist/client/assets/CodeEditor-0XHVI8Nu.js +1 -0
  75. package/dist/client/assets/CodeViewer-CykMVsfX.js +1 -0
  76. package/dist/client/assets/index--MBieNJA.js +1 -0
  77. package/dist/client/assets/index-BENeXQI_.js +1 -0
  78. package/dist/client/assets/index-BbBpoOxz.js +1 -0
  79. package/dist/client/assets/index-BdV9g5AM.js +6 -0
  80. package/dist/client/assets/index-BjAilRri.js +2 -0
  81. package/dist/client/assets/index-BqbhWo2I.js +3 -0
  82. package/dist/client/assets/index-CVbycZ0H.js +1 -0
  83. package/dist/client/assets/index-Cs5oz2oJ.js +5 -0
  84. package/dist/client/assets/index-D8KZVveX.js +1 -0
  85. package/dist/client/assets/index-DC4HMHxY.js +13 -0
  86. package/dist/client/assets/index-DbMebkkd.css +1 -0
  87. package/dist/client/assets/index-DcY2RXqX.js +1 -0
  88. package/dist/client/assets/index-Duy-tZYV.js +1 -0
  89. package/dist/client/assets/index-Dw7rDFmE.js +7 -0
  90. package/dist/client/assets/index-FlCUvrjv.js +2 -0
  91. package/dist/client/assets/index-K6OVmfhg.js +1 -0
  92. package/dist/client/assets/index-LjwgzZ7F.js +62 -0
  93. package/dist/client/assets/index-MLwyFRN0.js +1 -0
  94. package/dist/client/assets/index-OpqBpSjn.js +1 -0
  95. package/dist/client/assets/index-SsHei0HE.js +1 -0
  96. package/dist/client/assets/index-uQa2yckk.js +1 -0
  97. package/dist/client/assets/index-udkXoIER.js +1 -0
  98. package/dist/client/index.html +15 -0
  99. package/dist/client/vite.svg +1 -0
  100. package/dist/src/auth/google.js +57 -0
  101. package/dist/src/auth/keys.js +185 -0
  102. package/dist/src/auth/resolve.js +102 -0
  103. package/dist/src/auth/session.js +57 -0
  104. package/dist/src/cli/commands/config.js +100 -0
  105. package/dist/src/cli/commands/config.test.js +84 -0
  106. package/dist/src/cli/commands/service.js +93 -0
  107. package/dist/src/cli/commands/start.js +24 -0
  108. package/dist/src/cli/index.js +20 -0
  109. package/dist/src/config/index.js +90 -0
  110. package/dist/src/config/loadConfig.test.js +127 -0
  111. package/dist/src/config/resolve.js +134 -0
  112. package/dist/src/config/resolve.test.js +148 -0
  113. package/dist/src/config/schema.js +159 -0
  114. package/dist/src/config/substituteEnvVars.js +45 -0
  115. package/dist/src/config/substituteEnvVars.test.js +51 -0
  116. package/dist/src/config/types.js +5 -0
  117. package/dist/src/routes/api/auth-status.js +56 -0
  118. package/dist/src/routes/api/diagrams.js +35 -0
  119. package/dist/src/routes/api/directory.js +93 -0
  120. package/dist/src/routes/api/drives.js +15 -0
  121. package/dist/src/routes/api/export.js +218 -0
  122. package/dist/src/routes/api/fileContent.js +286 -0
  123. package/dist/src/routes/api/index.js +33 -0
  124. package/dist/src/routes/api/linkInfo.js +71 -0
  125. package/dist/src/routes/api/linkInfo.test.js +104 -0
  126. package/dist/src/routes/api/middleware.js +117 -0
  127. package/dist/src/routes/api/raw.js +38 -0
  128. package/dist/src/routes/api/runner.js +59 -0
  129. package/dist/src/routes/api/search.js +236 -0
  130. package/dist/src/routes/api/sharing.js +203 -0
  131. package/dist/src/routes/api/status.js +68 -0
  132. package/dist/src/routes/api/status.test.js +62 -0
  133. package/dist/src/routes/auth.js +99 -0
  134. package/dist/src/routes/event.js +77 -0
  135. package/dist/src/routes/event.test.js +206 -0
  136. package/dist/src/routes/health.js +10 -0
  137. package/dist/src/routes/keys.js +129 -0
  138. package/dist/src/routes/path/index.js +17 -0
  139. package/dist/src/routes/static.js +30 -0
  140. package/dist/src/server.js +90 -0
  141. package/dist/src/services/deepShareLinks.js +163 -0
  142. package/dist/src/services/diagramCache.js +104 -0
  143. package/dist/src/services/embeddedDiagrams.js +136 -0
  144. package/dist/src/services/eventLog.js +55 -0
  145. package/dist/src/services/eventLog.test.js +113 -0
  146. package/dist/src/services/eventQueue.js +154 -0
  147. package/dist/src/services/eventQueue.test.js +104 -0
  148. package/dist/src/services/export.js +220 -0
  149. package/dist/src/services/exportCache.js +196 -0
  150. package/dist/src/services/markdown.js +147 -0
  151. package/dist/src/services/mermaid.js +97 -0
  152. package/dist/src/services/plantuml.js +145 -0
  153. package/dist/src/services/puppeteer.js +156 -0
  154. package/dist/src/util/breadcrumbs.js +22 -0
  155. package/dist/src/util/crypto.js +56 -0
  156. package/dist/src/util/crypto.test.js +99 -0
  157. package/dist/src/util/fileDetection.js +66 -0
  158. package/dist/src/util/fileDetection.test.js +89 -0
  159. package/dist/src/util/formatters.js +43 -0
  160. package/dist/src/util/formatters.test.js +83 -0
  161. package/dist/src/util/packageVersion.js +25 -0
  162. package/dist/src/util/platform.js +148 -0
  163. package/dist/src/util/state.js +46 -0
  164. package/dist/vitest.config.js +12 -0
  165. package/favicon.svg +3 -0
  166. package/guides/access-decision-flow.mmd +24 -0
  167. package/guides/access-decision-flow.svg +1 -0
  168. package/guides/api-integration.md +236 -0
  169. package/guides/deployment.md +287 -0
  170. package/guides/event-gateway.md +204 -0
  171. package/guides/event-gateway.mmd +17 -0
  172. package/guides/event-gateway.svg +1 -0
  173. package/guides/exports.md +239 -0
  174. package/guides/setup.md +313 -0
  175. package/guides/sharing.md +204 -0
  176. package/jeeves-server.config.template.json +25 -0
  177. package/package.json +124 -0
  178. package/scripts/download-plantuml.js +70 -0
  179. package/src/auth/google.ts +93 -0
  180. package/src/auth/keys.ts +252 -0
  181. package/src/auth/resolve.ts +157 -0
  182. package/src/auth/session.ts +77 -0
  183. package/src/cli/commands/config.test.ts +107 -0
  184. package/src/cli/commands/config.ts +113 -0
  185. package/src/cli/commands/service.ts +129 -0
  186. package/src/cli/commands/start.ts +27 -0
  187. package/src/cli/index.ts +25 -0
  188. package/src/config/index.ts +113 -0
  189. package/src/config/loadConfig.test.ts +155 -0
  190. package/src/config/resolve.test.ts +192 -0
  191. package/src/config/resolve.ts +173 -0
  192. package/src/config/schema.ts +179 -0
  193. package/src/config/substituteEnvVars.test.ts +64 -0
  194. package/src/config/substituteEnvVars.ts +52 -0
  195. package/src/config/types.ts +129 -0
  196. package/src/routes/api/auth-status.ts +85 -0
  197. package/src/routes/api/diagrams.ts +53 -0
  198. package/src/routes/api/directory.ts +123 -0
  199. package/src/routes/api/drives.ts +23 -0
  200. package/src/routes/api/export.ts +314 -0
  201. package/src/routes/api/fileContent.ts +414 -0
  202. package/src/routes/api/index.ts +37 -0
  203. package/src/routes/api/linkInfo.test.ts +132 -0
  204. package/src/routes/api/linkInfo.ts +83 -0
  205. package/src/routes/api/middleware.ts +156 -0
  206. package/src/routes/api/raw.ts +54 -0
  207. package/src/routes/api/runner.ts +107 -0
  208. package/src/routes/api/search.ts +321 -0
  209. package/src/routes/api/sharing.ts +259 -0
  210. package/src/routes/api/status.test.ts +72 -0
  211. package/src/routes/api/status.ts +82 -0
  212. package/src/routes/auth.ts +143 -0
  213. package/src/routes/event.test.ts +248 -0
  214. package/src/routes/event.ts +109 -0
  215. package/src/routes/health.ts +13 -0
  216. package/src/routes/keys.ts +192 -0
  217. package/src/routes/path/index.ts +24 -0
  218. package/src/routes/static.ts +54 -0
  219. package/src/server.ts +104 -0
  220. package/src/services/deepShareLinks.ts +203 -0
  221. package/src/services/diagramCache.ts +128 -0
  222. package/src/services/embeddedDiagrams.ts +168 -0
  223. package/src/services/eventLog.test.ts +144 -0
  224. package/src/services/eventLog.ts +68 -0
  225. package/src/services/eventQueue.test.ts +127 -0
  226. package/src/services/eventQueue.ts +196 -0
  227. package/src/services/export.ts +267 -0
  228. package/src/services/exportCache.ts +216 -0
  229. package/src/services/markdown.ts +189 -0
  230. package/src/services/mermaid.ts +113 -0
  231. package/src/services/plantuml.ts +172 -0
  232. package/src/services/puppeteer.ts +188 -0
  233. package/src/types/fastify.d.ts +13 -0
  234. package/src/types/jsonmap.d.ts +10 -0
  235. package/src/types/plantuml-encoder.d.ts +4 -0
  236. package/src/util/breadcrumbs.ts +33 -0
  237. package/src/util/crypto.test.ts +132 -0
  238. package/src/util/crypto.ts +79 -0
  239. package/src/util/fileDetection.test.ts +115 -0
  240. package/src/util/fileDetection.ts +70 -0
  241. package/src/util/formatters.test.ts +105 -0
  242. package/src/util/formatters.ts +44 -0
  243. package/src/util/packageVersion.ts +30 -0
  244. package/src/util/platform.ts +178 -0
  245. package/src/util/state.ts +55 -0
  246. package/test-docs/diagram-retry-test.md +18 -0
  247. package/test-docs/embedded-diagrams.md +52 -0
  248. package/test-docs/lazy-diagrams-test.md +333 -0
  249. package/test-docs/page-a.md +7 -0
  250. package/test-docs/page-b.md +7 -0
  251. package/test-docs/page-c.md +7 -0
  252. package/test-docs/sub/page-d.md +7 -0
  253. package/test-docs/test-diagram.puml +13 -0
  254. package/test-docs/validate-deep-share.js +318 -0
  255. package/tsconfig.json +37 -0
  256. package/tsdoc.json +13 -0
  257. package/vendor/.plantuml-version +1 -0
  258. package/vendor/plantuml.jar +0 -0
  259. package/vitest.config.js +12 -0
  260. package/vitest.config.ts +13 -0
@@ -0,0 +1,52 @@
1
+ # Embedded Diagram Test
2
+
3
+ This page tests inline diagram rendering in markdown.
4
+
5
+ Foo!
6
+
7
+ ## Mermaid Diagram
8
+
9
+ ```mermaid
10
+ graph TD
11
+ A[Start] --> B{Decision}
12
+ B -->|Yes| C[Do something]
13
+ B -->|No| D[Do something else]
14
+ C --> E[End]
15
+ D --> E
16
+ ```
17
+
18
+ ## PlantUML Diagram
19
+
20
+ ```plantuml
21
+ @startuml
22
+ actor UserFoo
23
+ participant "Web App" as App
24
+ database "Database" as DB
25
+
26
+ User -> App: Request
27
+ App -> DB: Query
28
+ DB --> App: Results
29
+ App --> User: Response
30
+ @enduml
31
+ ```
32
+
33
+ ## Regular Code Block
34
+
35
+ ```javascript
36
+ // This should still render as syntax-highlighted code
37
+ function hello() {
38
+ console.log('Hello, world!');
39
+ }
40
+ ```
41
+
42
+ ## Mixed Content
43
+
44
+ Some text before a diagram.
45
+
46
+ ```mermaid
47
+ sequenceDiagram
48
+ Alice->>Bob: Hello Bob!
49
+ Bob-->>Alice: Hi Alice!
50
+ ```
51
+
52
+ And some text after.
@@ -0,0 +1,333 @@
1
+ # Lazy Diagram Loading Test
2
+
3
+ This page tests lazy-loaded embedded diagrams. The text below should appear **instantly** while diagrams render in the background.
4
+
5
+ ## Section 1: Introduction
6
+
7
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
8
+
9
+ ## Diagram 1: Complex Mermaid Flowchart
10
+
11
+ ```mermaid
12
+ graph TB
13
+ subgraph Client["🖥️ Client Layer"]
14
+ direction TB
15
+ Browser[Browser SPA]
16
+ AuthCtx[Auth Context]
17
+ Router[React Router]
18
+ LazyLoader[Lazy Diagram Loader]
19
+ Panzoom[Panzoom Controller]
20
+ ThemeEngine[Theme Engine]
21
+ Browser --> AuthCtx
22
+ Browser --> Router
23
+ Router --> LazyLoader
24
+ LazyLoader --> Panzoom
25
+ Browser --> ThemeEngine
26
+ end
27
+
28
+ subgraph Server["⚙️ Server Layer"]
29
+ direction TB
30
+ Fastify[Fastify Server]
31
+ AuthMW[Auth Middleware]
32
+ FileAPI[File API]
33
+ DiagramAPI[Diagram API]
34
+ ExportSvc[Export Service]
35
+ MarkdownSvc[Markdown Service]
36
+ DiagramCache[Diagram Cache]
37
+ EmbeddedDiag[Embedded Diagrams]
38
+ Fastify --> AuthMW
39
+ AuthMW --> FileAPI
40
+ AuthMW --> DiagramAPI
41
+ AuthMW --> ExportSvc
42
+ FileAPI --> MarkdownSvc
43
+ MarkdownSvc --> EmbeddedDiag
44
+ DiagramAPI --> DiagramCache
45
+ DiagramAPI --> EmbeddedDiag
46
+ EmbeddedDiag --> DiagramCache
47
+ end
48
+
49
+ subgraph Renderers["🎨 Diagram Renderers"]
50
+ direction TB
51
+ MermaidCLI[Mermaid CLI + Puppeteer]
52
+ PlantUMLJar[PlantUML Jar + Java]
53
+ PlantUMLServer[PlantUML Server Fallback]
54
+ MermaidCLI --> |SVG| CacheStore[(Cache Store)]
55
+ PlantUMLJar --> |SVG| CacheStore
56
+ PlantUMLServer --> |SVG| CacheStore
57
+ end
58
+
59
+ subgraph Storage["💾 Storage Layer"]
60
+ direction TB
61
+ FSWatcher[File System]
62
+ Config[Config TS + Zod]
63
+ State[State JSON]
64
+ InsiderKeys[Insider Keys]
65
+ Config --> State
66
+ State --> InsiderKeys
67
+ end
68
+
69
+ Client -->|HTTP| Server
70
+ DiagramCache -->|read/write| CacheStore
71
+ EmbeddedDiag -->|render| Renderers
72
+ FileAPI -->|read| FSWatcher
73
+ ExportSvc -->|Puppeteer| Browser
74
+ ```
75
+
76
+ ## Section 2: More Text
77
+
78
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
79
+
80
+ ## Diagram 2: Complex PlantUML Sequence
81
+
82
+ ```plantuml
83
+ @startuml
84
+ !theme cerulean
85
+ skinparam responseMessageBelowArrow true
86
+ skinparam maxMessageSize 200
87
+
88
+ actor User
89
+ participant "Browser SPA" as SPA
90
+ participant "Auth Middleware" as Auth
91
+ participant "File API" as FileAPI
92
+ participant "Markdown Service" as MD
93
+ participant "Embedded Diagrams" as Embed
94
+ participant "Diagram API" as DiagAPI
95
+ participant "Diagram Cache" as Cache
96
+ participant "Mermaid CLI" as Mermaid
97
+ participant "PlantUML Jar" as PlantUML
98
+
99
+ == Page Load ==
100
+ User -> SPA: Navigate to /browse/path/doc.md
101
+ SPA -> Auth: GET /api/auth/status
102
+ Auth --> SPA: { isInsider: true }
103
+
104
+ SPA -> FileAPI: GET /api/file/path/doc.md
105
+ FileAPI -> MD: parseMarkdown(content)
106
+ MD -> Embed: registerDiagram("mermaid", source1)
107
+ Embed --> MD: <placeholder hash="abc123">
108
+ MD -> Embed: registerDiagram("plantuml", source2)
109
+ Embed --> MD: <placeholder hash="def456">
110
+ MD --> FileAPI: { html (with placeholders), headings }
111
+ FileAPI --> SPA: JSON response (instant!)
112
+
113
+ == Lazy Diagram Loading ==
114
+ SPA -> SPA: Render markdown text immediately
115
+ SPA -> SPA: initLazyDiagrams()
116
+
117
+ par Parallel diagram fetches
118
+ SPA -> DiagAPI: GET /api/diagram/mermaid/abc123.svg
119
+ DiagAPI -> Cache: getCachedDiagram("mermaid", source)
120
+ alt Cache Hit
121
+ Cache --> DiagAPI: SVG content
122
+ else Cache Miss
123
+ Cache --> DiagAPI: null
124
+ DiagAPI -> Mermaid: renderMermaidSync(source)
125
+ Mermaid --> DiagAPI: SVG
126
+ DiagAPI -> Cache: cacheDiagram("mermaid", source, svg)
127
+ end
128
+ DiagAPI --> SPA: image/svg+xml (immutable cache headers)
129
+ SPA -> SPA: Replace spinner with SVG + panzoom
130
+
131
+ SPA -> DiagAPI: GET /api/diagram/plantuml/def456.svg
132
+ DiagAPI -> Cache: getCachedDiagram("plantuml", source)
133
+ alt Cache Hit
134
+ Cache --> DiagAPI: SVG content
135
+ else Cache Miss
136
+ Cache --> DiagAPI: null
137
+ DiagAPI -> PlantUML: renderPlantUmlSvg(source)
138
+ PlantUML --> DiagAPI: SVG
139
+ DiagAPI -> Cache: cacheDiagram("plantuml", source, svg)
140
+ end
141
+ DiagAPI --> SPA: image/svg+xml
142
+ SPA -> SPA: Replace spinner with SVG + panzoom
143
+ end
144
+
145
+ == Subsequent Visits ==
146
+ User -> SPA: Reload page
147
+ SPA -> FileAPI: GET /api/file/path/doc.md
148
+ FileAPI --> SPA: JSON (instant)
149
+ SPA -> DiagAPI: GET /api/diagram/mermaid/abc123.svg
150
+ DiagAPI -> Cache: getCachedDiagram() → HIT
151
+ Cache --> DiagAPI: SVG
152
+ DiagAPI --> SPA: SVG (from cache, ~1ms)
153
+ note right: All diagrams load instantly\non repeat visits
154
+
155
+ @enduml
156
+ ```
157
+
158
+ ## Section 3: Analysis
159
+
160
+ The architecture above demonstrates a clean separation between the document rendering pipeline and the diagram rendering pipeline. By decoupling these concerns, we achieve:
161
+
162
+ 1. **Fast time-to-first-byte** — markdown text renders without waiting for diagrams
163
+ 2. **Parallel rendering** — multiple diagrams render concurrently
164
+ 3. **Content-addressed caching** — identical diagram source always produces the same cache key
165
+ 4. **Progressive enhancement** — diagrams appear as they become available
166
+
167
+ ## Diagram 3: PlantUML Component Diagram
168
+
169
+ ```plantuml
170
+ @startuml
171
+ !theme cerulean
172
+ skinparam componentStyle rectangle
173
+ skinparam linetype ortho
174
+
175
+ package "Client (React SPA)" {
176
+ [FileBrowser] as FB
177
+ [Header] as HD
178
+ [LazyDiagram] as LD
179
+ [EmbeddedDiagramPanzoom] as EDP
180
+ [InlineSvgPanzoom] as ISP
181
+ [DownloadDropdown] as DD
182
+ [LinkDropdown] as LiD
183
+ [CodeEditor] as CE
184
+ [AuthContext] as AC
185
+
186
+ FB --> HD
187
+ FB --> LD
188
+ FB --> EDP
189
+ FB --> ISP
190
+ FB --> DD
191
+ FB --> LiD
192
+ FB --> CE
193
+ FB --> AC
194
+ }
195
+
196
+ package "Server (Fastify)" {
197
+ [Auth Middleware] as AM
198
+ [File Routes] as FR
199
+ [Diagram Routes] as DR
200
+ [Export Routes] as ER
201
+ [Event Gateway] as EG
202
+
203
+ package "Services" {
204
+ [Markdown Parser] as MP
205
+ [Embedded Diagrams] as ED
206
+ [Diagram Cache] as DC
207
+ [Deep Share Links] as DSL
208
+ [Export Service] as ES
209
+ [Event Queue] as EQ
210
+ }
211
+
212
+ package "Renderers" {
213
+ [Mermaid CLI] as MC
214
+ [PlantUML Jar] as PJ
215
+ [PlantUML Server] as PS
216
+ }
217
+
218
+ package "Auth" {
219
+ [Google OAuth] as GO
220
+ [Key Auth] as KA
221
+ [Session Manager] as SM
222
+ }
223
+
224
+ package "Config" {
225
+ [Zod Schema] as ZS
226
+ [Config Loader] as CL
227
+ [State Manager] as StM
228
+ }
229
+
230
+ AM --> GO
231
+ AM --> KA
232
+ AM --> SM
233
+ FR --> MP
234
+ FR --> DSL
235
+ MP --> ED
236
+ DR --> DC
237
+ DR --> ED
238
+ ED --> MC
239
+ ED --> PJ
240
+ ED --> PS
241
+ DC -[hidden]-> MC
242
+ ER --> ES
243
+ EG --> EQ
244
+ CL --> ZS
245
+ CL --> StM
246
+ }
247
+
248
+ package "Storage" {
249
+ database "File System" as FS
250
+ database ".diagram-cache/" as DCC
251
+ database "state.json" as SJ
252
+ database "jeeves.config.ts" as JC
253
+ }
254
+
255
+ FR --> FS
256
+ DC --> DCC
257
+ StM --> SJ
258
+ CL --> JC
259
+ ES -[hidden]-> FS
260
+
261
+ FB ..> FR : HTTP
262
+ FB ..> DR : HTTP
263
+ FB ..> ER : HTTP
264
+ AC ..> AM : HTTP
265
+
266
+ @enduml
267
+ ```
268
+
269
+ ## Diagram 4: Mermaid State Diagram
270
+
271
+ ```mermaid
272
+ stateDiagram-v2
273
+ [*] --> PageLoad
274
+
275
+ state PageLoad {
276
+ [*] --> FetchingFile
277
+ FetchingFile --> ParsingMarkdown: API response
278
+ ParsingMarkdown --> RegisteringDiagrams: code block found
279
+ RegisteringDiagrams --> ParsingMarkdown: placeholder inserted
280
+ ParsingMarkdown --> TextReady: parsing complete
281
+ }
282
+
283
+ state TextReady {
284
+ [*] --> RenderingText
285
+ RenderingText --> InitLazyDiagrams
286
+ InitLazyDiagrams --> FetchingDiagrams
287
+ }
288
+
289
+ state FetchingDiagrams {
290
+ [*] --> CheckCache
291
+ CheckCache --> CacheHit: found
292
+ CheckCache --> CacheMiss: not found
293
+
294
+ state CacheMiss {
295
+ [*] --> Rendering
296
+ Rendering --> MermaidCLI: type=mermaid
297
+ Rendering --> PlantUMLJar: type=plantuml
298
+ MermaidCLI --> WritingCache
299
+ PlantUMLJar --> WritingCache
300
+ WritingCache --> [*]
301
+ }
302
+
303
+ CacheHit --> ServingSVG
304
+ CacheMiss --> ServingSVG
305
+ ServingSVG --> [*]
306
+ }
307
+
308
+ state DiagramReady {
309
+ [*] --> InsertingSVG
310
+ InsertingSVG --> InitPanzoom
311
+ InitPanzoom --> Interactive
312
+ }
313
+
314
+ TextReady --> FetchingDiagrams: for each diagram
315
+ FetchingDiagrams --> DiagramReady: SVG received
316
+ DiagramReady --> [*]
317
+
318
+ state Interactive {
319
+ [*] --> Idle
320
+ Idle --> Zooming: scroll wheel
321
+ Zooming --> Idle: release
322
+ Idle --> Panning: drag
323
+ Panning --> Idle: release
324
+ Idle --> Fullscreen: click button
325
+ Fullscreen --> Idle: Esc / click button
326
+ }
327
+ ```
328
+
329
+ ## Section 4: Conclusion
330
+
331
+ If you're reading this text while diagrams above still show spinners, the lazy loading is working as designed. The text content was delivered without waiting for any diagram rendering. Each diagram loads independently and appears as soon as its SVG is ready.
332
+
333
+ On subsequent page loads, all diagrams should appear nearly instantly thanks to the content-addressed cache.
@@ -0,0 +1,7 @@
1
+ # Page A (Root)
2
+
3
+ Internal link to [Page B](page-b.md) (depth 1).
4
+
5
+ Internal link to [Sub Page](sub/page-d.md) (depth 1, inside subdirectory).
6
+
7
+ External link to [Google](https://www.google.com) (always works).
@@ -0,0 +1,7 @@
1
+ # Page B (Depth 1)
2
+
3
+ Internal link to [Page C](page-c.md) (depth 2 from root).
4
+
5
+ Internal link back to [Page A](page-a.md) (depth 2 from root).
6
+
7
+ External link to [GitHub](https://github.com) (always works).
@@ -0,0 +1,7 @@
1
+ # Page C (Depth 2)
2
+
3
+ This is the end of the chain.
4
+
5
+ Internal link to [Page A](page-a.md) (depth 3 from root — should be dead at depth ≤ 2).
6
+
7
+ External link to [Wikipedia](https://en.wikipedia.org) (always works).
@@ -0,0 +1,7 @@
1
+ # Page D (Subdirectory)
2
+
3
+ This page lives in a subdirectory.
4
+
5
+ Internal link to [Page B](../page-b.md) (depth 2 from root).
6
+
7
+ External link to [MDN](https://developer.mozilla.org) (always works).
@@ -0,0 +1,13 @@
1
+ @startuml
2
+ actor User
3
+ participant "Web Browser" as Browser
4
+ participant "Jeeves Server" as Server
5
+ participant "PlantUML Server" as PUML
6
+
7
+ User -> Browser: Open .puml file
8
+ Browser -> Server: GET /api/file/path/to/file.puml
9
+ Server -> PUML: GET /plantuml/svg/{encoded}
10
+ PUML --> Server: SVG content
11
+ Server --> Browser: { type: "plantuml", html: "<svg>..." }
12
+ Browser --> User: Rendered diagram with panzoom
13
+ @enduml