pugflow 2026.1__tar.gz

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 (34) hide show
  1. pugflow-2026.1/MANIFEST.in +1 -0
  2. pugflow-2026.1/PKG-INFO +510 -0
  3. pugflow-2026.1/README.md +497 -0
  4. pugflow-2026.1/pyproject.toml +33 -0
  5. pugflow-2026.1/setup.cfg +4 -0
  6. pugflow-2026.1/src/pugflow/__init__.py +7 -0
  7. pugflow-2026.1/src/pugflow/__main__.py +5 -0
  8. pugflow-2026.1/src/pugflow/cli.py +59 -0
  9. pugflow-2026.1/src/pugflow/render.py +71 -0
  10. pugflow-2026.1/src/pugflow/server.py +133 -0
  11. pugflow-2026.1/src/pugflow/web/app.mjs +2728 -0
  12. pugflow-2026.1/src/pugflow/web/docs.css +23 -0
  13. pugflow-2026.1/src/pugflow/web/docs.html +164 -0
  14. pugflow-2026.1/src/pugflow/web/editor-source.mjs +649 -0
  15. pugflow-2026.1/src/pugflow/web/index.html +188 -0
  16. pugflow-2026.1/src/pugflow/web/layout.mjs +449 -0
  17. pugflow-2026.1/src/pugflow/web/math-render.mjs +134 -0
  18. pugflow-2026.1/src/pugflow/web/parser.mjs +926 -0
  19. pugflow-2026.1/src/pugflow/web/pugflow.css +32 -0
  20. pugflow-2026.1/src/pugflow/web/pugflow.mjs +1169 -0
  21. pugflow-2026.1/src/pugflow/web/render-cli.mjs +29 -0
  22. pugflow-2026.1/src/pugflow/web/render.html +1 -0
  23. pugflow-2026.1/src/pugflow/web/reusable-style.mjs +53 -0
  24. pugflow-2026.1/src/pugflow/web/style-sheet.mjs +62 -0
  25. pugflow-2026.1/src/pugflow/web/styles.css +576 -0
  26. pugflow-2026.1/src/pugflow/web/text-editor.mjs +135 -0
  27. pugflow-2026.1/src/pugflow/web/vendor/mathjax/LICENSE +202 -0
  28. pugflow-2026.1/src/pugflow/web/vendor/mathjax/tex-svg-full.js +34 -0
  29. pugflow-2026.1/src/pugflow/web/vim-mode.mjs +367 -0
  30. pugflow-2026.1/src/pugflow.egg-info/PKG-INFO +510 -0
  31. pugflow-2026.1/src/pugflow.egg-info/SOURCES.txt +32 -0
  32. pugflow-2026.1/src/pugflow.egg-info/dependency_links.txt +1 -0
  33. pugflow-2026.1/src/pugflow.egg-info/entry_points.txt +2 -0
  34. pugflow-2026.1/src/pugflow.egg-info/top_level.txt +1 -0
@@ -0,0 +1 @@
1
+ recursive-include src/pugflow/web *
@@ -0,0 +1,510 @@
1
+ Metadata-Version: 2.4
2
+ Name: pugflow
3
+ Version: 2026.1
4
+ Summary: Build and export polished flow diagrams from readable Pug source.
5
+ Author: Pugflow contributors
6
+ License: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Environment :: Web Environment
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Pugflow
15
+
16
+ A source-first diagram editor and command-line renderer. Diagrams stay editable as readable `.pug` files, reusable presentation can live in a `.css` file, and SVG/PNG are export formats.
17
+
18
+ **[Try the online editor on GitHub Pages →](https://briday1.github.io/pugflow/)**
19
+
20
+ ## Install as a Python application
21
+
22
+ For development, install the checkout in editable mode:
23
+
24
+ ```powershell
25
+ python -m pip install -e .
26
+ pugflow
27
+ ```
28
+
29
+ The installed command opens the editor. Add `--vim` to begin in Vim mode:
30
+
31
+ ```powershell
32
+ python -m pugflow --vim
33
+ ```
34
+
35
+ The server opens <http://127.0.0.1:4173> automatically. Examples of server options:
36
+
37
+ ```powershell
38
+ pugflow --no-browser
39
+ pugflow --host 0.0.0.0 --port 8080 --vim
40
+ pugflow --demo
41
+ pugflow --gui diagram.pug --css diagram.css
42
+ pugflow --version
43
+ ```
44
+
45
+ Render directly from the command line. Pugflow uses an installed Edge, Chrome, or Chromium browser for exact parity with the editor; set `PUGFLOW_BROWSER` when it is not discovered automatically.
46
+
47
+ ```powershell
48
+ pugflow diagram.pug
49
+ pugflow diagram.pug --css styles.css --output diagram.png --scale 2
50
+ ```
51
+
52
+ `GET /healthz` returns server status and version as JSON.
53
+
54
+ The editor has `diagram.pug` and `styles.css` tabs with clear New, Open, Save, and Save As actions in the File menu. Reusable styles use CSS-shaped rules:
55
+
56
+ ```css
57
+ @node card {
58
+ shape: rounded;
59
+ fill: #ffffff;
60
+ outline: #94a3b8;
61
+ }
62
+
63
+ @flow warning {
64
+ color: #dc2626;
65
+ stroke-style: dashed;
66
+ }
67
+ ```
68
+
69
+ The editor opens as a blank `#canvas`; use `pugflow --demo` for the full feature tour. It provides live rendering, line numbers, highlighting, completions, a **File** menu for new/open/save actions using system files, a collapsible source panel, high-DPI PNG clipboard copying, and a Save dialog for PNG or SVG export. A project requires one Pug file. CSS is optional unless the Pug uses custom classes such as `.card`; select both files in the Open dialog or create CSS from the File menu. Each source tab shows its loaded filename. Source is not stored in the browser.
70
+
71
+ Drag the divider beside the source panel to resize it; the width is remembered.
72
+ Click any visible block in the preview to focus and select its corresponding source line.
73
+ Enable **Vim** beside the editor actions for Normal, Insert, and Visual modes. It starts off on every launch and supports standard movement, editing, yanking, pasting, marks, and undo/redo commands. Escape, Ctrl+[ and Ctrl+C return to Normal mode.
74
+
75
+ ## Basic Pug definition
76
+
77
+ ```pug
78
+ #canvas
79
+ graph
80
+ .id main
81
+ .node
82
+ .id root
83
+ .label Root
84
+ .node
85
+ .id left
86
+ .label Left path
87
+ .node
88
+ .id right
89
+ .label Right path
90
+ .flow
91
+ .from root
92
+ .to left
93
+ .arrow-style forward
94
+ .flow
95
+ .from root
96
+ .to right
97
+ ```
98
+
99
+ The common structure is intentionally small:
100
+
101
+ - `#canvas` contains one or more sibling `graph` components. Graphs never nest.
102
+ - Nodes are declared directly inside their graph and have explicit IDs when flows reference them.
103
+ - Every connection is an explicit `.flow` with `.from` and `.to`.
104
+ - Put a flow inside a graph when both endpoints belong to that graph. Put cross-graph flows directly under `#canvas`.
105
+ - Flow style fields such as `.color`, `.label`, and `.arrow-style` are direct children of `.flow`; there is no nested `.line` group.
106
+ - Blank lines and `//` comment lines are ignored.
107
+
108
+ For a long pipeline, declare each node and each connection at graph level:
109
+
110
+ ```pug
111
+ graph
112
+ .node
113
+ .id start
114
+ .label Start
115
+ .node
116
+ .id validate
117
+ .label Validate
118
+ .node
119
+ .id publish
120
+ .label Publish
121
+ .flow
122
+ .from start
123
+ .to validate
124
+ .flow
125
+ .from validate
126
+ .to publish
127
+ ```
128
+
129
+ This creates `Start -> Validate -> Publish`. A reusable flow class or local fields on each `.flow` style the connector.
130
+
131
+ Flows accept `.direction right`, `.direction left`, `.direction up`, or `.direction down`. Multiple flows may start at the same node—even in the same direction. Multiple outgoing flows are rendered as branches and multiple incoming flows are rendered as a merge. The layout assigns competing paths separate lanes so their nodes do not overlap. Arrowheads are controlled independently with `.arrow-style`.
132
+
133
+ ```pug
134
+ graph
135
+ .node
136
+ .id dispatcher
137
+ .label Dispatcher
138
+ .node
139
+ .id main
140
+ .label Main work
141
+ .node
142
+ .id audit
143
+ .label Audit work
144
+ .flow
145
+ .from dispatcher
146
+ .to main
147
+ .direction right
148
+ .flow
149
+ .from dispatcher
150
+ .to audit
151
+ .direction down
152
+ ```
153
+
154
+ Flows also accept `.ports shared` or `.ports distributed`. Shared ports attach every connection at the center of the relevant node face. Distributed ports space the connections uniformly across that face. Both default to shared ports.
155
+
156
+ ```pug
157
+ .flow
158
+ .from source-id
159
+ .to target-id
160
+ .direction right
161
+ .ports shared
162
+ ```
163
+
164
+ ## Reusable style classes
165
+
166
+ Define a styled node type above `#canvas`, then use its name anywhere you would normally use `node`. It inherits the canvas node defaults and overrides only the fields in its definition.
167
+
168
+ ```pug
169
+ @node my_node
170
+ .shape pill
171
+ .fill #245886
172
+ .color #ffffff
173
+
174
+ @flow warning_flow
175
+ .color #ef4444
176
+ .stroke-style dashed
177
+
178
+ @annotation warning_note
179
+ .color #f59e0b
180
+
181
+ #canvas
182
+ .defaults
183
+ .node
184
+ .outline #111111
185
+ graph
186
+ .my_node
187
+ .id root
188
+ .label Reusable styled node
189
+ .annotation
190
+ .above
191
+ .warning_note
192
+ | Styled annotation
193
+ .node
194
+ .id child
195
+ .label Child
196
+ .flow
197
+ .from root
198
+ .to child
199
+ .warning_flow
200
+ ```
201
+
202
+ Reusable node definitions create classes such as `.my_node`; reusable flow and annotation definitions create decorators such as `.warning_flow` and `.warning_note`. Local fields override the reusable style. Names must be unique across node, flow, and annotation definitions.
203
+
204
+ The complete original definition is preserved in [examples/original.pug](examples/original.pug).
205
+
206
+ ## ID-based flows
207
+
208
+ Give nodes IDs, then use the same `.flow` keyword for convergence, feedback, cross-graph links, or a target that appears later in the source:
209
+
210
+ ```pug
211
+ #canvas
212
+ graph
213
+ .node
214
+ .id api
215
+ .label API
216
+ .node
217
+ .id cache
218
+ .label Cache
219
+ .node
220
+ .id result
221
+ .label Result
222
+ .annotation
223
+ .above Paths converge here
224
+ .shape hexagon
225
+ .flow
226
+ .from api
227
+ .to result
228
+ .label live
229
+ .flow
230
+ .from cache
231
+ .to result
232
+ .label hit
233
+ ```
234
+
235
+ The parser resolves `.from` and `.to` after reading all nodes, so either endpoint may appear before or after the flow declaration. When several flows share a target, Pugflow automatically applies convergence layout and distributed merge routing.
236
+
237
+ For a feedback path, specify the endpoint directions independently:
238
+
239
+ ```pug
240
+ .flow
241
+ .from archived
242
+ .from-direction left
243
+ .to styled-text
244
+ .to-direction up
245
+ .ports shared
246
+ .label feedback
247
+ ```
248
+
249
+ The source and target must have explicit `.id` fields, but may appear before or after the flow declaration. `.from-direction` controls how the flow leaves the source; `.to-direction` independently controls how it enters the target.
250
+
251
+ ## Figure defaults
252
+
253
+ Pugflow has a small built-in rendering theme: white background with black blocks, text, annotations, and connections. Project CSS is optional and additive. Put per-document defaults on `#canvas`:
254
+
255
+ ```pug
256
+ #canvas
257
+ .background #fffaf0
258
+ .font Arial
259
+ .defaults
260
+ .node
261
+ .shape rounded
262
+ .fill #ffffff
263
+ .color #202020
264
+ .outline-width 2
265
+ .align center
266
+ .flow
267
+ .color #303030
268
+ .annotation
269
+ .color #606060
270
+ graph
271
+ .node
272
+ .label Root
273
+ ```
274
+
275
+ `.background` and `.font` belong directly to `#canvas`. Reusable node, flow, and annotation defaults are grouped under `.defaults`. Direct fields on a `.flow` override inherited defaults.
276
+
277
+ ## Block options
278
+
279
+ Node identity, text, layout, and appearance use separate readable fields. For easy scanning, keep them in that order:
280
+
281
+ ```pug
282
+ .node
283
+ .id service
284
+ .layer 1
285
+ .label
286
+ | Service name
287
+ | A clear multiline description
288
+ .width 220
289
+ .height auto
290
+ .align left
291
+ .shape pill
292
+ .fill #1e4f7a
293
+ .color #ffffff
294
+ .outline #93c5fd
295
+ .outline-style dashed
296
+ .outline-width 3
297
+ ```
298
+
299
+ Supported options:
300
+
301
+ | Field | Values |
302
+ | --- | --- |
303
+ | `.id` | A letter followed by letters, numbers, `_`, or `-` |
304
+ | `.layer` | Optional integer override; otherwise declaration order sets stacking within the graph |
305
+ | `.label` | Inline text, or indented `|` lines for explicit multiline text |
306
+ | `.shape` | `square`, `round`, `rounded`, `pill`, `diamond`, `hexagon` |
307
+ | `.fill`, `.color`, `.outline` | Any SVG/CSS color |
308
+ | `.outline-style` | `solid`, `dashed`, `dotted` |
309
+ | `.outline-width` | Number, in SVG pixels |
310
+ | `.width`, `.height` | Number or `auto` |
311
+ | `.align` | `left`, `center`, `right` |
312
+
313
+ Auto-sized blocks measure their content, wrap long labels, and grow vertically. Indented `|` lines create intentional line breaks and keep longer descriptions readable in the source. The old escaped-`\n` form is not supported.
314
+
315
+ ## Block annotations
316
+
317
+ Place any number of annotations above or below a node:
318
+
319
+ ```pug
320
+ .node
321
+ .label Controller
322
+ .annotation
323
+ .above
324
+ .color #bfdbfe
325
+ | Control plane
326
+ | Handles orchestration
327
+ .below Optional subsystem
328
+ ```
329
+
330
+ ## Hide items without changing layout
331
+
332
+ Add `.hidden` beside the node's other fields:
333
+
334
+ ```pug
335
+ .node
336
+ .annotation
337
+ .above Removed in the after diagram
338
+ .id legacy
339
+ .hidden
340
+ .label Legacy service
341
+ ```
342
+
343
+ The block still participates in measurement and layout, so every other block keeps the exact same position. The hidden block, its annotations, and all incoming/outgoing connections (including their labels and arrowheads) are omitted.
344
+
345
+ ## Click, locate, and manually offset
346
+
347
+ Click a block, block label, annotation, connection, or connection label in the preview to select its exact declaration in the editor. Drag boxes and text when the automatic result needs a visual nudge; the editor writes the resulting offsets back into the source. A translucent ghost marks the original position while dragging. Hold Cmd on macOS or Ctrl on other platforms to constrain movement to the dominant horizontal or vertical axis; Shift remains supported as an alternative.
348
+
349
+ Selecting a node or flow also opens the canvas inspector. Ctrl-click (Cmd-click on macOS) toggles additional items into the selection. The inspector shows only controls applicable to every selected item. Every inspector operation edits the Pug source directly.
350
+
351
+ Graphs are packed without overlap by default. Graph titles support `.label-position inside|outside`, `.align left|center|right`, `.color`, and the standard font fields. Use `.x-spacing` and `.y-spacing` to tune a graph's layout. Drag a graph to write its `.offset`; explicit offsets may overlap graph frames. Set `.layer 1` (or any integer) in source, use the inspector's **Graph Layer** selector, or reorder graphs in the collapsible **Graphs** section of the right-side **Graphs** panel. Higher layers render in front and equal layers retain source order. A flow renders at the higher layer of its two endpoint graphs, so it remains visible over both endpoints but may be obscured by an unrelated graph on a higher layer. Choose a graph in that panel to browse its nodes and flows; selecting an item opens its normal property inspector. The node list is ordered front to back. Initially, node declaration order determines that stacking without adding `.layer` fields. Dragging nodes or using **Node Layer** to send selected nodes to the front or back persists explicit `.layer` values in the source.
352
+
353
+ The **Node** builder adds an independent node to the chosen graph. The **Flow** builder places graph-filtered **From** and **To** endpoints side by side, with independent directions and shared flow options.
354
+
355
+ Use **+ New** above the canvas to add a Graph, Node, or Flow without hand-writing its initial structure. Branching, merging, and feedback are inferred from explicit flows. **Add Flow** in a selected node's inspector opens the same builder with that node preselected. These actions insert ordinary Pug; the source remains the single editable representation.
356
+
357
+ - Dragging a box writes `.offset (x, y)` inside its node.
358
+ - Dragging its label writes `.label-offset (x, y)` inside its node.
359
+ - Dragging an image inside a node writes `.image-offset (x, y)` without moving the node.
360
+ - Dragging a block annotation writes an indented `.offset (x, y)` field.
361
+ - Dragging a flow label writes `.label-offset (x, y)` directly inside its `.flow` declaration.
362
+
363
+ Offsets affect only the rendered position. The node's automatic layout slot remains fixed.
364
+
365
+ Use **Clean up** above the canvas after manual positioning to align connected flow nodes and collapse unnecessary bends. It writes corrected `.offset` tuples back into the source without changing flow faces or moving untouched sibling branches.
366
+
367
+ Nodes support SVG drop shadows through `.shadow-color`, `.shadow-offset-x`, `.shadow-offset-y`, `.shadow-blur`, and `.shadow-opacity`. A shadow is enabled when `shadow-color` is present; these fields work in `@node` definitions, diagram defaults, local nodes, and the canvas inspector.
368
+
369
+ Nodes can contain a clipped image using `.image`, with `.image-width`, `.image-height`, `.image-fit` (`contain`, `cover`, or `fill`), `.image-opacity`, and `.image-offset`. These fields work in reusable `@node` styles and in the canvas inspector. Relative paths and same-origin URLs export reliably to PNG; remote images require the image server to allow cross-origin canvas use. SVG exports retain the image URL.
370
+
371
+ ```pug
372
+ .node
373
+ .image photos/sample.png
374
+ .image-width 72
375
+ .image-height 72
376
+ .image-fit cover
377
+ .label Profile
378
+ ```
379
+
380
+ ## Flows, arrows, and annotations
381
+
382
+ Set appearance and annotation properties directly on a `.flow`. Use a reusable `@flow` class when several flows need identical styling.
383
+
384
+ ```pug
385
+ .flow
386
+ .from service-a
387
+ .to service-b
388
+ .arrow-style both
389
+ .stroke-style dashed
390
+ .color #ffffff
391
+ .width 3
392
+ .annotation-above synchronizes
393
+ .annotation-below retry path
394
+ ```
395
+
396
+ | Field | Values |
397
+ | --- | --- |
398
+ | `.arrow-style` | `forward` (default), `backward`, `both`, `none` |
399
+ | `.color` | Any SVG/CSS color |
400
+ | `.stroke-style` | `solid`, `dashed`, `dotted` |
401
+ | `.width` | Positive number |
402
+ | `.annotation-above` | Annotation above the flow |
403
+ | `.annotation-below` | Annotation below the flow |
404
+ | `.annotation-above-hidden`, `.annotation-below-hidden` | Hide either annotation independently |
405
+ | `.label-offset` | Manual `(x, y)` offset |
406
+
407
+ ## Math
408
+
409
+ Use `$...$` for inline math and `$$...$$` for a display equation on its own line. Pugflow uses a bundled MathJax renderer to produce real TeX as SVG paths, including in nodes, node annotations, and connection annotations. Equation dimensions participate in node sizing and diagram layout, and SVG/PNG/CLI exports remain self-contained and offline.
410
+
411
+ ```pug
412
+ .node
413
+ .label Transfer $x_i^2 \\rightarrow y_i$
414
+ ```
415
+
416
+ Display math can be mixed with ordinary multiline labels:
417
+
418
+ ```pug
419
+ .label
420
+ | Quadratic formula
421
+ | $$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$
422
+ ```
423
+
424
+ ## Embed in another page
425
+
426
+ Copy the files in `src/pugflow/web/`, then:
427
+
428
+ ```html
429
+ <link rel="stylesheet" href="./pugflow.css">
430
+ <div id="diagram"></div>
431
+
432
+ <script type="module">
433
+ import { createBlockDiagram } from "./pugflow.mjs";
434
+
435
+ const source = `#canvas
436
+ graph
437
+ .node
438
+ .label Root
439
+ .flow
440
+ .node
441
+ .label Child`;
442
+
443
+ const diagram = createBlockDiagram(document.querySelector("#diagram"), source);
444
+ diagram.render(updatedSource);
445
+ diagram.saveSource("architecture.pug");
446
+ diagram.saveSVG("architecture.svg");
447
+ await diagram.savePNG("architecture.png", 2);
448
+ </script>
449
+ ```
450
+
451
+ The returned object exposes `render(source)`, `toSVGString()`, `saveSource(filename)`, `saveSVG(filename)`, and `savePNG(filename, scale)`.
452
+
453
+ ## Theme and layout
454
+
455
+ Saved Pug figure defaults are usually the most portable option. You can still override CSS properties on the diagram container for an embedded diagram:
456
+
457
+ ```css
458
+ #diagram {
459
+ --diagram-background: #2e6ba7;
460
+ --diagram-label: #eee9dc;
461
+ --diagram-text: #eee9dc;
462
+ --diagram-merge: #ffd166;
463
+ --diagram-annotation: #dbeafe;
464
+ --diagram-font: Verdana, sans-serif;
465
+ }
466
+ ```
467
+
468
+ Pass layout spacing when creating the diagram:
469
+
470
+ ```js
471
+ createBlockDiagram(element, source, {
472
+ layout: { horizontalGutter: 120, verticalGutter: 36, padding: 60 },
473
+ });
474
+ ```
475
+
476
+ ## Project layout
477
+
478
+ ```text
479
+ src/pugflow/
480
+ cli.py Python command-line interface
481
+ server.py HTTP server and health endpoint
482
+ web/ Browser application and reusable ES modules
483
+ tests/
484
+ python/ Server tests
485
+ js/ Parser, layout, and math tests
486
+ examples/ Loadable Pug diagram definitions
487
+ dist/ Generated PyInstaller output (gitignored)
488
+ ```
489
+
490
+ The browser source under `web/` is package data and is served directly as ES modules. There is no generated JavaScript bundle or frontend build step.
491
+
492
+ ## Build a standalone executable
493
+
494
+ The included PyInstaller spec embeds the web frontend alongside the Python server:
495
+
496
+ ```powershell
497
+ python -m pip install pyinstaller
498
+ pyinstaller pugflow.spec
499
+ ```
500
+
501
+ The resulting `dist/pugflow.exe` runs the same web application and opens it in the default browser. PyInstaller is a build-time dependency only; it is not required by the installed application.
502
+
503
+ ## Tests
504
+
505
+ ```powershell
506
+ node --test tests/js
507
+ python -m unittest tests.python.test_server -v
508
+ ```
509
+
510
+ The optional JavaScript tests use the Node.js 18+ built-in runner directly; no npm project or packages are involved. Python server tests use only the standard library. The application itself has no third-party runtime dependencies.