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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcdview
3
- Version: 0.26.2
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 (off by default) |
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 (off by default) |
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 (off by default)")
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
- args.credit, args.credit_url, bool(args.diff)))
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)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "mcdview"
7
- version = "0.26.2"
7
+ version = "0.28.0"
8
8
  description = "Turn a SQL data model into one self-contained, interactive HTML page"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -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