mcdview 0.26.0__tar.gz → 0.26.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.
- {mcdview-0.26.0 → mcdview-0.26.2}/PKG-INFO +19 -1
- {mcdview-0.26.0 → mcdview-0.26.2}/README.md +18 -0
- {mcdview-0.26.0 → mcdview-0.26.2}/mcdview.py +15 -5
- {mcdview-0.26.0 → mcdview-0.26.2}/pyproject.toml +1 -1
- {mcdview-0.26.0 → mcdview-0.26.2}/templates/explorateur.html +14 -4
- {mcdview-0.26.0 → mcdview-0.26.2}/.gitignore +0 -0
- {mcdview-0.26.0 → mcdview-0.26.2}/LICENSE +0 -0
- {mcdview-0.26.0 → mcdview-0.26.2}/logo.svg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcdview
|
|
3
|
-
Version: 0.26.
|
|
3
|
+
Version: 0.26.2
|
|
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/
|
|
@@ -323,6 +323,24 @@ file's header.
|
|
|
323
323
|
|
|
324
324
|
## Changelog
|
|
325
325
|
|
|
326
|
+
### v0.26.2 — Auto-dismiss the hint banner (2026-08-30)
|
|
327
|
+
|
|
328
|
+
- The transient hint banner (e.g. "No probable missing FK", "No match", a
|
|
329
|
+
cycle/type/ref count) now clears itself after ~2.6 s, so it no longer sits
|
|
330
|
+
over the menus that open below it. The join-path prompts stay put until you
|
|
331
|
+
pick the two tables.
|
|
332
|
+
|
|
333
|
+
### v0.26.1 — Parse inline-opening multi-line CREATE TABLE (2026-08-30)
|
|
334
|
+
|
|
335
|
+
- The built-in PostgreSQL parser now reads a `CREATE TABLE` whose `(` is
|
|
336
|
+
followed by columns on the same line and whose body continues on later lines
|
|
337
|
+
(closing `)` elsewhere) — e.g. `CREATE TABLE t (id int,\n FOREIGN KEY …\n);`.
|
|
338
|
+
Previously it sat between the two fast passes and was silently dropped in a
|
|
339
|
+
mixed file (only rescued by sqlglot when the whole file had zero
|
|
340
|
+
regex-parseable tables). The single-line pass now extends to the statement's
|
|
341
|
+
closing `);` within a bounded window (a C-level search, no copy), so the
|
|
342
|
+
ReDoS/DoS budget is unchanged (the orphan-openers stress stays ~0.4 s).
|
|
343
|
+
|
|
326
344
|
### v0.26.0 — SVG preview, view deep-links, schema lint (2026-08-30)
|
|
327
345
|
|
|
328
346
|
- `--to-preview` emits a static SVG snapshot of the diagram (auto-layout,
|
|
@@ -301,6 +301,24 @@ file's header.
|
|
|
301
301
|
|
|
302
302
|
## Changelog
|
|
303
303
|
|
|
304
|
+
### v0.26.2 — Auto-dismiss the hint banner (2026-08-30)
|
|
305
|
+
|
|
306
|
+
- The transient hint banner (e.g. "No probable missing FK", "No match", a
|
|
307
|
+
cycle/type/ref count) now clears itself after ~2.6 s, so it no longer sits
|
|
308
|
+
over the menus that open below it. The join-path prompts stay put until you
|
|
309
|
+
pick the two tables.
|
|
310
|
+
|
|
311
|
+
### v0.26.1 — Parse inline-opening multi-line CREATE TABLE (2026-08-30)
|
|
312
|
+
|
|
313
|
+
- The built-in PostgreSQL parser now reads a `CREATE TABLE` whose `(` is
|
|
314
|
+
followed by columns on the same line and whose body continues on later lines
|
|
315
|
+
(closing `)` elsewhere) — e.g. `CREATE TABLE t (id int,\n FOREIGN KEY …\n);`.
|
|
316
|
+
Previously it sat between the two fast passes and was silently dropped in a
|
|
317
|
+
mixed file (only rescued by sqlglot when the whole file had zero
|
|
318
|
+
regex-parseable tables). The single-line pass now extends to the statement's
|
|
319
|
+
closing `);` within a bounded window (a C-level search, no copy), so the
|
|
320
|
+
ReDoS/DoS budget is unchanged (the orphan-openers stress stays ~0.4 s).
|
|
321
|
+
|
|
304
322
|
### v0.26.0 — SVG preview, view deep-links, schema lint (2026-08-30)
|
|
305
323
|
|
|
306
324
|
- `--to-preview` emits a static SVG snapshot of the diagram (auto-layout,
|
|
@@ -271,14 +271,24 @@ def analyser_sql(chemin):
|
|
|
271
271
|
cle = f"{m.group(1) or 'public'}.{m.group(2)}"
|
|
272
272
|
if cle in tables: # already built by the multi-line pass
|
|
273
273
|
continue
|
|
274
|
-
#
|
|
275
|
-
#
|
|
274
|
+
# first try the opener's own line only — the common single-line table,
|
|
275
|
+
# and cheap even on a "CREATE TABLE a (\n" bomb (empty body)
|
|
276
276
|
fin_ligne = src.find('\n', m.end())
|
|
277
|
-
|
|
278
|
-
entrees, ok = decouper_corps(
|
|
277
|
+
corps_txt = src[m.end():fin_ligne if fin_ligne != -1 else len(src)]
|
|
278
|
+
entrees, ok = decouper_corps(corps_txt)
|
|
279
|
+
if not ok:
|
|
280
|
+
# the body runs past the opener's line (e.g. "(id int,\n FOREIGN KEY
|
|
281
|
+
# …\n);"). Look for a plausible statement close ");" within a bounded
|
|
282
|
+
# window — a C-level find with no copy, so many unterminated openers
|
|
283
|
+
# stay cheap — then depth-split only that slice
|
|
284
|
+
borne = min(len(src), m.end() + 20000)
|
|
285
|
+
j = src.find(');', m.end(), borne)
|
|
286
|
+
if j != -1:
|
|
287
|
+
corps_txt = src[m.end():j + 1]
|
|
288
|
+
entrees, ok = decouper_corps(corps_txt)
|
|
279
289
|
if ok and entrees:
|
|
280
290
|
tables[cle] = entrees_en_table(m.group(1) or 'public', m.group(2), entrees)
|
|
281
|
-
corps_par_cle[cle] =
|
|
291
|
+
corps_par_cle[cle] = corps_txt
|
|
282
292
|
|
|
283
293
|
# partitions: constraints carried by a partition are folded back into
|
|
284
294
|
# the parent, and the partitions themselves do not appear in the model
|
|
@@ -1135,8 +1135,18 @@ function arcEntre(a, b) { // the FK connecting a and b, either direction
|
|
|
1135
1135
|
(f.de === b && f.vers === a)) || null;
|
|
1136
1136
|
}
|
|
1137
1137
|
const indice = document.getElementById("indice");
|
|
1138
|
-
|
|
1139
|
-
function
|
|
1138
|
+
let indiceTimer = null;
|
|
1139
|
+
function montrerIndice(txt, persistant) {
|
|
1140
|
+
indice.textContent = txt; indice.hidden = false;
|
|
1141
|
+
if (indiceTimer) { clearTimeout(indiceTimer); indiceTimer = null; }
|
|
1142
|
+
// transient info (no result, no cycle…) clears itself so it never sits over
|
|
1143
|
+
// the menus that open below it; a persistent prompt (join mode) stays put
|
|
1144
|
+
if (!persistant) indiceTimer = setTimeout(cacherIndice, 2600);
|
|
1145
|
+
}
|
|
1146
|
+
function cacherIndice() {
|
|
1147
|
+
if (indiceTimer) { clearTimeout(indiceTimer); indiceTimer = null; }
|
|
1148
|
+
indice.hidden = true;
|
|
1149
|
+
}
|
|
1140
1150
|
// French UI strings built at runtime; the EN build swaps them via TRADUCTIONS
|
|
1141
1151
|
const TXT = {
|
|
1142
1152
|
aucuneRelation: "Aucune table liée.",
|
|
@@ -1186,7 +1196,7 @@ function choisirJointure(cle) {
|
|
|
1186
1196
|
jointure.premier = cle;
|
|
1187
1197
|
Object.keys(elems).forEach(c => elems[c].classList.remove("depart"));
|
|
1188
1198
|
elems[cle].classList.add("depart");
|
|
1189
|
-
montrerIndice(TXT.choisirSeconde);
|
|
1199
|
+
montrerIndice(TXT.choisirSeconde, true);
|
|
1190
1200
|
} else {
|
|
1191
1201
|
const a = jointure.premier, b = cle;
|
|
1192
1202
|
jointure.actif = false; jointure.premier = null;
|
|
@@ -1410,7 +1420,7 @@ document.getElementById("btnJointure").addEventListener("click", () => {
|
|
|
1410
1420
|
sortirModes(); vueGenerale();
|
|
1411
1421
|
jointure.actif = true; jointure.premier = null;
|
|
1412
1422
|
btn.classList.add("actif");
|
|
1413
|
-
montrerIndice(TXT.choisirPremiere);
|
|
1423
|
+
montrerIndice(TXT.choisirPremiere, true);
|
|
1414
1424
|
});
|
|
1415
1425
|
|
|
1416
1426
|
if (!D.fks.some(f => f.audit)) document.getElementById("labelAudit").hidden = true;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|