From b60c2d8ed42fedc935ed502e31966566c45f9240 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 22 Aug 2026 11:52:56 +0700 Subject: [PATCH] fix(docs): stop a snippet mid-sentence from returning 500, and gate it --- docs/features/query-results.mdx | 6 ++--- docs/features/table-structure.mdx | 2 +- docs/scripts/check-links.py | 39 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/docs/features/query-results.mdx b/docs/features/query-results.mdx index 308e891f4..f156d20c2 100644 --- a/docs/features/query-results.mdx +++ b/docs/features/query-results.mdx @@ -36,11 +36,11 @@ The results panel expands itself when a query runs. The toolbar's trash button c ## The row cap -A `SELECT` or `WITH` query with no `LIMIT`, `FETCH FIRST` or `TOP` of its own stops at the row cap. , and `EXPLAIN`, `SHOW`, writes and DDL are never capped. +A `SELECT` or `WITH` query with no `LIMIT`, `FETCH FIRST` or `TOP` of its own stops at the row cap. -When the cap trims a result the status bar reads **Showing N rows** and offers **Fetch All**, which extends the result in place. To skip the cap for one run, press `Cmd+Option+Enter` or choose **Execute Without Limit** from the Execute button's menu. + -The cap and its off switch are in [Settings > Data](/customization/data-settings#query-result-row-cap). +When the cap trims a result the status bar reads **Showing N rows** and offers **Fetch All**, which extends the result in place. To skip the cap for one run, press `Cmd+Option+Enter` or choose **Execute Without Limit** from the Execute button's menu. ## Statements that return no rows diff --git a/docs/features/table-structure.mdx b/docs/features/table-structure.mdx index fc4776535..3ebbc0e4a 100644 --- a/docs/features/table-structure.mdx +++ b/docs/features/table-structure.mdx @@ -55,7 +55,7 @@ Right-click a foreign key and choose **Open [table]** to jump to the referenced ## Saving changes -; see [Change Tracking](/features/change-tracking) for the queue, undo (`Cmd+Z`) and redo (`Cmd+Shift+Z`). A save runs on the tab's own connection, database, and schema, the ones it was opened on, and never moves the sidebar or the toolbar. + [Change Tracking](/features/change-tracking) covers the queue, undo (`Cmd+Z`) and redo (`Cmd+Shift+Z`). A save runs on the tab's own connection, database, and schema, the ones it was opened on, and never moves the sidebar or the toolbar. - **Save Changes** (`Cmd+S` or the toolbar checkmark) applies the queue. Changes that can lose data, dropping a column, changing a type, adding NOT NULL, changing the primary key, first show a confirmation listing each one. - **Preview SQL** (`Cmd+Shift+P`) shows the generated statements without executing them. diff --git a/docs/scripts/check-links.py b/docs/scripts/check-links.py index 3d4a4d2eb..289286dcc 100755 --- a/docs/scripts/check-links.py +++ b/docs/scripts/check-links.py @@ -28,6 +28,44 @@ def nav_pages(node, out, collecting=False): out.add(node) +IMPORT = re.compile(r'^import\s+(\w+)\s+from\s+"(/snippets/[^"]+)"', re.M) +CONTINUES = re.compile(r"^[,;:)]|^(and|or|but|so|then|which|while|with)\b") + + +def check_snippets(path, raw, failures): + """A snippet may end a line, but the sentence may not carry on past it. + + Snippets are block content: several sentences, sometimes a markdown link that wraps. Starting a + new sentence after one on the same line renders fine. Continuing the same sentence does not: + `features/query-results.mdx` shipped `, and ...`, which built green under + `mint validate` and returned HTTP 500 in production. + """ + rel = path.relative_to(DOCS) + declared = {} + for name, source in IMPORT.findall(raw): + declared[name] = source + if not (DOCS / source.lstrip("/")).exists(): + failures.append(f"{rel} imports {source}, which is not in docs/snippets") + if not declared: + return + + used = "|".join(re.escape(n) for n in declared) + in_fence = False + for line_no, line in enumerate(raw.splitlines(), 1): + if line.lstrip().startswith("```"): + in_fence = not in_fence + continue + if in_fence: + continue + for match in re.finditer(rf"<({used})\b[^>]*/>", line): + trailing = line[match.end():].strip() + if trailing and CONTINUES.match(trailing): + failures.append( + f"{rel}:{line_no} carries the sentence on past <{match.group(1)} />; " + f"a snippet is block content, so start a new sentence or a new line" + ) + + def main() -> int: config = json.loads((DOCS / "docs.json").read_text()) pages = set() @@ -62,6 +100,7 @@ def main() -> int: continue rel = path.relative_to(DOCS) body = FENCE.sub("", path.read_text()) + check_snippets(path, body, failures) for line_no, line in enumerate(body.splitlines(), 1): for target in LINK.findall(line): page, _, anchor = target.partition("#")