quickdbd-cli 0.1.12__tar.gz → 0.1.13__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 (61) hide show
  1. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/PKG-INFO +5 -1
  2. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/README.md +4 -0
  3. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/pyproject.toml +1 -1
  4. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/scripts/build_gallery.py +2 -2
  5. quickdbd_cli-0.1.13/src/quickdbd_cli/__init__.py +1 -0
  6. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/style.css +78 -59
  7. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/viewer.js +1 -1
  8. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/html.py +27 -6
  9. quickdbd_cli-0.1.12/src/quickdbd_cli/__init__.py +0 -1
  10. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/.gitignore +0 -0
  11. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/LICENSE +0 -0
  12. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/NOTICE +0 -0
  13. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/examples/quickdbd-sample.txt +0 -0
  14. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/examples/synthetic/finance.txt +0 -0
  15. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/examples/synthetic/hr.txt +0 -0
  16. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/examples/synthetic/inventory.txt +0 -0
  17. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/examples/synthetic/marketing.txt +0 -0
  18. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/examples/synthetic/qdbd.layout.json +0 -0
  19. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/examples/synthetic/sales.txt +0 -0
  20. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/scripts/gen_font_metrics.py +0 -0
  21. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/scripts/gen_schema.py +0 -0
  22. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/scripts/gen_thumbnails.py +0 -0
  23. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/scripts/release.sh +0 -0
  24. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/__main__.py +0 -0
  25. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/Inter-Bold.ttf +0 -0
  26. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/Inter-Bold.woff2 +0 -0
  27. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/Inter-LICENSE.txt +0 -0
  28. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/Inter-Regular.ttf +0 -0
  29. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/Inter-Regular.woff2 +0 -0
  30. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/editor.js +0 -0
  31. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/elk-LICENSE.md +0 -0
  32. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/elk.bundled.js +0 -0
  33. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/font-metrics.json +0 -0
  34. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/assets/render.js +0 -0
  35. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/cli.py +0 -0
  36. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/dbt.py +0 -0
  37. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/diff.py +0 -0
  38. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/export.py +0 -0
  39. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/jsrt.py +0 -0
  40. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/layout.py +0 -0
  41. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/measure.py +0 -0
  42. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/model.py +0 -0
  43. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/parser.py +0 -0
  44. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/project.py +0 -0
  45. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/serve.py +0 -0
  46. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/share.py +0 -0
  47. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/src/quickdbd_cli/tags.py +0 -0
  48. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/fixtures/jaffle/LICENSE +0 -0
  49. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/fixtures/jaffle/README.md +0 -0
  50. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/fixtures/jaffle/catalog.json +0 -0
  51. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/fixtures/jaffle/manifest.json +0 -0
  52. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_dbt.py +0 -0
  53. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_diff.py +0 -0
  54. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_gallery.py +0 -0
  55. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_parser.py +0 -0
  56. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_path.py +0 -0
  57. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_pipeline.py +0 -0
  58. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_select.py +0 -0
  59. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_serve.py +0 -0
  60. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_share.py +0 -0
  61. {quickdbd_cli-0.1.12 → quickdbd_cli-0.1.13}/tests/test_tags.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: quickdbd-cli
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Compile QuickDBD-syntax schema files into interactive HTML ER diagrams, with no table limit.
5
5
  Project-URL: Homepage, https://github.com/MarkPhamm/quickdbd-cli
6
6
  Author: Minh (Mark) Pham
@@ -244,6 +244,10 @@ You edit the text; the diagram is generated from it. Table positions are the one
244
244
  - [Schema Diffs](https://qdbd.dev/diffs/), the [GitHub Action](https://qdbd.dev/github-action/) and the [CLI reference](https://qdbd.dev/cli/)
245
245
  - [Development](https://qdbd.dev/development/): working on qdbd itself, releasing, and adding a demo
246
246
 
247
+ ## About the author
248
+
249
+ qdbd is built and maintained by **Minh (Mark) Pham** ([@MarkPhamm](https://github.com/MarkPhamm)). Issues, ideas and pull requests are welcome on [GitHub](https://github.com/MarkPhamm/quickdbd-cli/issues).
250
+
247
251
  ## License
248
252
 
249
253
  Apache-2.0. Bundled third-party files (ELK, Inter) and the sources of the demo schemas are listed in [NOTICE](https://github.com/MarkPhamm/quickdbd-cli/blob/main/NOTICE).
@@ -216,6 +216,10 @@ You edit the text; the diagram is generated from it. Table positions are the one
216
216
  - [Schema Diffs](https://qdbd.dev/diffs/), the [GitHub Action](https://qdbd.dev/github-action/) and the [CLI reference](https://qdbd.dev/cli/)
217
217
  - [Development](https://qdbd.dev/development/): working on qdbd itself, releasing, and adding a demo
218
218
 
219
+ ## About the author
220
+
221
+ qdbd is built and maintained by **Minh (Mark) Pham** ([@MarkPhamm](https://github.com/MarkPhamm)). Issues, ideas and pull requests are welcome on [GitHub](https://github.com/MarkPhamm/quickdbd-cli/issues).
222
+
219
223
  ## License
220
224
 
221
225
  Apache-2.0. Bundled third-party files (ELK, Inter) and the sources of the demo schemas are listed in [NOTICE](https://github.com/MarkPhamm/quickdbd-cli/blob/main/NOTICE).
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "quickdbd-cli"
7
- version = "0.1.12"
7
+ version = "0.1.13"
8
8
  description = "Compile QuickDBD-syntax schema files into interactive HTML ER diagrams, with no table limit."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -37,8 +37,8 @@ KINDS = ("source", "dbt", "of")
37
37
 
38
38
  # Added to every demo page: a way back to the gallery, as the first item of the viewer's toolbar.
39
39
  BACK_LINK = (
40
- '<a href="../" style="color:var(--blue);background:#fff;padding:5px 10px;border-radius:6px;text-decoration:none;'
41
- 'font-weight:500;box-shadow:0 1px 2px rgba(0,0,0,.12)">&larr; All demos</a><div class="sep"></div>'
40
+ '<a href="../" style="color:var(--blue);padding:5px 9px;border-radius:6px;text-decoration:none;'
41
+ 'font-weight:500">&larr; All demos</a><div class="sep"></div>'
42
42
  )
43
43
 
44
44
 
@@ -0,0 +1 @@
1
+ __version__ = "0.1.13"
@@ -1,11 +1,19 @@
1
1
  :root {
2
- --bg: #f4f5f4;
2
+ --bg: #f5f6f7;
3
3
  --blue: #2b5797;
4
- --ink: #333;
5
- --muted: #8a8f96;
4
+ --ink: #15181c;
5
+ --ink-2: #4a515b;
6
+ --muted: #6b7280;
6
7
  --panel: #ffffff;
7
- --line: #dfe3e8;
8
+ --line: #e4e7eb;
9
+ --hover: #f1f3f5;
10
+ --sel: #eaf0f8;
11
+ --amber: #f0a020;
12
+ --shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 8px 24px rgba(16, 24, 40, .07);
8
13
  }
14
+ ::selection { background: #fde3b0; color: var(--ink); }
15
+ :focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }
16
+ * { scrollbar-width: thin; scrollbar-color: #cfd4da transparent; }
9
17
  * { box-sizing: border-box; }
10
18
  html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
11
19
  font-family: Inter, "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; overflow: hidden; }
@@ -26,32 +34,36 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
26
34
  #canvas.panning .t { cursor: grabbing; }
27
35
 
28
36
  /* toolbar (top right, like QuickDBD's zoom controls) */
29
- .bar { position: absolute; top: 14px; right: 16px; display: flex; gap: 6px; align-items: center; }
30
- .bar button, .seg button { border: 0; background: transparent; color: #555; font: inherit; cursor: pointer;
31
- padding: 6px 9px; border-radius: 4px; }
32
- .bar button:hover, .seg button:hover { background: #e4e7ea; }
33
- .bar button.on { background: #fff; color: var(--blue); box-shadow: 0 1px 2px rgba(0,0,0,.12); }
34
- .zoomval { min-width: 48px; text-align: center; color: #666; font-variant-numeric: tabular-nums; }
35
- .seg { display: flex; background: #e9ecee; border-radius: 6px; padding: 2px; }
36
- .seg button.on { background: #fff; color: var(--blue); box-shadow: 0 1px 2px rgba(0,0,0,.12); }
37
- .sep { width: 1px; height: 20px; background: #d5d9dd; margin: 0 4px; }
37
+ .bar { position: absolute; top: 14px; right: 16px; display: flex; gap: 2px; align-items: center; padding: 4px;
38
+ background: var(--panel); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow); z-index: 4; }
39
+ .bar button, .seg button { border: 0; background: transparent; color: var(--ink-2); font: inherit; font-weight: 500;
40
+ cursor: pointer; padding: 5px 9px; border-radius: 6px; transition: background .12s, color .12s; }
41
+ .bar button:hover, .seg button:hover { background: var(--hover); color: var(--ink); }
42
+ .bar button.on { background: var(--ink); color: #fff; }
43
+ .zoomval { min-width: 46px; text-align: center; color: var(--muted); font-variant-numeric: tabular-nums; }
44
+ .seg { display: flex; background: var(--hover); border-radius: 7px; padding: 2px; }
45
+ .seg button.on { background: var(--panel); color: var(--ink); box-shadow: 0 1px 2px rgba(16, 24, 40, .12); }
46
+ .sep { width: 1px; height: 18px; background: var(--line); margin: 0 4px; }
47
+ .bar button svg, .exhead button svg, .details .close svg { display: block; }
48
+ #zin, #zout, #zfit { padding: 5px 6px; }
38
49
 
39
50
  /* explorer (left): search + table tree grouped by file/folder */
40
51
  .explorer { position: absolute; top: 14px; left: 16px; width: 270px; max-height: calc(100% - 60px); display: flex;
41
- flex-direction: column; background: #fff; border: 1px solid var(--line); border-radius: 8px;
42
- box-shadow: 0 4px 14px rgba(0,0,0,.06); z-index: 3; }
52
+ flex-direction: column; background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
53
+ box-shadow: var(--shadow); z-index: 3; }
43
54
  .exhead { display: flex; align-items: center; gap: 4px; padding: 6px; border-bottom: 1px solid var(--line); }
44
55
  .explorer.collapsed .exhead { border-bottom: 0; }
45
- .exhead button { border: 0; background: transparent; cursor: pointer; font-size: 15px; color: #666; padding: 4px 6px; border-radius: 4px; }
46
- .exhead button:hover { background: #eef1f4; }
47
- .exhead input { flex: 1; min-width: 0; padding: 6px 8px; border: 1px solid transparent; border-radius: 5px; font: inherit;
48
- background: #f4f5f6; outline: none; }
49
- .exhead input:focus { border-color: var(--blue); background: #fff; }
56
+ .exhead button { border: 0; background: transparent; cursor: pointer; font-size: 15px; color: var(--muted); padding: 4px 7px; border-radius: 6px; }
57
+ .exhead button:hover { background: var(--hover); color: var(--ink); }
58
+ .exhead input { flex: 1; min-width: 0; padding: 6px 9px; border: 1px solid transparent; border-radius: 7px; font: inherit;
59
+ background: var(--hover); color: var(--ink); outline: none; }
60
+ .exhead input::placeholder, .exfilter input::placeholder, .details .pathbox input::placeholder { color: var(--muted); }
61
+ .exhead input:focus { border-color: var(--ink-2); background: var(--panel); }
50
62
  .exfilter { padding: 6px 6px 4px; border-bottom: 1px solid var(--line); }
51
63
  .explorer.collapsed .exfilter { display: none; }
52
- .exfilter input { width: 100%; padding: 5px 8px; border: 1px solid var(--line); border-radius: 5px; font: 12px Menlo, Consolas, monospace;
53
- outline: none; }
54
- .exfilter input:focus { border-color: var(--blue); }
64
+ .exfilter input { width: 100%; padding: 5px 8px; border: 1px solid var(--line); border-radius: 7px; font: 12px ui-monospace, Menlo, Consolas, monospace;
65
+ color: var(--ink); outline: none; }
66
+ .exfilter input:focus { border-color: var(--ink-2); }
55
67
  .exfilter input.bad { border-color: #e57373; }
56
68
  .fstat { font-size: 11px; color: var(--muted); padding: 3px 2px 0; min-height: 14px; }
57
69
  .fstat.bad { color: #c0392b; }
@@ -62,50 +74,55 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
62
74
  .tchip i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
63
75
  .tchip small { color: var(--muted); }
64
76
  .tchip:hover { border-color: #b8c2d0; }
65
- .tchip.on { border-color: var(--blue); background: #eef3fa; }
77
+ .tchip.on { border-color: var(--ink-2); background: var(--sel); }
66
78
  .tdot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin: 0 6px 1px -13px; vertical-align: middle; }
67
79
  .tree.flat .tdot { margin-left: 0; }
68
80
  .details .ttags { margin: -4px 0 10px; display: flex; gap: 4px; flex-wrap: wrap; }
69
81
  .details .ttag { color: #fff; font-size: 11px; padding: 1px 8px; border-radius: 10px; cursor: pointer; text-decoration: none; }
70
82
  .tree { overflow: auto; padding: 4px 0 8px; }
71
83
  .explorer.collapsed .tree { display: none; }
72
- .gh { padding: 6px 12px 4px; font-size: 11px; font-weight: bold; color: var(--muted); text-transform: uppercase;
73
- letter-spacing: .04em; cursor: pointer; user-select: none; display: flex; justify-content: space-between; }
74
- .gh::before { content: "\25BE"; margin-right: 6px; }
75
- .grp.shut .gh::before { content: "\25B8"; }
84
+ .gh { padding: 8px 12px 4px; font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase;
85
+ letter-spacing: .05em; cursor: pointer; user-select: none; display: flex; align-items: center; justify-content: space-between; }
86
+ .gh::before { content: ""; width: 5px; height: 5px; margin: -2px 9px 0 2px; border-right: 1.5px solid currentColor;
87
+ border-bottom: 1.5px solid currentColor; transform: rotate(45deg); transition: transform .15s; }
88
+ .grp.shut .gh::before { transform: rotate(-45deg); margin-top: 0; }
89
+ .gh:hover { color: var(--ink); }
76
90
  .gh span { font-weight: normal; }
77
91
  .gh .gname { flex: 1; }
78
92
  .grp.shut .gl { display: none; }
79
93
  .ti { padding: 4px 12px 4px 26px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
80
94
  .tree.flat .ti { padding-left: 14px; }
81
95
  .ti small { color: var(--muted); margin-left: 6px; }
82
- .ti:hover, .ti.sel { background: #eef3fa; }
96
+ .ti { border-radius: 6px; margin: 0 6px; padding-left: 20px; }
97
+ .ti:hover { background: var(--hover); }
98
+ .ti.sel { background: var(--sel); }
83
99
  .ti.cur { color: var(--blue); font-weight: bold; }
84
100
  .tree .empty { padding: 8px 14px; color: var(--muted); }
85
101
 
86
102
  /* details drawer (right) */
87
- .details { position: absolute; top: 58px; right: 16px; bottom: 16px; width: 380px; background: #fff;
88
- border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,.08); overflow: auto;
103
+ .details { position: absolute; top: 64px; right: 16px; bottom: 16px; width: 380px; background: var(--panel);
104
+ border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow); overflow: auto;
89
105
  display: none; z-index: 3; padding: 16px 18px; }
90
106
  .details.open { display: block; }
91
107
  .has-details .minimap { right: 412px; }
92
- .details .close { position: absolute; top: 8px; right: 10px; border: 0; background: transparent; font-size: 20px;
93
- color: #888; cursor: pointer; }
94
- .details h2 { margin: 0 24px 2px 0; font-size: 18px; color: var(--blue); word-break: break-word; }
108
+ .details .close { position: absolute; top: 10px; right: 10px; width: 28px; height: 28px; border: 0; border-radius: 6px;
109
+ background: transparent; display: flex; align-items: center; justify-content: center; color: var(--muted); cursor: pointer; }
110
+ .details .close:hover { background: var(--hover); color: var(--ink); }
111
+ .details h2 { margin: 0 28px 2px 0; font-size: 18px; font-weight: 650; letter-spacing: -.01em; color: var(--ink); word-break: break-word; }
95
112
  .details .meta { color: var(--muted); font-size: 12px; margin-bottom: 10px; }
96
113
  .details .doc { white-space: pre-wrap; margin: 8px 0 12px; line-height: 1.45; }
97
- .details h3 { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 16px 0 6px; }
114
+ .details h3 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 18px 0 6px; }
98
115
  .details table { width: 100%; border-collapse: collapse; font-size: 12px; }
99
- .details td { padding: 5px 4px; border-top: 1px solid #eef0f2; vertical-align: top; }
116
+ .details td { padding: 6px 4px; border-top: 1px solid var(--line); vertical-align: top; }
100
117
  .details td.cn { font-weight: 600; word-break: break-word; }
101
- .details td.ct { color: #888; text-align: right; white-space: nowrap; }
102
- .details .cd { color: #666; font-weight: normal; margin-top: 2px; white-space: pre-wrap; }
118
+ .details td.ct { color: var(--muted); text-align: right; white-space: nowrap; }
119
+ .details .cd { color: var(--ink-2); font-weight: normal; margin-top: 2px; white-space: pre-wrap; }
103
120
  .details .tag { display: inline-block; font-size: 10px; padding: 0 5px; border-radius: 3px; background: #eef1f5;
104
121
  color: #6b7a8c; margin: 0 3px 0 0; font-weight: normal; }
105
122
  .details .tag.pk { background: #dfe8f6; color: var(--blue); }
106
123
  .details .tag.fk { background: #ece6f7; color: #6a4fa3; }
107
124
  .details ul { list-style: none; margin: 0; padding: 0; }
108
- .details li { padding: 5px 0; border-top: 1px solid #eef0f2; }
125
+ .details li { padding: 6px 0; border-top: 1px solid var(--line); }
109
126
  .details a { color: var(--blue); text-decoration: none; cursor: pointer; }
110
127
  .details a:hover { text-decoration: underline; }
111
128
  .details .card { color: var(--muted); font-size: 11px; margin-left: 4px; }
@@ -113,22 +130,23 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
113
130
  .details .hidden { color: var(--muted); }
114
131
 
115
132
  /* minimap (bottom right) */
116
- .minimap { position: absolute; right: 16px; bottom: 16px; width: 200px; height: 140px; background: rgba(255,255,255,.9);
117
- border: 1px solid var(--line); border-radius: 6px; overflow: hidden; cursor: pointer; }
133
+ .minimap { position: absolute; right: 16px; bottom: 16px; width: 200px; height: 140px; background: rgba(255, 255, 255, .94);
134
+ border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow); overflow: hidden; cursor: pointer; }
118
135
  .minimap svg { width: 100%; height: 100%; display: block; }
119
136
  .minimap .vpr { fill: rgba(43,87,151,.12); stroke: var(--blue); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
120
137
 
121
- .toast { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); background: #23272b; color: #fff;
122
- padding: 8px 14px; border-radius: 6px; font-size: 12px; opacity: 0; transition: opacity .2s; pointer-events: none; z-index: 6; }
138
+ .toast { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); background: var(--ink); color: #fff;
139
+ padding: 8px 14px; border-radius: 8px; font-size: 12px; opacity: 0; transition: opacity .2s; pointer-events: none; z-index: 6; }
123
140
  .toast.open { opacity: 1; }
124
141
 
125
142
  /* path finder (in the details panel) */
126
143
  .details .pathbox { display: flex; gap: 6px; margin: 10px 0 4px; }
127
- .details .pathbox input { flex: 1; min-width: 0; padding: 5px 8px; border: 1px solid var(--line); border-radius: 5px; font: inherit; outline: none; }
128
- .details .pathbox input:focus { border-color: var(--blue); }
144
+ .details .pathbox input { flex: 1; min-width: 0; padding: 6px 9px; border: 1px solid var(--line); border-radius: 7px; font: inherit;
145
+ color: var(--ink); outline: none; }
146
+ .details .pathbox input:focus { border-color: var(--ink-2); }
129
147
  .details .pathres ol { margin: 6px 0 8px 18px; padding: 0; }
130
148
  .details .pathres li { border: 0; padding: 2px 0; }
131
- .details .pathres pre { background: #f6f8fa; border: 1px solid #eceff2; border-radius: 6px; padding: 8px; font-size: 11px;
149
+ .details .pathres pre { background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 8px; font-size: 11px;
132
150
  overflow-x: auto; margin: 6px 0; }
133
151
  .details .pathres .acts a { margin-right: 12px; font-size: 12px; }
134
152
  .details .pathres .none { margin-top: 6px; }
@@ -137,8 +155,8 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
137
155
  .t.ph .tb { stroke: #f0a020; stroke-width: 2.5; }
138
156
 
139
157
  /* diff banner (build --diff-base) */
140
- .diffbar { position: absolute; top: 58px; left: 50%; transform: translateX(-50%); background: #fff; border: 1px solid var(--line);
141
- border-radius: 8px; padding: 6px 12px; font-size: 12px; box-shadow: 0 4px 14px rgba(0,0,0,.06); display: none; z-index: 2;
158
+ .diffbar { position: absolute; top: 64px; left: 50%; transform: translateX(-50%); background: var(--panel); border: 1px solid var(--line);
159
+ border-radius: 10px; padding: 7px 14px; font-size: 12px; box-shadow: var(--shadow); display: none; z-index: 2;
142
160
  white-space: nowrap; }
143
161
  .diffbar.open { display: block; }
144
162
  .diffbar b.add { color: #2e7d32; }
@@ -155,7 +173,7 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
155
173
  .details .state.changed { background: #d48806; }
156
174
 
157
175
  /* doc-comment tooltip */
158
- .tip { position: absolute; display: none; max-width: 340px; background: #23272b; color: #eee; border-radius: 6px;
176
+ .tip { position: absolute; display: none; max-width: 340px; background: var(--ink); color: #eef0f2; border-radius: 8px;
159
177
  padding: 8px 10px; font-size: 12px; line-height: 1.45; pointer-events: none; box-shadow: 0 4px 14px rgba(0,0,0,.25);
160
178
  z-index: 5; }
161
179
  .tip.open { display: block; }
@@ -166,17 +184,18 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
166
184
  .hint { position: absolute; left: 16px; bottom: 14px; color: var(--muted); font-size: 12px; }
167
185
 
168
186
  /* serve: editor pane */
169
- #side { width: 420px; display: flex; flex-direction: column; background: #343a40; color: #ddd; border-right: 1px solid #222; }
187
+ #side { width: 420px; display: flex; flex-direction: column; background: #0f1114; color: #d9dce1; border-right: 1px solid #000; }
170
188
  #side.hidden { display: none; }
171
- .tabs { display: flex; overflow-x: auto; background: #2b3035; flex: none; }
172
- .tabs button { background: transparent; color: #aab; border: 0; padding: 8px 12px; font: inherit; cursor: pointer; white-space: nowrap; }
173
- .tabs button.on { color: #fff; background: #343a40; }
189
+ .tabs { display: flex; overflow-x: auto; background: #08090b; border-bottom: 1px solid rgba(255, 255, 255, .08); flex: none; }
190
+ .tabs button { background: transparent; color: #a1a7b0; border: 0; padding: 9px 13px; font: inherit; cursor: pointer; white-space: nowrap; }
191
+ .tabs button:hover { color: #edeef0; }
192
+ .tabs button.on { color: #edeef0; background: #0f1114; box-shadow: inset 0 -2px 0 var(--amber); }
174
193
  .tabs button .dirty { color: #f0a020; }
175
194
  #editor { flex: 1; min-height: 0; position: relative; }
176
195
  #editor .CodeMirror, #editor textarea { position: absolute; inset: 0; height: 100%; width: 100%; font-size: 13px;
177
- font-family: Menlo, Consolas, monospace; background: #343a40; color: #ddd; border: 0; padding: 6px; resize: none; }
178
- #problems { height: 140px; flex: none; overflow: auto; border-top: 2px solid #4caf50; padding: 8px 10px;
179
- font-family: Menlo, Consolas, monospace; font-size: 12px; color: #ccc; }
196
+ font-family: ui-monospace, Menlo, Consolas, monospace; background: #0f1114; color: #d9dce1; border: 0; padding: 6px; resize: none; }
197
+ #problems { height: 140px; flex: none; overflow: auto; border-top: 2px solid #4ade80; padding: 8px 10px; background: #08090b;
198
+ font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; color: #a1a7b0; }
180
199
  #problems.bad { border-top-color: #e57373; }
181
200
  #problems .err { color: #ff9b9b; cursor: pointer; }
182
201
  #problems .warn { color: #f0c674; cursor: pointer; }
@@ -185,17 +204,17 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
185
204
  .banner button { margin-left: 8px; }
186
205
  .cm-qdbd-op { color: #f0a020; }
187
206
  .cm-qdbd-kw { color: #8fbcff; }
188
- .CodeMirror-gutters { background: #2f353a !important; border-right: 0 !important; }
207
+ .CodeMirror-gutters { background: #0b0c0f !important; border-right: 0 !important; }
189
208
  .cm-s-default .cm-comment { color: #7f8c8d; }
190
209
  .cm-s-default .cm-header { color: #6fc3df; }
191
210
  .CodeMirror-cursor { border-left-color: #fff !important; }
192
- .CodeMirror-selected { background: #4a525a !important; }
211
+ .CodeMirror-selected { background: #2a2e35 !important; }
193
212
  .lineerr { background: rgba(229,115,115,.18); }
194
213
 
195
214
  /* narrow screens and embedded frames: toolbar to the bottom, smaller minimap */
196
215
  @media (max-width: 900px) {
197
216
  .bar { top: auto; bottom: 12px; right: auto; left: 12px; flex-wrap: wrap; max-width: calc(100% - 24px);
198
- background: rgba(255,255,255,.92); border-radius: 8px; padding: 2px; box-shadow: 0 2px 10px rgba(0,0,0,.08); }
217
+ border-radius: 10px; padding: 3px; }
199
218
  .hint { display: none; }
200
219
  .minimap { width: 140px; height: 100px; bottom: auto; top: 14px; right: 12px; }
201
220
  .explorer { max-width: calc(100% - 180px); }
@@ -60,7 +60,7 @@
60
60
  // Keep clear of the floating search box / toolbar at the top and, on narrow screens, the toolbar at the bottom.
61
61
  var top = 70, bottom = sz[0] < 900 ? 70 : pad, availH = sz[1] - top - bottom;
62
62
  var k = Math.min((sz[0] - 2 * pad) / (b[2] - b[0]), availH / (b[3] - b[1]), 1.5);
63
- k = Math.max(k, 0.05);
63
+ k = Math.max(k, 0.03); // same floor as manual zoom, so wide diagrams still fit a phone screen
64
64
  S.view = { k: k, x: (sz[0] - (b[2] - b[0]) * k) / 2 - b[0] * k, y: top + (availH - (b[3] - b[1]) * k) / 2 - b[1] * k };
65
65
  applyView();
66
66
  }
@@ -23,6 +23,25 @@ def _escape(text: str) -> str:
23
23
  return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;")
24
24
 
25
25
 
26
+ def _icon(d: str) -> str:
27
+ """A 16px stroke icon, drawn in the toolbar's text colour."""
28
+ return (
29
+ '<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true">'
30
+ f'<path d="{d}" fill="none" stroke="currentColor" stroke-width="1.8"'
31
+ ' stroke-linecap="round" stroke-linejoin="round"/>'
32
+ "</svg>"
33
+ )
34
+
35
+
36
+ ICONS = {
37
+ "icon_menu": _icon("M4 6h16M4 12h16M4 18h16"),
38
+ "icon_close": _icon("M6 6l12 12M18 6L6 18"),
39
+ "icon_minus": _icon("M5 12h14"),
40
+ "icon_plus": _icon("M12 5v14M5 12h14"),
41
+ "icon_fit": _icon("M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5"),
42
+ }
43
+
44
+
26
45
  BODY = """
27
46
  <div id="app">
28
47
  {side}
@@ -30,7 +49,7 @@ BODY = """
30
49
  <svg id="canvas" xmlns="http://www.w3.org/2000/svg"><g id="vp"></g></svg>
31
50
  <div class="explorer" id="explorer">
32
51
  <div class="exhead">
33
- <button id="extoggle" title="Show/hide table list">&#9776;</button>
52
+ <button id="extoggle" title="Show/hide table list" aria-label="Show or hide the table list">{icon_menu}</button>
34
53
  <input id="q" type="search" placeholder="Search {count} tables ( / )" autocomplete="off" spellcheck="false">
35
54
  </div>
36
55
  <div class="exfilter">
@@ -42,7 +61,7 @@ BODY = """
42
61
  <div id="tree" class="tree"></div>
43
62
  </div>
44
63
  <aside class="details" id="details" aria-label="Table details">
45
- <button class="close" id="dclose" title="Close (Esc)">&times;</button>
64
+ <button class="close" id="dclose" title="Close (Esc)" aria-label="Close">{icon_close}</button>
46
65
  <div id="dbody"></div>
47
66
  </aside>
48
67
  <div class="bar">
@@ -59,10 +78,10 @@ BODY = """
59
78
  <button id="xpng" title="Export PNG">PNG</button>
60
79
  <button id="xdrawio" title="Export an editable draw.io / diagrams.net file">draw.io</button>
61
80
  <div class="sep"></div>
62
- <button id="zout" title="Zoom out">&#8722;</button>
81
+ <button id="zout" title="Zoom out" aria-label="Zoom out">{icon_minus}</button>
63
82
  <span class="zoomval" id="zoomval">100%</span>
64
- <button id="zin" title="Zoom in">+</button>
65
- <button id="zfit" title="Fit to screen">&#9678;</button>
83
+ <button id="zin" title="Zoom in" aria-label="Zoom in">{icon_plus}</button>
84
+ <button id="zfit" title="Fit to screen" aria-label="Fit to screen">{icon_fit}</button>
66
85
  </div>
67
86
  <div class="minimap">
68
87
  <svg id="mini" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet"></svg>
@@ -113,7 +132,9 @@ def render_page(model: dict, positions: dict, title: str, serve: bool = False, l
113
132
  hint = (
114
133
  "Drag tables to rearrange (not saved). Click a table for details. Scroll to zoom, drag empty space to pan."
115
134
  )
116
- body = BODY.format(side=SIDE if serve else "", count=len(model["tables"]), hint=hint, filter_help=FILTER_HELP)
135
+ body = BODY.format(
136
+ side=SIDE if serve else "", count=len(model["tables"]), hint=hint, filter_help=FILTER_HELP, **ICONS
137
+ )
117
138
  head_extra = ""
118
139
  scripts = ""
119
140
  if serve:
@@ -1 +0,0 @@
1
- __version__ = "0.1.12"
File without changes
File without changes
File without changes