quickdbd-cli 0.1.1__tar.gz → 0.1.2__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.
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/PKG-INFO +3 -2
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/README.md +2 -1
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/pyproject.toml +1 -1
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/scripts/release.sh +7 -2
- quickdbd_cli-0.1.2/src/quickdbd_cli/__init__.py +1 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/render.js +15 -4
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/style.css +9 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/viewer.js +45 -2
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/html.py +1 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/measure.py +10 -3
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/tests/test_pipeline.py +31 -0
- quickdbd_cli-0.1.1/src/quickdbd_cli/__init__.py +0 -1
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/.gitignore +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/LICENSE +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/NOTICE +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/examples/quickdbd-sample.txt +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/examples/synthetic/finance.txt +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/examples/synthetic/hr.txt +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/examples/synthetic/inventory.txt +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/examples/synthetic/marketing.txt +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/examples/synthetic/qdbd.layout.json +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/examples/synthetic/sales.txt +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/scripts/gen_font_metrics.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/scripts/gen_schema.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/__main__.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/Inter-Bold.ttf +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/Inter-Bold.woff2 +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/Inter-LICENSE.txt +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/Inter-Regular.ttf +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/Inter-Regular.woff2 +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/editor.js +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/elk-LICENSE.md +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/elk.bundled.js +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/assets/font-metrics.json +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/cli.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/export.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/jsrt.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/layout.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/model.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/parser.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/project.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/src/quickdbd_cli/serve.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/tests/test_parser.py +0 -0
- {quickdbd_cli-0.1.1 → quickdbd_cli-0.1.2}/tests/test_serve.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: quickdbd-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
@@ -55,6 +55,7 @@ Not affiliated with QuickDBD. It reads the same text syntax, so schemas move fre
|
|
|
55
55
|
- click a table to focus on it and its neighbours
|
|
56
56
|
- collapse tables: full / keys only / names only
|
|
57
57
|
- hover a column to highlight its relationship
|
|
58
|
+
- hover a dotted-underlined table or column to read its `#` doc comments
|
|
58
59
|
- PNG/SVG export buttons
|
|
59
60
|
- **Live editing:** `qdbd serve` reloads when you save, has a browser editor pane with autosave, and remembers where you drag tables.
|
|
60
61
|
- **Many files, one diagram:** point it at a folder and foreign keys can cross files.
|
|
@@ -157,7 +158,7 @@ TWINE_USERNAME=__token__
|
|
|
157
158
|
TWINE_PASSWORD=pypi-...
|
|
158
159
|
```
|
|
159
160
|
|
|
160
|
-
Bump `version` in `pyproject.toml` and `src/quickdbd_cli/__init__.py`, commit, then run `scripts/release.sh`. It builds, uploads to PyPI, tags `vX.Y.Z` and creates the GitHub release.
|
|
161
|
+
Bump `version` in `pyproject.toml` and `src/quickdbd_cli/__init__.py`, commit, then run `PATH="$PWD/.venv/bin:$PATH" scripts/release.sh`. It builds, uploads to PyPI, tags `vX.Y.Z` and creates the GitHub release.
|
|
161
162
|
|
|
162
163
|
## License
|
|
163
164
|
|
|
@@ -30,6 +30,7 @@ Not affiliated with QuickDBD. It reads the same text syntax, so schemas move fre
|
|
|
30
30
|
- click a table to focus on it and its neighbours
|
|
31
31
|
- collapse tables: full / keys only / names only
|
|
32
32
|
- hover a column to highlight its relationship
|
|
33
|
+
- hover a dotted-underlined table or column to read its `#` doc comments
|
|
33
34
|
- PNG/SVG export buttons
|
|
34
35
|
- **Live editing:** `qdbd serve` reloads when you save, has a browser editor pane with autosave, and remembers where you drag tables.
|
|
35
36
|
- **Many files, one diagram:** point it at a folder and foreign keys can cross files.
|
|
@@ -132,7 +133,7 @@ TWINE_USERNAME=__token__
|
|
|
132
133
|
TWINE_PASSWORD=pypi-...
|
|
133
134
|
```
|
|
134
135
|
|
|
135
|
-
Bump `version` in `pyproject.toml` and `src/quickdbd_cli/__init__.py`, commit, then run `scripts/release.sh`. It builds, uploads to PyPI, tags `vX.Y.Z` and creates the GitHub release.
|
|
136
|
+
Bump `version` in `pyproject.toml` and `src/quickdbd_cli/__init__.py`, commit, then run `PATH="$PWD/.venv/bin:$PATH" scripts/release.sh`. It builds, uploads to PyPI, tags `vX.Y.Z` and creates the GitHub release.
|
|
136
137
|
|
|
137
138
|
## License
|
|
138
139
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "quickdbd-cli"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
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"
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Build and upload the current version to PyPI using credentials from .env,
|
|
3
3
|
# then tag and create the GitHub release.
|
|
4
|
-
# Usage: bump `version` in pyproject.toml and src/quickdbd_cli/__init__.py, commit, then run
|
|
4
|
+
# Usage: bump `version` in pyproject.toml and src/quickdbd_cli/__init__.py, commit, then run
|
|
5
|
+
# PATH="$PWD/.venv/bin:$PATH" scripts/release.sh
|
|
5
6
|
set -euo pipefail
|
|
6
7
|
cd "$(dirname "$0")/.."
|
|
7
8
|
|
|
@@ -12,7 +13,11 @@ version=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','
|
|
|
12
13
|
[ -z "$(git status --porcelain --untracked-files=no)" ] || { echo "error: uncommitted changes" >&2; exit 1; }
|
|
13
14
|
|
|
14
15
|
rm -rf dist
|
|
15
|
-
|
|
16
|
+
# uv-created venvs have no pip; only install the tools when they're missing.
|
|
17
|
+
python3 -c "import build, twine" 2>/dev/null || {
|
|
18
|
+
if command -v uv >/dev/null; then uv pip install -q --python "$(command -v python3)" build twine
|
|
19
|
+
else python3 -m pip install -q --upgrade build twine; fi
|
|
20
|
+
}
|
|
16
21
|
python3 -m build
|
|
17
22
|
python3 -m twine check dist/*
|
|
18
23
|
python3 -m twine upload --non-interactive dist/*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.2"
|
|
@@ -66,13 +66,22 @@
|
|
|
66
66
|
'<path d="M' + n(x + 6.5) + " " + n(cy) + "h7m-2 0v3m-2.5-3v2" + '"/></g>';
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
/* Dotted underline marking text that has a doc comment (interactive viewer only). */
|
|
70
|
+
function docMark(x, y, w, color) {
|
|
71
|
+
return '<line class="dm" x1="' + n(x) + '" y1="' + n(y) + '" x2="' + n(x + w) + '" y2="' + n(y) +
|
|
72
|
+
'" stroke="' + color + '" stroke-width="1" stroke-dasharray="1.5 2"/>';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function renderTable(model, t, g, p, docMarks) {
|
|
70
76
|
var st = model.style, w = g.w, h = g.h, out = [];
|
|
71
77
|
out.push('<g class="t" data-id="' + esc(t.id) + '" transform="translate(' + n(p[0]) + "," + n(p[1]) + ')">');
|
|
72
78
|
out.push('<rect class="tb" width="' + w + '" height="' + h + '" rx="2" fill="' + C.body + '" stroke="' + C.border + '"/>');
|
|
73
79
|
out.push('<path class="th" d="M0 2a2 2 0 0 1 2-2h' + (w - 4) + "a2 2 0 0 1 2 2v" + (st.headerH - 2) + "h-" + w + 'z" fill="' + C.header + '"/>');
|
|
74
80
|
out.push('<text x="' + st.padX + '" y="' + n(st.headerH / 2 + st.headerSize * 0.36) + '" fill="' + C.headerText +
|
|
75
81
|
'" font-family="' + FONT + '" font-size="' + st.headerSize + '">' + esc(t.name) + "</text>");
|
|
82
|
+
if (docMarks && t.doc) {
|
|
83
|
+
out.push(docMark(st.padX, st.headerH / 2 + st.headerSize * 0.36 + 3, t.nameW, "rgba(255,255,255,.7)"));
|
|
84
|
+
}
|
|
76
85
|
g.cols.forEach(function (c, i) {
|
|
77
86
|
var y = st.headerH + i * st.rowH, cy = y + st.rowH / 2, base = n(cy + st.rowSize * 0.36);
|
|
78
87
|
var weight = c.pk || c.fk ? ' font-weight="bold"' : "";
|
|
@@ -81,6 +90,7 @@
|
|
|
81
90
|
out.push('<rect class="rb" y="' + y + '" width="' + w + '" height="' + st.rowH + '" fill="' + C.body + '" fill-opacity="0"/>');
|
|
82
91
|
out.push('<text x="' + st.padX + '" y="' + base + '" fill="' + color + '" font-family="' + FONT + '" font-size="' +
|
|
83
92
|
st.rowSize + '"' + weight + ">" + esc(c.name) + "</text>");
|
|
93
|
+
if (docMarks && c.doc) out.push(docMark(st.padX, cy + st.rowSize * 0.36 + 2.5, c.nameW, color));
|
|
84
94
|
var bx = st.padX + c.nameW + 6;
|
|
85
95
|
c.badges.forEach(function (b) {
|
|
86
96
|
var bh = st.badgeSize + 5;
|
|
@@ -164,9 +174,10 @@
|
|
|
164
174
|
return model.rels.map(function (r) { return renderEdge(model, geo, pos, r); }).join("");
|
|
165
175
|
}
|
|
166
176
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
var
|
|
177
|
+
/* opts.docMarks: underline tables/columns that have doc comments (viewer only, not exports). */
|
|
178
|
+
function renderInner(model, pos, mode, opts) {
|
|
179
|
+
var geo = geometry(model, mode), marks = !!(opts && opts.docMarks);
|
|
180
|
+
var tables = model.tables.map(function (t) { return pos[t.id] ? renderTable(model, t, geo[t.id], pos[t.id], marks) : ""; }).join("");
|
|
170
181
|
return '<g class="edges">' + renderEdges(model, pos, mode, geo) + '</g><g class="tables">' + tables + "</g>";
|
|
171
182
|
}
|
|
172
183
|
|
|
@@ -53,6 +53,15 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink);
|
|
|
53
53
|
.minimap svg { width: 100%; height: 100%; display: block; }
|
|
54
54
|
.minimap .vpr { fill: rgba(43,87,151,.12); stroke: var(--blue); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
|
|
55
55
|
|
|
56
|
+
/* doc-comment tooltip */
|
|
57
|
+
.tip { position: absolute; display: none; max-width: 340px; background: #23272b; color: #eee; border-radius: 6px;
|
|
58
|
+
padding: 8px 10px; font-size: 12px; line-height: 1.45; pointer-events: none; box-shadow: 0 4px 14px rgba(0,0,0,.25);
|
|
59
|
+
z-index: 5; }
|
|
60
|
+
.tip.open { display: block; }
|
|
61
|
+
.tip .tt { font-weight: bold; margin-bottom: 3px; }
|
|
62
|
+
.tip .tt span { font-weight: normal; color: #9aa4ad; margin-left: 8px; }
|
|
63
|
+
.tip .td { white-space: pre-wrap; color: #d8dde2; }
|
|
64
|
+
|
|
56
65
|
.hint { position: absolute; left: 16px; bottom: 14px; color: var(--muted); font-size: 12px; }
|
|
57
66
|
|
|
58
67
|
/* serve: editor pane */
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
/* ------------------------------------------------------------- render */
|
|
26
26
|
function render() {
|
|
27
|
-
vp.innerHTML = Q.renderInner(S.model, S.pos, S.mode);
|
|
27
|
+
vp.innerHTML = Q.renderInner(S.model, S.pos, S.mode, { docMarks: true });
|
|
28
28
|
applyFocus();
|
|
29
29
|
drawMinimap();
|
|
30
30
|
}
|
|
@@ -124,7 +124,50 @@
|
|
|
124
124
|
if (t) t.classList.add("hl");
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
|
-
vp.addEventListener("mouseleave", clearHover);
|
|
127
|
+
vp.addEventListener("mouseleave", function () { clearHover(); hideTip(); });
|
|
128
|
+
|
|
129
|
+
/* ------------------------------------------------------------- doc-comment tooltips */
|
|
130
|
+
var tip = document.getElementById("tip");
|
|
131
|
+
function hideTip() { tip.classList.remove("open"); }
|
|
132
|
+
function showTip(ev, title, sub, doc) {
|
|
133
|
+
tip.innerHTML = "";
|
|
134
|
+
var h = document.createElement("div");
|
|
135
|
+
h.className = "tt";
|
|
136
|
+
h.textContent = title;
|
|
137
|
+
if (sub) {
|
|
138
|
+
var s = document.createElement("span");
|
|
139
|
+
s.textContent = sub;
|
|
140
|
+
h.appendChild(s);
|
|
141
|
+
}
|
|
142
|
+
var d = document.createElement("div");
|
|
143
|
+
d.className = "td";
|
|
144
|
+
d.textContent = doc;
|
|
145
|
+
tip.appendChild(h);
|
|
146
|
+
tip.appendChild(d);
|
|
147
|
+
tip.classList.add("open");
|
|
148
|
+
moveTip(ev);
|
|
149
|
+
}
|
|
150
|
+
function moveTip(ev) {
|
|
151
|
+
var r = svg.getBoundingClientRect(), x = ev.clientX - r.left + 14, y = ev.clientY - r.top + 14;
|
|
152
|
+
var w = tip.offsetWidth, h = tip.offsetHeight;
|
|
153
|
+
if (x + w > r.width - 8) x = ev.clientX - r.left - w - 14;
|
|
154
|
+
if (y + h > r.height - 8) y = ev.clientY - r.top - h - 14;
|
|
155
|
+
tip.style.left = Math.max(8, x) + "px";
|
|
156
|
+
tip.style.top = Math.max(8, y) + "px";
|
|
157
|
+
}
|
|
158
|
+
vp.addEventListener("mousemove", function (ev) {
|
|
159
|
+
if (drag && drag.moved) { hideTip(); return; }
|
|
160
|
+
var tEl = ev.target.closest && ev.target.closest(".t");
|
|
161
|
+
if (!tEl) { hideTip(); return; }
|
|
162
|
+
var t = byId[tEl.getAttribute("data-id")], row = ev.target.closest(".r");
|
|
163
|
+
if (row) {
|
|
164
|
+
var cid = row.getAttribute("data-c"), c = t.cols.filter(function (x) { return x.id === cid; })[0];
|
|
165
|
+
if (c && c.doc) showTip(ev, t.name + "." + c.name, c.type, c.doc);
|
|
166
|
+
else hideTip();
|
|
167
|
+
} else if (t.doc && ev.target.closest(".th, text")) {
|
|
168
|
+
showTip(ev, t.name, t.aliases.length ? "as " + t.aliases.join(", ") : "", t.doc);
|
|
169
|
+
} else hideTip();
|
|
170
|
+
});
|
|
128
171
|
|
|
129
172
|
/* ------------------------------------------------------------- pointer: pan, click, drag */
|
|
130
173
|
var drag = null;
|
|
@@ -60,7 +60,7 @@ def _column_json(col: Column) -> dict:
|
|
|
60
60
|
name_w = text_width(col.name, s["rowSize"], bold)
|
|
61
61
|
bs = [{"t": b, "w": round(text_width(b, s["badgeSize"]) + 2 * s["badgePad"], 2)} for b in badges(col)]
|
|
62
62
|
type_w = text_width(col.type or "", s["rowSize"])
|
|
63
|
-
|
|
63
|
+
out = {
|
|
64
64
|
"id": col.id,
|
|
65
65
|
"name": col.name,
|
|
66
66
|
"type": col.type or "",
|
|
@@ -75,12 +75,16 @@ def _column_json(col: Column) -> dict:
|
|
|
75
75
|
"typeW": type_w,
|
|
76
76
|
"badges": bs,
|
|
77
77
|
}
|
|
78
|
+
if col.comments:
|
|
79
|
+
out["doc"] = "\n".join(col.comments)
|
|
80
|
+
return out
|
|
78
81
|
|
|
79
82
|
|
|
80
83
|
def table_json(table: Table) -> dict:
|
|
81
84
|
s = STYLE
|
|
82
85
|
cols = [_column_json(c) for c in table.columns.values() if not c.virtual]
|
|
83
|
-
|
|
86
|
+
name_w = text_width(table.name, s["headerSize"])
|
|
87
|
+
w = name_w + 2 * s["padX"]
|
|
84
88
|
for c in cols:
|
|
85
89
|
row = c["nameW"] + c["typeW"] + 2 * s["padX"] + s["gap"]
|
|
86
90
|
row += sum(b["w"] + s["badgeGap"] for b in c["badges"])
|
|
@@ -89,7 +93,10 @@ def table_json(table: Table) -> dict:
|
|
|
89
93
|
w = max(w, row)
|
|
90
94
|
w = max(round(w), s["minW"])
|
|
91
95
|
h = s["headerH"] + len(cols) * s["rowH"] + s["bottomPad"]
|
|
92
|
-
|
|
96
|
+
out = {"id": table.id, "name": table.name, "aliases": table.aliases, "w": w, "h": h, "nameW": name_w, "cols": cols}
|
|
97
|
+
if table.comments:
|
|
98
|
+
out["doc"] = "\n".join(table.comments)
|
|
99
|
+
return out
|
|
93
100
|
|
|
94
101
|
|
|
95
102
|
def model_json(schema: Schema) -> dict:
|
|
@@ -186,3 +186,34 @@ def test_missing_path(capsys):
|
|
|
186
186
|
@pytest.mark.parametrize("bad_suffix", ["out.jpg"])
|
|
187
187
|
def test_export_rejects_unknown_format(tmp_path, bad_suffix):
|
|
188
188
|
assert main(["export", str(SAMPLE), "-o", str(tmp_path / bad_suffix)]) == 2
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
DOCS = """# Customers who placed at least one order
|
|
192
|
+
Customer # one row per person
|
|
193
|
+
-
|
|
194
|
+
CustomerId PK int
|
|
195
|
+
# Contact address
|
|
196
|
+
Email string # verified
|
|
197
|
+
Name string
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def test_doc_comments_in_model():
|
|
202
|
+
m = model_json(compile_text(DOCS))
|
|
203
|
+
t = m["tables"][0]
|
|
204
|
+
assert t["doc"] == "Customers who placed at least one order\none row per person"
|
|
205
|
+
cols = {c["id"]: c for c in t["cols"]}
|
|
206
|
+
assert cols["Email"]["doc"] == "Contact address\nverified"
|
|
207
|
+
assert "doc" not in cols["Name"]
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def test_doc_marks_only_in_viewer_not_exports():
|
|
211
|
+
from quickdbd_cli.jsrt import runtime
|
|
212
|
+
|
|
213
|
+
m = model_json(compile_text(DOCS))
|
|
214
|
+
pos = {"Customer": [0, 0]}
|
|
215
|
+
rt = runtime()
|
|
216
|
+
rt.load("render.js")
|
|
217
|
+
viewer = rt.call("qdbd.renderInner", m, pos, "full", {"docMarks": True})
|
|
218
|
+
assert viewer.count('class="dm"') == 2 # table header + Email
|
|
219
|
+
assert 'class="dm"' not in export.render_svg(m, pos, embed_font=False)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|