quickdbd-cli 0.3.0__py3-none-any.whl → 0.3.2__py3-none-any.whl

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.
quickdbd_cli/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.3.0"
1
+ __version__ = "0.3.2"
quickdbd_cli/agent.py CHANGED
@@ -471,6 +471,8 @@ def describe_tables(ws: Workspace, args: dict) -> Result:
471
471
  flags.append("auto")
472
472
  if col["default"] is not None:
473
473
  flags.append(f"default={col['default']}")
474
+ if col.get("tags"):
475
+ flags.append(f"tags {', '.join(col['tags'])}")
474
476
  if col["type"] in enums:
475
477
  vals = enums[col["type"]]
476
478
  flags.append("enum(" + ", ".join(vals[:20]) + (", …" if len(vals) > 20 else "") + ")")
@@ -52,14 +52,14 @@
52
52
  return set;
53
53
  }
54
54
 
55
- /* Visible columns of each table for a collapse mode: "full" | "keys" | "header". */
55
+ /* Visible columns of each table for a collapse mode: "full" | "keys" | "header". Tagged columns count as keys. */
56
56
  function geometry(model, mode) {
57
57
  var st = model.style, rel = mode === "keys" ? relatedColumns(model) : null, out = {};
58
58
  model.tables.forEach(function (t) {
59
59
  var cols = [];
60
60
  if (mode !== "header") {
61
61
  t.cols.forEach(function (c) {
62
- if (mode === "full" || c.pk || c.fk || rel[t.id + "\u0000" + c.id]) cols.push(c);
62
+ if (mode === "full" || c.pk || c.fk || c.color || rel[t.id + "\u0000" + c.id]) cols.push(c);
63
63
  });
64
64
  }
65
65
  var rows = {};
@@ -105,14 +105,22 @@
105
105
  g.cols.forEach(function (c, i) {
106
106
  var y = st.headerH + i * st.rowH, cy = y + st.rowH / 2, base = n(cy + st.rowSize * 0.36);
107
107
  var weight = c.pk || c.fk ? ' font-weight="bold"' : "";
108
- var color = c.pk ? C.pk : c.fk ? C.fk : C.text, rn = c.pk ? "rn rpk" : c.fk ? "rn rfk" : "rn";
108
+ var color = c.color || (c.pk ? C.pk : c.fk ? C.fk : C.text), rn = c.pk ? "rn rpk" : c.fk ? "rn rfk" : "rn";
109
109
  out.push('<g class="r" data-c="' + esc(c.id) + '">');
110
+ // a tagged column: tinted row and a bar in the tag colour (a diff bar, drawn next, covers the bar)
111
+ if (c.color) {
112
+ out.push('<rect y="' + y + '" width="' + w + '" height="' + st.rowH + '" fill="' + c.color + '" fill-opacity=".1"/>');
113
+ out.push('<rect y="' + (y + 3) + '" width="3" height="' + (st.rowH - 6) + '" fill="' + c.color + '"/>');
114
+ }
110
115
  out.push('<rect class="rb" y="' + y + '" width="' + w + '" height="' + st.rowH + '" fill="' + C.body + '" fill-opacity="0"/>');
111
116
  var cstate = t.diff && t.diff.cols && t.diff.cols[c.id];
112
117
  if (cstate) out.push('<rect y="' + (y + 3) + '" width="3" height="' + (st.rowH - 6) + '" fill="' + C[cstate] + '"/>');
113
- out.push('<text class="' + rn + '" x="' + st.padX + '" y="' + base + '" fill="' + color + '" font-family="' + FONT + '" font-size="' +
114
- st.rowSize + '"' + weight + ">" + esc(c.name) + "</text>");
118
+ out.push('<text class="' + rn + '" x="' + st.padX + '" y="' + base + '" fill="' + color + '"' + (c.color ? ' style="fill:' + c.color + '"' : "") +
119
+ ' font-family="' + FONT + '" font-size="' + st.rowSize + '"' + weight + ">" + esc(c.name) + "</text>");
115
120
  if (docMarks && c.doc) out.push(docMark(st.padX, cy + st.rowSize * 0.36 + 2.5, c.nameW, color));
121
+ if (c.tags && c.tags.indexOf("removed") >= 0) {
122
+ out.push('<line x1="' + st.padX + '" y1="' + n(cy) + '" x2="' + n(st.padX + c.nameW) + '" y2="' + n(cy) + '" stroke="' + color + '" stroke-width="1.2"/>');
123
+ }
116
124
  var bx = st.padX + c.nameW + 6;
117
125
  c.badges.forEach(function (b) {
118
126
  var bh = st.badgeSize + 5;
@@ -337,11 +345,12 @@
337
345
  }, g(0, HEADH + i * ROWH, w, ROWH)));
338
346
  var base = "shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;html=0;";
339
347
  var flags = c.badges.map(function (x) { return x.t; }).join(" ");
348
+ var fs = (c.pk ? 5 : c.fk ? 1 : 0) | (c.tags && c.tags.indexOf("removed") >= 0 ? 8 : 0); // bold, underline, strike
340
349
  cells.push(cell({ id: id(), value: key, vertex: "1", parent: rid, style: base + "fontStyle=1;fontColor=#2b5797;align=center;fontSize=11;" },
341
350
  g(0, 0, KEYW, ROWH)));
342
351
  cells.push(cell({
343
352
  id: id(), value: c.name + (flags ? " [" + flags + "]" : "") + (c.type ? " : " + c.type : ""), vertex: "1", parent: rid,
344
- style: base + "align=left;spacingLeft=6;fontSize=12;" + (c.pk ? "fontStyle=5;" : c.fk ? "fontStyle=1;" : ""),
353
+ style: base + "align=left;spacingLeft=6;fontSize=12;" + (fs ? "fontStyle=" + fs + ";" : "") + (c.color ? "fontColor=" + c.color + ";" : ""),
345
354
  }, g(KEYW, 0, w - KEYW, ROWH)));
346
355
  });
347
356
  });
@@ -407,7 +416,10 @@
407
416
  else if (method === "group") ok = re.test(t.group || "") || (t.group || "").toLowerCase().indexOf(pat.toLowerCase() + "/") === 0;
408
417
  else if (method === "file") ok = re.test(t.file || "") || re.test((t.file || "").split("/").pop());
409
418
  else if (method === "col" || method === "column") ok = t.cols.some(function (c) { return re.test(c.name); });
410
- else if (method === "tag") ok = (t.tags || []).some(function (x) { return re.test(x); });
419
+ else if (method === "tag") {
420
+ var has = function (x) { return re.test(x); };
421
+ ok = (t.tags || []).some(has) || t.cols.some(function (c) { return (c.tags || []).some(has); });
422
+ }
411
423
  else if (method === "diff" || method === "state") {
412
424
  var ds = t.diff && t.diff.state, want = pat.toLowerCase();
413
425
  ok = !!ds && (want === "modified" || want === "*" || want === ds || (want === "new" && ds === "added"));
@@ -78,6 +78,7 @@ Declare a relationship once, in either direction.
78
78
  - `#` starts a comment, except inside double quotes. Comment lines directly above a table or column, plus a comment at the end of its line, become its documentation.
79
79
  - Tags give tables a role and a header colour: `# @tag: gold, pii` above a table. Names like `dim_`, `fct_`, `stg_`, `int_`, `raw_` are tagged automatically.
80
80
  - `# @color gold #b8860b` sets a tag's colour (anywhere in any file).
81
+ - Columns take tags too, on or above the column line: `discount decimal # @tag: added`. The row is tinted in the tag's colour; `added` is green, `removed` is red and struck through. Use them to mark proposed column changes for review.
81
82
 
82
83
  ## Settings and layout sections
83
84
 
@@ -552,6 +552,10 @@
552
552
  if (c.pk) tags.push('<span class="tag pk">PK</span>');
553
553
  if (c.fk) tags.push('<span class="tag fk">FK</span>');
554
554
  c.badges.forEach(function (b) { tags.push('<span class="tag">' + Q.esc(b.t) + "</span>"); });
555
+ (c.tags || []).forEach(function (g) {
556
+ var tc = (S.model.tags || []).filter(function (x) { return x.name === g; })[0];
557
+ tags.push('<a class="ttag" data-tag="' + Q.esc(g) + '" style="background:' + Q.esc(tc ? tc.color : "#2b5797") + '">' + Q.esc(g) + "</a>");
558
+ });
555
559
  out.push('<tr><td class="cn">' + Q.esc(c.name) + " " + tags.join("") + (c.doc ? '<div class="cd">' + Q.esc(c.doc) + "</div>" : "") +
556
560
  '</td><td class="ct">' + Q.esc(c.type) + "</td></tr>");
557
561
  });
quickdbd_cli/convert.py CHANGED
@@ -82,7 +82,7 @@ def canonical(schema: Schema, lost: set[tuple]) -> dict:
82
82
  continue
83
83
  col = {
84
84
  "type": c.type or "", "pk": c.pk, "unique": c.unique, "index": c.index, "nullable": c.nullable,
85
- "identity": c.identity, "default": _norm_default(c.default), "doc": _doc(c.comments),
85
+ "identity": c.identity, "default": _norm_default(c.default), "doc": _doc(c.comments), "tags": c.tags,
86
86
  } # fmt: skip
87
87
  for k in list(col):
88
88
  if ("col", t.name, c.name, k) in lost:
@@ -202,7 +202,8 @@ class _DbmlWriter:
202
202
  self.res.lost.add(("col", t.name, c.name, "type"))
203
203
  typ = "unknown"
204
204
  typ = typ if _DBML_TYPE.fullmatch(typ) else _dbml_name(typ)
205
- out.append(f" {_dbml_name(c.name)} {typ}" + (f" [{', '.join(settings)}]" if settings else ""))
205
+ tags = f" // @tag: {', '.join(c.tags)}" if c.tags else ""
206
+ out.append(f" {_dbml_name(c.name)} {typ}" + (f" [{', '.join(settings)}]" if settings else "") + tags)
206
207
  if indexed:
207
208
  out += ["", " indexes {"] + [f" {_dbml_name(n)}" for n in indexed] + [" }"]
208
209
  if t.comments:
@@ -367,6 +368,8 @@ class _QuickdbdWriter:
367
368
  self.res.lost.add(("col", t.name, c.name, "default"))
368
369
  c = dataclasses.replace(c, default=None)
369
370
  out += [f"# {x}" for x in c.comments if x.strip()]
371
+ if c.tags:
372
+ out.append(f"# @tag: {', '.join(c.tags)}")
370
373
  out.append(_quickdbd_column(c, self.fks.get((t.id, c.id), [])))
371
374
  return out
372
375
 
quickdbd_cli/dbml.py CHANGED
@@ -1131,6 +1131,7 @@ class _Interpreter:
1131
1131
  elif s.key == "note" and s.value and s.value[0].kind in ("str", "quoted"):
1132
1132
  v = s.value[0]
1133
1133
  col.comments = _doc_lines(_normalize_note(v.value) if v.multiline else v.value)
1134
+ self._col_tags(col)
1134
1135
  t.columns[col.id] = col
1135
1136
  for ix in indexes:
1136
1137
  missing = [c for c in ix.columns if encode(c) not in t.columns]
@@ -1291,6 +1292,18 @@ class _Interpreter:
1291
1292
  target[:0] = [x for x in split_tags(m.group(2)) if x not in target]
1292
1293
  line -= 1
1293
1294
 
1295
+ def _col_tags(self, col: Column) -> None:
1296
+ """`// @tag:` at the end of the column's line, or on comment lines right above it."""
1297
+ lines = [col.line]
1298
+ line = col.line - 1
1299
+ while line in self.comments and line not in self.code_lines:
1300
+ lines.append(line)
1301
+ line -= 1
1302
+ for line in reversed(lines):
1303
+ m = TAG_RE.match(self.comments.get(line, ""))
1304
+ if m and not m.group(1).lower().startswith("dbt"):
1305
+ col.tags += [x for x in split_tags(m.group(2)) if x not in col.tags]
1306
+
1294
1307
  def colors(self) -> None:
1295
1308
  first_code = min(self.code_lines, default=0)
1296
1309
  self.fp.general_comments = [
quickdbd_cli/measure.py CHANGED
@@ -79,6 +79,8 @@ def _column_json(col: Column) -> dict:
79
79
  }
80
80
  if col.comments:
81
81
  out["doc"] = "\n".join(col.comments)
82
+ if col.tags:
83
+ out["tags"] = list(col.tags)
82
84
  return out
83
85
 
84
86
 
quickdbd_cli/model.py CHANGED
@@ -47,6 +47,7 @@ class Column:
47
47
  default: str | None = None
48
48
  virtual: bool = False
49
49
  comments: list[str] = field(default_factory=list)
50
+ tags: list[str] = field(default_factory=list) # `# @tag: ...` comments
50
51
 
51
52
 
52
53
  @dataclass
quickdbd_cli/parser.py CHANGED
@@ -475,7 +475,13 @@ class _FileParser:
475
475
  if is_virtual(ident):
476
476
  return Column(VIRTUAL_FIELD, "", e.line, virtual=True)
477
477
  tokens = [tokens[0]] + self._merge_paren_tokens(tokens[1:], e.line)
478
- col = Column(ident, name, e.line, comments=list(e.comments))
478
+ col = Column(ident, name, e.line)
479
+ for c in e.comments:
480
+ m = TAG_RE.match(c)
481
+ if m and not m.group(1).lower().startswith("dbt"):
482
+ col.tags += [t for t in split_tags(m.group(2)) if t not in col.tags]
483
+ else:
484
+ col.comments.append(c)
479
485
  fk_at = -1
480
486
  d = 0
481
487
  while d + 1 < len(tokens):
quickdbd_cli/tags.py CHANGED
@@ -8,10 +8,15 @@ A table's tags come from the first source that has any:
8
8
 
9
9
  The header takes the colour of the table's first tag. ``# @color TAG #hex`` overrides the defaults, and a DBML
10
10
  ``headercolor`` beats both.
11
+
12
+ Columns take tags too (``# @tag: added`` on or above the column line), which mark the row in the first tag's colour;
13
+ ``added`` and ``removed`` default to green and red, for hand-marked proposed changes.
11
14
  """
12
15
 
13
16
  from __future__ import annotations
14
17
 
18
+ from collections.abc import Iterable
19
+
15
20
  from .model import Schema, Table
16
21
 
17
22
  # tag -> name prefixes (matched as `prefix_...` or `PrefixName`)
@@ -23,13 +28,16 @@ NAME_TAGS: list[tuple[str, tuple[str, ...]]] = [
23
28
  ("raw", ("raw", "src")),
24
29
  ]
25
30
 
26
- # Defaults avoid the diff colours (green = added, amber = changed) and the untagged blue.
31
+ # Table-role defaults avoid the diff colours (green = added, amber = changed) and the untagged blue; `added` and
32
+ # `removed` are meant for columns, and use the diff green on purpose.
27
33
  DEFAULT_COLORS = {
28
34
  "dim": "#00838f",
29
35
  "fact": "#c2185b",
30
36
  "staging": "#546e7a",
31
37
  "intermediate": "#7b1fa2",
32
38
  "raw": "#6d4c41",
39
+ "added": "#2e7d32",
40
+ "removed": "#c62828",
33
41
  }
34
42
  PALETTE = ["#0277bd", "#4527a0", "#00695c", "#ad1457", "#827717", "#bf360c", "#37474f", "#283593", "#5d4037"]
35
43
 
@@ -65,9 +73,9 @@ def table_tags(t: Table) -> list[str]:
65
73
  return list(t.dbt_tags)
66
74
 
67
75
 
68
- def tag_colors(schema: Schema, tags_by_table: dict[str, list[str]]) -> dict[str, str]:
76
+ def tag_colors(schema: Schema, tag_lists: Iterable[list[str]]) -> dict[str, str]:
69
77
  """Colour of every tag in use: explicit @color, else the default, else the next palette colour (by name)."""
70
- used = sorted({tag for tags in tags_by_table.values() for tag in tags})
78
+ used = sorted({tag for tags in tag_lists for tag in tags})
71
79
  out: dict[str, str] = {}
72
80
  i = 0
73
81
  for tag in used:
@@ -82,17 +90,22 @@ def tag_colors(schema: Schema, tags_by_table: dict[str, list[str]]) -> dict[str,
82
90
 
83
91
 
84
92
  def annotate(schema: Schema, tables: list[dict]) -> list[dict]:
85
- """Add ``tags`` and ``color`` to each table dict of the model JSON; return the legend."""
93
+ """Add ``tags`` and ``color`` to each table dict of the model JSON, and ``color`` to tagged columns; return the
94
+ legend (count = tables carrying the tag, on the table or on a column)."""
86
95
  by_id = {t["id"]: table_tags(schema.tables[t["id"]]) for t in tables}
87
- colors = tag_colors(schema, by_id)
96
+ col_tags = {t["id"]: [g for c in t["cols"] for g in c.get("tags", [])] for t in tables}
97
+ colors = tag_colors(schema, [*by_id.values(), *col_tags.values()])
88
98
  counts: dict[str, int] = {}
89
99
  for t in tables:
90
100
  tags = by_id[t["id"]]
91
101
  if tags:
92
102
  t["tags"] = tags
93
103
  t["color"] = colors[tags[0]]
94
- for tag in tags:
95
- counts[tag] = counts.get(tag, 0) + 1
104
+ for c in t["cols"]:
105
+ if c.get("tags"):
106
+ c["color"] = colors[c["tags"][0]]
107
+ for tag in dict.fromkeys(tags + col_tags[t["id"]]):
108
+ counts[tag] = counts.get(tag, 0) + 1
96
109
  own = schema.tables[t["id"]].color # DBML headercolor
97
110
  if own:
98
111
  t["color"] = own
@@ -1,8 +1,12 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: quickdbd-cli
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Compile QuickDBD-syntax schema files into interactive HTML ER diagrams, with no table limit.
5
- Project-URL: Homepage, https://github.com/MarkPhamm/quickdbd-cli
5
+ Project-URL: Homepage, https://qdbd.dev/
6
+ Project-URL: Documentation, https://qdbd.dev/guide/
7
+ Project-URL: Source, https://github.com/MarkPhamm/quickdbd-cli
8
+ Project-URL: Changelog, https://github.com/MarkPhamm/quickdbd-cli/releases
9
+ Project-URL: Issues, https://github.com/MarkPhamm/quickdbd-cli/issues
6
10
  Author: Minh (Mark) Pham
7
11
  License-Expression: Apache-2.0
8
12
  License-File: LICENSE
@@ -10,8 +14,13 @@ License-File: NOTICE
10
14
  License-File: src/quickdbd_cli/assets/Inter-LICENSE.txt
11
15
  License-File: src/quickdbd_cli/assets/elk-LICENSE.md
12
16
  Keywords: database,dbml,diagram,erd,mcp,quickdbd,schema
17
+ Classifier: Development Status :: 4 - Beta
13
18
  Classifier: Environment :: Console
19
+ Classifier: Operating System :: OS Independent
14
20
  Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
15
24
  Classifier: Topic :: Database
16
25
  Classifier: Topic :: Software Development :: Documentation
17
26
  Requires-Python: >=3.11
@@ -36,6 +45,21 @@ Description-Content-Type: text/markdown
36
45
 
37
46
  <p align="center"><b>Interactive ER diagrams from QuickDBD text or a dbt project, readable at 200+ tables</b></p>
38
47
 
48
+ <p align="center">
49
+ <a href="https://pypi.org/project/quickdbd-cli/"><img src="https://img.shields.io/pypi/v/quickdbd-cli?label=PyPI" alt="PyPI version"></a>
50
+ <a href="https://pypi.org/project/quickdbd-cli/"><img src="https://img.shields.io/pypi/pyversions/quickdbd-cli" alt="Python versions"></a>
51
+ <a href="https://github.com/MarkPhamm/quickdbd-cli/actions/workflows/ci.yml?query=branch%3Amain"><img src="https://img.shields.io/github/actions/workflow/status/MarkPhamm/quickdbd-cli/ci.yml?branch=main&label=CI" alt="CI status"></a>
52
+ <a href="https://qdbd.dev/"><img src="https://img.shields.io/github/actions/workflow/status/MarkPhamm/quickdbd-cli/erd.yml?branch=main&label=docs" alt="Docs status"></a>
53
+ <a href="https://pepy.tech/projects/quickdbd-cli"><img src="https://img.shields.io/pepy/dt/quickdbd-cli?label=downloads" alt="Total downloads"></a>
54
+ <br>
55
+ <a href="https://marketplace.visualstudio.com/items?itemName=MarkPhamm.quickdbd"><img src="https://vsmarketplacebadges.dev/version-short/MarkPhamm.quickdbd.svg?label=VS%20Code" alt="VS Code Marketplace version"></a>
56
+ <a href="https://open-vsx.org/extension/MarkPhamm/quickdbd"><img src="https://img.shields.io/open-vsx/v/MarkPhamm/quickdbd?label=Open%20VSX" alt="Open VSX version"></a>
57
+ <a href="https://open-vsx.org/extension/MarkPhamm/quickdbd"><img src="https://img.shields.io/open-vsx/dt/MarkPhamm/quickdbd?label=Open%20VSX%20downloads" alt="Open VSX downloads"></a>
58
+ <a href="https://github.com/MarkPhamm/quickdbd-cli/releases"><img src="https://img.shields.io/github/v/release/MarkPhamm/quickdbd-cli?label=release" alt="Latest release"></a>
59
+ <a href="https://github.com/MarkPhamm/quickdbd-cli/blob/main/LICENSE"><img src="https://img.shields.io/github/license/MarkPhamm/quickdbd-cli" alt="License"></a>
60
+ <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
61
+ </p>
62
+
39
63
  <p align="center">
40
64
  <a href="https://qdbd.dev/">Docs</a> · <a href="https://qdbd.dev/demo/">Live demos</a> · <a href="#quickstart">Quickstart</a> · <a href="https://pypi.org/project/quickdbd-cli/">PyPI</a> · <a href="https://marketplace.visualstudio.com/items?itemName=MarkPhamm.quickdbd">VS Code Marketplace</a> · <a href="https://open-vsx.org/extension/MarkPhamm/quickdbd">Open VSX</a>
41
65
  </p>
@@ -1,9 +1,9 @@
1
- quickdbd_cli/__init__.py,sha256=VrXpHDu3erkzwl_WXrqINBm9xWkcyUy53IQOj042dOs,22
1
+ quickdbd_cli/__init__.py,sha256=vNiWJ14r_cw5t_7UDqDQIVZvladKFGyHH2avsLpN7Vg,22
2
2
  quickdbd_cli/__main__.py,sha256=E6Gls0DNz8GQK2K-kOUIx8cYhgANW_CH54VKrfCfs14,52
3
- quickdbd_cli/agent.py,sha256=toPaflioDIGsL9x1ZPKS7fQLik5mkWLbNNS1vJmC_RE,37326
3
+ quickdbd_cli/agent.py,sha256=pZzKc9DMqN6pX1ZzXgcb11ZqX91wuJZW1f6xO2uGc2M,37421
4
4
  quickdbd_cli/cli.py,sha256=GJnOpXVwEpJHUQkagGrMc27x5vt1N6Ybj1-tX-TLPzE,29288
5
- quickdbd_cli/convert.py,sha256=Fl8ScZtux0SSxg-DOfs_weESQfu0y6AZK11UpA0TyV8,16507
6
- quickdbd_cli/dbml.py,sha256=rdEEQqK4QEalX3K_pkqSGIZW5xt7orQjp8g8LQuEBZo,58816
5
+ quickdbd_cli/convert.py,sha256=1AYFm4YmEav_wZp7xCAcL7TsD3qC17Y1I5g6V_fyAU0,16682
6
+ quickdbd_cli/dbml.py,sha256=tHJOtMm1PHx4-yqs6rncPqdDfbwPcW8F54j_kKlWkx0,59413
7
7
  quickdbd_cli/dbt.py,sha256=AMHzERmc8WfL1tBLX4bJdPVghIHrqrfx8nMDbZMrueY,23100
8
8
  quickdbd_cli/diff.py,sha256=UBiCE3dk_cN-xSRZFQoLiIIFh_FAVZUpLwsdtHG9eBo,9986
9
9
  quickdbd_cli/export.py,sha256=pjWe3oloaxVkV2b96GllQR4faB9OMtbNuTscxwjQhsk,2983
@@ -11,13 +11,13 @@ quickdbd_cli/html.py,sha256=fiMsBPkBiCpxz-8x4_SFaeejdnHCAAK0IVlrimbpS5I,7950
11
11
  quickdbd_cli/jsrt.py,sha256=_sRkmUbgHDTwK272jeTNUwojfjUKAkv4UeD2E2u3H1A,3464
12
12
  quickdbd_cli/layout.py,sha256=ajzJCJQ8ofnYj8dhz8aWq-LV2tmW5BHwJQ2LRoeSWaM,9998
13
13
  quickdbd_cli/mcp.py,sha256=ibUg1a50BBco-hZABdxTexGZi_gclFCdcBDalTvFar8,12350
14
- quickdbd_cli/measure.py,sha256=TsYINRmz8H3B4jHU3FLfHPl7QKECIRV0GFCLxORL77A,5915
15
- quickdbd_cli/model.py,sha256=c6vf7bnEswvlLqJrqiwvL3jAmiTAKh0W3PR5HBlxZXI,3276
16
- quickdbd_cli/parser.py,sha256=MQDWs4mYIwouM7G__ZJbLZIJvAxgyVwwgvht2GCM7zs,32779
14
+ quickdbd_cli/measure.py,sha256=Nyk47FiJokPvTStKz23mgXkO0HnXKWOts90kp1gCjng,5969
15
+ quickdbd_cli/model.py,sha256=lQcj89gDg2y4v_xhJX0_PWoWKGx0rg2emREVL_LA6uQ,3352
16
+ quickdbd_cli/parser.py,sha256=MpWvYWNMIfl8PNKGDyVqVA_RUsuD21oZQqTT7yZd89g,33018
17
17
  quickdbd_cli/project.py,sha256=Iu6aXJNxCbM9KDRbLaxTb7SfbVDv7PkajzKZX4-XfDk,4570
18
18
  quickdbd_cli/serve.py,sha256=NqYAcfT4lySRckAG2tkrZwmRbzYDjdNh18Yh4Er_hPo,12271
19
19
  quickdbd_cli/share.py,sha256=42VOsau_Ek3rDriakuAxt8pDenimEMrfbGgSNe74GV8,3840
20
- quickdbd_cli/tags.py,sha256=dXWATK6z1eeuwZmp9AoXuS3deTAuLwHxzd_FGnGKZ-I,3372
20
+ quickdbd_cli/tags.py,sha256=fOMcz3N8YAIqh5uJJ3GuYMBCkfOViGRCVNb3Ufz63GM,4098
21
21
  quickdbd_cli/targets.py,sha256=zvge0c2_XOC13gnv2C_XMf_ZmDcpOFPzld2PoyOtyxU,8740
22
22
  quickdbd_cli/assets/Inter-Bold.ttf,sha256=KIMWCZseCkekcW0VkJgAXu98AGaSHzTjIAOT29sBlH8,420428
23
23
  quickdbd_cli/assets/Inter-Bold.woff2,sha256=-oiBJ7baAVtlVp8DUfO1w5GtkokElR8cIOn4RiqNleo,114840
@@ -28,15 +28,15 @@ quickdbd_cli/assets/editor.js,sha256=Gare_MeAOKlc2QZpTR9nD8Ty-U6JBY3HRWAeMnDkCsU
28
28
  quickdbd_cli/assets/elk-LICENSE.md,sha256=Y36B9KG2tAeVNcSZ_KBeI4z3YFwf9bdtYNfafOlnAMk,14443
29
29
  quickdbd_cli/assets/elk.bundled.js,sha256=EiLkT5U853Rq8jgB5yNwj45vQ2uLN3pqX8dVLzSjB7M,1609707
30
30
  quickdbd_cli/assets/font-metrics.json,sha256=sXSiElxQSK8md8IEePLwh16TTdAqKt9rV140pvMlVS8,8654
31
- quickdbd_cli/assets/render.js,sha256=Y0suuf8MZsjmdlpzijWSH9Gjaz5re8MDnpfTkarNq1I,27971
31
+ quickdbd_cli/assets/render.js,sha256=3Jv7On2X9MghnP-GInfkkfsBFgMC1vg6VkpYfOzgjwM,28944
32
32
  quickdbd_cli/assets/style.css,sha256=HDF9tWXoQ0DRhSCiSmMDaXysK0Wd0VWW4_iwKgQdLFg,16185
33
- quickdbd_cli/assets/syntax-reference.md,sha256=FAnmUkDrEsODcvV6-8aHiUnU-SKSOhsgCi5lXlTbp1Y,5087
34
- quickdbd_cli/assets/viewer.js,sha256=9N3SySyPwKmWYn83qlaaVRSnqcs7rRfyq9i_lyOJtpo,39394
35
- quickdbd_cli-0.3.0.dist-info/METADATA,sha256=o1aVKTskTpfv-5B8GvAAo2TN2RYkzMFsmvKYy9PJEM8,14560
36
- quickdbd_cli-0.3.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
37
- quickdbd_cli-0.3.0.dist-info/entry_points.txt,sha256=nRhiYYug-XOY95nWUmi4oanico3Zjkfqk2OHtIE6SQ0,47
38
- quickdbd_cli-0.3.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
39
- quickdbd_cli-0.3.0.dist-info/licenses/NOTICE,sha256=pyv3BfIYiGzKLU4w-GcBe7GXoXxHqZ97Mf6Zpx_3_i0,2067
40
- quickdbd_cli-0.3.0.dist-info/licenses/src/quickdbd_cli/assets/Inter-LICENSE.txt,sha256=JiSB6ERSGzJvXs0FPlm5jIstp4yO4b27boF0MF5Uk1o,4380
41
- quickdbd_cli-0.3.0.dist-info/licenses/src/quickdbd_cli/assets/elk-LICENSE.md,sha256=Y36B9KG2tAeVNcSZ_KBeI4z3YFwf9bdtYNfafOlnAMk,14443
42
- quickdbd_cli-0.3.0.dist-info/RECORD,,
33
+ quickdbd_cli/assets/syntax-reference.md,sha256=WERcsWjyrfeHQPgxQriWKBsqFJnmWTQ2oRZjKYAHhKc,5322
34
+ quickdbd_cli/assets/viewer.js,sha256=T7AD6qQ3GmHN4iL8MX19GZ_kQO46hfPsJp7AsMYyRYU,39683
35
+ quickdbd_cli-0.3.2.dist-info/METADATA,sha256=3Qc1utZqKyjVciyy0ZvUH-0ADh_OlH817rA9ZK9TbZw,17009
36
+ quickdbd_cli-0.3.2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
37
+ quickdbd_cli-0.3.2.dist-info/entry_points.txt,sha256=nRhiYYug-XOY95nWUmi4oanico3Zjkfqk2OHtIE6SQ0,47
38
+ quickdbd_cli-0.3.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
39
+ quickdbd_cli-0.3.2.dist-info/licenses/NOTICE,sha256=pyv3BfIYiGzKLU4w-GcBe7GXoXxHqZ97Mf6Zpx_3_i0,2067
40
+ quickdbd_cli-0.3.2.dist-info/licenses/src/quickdbd_cli/assets/Inter-LICENSE.txt,sha256=JiSB6ERSGzJvXs0FPlm5jIstp4yO4b27boF0MF5Uk1o,4380
41
+ quickdbd_cli-0.3.2.dist-info/licenses/src/quickdbd_cli/assets/elk-LICENSE.md,sha256=Y36B9KG2tAeVNcSZ_KBeI4z3YFwf9bdtYNfafOlnAMk,14443
42
+ quickdbd_cli-0.3.2.dist-info/RECORD,,