predictygraph 0.2.3__tar.gz → 0.2.4__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 (54) hide show
  1. {predictygraph-0.2.3 → predictygraph-0.2.4}/PKG-INFO +32 -8
  2. {predictygraph-0.2.3 → predictygraph-0.2.4}/README.md +31 -7
  3. {predictygraph-0.2.3 → predictygraph-0.2.4}/pyproject.toml +1 -1
  4. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/layout.py +17 -8
  5. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_stack.py +14 -0
  6. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/__init__.py +0 -0
  7. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/__main__.py +0 -0
  8. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/anim.py +0 -0
  9. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/cli.py +0 -0
  10. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/default.css +0 -0
  11. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/Carlito-Bold.ttf +0 -0
  12. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/Carlito-Regular.ttf +0 -0
  13. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/DejaVuSans-Bold.ttf +0 -0
  14. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/DejaVuSans.ttf +0 -0
  15. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/LiberationMono-Bold.ttf +0 -0
  16. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/LiberationMono-Regular.ttf +0 -0
  17. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/LiberationSans-Bold.ttf +0 -0
  18. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/LiberationSans-Regular.ttf +0 -0
  19. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/LiberationSerif-Bold.ttf +0 -0
  20. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts/LiberationSerif-Regular.ttf +0 -0
  21. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/fonts.py +0 -0
  22. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/ir.py +0 -0
  23. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/model.py +0 -0
  24. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/parser.py +0 -0
  25. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/render/__init__.py +0 -0
  26. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/render/apng.py +0 -0
  27. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/render/svg.py +0 -0
  28. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/route.py +0 -0
  29. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/safe.py +0 -0
  30. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/scene.py +0 -0
  31. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/style.py +0 -0
  32. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/styleutil.py +0 -0
  33. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/text.py +0 -0
  34. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/theme.py +0 -0
  35. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/catppuccin-frappe.toml +0 -0
  36. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/catppuccin-latte.toml +0 -0
  37. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/catppuccin-macchiato.toml +0 -0
  38. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/catppuccin-mocha.toml +0 -0
  39. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/default.toml +0 -0
  40. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/dracula.toml +0 -0
  41. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/github-light.toml +0 -0
  42. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/gruvbox-dark.toml +0 -0
  43. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/hami.toml +0 -0
  44. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/nord.toml +0 -0
  45. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/solarized-dark.toml +0 -0
  46. {predictygraph-0.2.3 → predictygraph-0.2.4}/src/predictygraph/themes/solarized-light.toml +0 -0
  47. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_annotations.py +0 -0
  48. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_diagonal.py +0 -0
  49. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_fixes.py +0 -0
  50. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_hardening.py +0 -0
  51. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_predictygraph.py +0 -0
  52. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_routing.py +0 -0
  53. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_scene.py +0 -0
  54. {predictygraph-0.2.3 → predictygraph-0.2.4}/tests/test_targets.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: predictygraph
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Predictable graphs: a readable, CSS-styled diagram DSL with per-group layouts, rendered to SVG/APNG
5
5
  Author-Email: Reza Jelveh <git@jelveh.me>
6
6
  License: GPL-3.0-or-later
@@ -27,16 +27,40 @@ Editor support: [tree-sitter-pdg](https://github.com/predictygraph/tree-sitter-p
27
27
  Rendered examples and the gallery: [predictygraph.github.io](https://predictygraph.github.io/). This repo keeps
28
28
  only `.pdg` sources; images live in the docs repo (git-lfs).
29
29
 
30
+ ## Install
31
+
32
+ ```bash
33
+ uv tool install "predictygraph[apng]" # or: pipx install "predictygraph[apng]"
34
+ ```
35
+
36
+ `[apng]` adds PNG output. `pdg` is the short alias of the `predictygraph` command.
37
+
38
+ ## Use
39
+
30
40
  ```bash
31
- uv run pdg examples/hami_flow.pdg # -> examples/hami_flow.svg (not committed)
32
- uv run pdg diagram.pdg --css theme.css -o out.svg
33
- uv run pdg diagram.pdg -o out.png # animated PNG (APNG)
34
- uv run pdg diagram.pdg --check # validate only
35
- uv run pdg diagram.pdg -o d.png --width 1000 --colors 64 # small PNG for chat
36
- uv run pdg diagram.pdg --target web # size labels to fit any browser font
41
+ pdg examples/annotations.pdg # -> examples/annotations.svg (not committed)
42
+ pdg diagram.pdg --css theme.css -o out.svg
43
+ pdg diagram.pdg -o out.png # PNG (animated if the diagram moves)
44
+ pdg diagram.pdg --check # validate only
45
+ pdg diagram.pdg -o d.png --width 1000 --colors 64 # small PNG for chat
46
+ pdg diagram.pdg --target web # size labels to fit any browser font
37
47
  ```
38
48
 
39
- `pdg` is the short alias of the `predictygraph` command.
49
+ From a checkout, prefix these with `uv run`. Start with
50
+ [examples/annotations.pdg](examples/annotations.pdg): one small diagram that uses every
51
+ annotation feature, with a comment for each.
52
+
53
+ ## Agent skill
54
+
55
+ [skills/predictygraph](skills/predictygraph) teaches an AI agent to write, render and
56
+ check `.pdg` diagrams.
57
+
58
+ ```bash
59
+ # Hermes Agent
60
+ hermes skills install https://raw.githubusercontent.com/predictygraph/predictygraph/master/skills/predictygraph/SKILL.md
61
+ # Claude Code and other agents that read SKILL.md folders: copy the folder
62
+ cp -r skills/predictygraph ~/.claude/skills/
63
+ ```
40
64
 
41
65
  ## Credits
42
66
 
@@ -13,16 +13,40 @@ Editor support: [tree-sitter-pdg](https://github.com/predictygraph/tree-sitter-p
13
13
  Rendered examples and the gallery: [predictygraph.github.io](https://predictygraph.github.io/). This repo keeps
14
14
  only `.pdg` sources; images live in the docs repo (git-lfs).
15
15
 
16
+ ## Install
17
+
18
+ ```bash
19
+ uv tool install "predictygraph[apng]" # or: pipx install "predictygraph[apng]"
20
+ ```
21
+
22
+ `[apng]` adds PNG output. `pdg` is the short alias of the `predictygraph` command.
23
+
24
+ ## Use
25
+
16
26
  ```bash
17
- uv run pdg examples/hami_flow.pdg # -> examples/hami_flow.svg (not committed)
18
- uv run pdg diagram.pdg --css theme.css -o out.svg
19
- uv run pdg diagram.pdg -o out.png # animated PNG (APNG)
20
- uv run pdg diagram.pdg --check # validate only
21
- uv run pdg diagram.pdg -o d.png --width 1000 --colors 64 # small PNG for chat
22
- uv run pdg diagram.pdg --target web # size labels to fit any browser font
27
+ pdg examples/annotations.pdg # -> examples/annotations.svg (not committed)
28
+ pdg diagram.pdg --css theme.css -o out.svg
29
+ pdg diagram.pdg -o out.png # PNG (animated if the diagram moves)
30
+ pdg diagram.pdg --check # validate only
31
+ pdg diagram.pdg -o d.png --width 1000 --colors 64 # small PNG for chat
32
+ pdg diagram.pdg --target web # size labels to fit any browser font
23
33
  ```
24
34
 
25
- `pdg` is the short alias of the `predictygraph` command.
35
+ From a checkout, prefix these with `uv run`. Start with
36
+ [examples/annotations.pdg](examples/annotations.pdg): one small diagram that uses every
37
+ annotation feature, with a comment for each.
38
+
39
+ ## Agent skill
40
+
41
+ [skills/predictygraph](skills/predictygraph) teaches an AI agent to write, render and
42
+ check `.pdg` diagrams.
43
+
44
+ ```bash
45
+ # Hermes Agent
46
+ hermes skills install https://raw.githubusercontent.com/predictygraph/predictygraph/master/skills/predictygraph/SKILL.md
47
+ # Claude Code and other agents that read SKILL.md folders: copy the folder
48
+ cp -r skills/predictygraph ~/.claude/skills/
49
+ ```
26
50
 
27
51
  ## Credits
28
52
 
@@ -12,7 +12,7 @@ dependencies = [
12
12
  ]
13
13
  requires-python = ">=3.11"
14
14
  readme = "README.md"
15
- version = "0.2.3"
15
+ version = "0.2.4"
16
16
 
17
17
  [project.license]
18
18
  text = "GPL-3.0-or-later"
@@ -160,6 +160,9 @@ class LineLayout(Layout):
160
160
  if j != i + 1:
161
161
  continue
162
162
  w, _, _ = text_block(e.label, e.label_style or e.style, 11, bold=False)
163
+ if e.attrs.get("step"): # the step badge sits just left of the label
164
+ bw, bh, _ = text_block(e.attrs["step"][:3], e.step_style or e.style, 11, bold=True)
165
+ w += max(bw, bh) + 12
163
166
  need[i] = max(need.get(i, 0.0), w + 34)
164
167
  return need
165
168
 
@@ -570,20 +573,26 @@ def shift(item: Item, dx: float) -> None:
570
573
 
571
574
  def align_x(doc: Document) -> None:
572
575
  """`align-x=ID`: centre an item horizontally on another item, e.g. line up a box with
573
- the one it calls in the panel below. It only moves within its parent's content box and
574
- never past a sibling, so nothing overlaps and no group is resized."""
576
+ the one it calls in the panel below. Siblings on the side it moves towards travel with
577
+ it, so every gap (and the edge labels in it) keeps its width; the whole block stays
578
+ inside the parent's content box, so no group is resized and nothing overlaps."""
575
579
  for item in list(doc.walk()):
576
580
  ref = doc.items.get(item.attrs.get("align-x", ""))
577
581
  p = item.parent
578
582
  if ref is None or ref is item or p is None:
579
583
  continue
580
584
  pr = box4(p.style.get("padding"), 14)[1]
581
- sibs = [s for s in p.children if s is not item]
582
- lo = max([s.ax + s.w + 8 for s in sibs if s.ax + s.w <= item.ax + 1e-6], default=p.ax + p.ox)
583
- hi = min([s.ax - 8 for s in sibs if s.ax >= item.ax + item.w - 1e-6], default=p.ax + p.w - pr)
584
- new = min(max(ref.cx - item.w / 2, lo), hi - item.w)
585
- if abs(new - item.ax) > 0.01:
586
- shift(item, new - item.ax)
585
+ lo_edge, hi_edge = p.ax + p.ox, p.ax + p.w - pr
586
+ dx = ref.cx - item.cx
587
+ if dx > 0: # item and everything right of it move right, up to the right edge
588
+ block = [s for s in p.children if s is item or s.ax >= item.ax + item.w - 1e-6]
589
+ dx = min(dx, hi_edge - max(s.ax + s.w for s in block))
590
+ else: # item and everything left of it move left, down to the left edge
591
+ block = [s for s in p.children if s is item or s.ax + s.w <= item.ax + 1e-6]
592
+ dx = max(dx, lo_edge - min(s.ax for s in block))
593
+ if abs(dx) > 0.01:
594
+ for s in block:
595
+ shift(s, dx)
587
596
 
588
597
 
589
598
  def layout(doc: Document) -> None:
@@ -82,3 +82,17 @@ def test_accent_bar_stays_inside_rounded_corners():
82
82
  assert min(ys) > 0 and max(ys) < 40 # starts below the top edge: it follows the arc
83
83
  right = accent_segs(0, 0, 100, 40, 4, 10, "right")
84
84
  assert min(s[-2] for s in right if s[0] != "Z") >= 96
85
+
86
+
87
+ def test_align_x_keeps_gaps_by_moving_neighbours():
88
+ src = ('graph layout=column align=stretch\n'
89
+ 'group top layout=row gap=300 {\n p "p"\n q "q"\n}\n'
90
+ 'group bottom layout=row gap=30 {\n a "aaaa" align-x=q\n b "bbbb"\n}\n'
91
+ 'a -> b "a fairly long label"\n')
92
+ plain = parse(src.replace(" align-x=q", ""))
93
+ build_scene(plain)
94
+ doc = parse(src)
95
+ build_scene(doc)
96
+ gap = lambda d: d.items["b"].ax - (d.items["a"].ax + d.items["a"].w)
97
+ assert abs(gap(doc) - gap(plain)) < 0.01 # b moved with a: the label still fits
98
+ assert doc.items["a"].ax > plain.items["a"].ax