mcdview 0.26.2__tar.gz → 0.28.0__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.
- {mcdview-0.26.2 → mcdview-0.28.0}/PKG-INFO +26 -2
- {mcdview-0.26.2 → mcdview-0.28.0}/README.md +25 -1
- {mcdview-0.26.2 → mcdview-0.28.0}/mcdview.py +59 -3
- {mcdview-0.26.2 → mcdview-0.28.0}/pyproject.toml +1 -1
- {mcdview-0.26.2 → mcdview-0.28.0}/templates/explorateur.html +13 -0
- {mcdview-0.26.2 → mcdview-0.28.0}/.gitignore +0 -0
- {mcdview-0.26.2 → mcdview-0.28.0}/LICENSE +0 -0
- {mcdview-0.26.2 → mcdview-0.28.0}/logo.svg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcdview
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.28.0
|
|
4
4
|
Summary: Turn a SQL data model into one self-contained, interactive HTML page
|
|
5
5
|
Project-URL: Homepage, https://github.com/Gheop/mcdview
|
|
6
6
|
Project-URL: Demo, https://gheop.github.io/mcdview/
|
|
@@ -210,8 +210,9 @@ In the page:
|
|
|
210
210
|
| `--dialect NAME` | Input SQL dialect (default: `auto`); non-PostgreSQL needs `sqlglot` |
|
|
211
211
|
| `--home-url URL` | Wrap the header logo in a link to this URL |
|
|
212
212
|
| `--logo FILE` | Replace the header logo with this image (svg/png/jpg…, shown 22×22) |
|
|
213
|
-
| `--credit TEXT` | Discreet attribution badge, bottom-right (
|
|
213
|
+
| `--credit TEXT` | Discreet attribution badge, bottom-right; auto-set to `mcdview` (linking mcdview.dev) on a branded page |
|
|
214
214
|
| `--credit-url URL` | Make the `--credit` badge a link to this URL |
|
|
215
|
+
| `--no-credit` | Never place the attribution badge, even on a branded page |
|
|
215
216
|
| `--db URL` | Read a live database's schema instead of a file (`postgresql://…` via `pg_dump`, `mysql://…` via `mysqldump`); CLI only |
|
|
216
217
|
| `--diff BASELINE` | Compare against an older model (any supported format); added/removed/changed tables, columns and FKs are colored |
|
|
217
218
|
| `--summary FILE` | With `--diff`: also write a JSON summary of the changes (counts + change list) to `FILE` |
|
|
@@ -323,6 +324,29 @@ file's header.
|
|
|
323
324
|
|
|
324
325
|
## Changelog
|
|
325
326
|
|
|
327
|
+
### v0.28.0 — Auto attribution badge on branded pages (2026-08-31)
|
|
328
|
+
|
|
329
|
+
- A branded page (`--logo` or `--home-url`) now carries a discreet clickable
|
|
330
|
+
`mcdview` badge by default, linking to https://mcdview.dev. Branding drops the
|
|
331
|
+
header link back to mcdview, so the badge keeps the attribution. An explicit
|
|
332
|
+
`--credit` still sets its own text and url; a plain, unbranded page stays bare.
|
|
333
|
+
- New `--no-credit` opts out of the badge, even on a branded page.
|
|
334
|
+
|
|
335
|
+
### v0.27.1 — Fix SVG export from a zoomed-out diagram (2026-08-31)
|
|
336
|
+
|
|
337
|
+
- SVG export now always draws full table boxes. Exporting while the diagram was
|
|
338
|
+
zoomed out (header-only, level-of-detail view) sized each box to its header
|
|
339
|
+
alone, so the columns spilled out with no background or border and the FK
|
|
340
|
+
links anchored to the header center. The export reflows to full detail before
|
|
341
|
+
measuring, so its output no longer depends on the current zoom level.
|
|
342
|
+
|
|
343
|
+
### v0.27.0 — `--to-dico` data dictionary on the CLI (2026-08-30)
|
|
344
|
+
|
|
345
|
+
- `--to-dico` outputs a Markdown data dictionary (one `## schema.table` section
|
|
346
|
+
with a `column / type / key` table) instead of the HTML page — to `-o` if
|
|
347
|
+
given, else stdout. Same content as the in-page **export → Markdown**, now
|
|
348
|
+
scriptable for a docs/CI pipeline like `--to-mermaid` and `--to-preview`.
|
|
349
|
+
|
|
326
350
|
### v0.26.2 — Auto-dismiss the hint banner (2026-08-30)
|
|
327
351
|
|
|
328
352
|
- The transient hint banner (e.g. "No probable missing FK", "No match", a
|
|
@@ -188,8 +188,9 @@ In the page:
|
|
|
188
188
|
| `--dialect NAME` | Input SQL dialect (default: `auto`); non-PostgreSQL needs `sqlglot` |
|
|
189
189
|
| `--home-url URL` | Wrap the header logo in a link to this URL |
|
|
190
190
|
| `--logo FILE` | Replace the header logo with this image (svg/png/jpg…, shown 22×22) |
|
|
191
|
-
| `--credit TEXT` | Discreet attribution badge, bottom-right (
|
|
191
|
+
| `--credit TEXT` | Discreet attribution badge, bottom-right; auto-set to `mcdview` (linking mcdview.dev) on a branded page |
|
|
192
192
|
| `--credit-url URL` | Make the `--credit` badge a link to this URL |
|
|
193
|
+
| `--no-credit` | Never place the attribution badge, even on a branded page |
|
|
193
194
|
| `--db URL` | Read a live database's schema instead of a file (`postgresql://…` via `pg_dump`, `mysql://…` via `mysqldump`); CLI only |
|
|
194
195
|
| `--diff BASELINE` | Compare against an older model (any supported format); added/removed/changed tables, columns and FKs are colored |
|
|
195
196
|
| `--summary FILE` | With `--diff`: also write a JSON summary of the changes (counts + change list) to `FILE` |
|
|
@@ -301,6 +302,29 @@ file's header.
|
|
|
301
302
|
|
|
302
303
|
## Changelog
|
|
303
304
|
|
|
305
|
+
### v0.28.0 — Auto attribution badge on branded pages (2026-08-31)
|
|
306
|
+
|
|
307
|
+
- A branded page (`--logo` or `--home-url`) now carries a discreet clickable
|
|
308
|
+
`mcdview` badge by default, linking to https://mcdview.dev. Branding drops the
|
|
309
|
+
header link back to mcdview, so the badge keeps the attribution. An explicit
|
|
310
|
+
`--credit` still sets its own text and url; a plain, unbranded page stays bare.
|
|
311
|
+
- New `--no-credit` opts out of the badge, even on a branded page.
|
|
312
|
+
|
|
313
|
+
### v0.27.1 — Fix SVG export from a zoomed-out diagram (2026-08-31)
|
|
314
|
+
|
|
315
|
+
- SVG export now always draws full table boxes. Exporting while the diagram was
|
|
316
|
+
zoomed out (header-only, level-of-detail view) sized each box to its header
|
|
317
|
+
alone, so the columns spilled out with no background or border and the FK
|
|
318
|
+
links anchored to the header center. The export reflows to full detail before
|
|
319
|
+
measuring, so its output no longer depends on the current zoom level.
|
|
320
|
+
|
|
321
|
+
### v0.27.0 — `--to-dico` data dictionary on the CLI (2026-08-30)
|
|
322
|
+
|
|
323
|
+
- `--to-dico` outputs a Markdown data dictionary (one `## schema.table` section
|
|
324
|
+
with a `column / type / key` table) instead of the HTML page — to `-o` if
|
|
325
|
+
given, else stdout. Same content as the in-page **export → Markdown**, now
|
|
326
|
+
scriptable for a docs/CI pipeline like `--to-mermaid` and `--to-preview`.
|
|
327
|
+
|
|
304
328
|
### v0.26.2 — Auto-dismiss the hint banner (2026-08-30)
|
|
305
329
|
|
|
306
330
|
- The transient hint banner (e.g. "No probable missing FK", "No match", a
|
|
@@ -1606,6 +1606,36 @@ def vers_mermaid(tables, fks):
|
|
|
1606
1606
|
return '\n'.join(lignes) + '\n'
|
|
1607
1607
|
|
|
1608
1608
|
|
|
1609
|
+
def vers_dico(tables, fks, titre):
|
|
1610
|
+
"""A Markdown data dictionary: one section per table with a
|
|
1611
|
+
column / type / key row. Pastes into a wiki or a .md (GitHub/GitLab render
|
|
1612
|
+
the tables). Same shape as the in-page "export → Markdown"."""
|
|
1613
|
+
def cell(s):
|
|
1614
|
+
return str(s).replace('|', '\\|')
|
|
1615
|
+
fk_par = {}
|
|
1616
|
+
for f in fks:
|
|
1617
|
+
fk_par.setdefault(f['de'], {})[f['col']] = f['vers']
|
|
1618
|
+
lignes = ['# ' + titre, '']
|
|
1619
|
+
for cle in sorted(tables):
|
|
1620
|
+
t = tables[cle]
|
|
1621
|
+
fk = fk_par.get(cle, {})
|
|
1622
|
+
lignes += ['## ' + cle, '']
|
|
1623
|
+
if t.get('comment'):
|
|
1624
|
+
lignes += ['> ' + t['comment'].replace('\n', ' '), '']
|
|
1625
|
+
lignes += ['| column | type | key |', '| --- | --- | --- |']
|
|
1626
|
+
for c in t['cols']:
|
|
1627
|
+
if c['nom'] in t['pk']:
|
|
1628
|
+
k = 'PK'
|
|
1629
|
+
elif c['nom'] in fk:
|
|
1630
|
+
k = 'FK → ' + fk[c['nom']].split('.', 1)[-1]
|
|
1631
|
+
else:
|
|
1632
|
+
k = ''
|
|
1633
|
+
typ = c['type'] + (' NOT NULL' if c['nn'] else '')
|
|
1634
|
+
lignes.append(f"| {cell(c['nom'])} | {cell(typ)} | {cell(k)} |")
|
|
1635
|
+
lignes.append('')
|
|
1636
|
+
return '\n'.join(lignes)
|
|
1637
|
+
|
|
1638
|
+
|
|
1609
1639
|
def vers_svg(tables, fks, couleurs):
|
|
1610
1640
|
"""A static SVG snapshot of the diagram, for social/OpenGraph cards: the
|
|
1611
1641
|
auto-layout positions, the same box sizing as the interactive page, table
|
|
@@ -1678,6 +1708,10 @@ def principal():
|
|
|
1678
1708
|
ap.add_argument('--to-preview', action='store_true',
|
|
1679
1709
|
help='output a static SVG snapshot of the diagram (for a social '
|
|
1680
1710
|
'card / OpenGraph image) instead of the HTML page')
|
|
1711
|
+
ap.add_argument('--to-dico', action='store_true',
|
|
1712
|
+
help='output a Markdown data dictionary (one section per table, '
|
|
1713
|
+
'column/type/key) instead of the HTML page; to -o if given, '
|
|
1714
|
+
'else stdout')
|
|
1681
1715
|
ap.add_argument('--lint', action='store_true',
|
|
1682
1716
|
help='check the schema against a set of rules (missing PK, '
|
|
1683
1717
|
'unindexed FK, naming…) and print JSON violations instead '
|
|
@@ -1703,9 +1737,12 @@ def principal():
|
|
|
1703
1737
|
ap.add_argument('--logo', default=None, metavar='FILE',
|
|
1704
1738
|
help="replace the header logo (svg/png/jpg…, shown 22×22)")
|
|
1705
1739
|
ap.add_argument('--credit', default=None, metavar='TEXT',
|
|
1706
|
-
help="discreet attribution badge, bottom-right
|
|
1740
|
+
help="discreet attribution badge, bottom-right; auto-set to "
|
|
1741
|
+
"'mcdview' (linking mcdview.dev) on a branded page")
|
|
1707
1742
|
ap.add_argument('--credit-url', default=None, metavar='URL',
|
|
1708
1743
|
help="make the --credit badge a link to this URL")
|
|
1744
|
+
ap.add_argument('--no-credit', action='store_true',
|
|
1745
|
+
help="never place the attribution badge, even on a branded page")
|
|
1709
1746
|
args = ap.parse_args()
|
|
1710
1747
|
if args.summary and not args.diff:
|
|
1711
1748
|
ap.error('--summary only applies with --diff')
|
|
@@ -1720,7 +1757,7 @@ def principal():
|
|
|
1720
1757
|
|
|
1721
1758
|
generer(args, ap)
|
|
1722
1759
|
if args.watch:
|
|
1723
|
-
if args.db or args.to_mermaid or args.to_preview or not args.sql:
|
|
1760
|
+
if args.db or args.to_mermaid or args.to_preview or args.to_dico or not args.sql:
|
|
1724
1761
|
ap.error('--watch needs a model file (not --db or --to-mermaid)')
|
|
1725
1762
|
surveiller(args, ap)
|
|
1726
1763
|
|
|
@@ -1922,6 +1959,15 @@ def generer(args, ap):
|
|
|
1922
1959
|
sys.stdout.write(mmd)
|
|
1923
1960
|
return
|
|
1924
1961
|
|
|
1962
|
+
if args.to_dico:
|
|
1963
|
+
md = vers_dico(tables, fks, args.titre or nom_defaut)
|
|
1964
|
+
if args.sortie:
|
|
1965
|
+
Path(args.sortie).write_text(md)
|
|
1966
|
+
print(f'{len(tables)} tables, {len(fks)} FKs → {args.sortie} (data dictionary)')
|
|
1967
|
+
else:
|
|
1968
|
+
sys.stdout.write(md)
|
|
1969
|
+
return
|
|
1970
|
+
|
|
1925
1971
|
if args.diff:
|
|
1926
1972
|
vieux = charger(args.diff, args.dialect)[:2]
|
|
1927
1973
|
tables, fks = comparer(vieux, (tables, fks))
|
|
@@ -1951,9 +1997,19 @@ def generer(args, ap):
|
|
|
1951
1997
|
|
|
1952
1998
|
titre = args.titre or nom_defaut
|
|
1953
1999
|
sortie = args.sortie or sortie_defaut
|
|
2000
|
+
# Attribution badge. A branded page (--logo or --home-url) drops the header
|
|
2001
|
+
# link back to mcdview, so unless the caller opts out or sets its own credit,
|
|
2002
|
+
# stamp a discreet clickable "mcdview". An explicit --credit keeps its own
|
|
2003
|
+
# text/url; a plain page (unbranded) stays bare.
|
|
2004
|
+
credit, credit_url = args.credit, args.credit_url
|
|
2005
|
+
if args.no_credit:
|
|
2006
|
+
credit = None
|
|
2007
|
+
elif credit is None and (args.logo or args.home_url):
|
|
2008
|
+
credit = 'mcdview'
|
|
2009
|
+
credit_url = credit_url or 'https://mcdview.dev'
|
|
1954
2010
|
Path(sortie).write_text(composer_page(tables, fks, titre, args.lang, couleurs,
|
|
1955
2011
|
dialecte, args.home_url, args.logo,
|
|
1956
|
-
|
|
2012
|
+
credit, credit_url, bool(args.diff)))
|
|
1957
2013
|
if args.diff:
|
|
1958
2014
|
if args.summary:
|
|
1959
2015
|
resume = resume_diff(tables, fks, args.diff)
|
|
@@ -879,6 +879,19 @@ btnReorg.addEventListener("click", reorganiser);
|
|
|
879
879
|
function exporterSVG() {
|
|
880
880
|
const pad = 24, vis = Object.keys(elems).filter(c => !elems[c].classList.contains("efface"));
|
|
881
881
|
if (!vis.length) return;
|
|
882
|
+
// The export always draws every column, but a zoomed-out (compact) page
|
|
883
|
+
// collapses each node to its header, which would size the boxes and anchor the
|
|
884
|
+
// FK links to the header alone. Drop compact for the measurement (synchronous,
|
|
885
|
+
// restored before we return, so no flicker) so the DOM reflows to full detail.
|
|
886
|
+
const etaitCompact = plan.classList.contains("compact");
|
|
887
|
+
if (etaitCompact) plan.classList.remove("compact");
|
|
888
|
+
try {
|
|
889
|
+
exporterSVGImpl(pad, vis);
|
|
890
|
+
} finally {
|
|
891
|
+
if (etaitCompact) plan.classList.add("compact");
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
function exporterSVGImpl(pad, vis) {
|
|
882
895
|
let bx0 = 1e9, by0 = 1e9, bx1 = -1e9, by1 = -1e9;
|
|
883
896
|
vis.forEach(c => {
|
|
884
897
|
const e = elems[c];
|
|
File without changes
|
|
File without changes
|
|
File without changes
|