From 3f92e8f87e604a67022011bc788a1627fc087b38 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Aug 2026 12:17:25 +0000 Subject: [PATCH] Open the samples page from the home page, and drop the page about it resources/samples.md described three catalogues it does not own: what each holds, how many apps that is, how to read a row, how to run one. All of it is already on the pages themselves, which carry the search, the filters and a bar linking the other two - so the page here was a stop between the reader and the corpus, and a second copy of four figures somebody else maintains. The home page button now opens https://abap2ui5.github.io/samples/ directly. The four pages that pointed at the removed page name the three catalogue pages instead, and the sidebar entry is gone. check:counts existed only to hold those four figures against the catalogues. With the prose copy gone there is nothing left to check, so the gate and scripts/check-corpus-counts.mjs go with it - six gates become five in package.json, both workflows, AGENTS.md and README.md. scripts/lib/catalogue.mjs stays: link-samples.mjs parses with it and generate-llms.mjs still counts the three catalogues into llms.txt, which is why CI keeps the two sparse checkouts. Verified: npm run check green, all five, with an abap2UI5/samples checkout so check:samples reported rather than skipped. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Fqonz6wkm3wGyER57qNwGE --- .github/workflows/check.yml | 17 ++--- .github/workflows/deploy.yml | 7 +- AGENTS.md | 28 ++++---- CLAUDE.md | 2 +- README.md | 16 ++--- docs/.vitepress/config.mjs | 17 +++-- docs/advanced/mcp_server.md | 6 +- docs/advanced/vscode.md | 4 +- docs/get_started/next.md | 2 +- docs/get_started/tooling.md | 8 +-- docs/index.md | 24 ++++--- docs/resources/samples.md | 112 ----------------------------- package.json | 5 +- scripts/check-corpus-counts.mjs | 120 -------------------------------- 14 files changed, 65 insertions(+), 303 deletions(-) delete mode 100644 docs/resources/samples.md delete mode 100644 scripts/check-corpus-counts.mjs diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 32f9787f..4aa8594f 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -40,10 +40,11 @@ jobs: path: .samples fetch-depth: 1 - # The other two catalogues, for the counts on resources/samples.md. Only - # SAMPLES.md is needed, so only SAMPLES.md is fetched — and an unreachable - # repository costs one verified figure, never the run: check:counts skips - # what it cannot read and says which ones those were. + # The other two catalogues, for the figures generate-llms.mjs counts + # into llms.txt during docs:build. Only SAMPLES.md is needed, so only + # SAMPLES.md is fetched — and an unreachable repository costs one + # counted figure, never the run: the generator leaves a number it + # cannot count out of the line it writes. - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 continue-on-error: true with: @@ -105,11 +106,3 @@ jobs: - name: sample links if: ${{ !cancelled() }} run: npm run check:samples - - # the four figures on resources/samples.md - three per-repository counts - # and the total they add up to - against the catalogues themselves. The - # generated llms.txt leaves a number out when it cannot count it; a prose - # page cannot, so the number stays and this is what holds it - - name: corpus counts - if: ${{ !cancelled() }} - run: npm run check:counts diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a0178536..d4899afb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -68,8 +68,8 @@ jobs: sparse-checkout: SAMPLES.md sparse-checkout-cone-mode: false # samples-stack was missing here while generate-llms.mjs counts three - # catalogues and check:counts holds four figures against them. The deploy - # therefore published a total it had counted two thirds of. + # catalogues into the llms.txt it publishes. The deploy therefore + # published a list it had counted two thirds of. - name: Sample catalogues (stack) continue-on-error: true uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -106,9 +106,6 @@ jobs: - name: sample links if: ${{ !cancelled() }} run: npm run check:samples - - name: corpus counts - if: ${{ !cancelled() }} - run: npm run check:counts # …and only then the thing that gets published. `docs:build` is itself # one of the gates - a page that does not build is a page nobody can diff --git a/AGENTS.md b/AGENTS.md index e75fa337..163ea6aa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,16 +19,16 @@ person reads the page. Do not put "as an AI, …" prose back into `docs/`. | `scripts/generate-llms.mjs` | Builds `llms.txt` / `llms-full.txt` / per-page markdown from the sidebar. Runs inside `docs:build`, so the deploy publishes them | | `scripts/check-version.mjs` | The release number in the nav bar, the deprecations page and the changelog, against the newest release tag of the framework | | `docs/.vitepress/playground.mjs` | Decides which fenced ABAP example gets a **Run** button, and wraps the fence; `theme/playground.js` is the browser half | -| `scripts/lib/catalogue.mjs` | Parses a sample catalogue's rows; pinned by `test/catalogue.test.mjs`, because it has stopped matching twice and both times answered wrongly instead of failing | +| `scripts/lib/catalogue.mjs` | Parses and counts a sample catalogue's rows, for `link-samples.mjs` and for the figures `generate-llms.mjs` writes into `llms.txt`; pinned by `test/catalogue.test.mjs`, because it has stopped matching twice and both times answered wrongly instead of failing | ## Build & verify — run before every commit ```bash -npm run check # test + check:version + docs:build + check:examples + check:samples + check:counts +npm run check # test + check:version + docs:build + check:examples + check:samples ``` -A documentation repository has no compiler for its prose, but six things in it -are decidable, and all six are decided before a merge: +A documentation repository has no compiler for its prose, but five things in it +are decidable, and all five are decided before a merge: | | | |---|---| @@ -37,9 +37,8 @@ are decidable, and all six are decided before a merge: | `docs:build` | a page that does not build is a page nobody can read | | `check:examples` | the ABAP in the fenced blocks, against the real framework: does it compile, and does the view it builds name controls and properties that exist on the UI5 floor this documentation targets | | `check:samples` | the **Working Samples** blocks, against [abap2UI5/samples](https://github.com/abap2UI5/samples) | -| `check:counts` | the four figures on `resources/samples.md` — one count per sample repository and the total they add up to — against the catalogues themselves | -`.github/workflows/check.yml` runs the same six, in the same order. Keep the +`.github/workflows/check.yml` runs the same five, in the same order. Keep the two in step: a step that exists only in `package.json` is a step no pull request has to pass, which is how `npm test` — the pin added *because* the catalogue parser broke twice in silence — went a release without CI. @@ -49,12 +48,15 @@ clone it as a sibling. Without one it *skips* rather than fails, so verify the output says what you think it says. CI checks out `abap2UI5/samples@main` explicitly for this reason. -`check:counts` reads all three catalogues the same way, and skips per -repository: with only `samples` at hand it verifies that one figure, says the -other two were not verified, and leaves the total alone (it needs all three). -CI sparse-checks out `SAMPLES.md` from `samples-controls` and `samples-stack` -so the page is fully checked; both are `continue-on-error`, because an -unreachable repository must cost a figure and not the run. +There used to be a sixth, `check:counts`, holding four figures on a +`resources/samples.md` page against the catalogues themselves. That page is +gone — the home page opens [the samples page](https://abap2ui5.github.io/samples/) +directly and each catalogue introduces itself — and with it the only prose +copy of a number this repository does not own. `generate-llms.mjs` still counts +the three catalogues into `llms.txt`, which is why CI sparse-checks out +`SAMPLES.md` from `samples-controls` and `samples-stack`; both are +`continue-on-error`, because an unreachable repository must cost a figure and +not the run, and a generated line can simply leave the number out. ## What the site publishes for machines @@ -110,7 +112,7 @@ The code travels in the playground's URL fragment, read out of the rendered block at click time — so nothing is hosted here, and the example that runs is the text on the page rather than a copy of it. -**This is the seventh decidable thing in this repository and the only one CI +**This is the sixth decidable thing in this repository and the only one CI cannot decide.** Whether an example runs is a question only a playground can answer, and a playground is a three-minute build of another repository. So the rules in `docs/.vitepress/playground.mjs` are an approximation, they fail diff --git a/CLAUDE.md b/CLAUDE.md index cfcc4f3a..e216a73f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # CLAUDE.md All project guidance lives in **[AGENTS.md](AGENTS.md)** — the single source of -truth for this repository (how the site is built, the six gates, the playground rule engine, and what may be written where). +truth for this repository (how the site is built, the five gates, the playground rule engine, and what may be written where). Read `AGENTS.md` before making any change. diff --git a/README.md b/README.md index f602b1f7..56f0018b 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,18 @@ Every contribution makes the documentation better for the community! ```sh npm ci npm run docs:dev # the site, with hot reload -npm run check # what CI runs, all six steps +npm run check # what CI runs, all five steps ``` ### What CI checks -A documentation repository has no compiler for its prose, but six things in it -are decidable, and `npm run check` decides all six before a merge — the prose +A documentation repository has no compiler for its prose, but five things in it +are decidable, and `npm run check` decides all five before a merge — the prose builds (`docs:build`), the fenced ABAP examples compile and the views they -build name real UI5 API (`check:examples`), the sample links and the sample -counts still match the sample repositories (`check:samples`, `check:counts`), -the release number in the nav bar still matches the framework -(`check:version`), and the catalogue parser still parses (`test`). +build name real UI5 API (`check:examples`), the sample links still match the +sample repositories (`check:samples`), the release number in the nav bar still +matches the framework (`check:version`), and the catalogue parser still parses +(`test`). `.github/workflows/check.yml` runs the same list in the same order, so a green `npm run check` locally is a green pull request — and `deploy.yml` runs it again before it publishes, so the site is only ever built from a tree that @@ -34,7 +34,7 @@ passed. Several of these go stale without anybody touching this repository (a release is published elsewhere, a sample class is renamed elsewhere), which is why the deploy re-runs them rather than trusting the merge. -**[AGENTS.md](AGENTS.md) describes each of the six**, what a failure means and +**[AGENTS.md](AGENTS.md) describes each of the five**, what a failure means and which of them need a sibling checkout to say anything at all — read it before changing anything beyond prose. diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 4713c784..aa0861a2 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -138,8 +138,8 @@ export default defineConfig({ // sample catalogues on top of them, which meant nine entries in two // groups and a reader scanning for "where is the code" reading past // half of it first. The catalogues are a reading destination and are - // linked where a reader looks for one — /resources/samples in the - // sidebar, and the cookbook chapters; this menu answers the other + // linked where a reader looks for one — the button under the home + // page grid, and the cookbook chapters; this menu answers the other // question, which repository to clone. text: "Links", items: [ @@ -539,13 +539,12 @@ export default defineConfig({ collapsed: true, items: [ { text: "References", link: "/resources/references" }, - // Several hundred working apps in three repositories, and until this - // page the only way to find out which one to open was to know all - // three existed. The cookbook links individual samples per chapter; - // this says which CATALOGUE answers which question. The figures live - // on the page itself, where check:counts verifies them against the - // catalogues - do not repeat one here, where nothing would. - { text: "Sample Catalogues", link: "/resources/samples" }, + // No "Sample Catalogues" entry here any more. A page that only + // described the three catalogues put a stop between the reader and + // the corpus, and had to be kept true about counts and facets it + // did not own. The catalogue pages introduce themselves and link + // one another; the home page opens the first of them directly, and + // the cookbook links individual samples per chapter. { text: "Who Uses abap2UI5?", link: "/resources/who_uses" }, { text: "Release Notes", link: "/resources/changelog" }, { text: "Deprecations", link: "/resources/deprecations" }, diff --git a/docs/advanced/mcp_server.md b/docs/advanced/mcp_server.md index 15b1e240..88b25797 100644 --- a/docs/advanced/mcp_server.md +++ b/docs/advanced/mcp_server.md @@ -90,8 +90,10 @@ thing here. It answers *"has somebody already built a value help, a tree, navigation between two apps?"* out of **614 working apps in three repositories**, and hands back a class to read rather than a snippet to trust. Any one of the three catalogues is enough to start; a missing clone is reported -in the answer, not fatal. See [Sample Catalogues](/resources/samples) for what -each one covers. +in the answer, not fatal. Each catalogue says what it covers on its own page — +[Learn](https://abap2ui5.github.io/samples/), +[Controls](https://abap2ui5.github.io/samples-controls/), +[Stack](https://abap2ui5.github.io/samples-stack/). ### Level 3 — see the running app (a browser, and time) diff --git a/docs/advanced/vscode.md b/docs/advanced/vscode.md index e80c0232..3e77cb00 100644 --- a/docs/advanced/vscode.md +++ b/docs/advanced/vscode.md @@ -248,8 +248,8 @@ can help while the chain is being written rather than after it: with run, preview and check on it: the list that says which thirty apps a repository has. - **Show Examples for this Control** — put the cursor on an `ele( )` call and - the [sample catalogues](/resources/samples) are searched for working uses of - that control, richest first, opening at the line. It reads the catalogues + the [sample catalogues](https://abap2ui5.github.io/samples/) are searched for + working uses of that control, richest first, opening at the line. It reads the catalogues from `abap2ui5.mcp.reposRoot`, so it needs those checkouts. ### Starting from a template diff --git a/docs/get_started/next.md b/docs/get_started/next.md index 5aecdf2d..33bd62b6 100644 --- a/docs/get_started/next.md +++ b/docs/get_started/next.md @@ -8,7 +8,7 @@ You've installed abap2UI5 and built your first app. From here, pick the directio ## Sample Apps Hundreds of working apps, and the fastest way to learn abap2UI5 is to read one that already does what you are about to write. They live in three repositories, each with a page that searches it — [**Learn**](https://abap2ui5.github.io/samples/) is the one to start on: the path from the smallest app that runs to files, devices and custom CSS, one idea per sample. -Looking for one in particular? Search the page, or `Ctrl+F` the [catalogue](https://github.com/abap2UI5/samples/blob/main/SAMPLES.md) for `f4`, `tree` or `nav_app_call`. [Sample Catalogues](/resources/samples) tells the three repositories apart, and the [Cookbook](/cookbook/overview) links the same apps from the page that explains the pattern. +Looking for one in particular? Search the page, or `Ctrl+F` the [catalogue](https://github.com/abap2UI5/samples/blob/main/SAMPLES.md) for `f4`, `tree` or `nav_app_call`. [**Controls**](https://abap2ui5.github.io/samples-controls/) is the UI5 demo kit rebuilt control by control and [**Stack**](https://abap2ui5.github.io/samples-stack/) the samples that need something from your system — each page links the other two at its top. The [Cookbook](/cookbook/overview) links the same apps from the page that explains the pattern. ![Sample apps overview showing tables, lists, trees, and other UI5 controls](/get_started/image-1.png) diff --git a/docs/get_started/tooling.md b/docs/get_started/tooling.md index 1e7a32d3..5f18607b 100644 --- a/docs/get_started/tooling.md +++ b/docs/get_started/tooling.md @@ -75,7 +75,7 @@ Three repositories, each with a searchable page of its own: control does what?”*, and [**Stack**](https://abap2ui5.github.io/samples-stack/) for *“Will my system run it?”*. -[Sample Catalogues](/resources/samples) is the page that tells the three apart -— what each one holds, how many, and which to search for what you are asking. -All three install with abapGit and carry an overview app that lists everything -they contain. +Each page says what its own corpus holds, how many apps that is, and carries +the search and the filters for it — and links the other two in the bar at its +top, so any one of the three is a way in to all of them. All three install with +abapGit and carry an overview app that lists everything they contain. diff --git a/docs/index.md b/docs/index.md index 3d8e0e9a..0b4023e5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -32,10 +32,10 @@ hero: # card not spent on a journey. # # Samples are NOT a card either, and that is the one deliberate gap: the -# catalogues are a reading destination of their own, and a card that looks -# like the three around it and then hands you a corpus is the card people -# click by accident. They sit below the grid instead, as a single button, set -# apart, where leaving the grid is the obvious thing to be doing. +# catalogue is a reading destination of its own, and a card that looks like +# the three around it and then hands you a corpus is the card people click by +# accident. It sits below the grid instead, as a single button, set apart, +# where leaving the grid — and this site — is the obvious thing to be doing. features: - title: Cookbook icon: @@ -51,17 +51,19 @@ features: link: https://github.com/abap2UI5/abap2UI5/ --- - +
-Looking for a working app to copy? The sample catalogues are searchable in the browser — nothing to install. +Looking for a working app to copy? Hundreds of them are searchable in the browser — nothing to install. {.a2ui5-catalogues-lead} -[Browse the Samples](/resources/samples) +[Browse the Samples](https://abap2ui5.github.io/samples/) {.a2ui5-catalogues-links}
diff --git a/docs/resources/samples.md b/docs/resources/samples.md deleted file mode 100644 index 7beb046f..00000000 --- a/docs/resources/samples.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -outline: [2, 4] ---- -# Sample Catalogues - -**612 working apps, in three repositories.** Every one is a single ABAP class -that compiles, renders, and is downported to three releases — so a sample is -never a fragment you have to trust, it is an app you can pull and run. - -The three answer three different questions. Picking the wrong one costs more -time than reading this page. - -| | | you are asking | -|---|--:|---| -| [**Learn**](https://abap2ui5.github.io/samples/) — abap2UI5/samples, [catalogue](https://github.com/abap2UI5/samples/blob/main/SAMPLES.md) | 150 | *“Where do I start?”* — value help, navigation between apps, trees, tables, timers, file up- and download. Runs on a bare abap2UI5 install. | -| [**Controls**](https://abap2ui5.github.io/samples-controls/) — abap2UI5/samples-controls, [catalogue](https://github.com/abap2UI5/samples-controls/blob/main/SAMPLES.md) | 430 | *“Which control does what?”* — the UI5 demo kit, rebuilt control by control, grouped by library. | -| [**Stack**](https://abap2ui5.github.io/samples-stack/) — abap2UI5/samples-stack, [catalogue](https://github.com/abap2UI5/samples-stack/blob/main/SAMPLES.md) | 32 | *“Will my system run it?”* — OData, RAP, APC, MIME, the Fiori Launchpad. Each needs something the framework alone does not give you. | - -They are not three steps to work through in order. **Learn** is a path and does -have a beginning; **Controls** is a reference you come back to whenever you -need one control; **Stack** only matters once the app has to talk to something -in your system. Pick the one that matches what you are asking today. - -::: tip The three verbs are the same everywhere -**Learn**, **Controls** and **Stack** are what the three pages call each other -in the bar at the top of each of them, and what the playground calls them in -its About dialog. Same word, same page, wherever you meet it. -::: - -## Two ways to read a catalogue - -Each repository publishes its corpus twice, from one scan, so the two cannot -disagree: - -| | | -|---|---| -| the **page** (the first link in each row above) | searchable in the browser, with the facets that corpus is actually asked for — a release your system runs, a control used anywhere in a view, a technology and the setup it needs | -| the **catalogue** `SAMPLES.md` | the same corpus as one long page on GitHub, for `Ctrl+F` and for reading offline. The counts above are of these. | - -The pages are the better answer to *"is there a sample for X"*, because they -filter; the catalogues are the better answer to *"show me everything"*. The -page for **Learn** deliberately shows only the portable subset that survives -every build, so it lists fewer apps than the 150 the catalogue counts. - -## The pages have the same shape on purpose - -Every row of every catalogue reads the same way: - -> **sap.m.Breadcrumbs** -> Breadcrumbs is useful for displaying link hierarchy -> breadcrumbs sap.m breadcrumb trail separator link hbox label select - -The **title** says which sample it is, the **sentence** says what it shows, and -the **small type** are the words to search the page for — the terms somebody -would type who does not yet know the sample exists. `Ctrl+F` on any of the -three pages is a real search, not a scroll. - -None of it is written on the page. All three lines live **on the class**, as -its abapGit short text and two comment lines above `CLASS … DEFINITION`: - -```abap -" @keywords f4 search help suggestion input dialog select -" @summary The value help, both halves: suggestions while typing and the F4 dialog behind the field. -CLASS z2ui5_cl_smp_app_009 DEFINITION PUBLIC. -``` - -The catalogues are generated from those lines, and each repository refuses a -sample that is missing one. So a page can never describe a sample differently -from the class it links to — and a search engine that drops you into the class -gives you the same sentence the catalogue would have. - -## For AI agents - -The same three catalogues are queryable through the -[MCP server](/advanced/mcp_server) — the `examples` tool searches -all of them at once and answers with a repository, a class name and a path to -read, never with a copied snippet: - -``` -examples { query: "value help f4" } -examples { query: "wizard", repo: "samples-controls" } -``` - -The neighbouring question — *can abap2UI5 express this UI5 feature at all* — is -the `capabilities` tool, out of `samples-controls`' -[CAPABILITIES.md](https://github.com/abap2UI5/samples-controls/blob/main/CAPABILITIES.md). -Neither answers the other: a control being expressible says nothing about how -an app that uses it is put together. - -## Running one - -Install [abap2UI5](https://github.com/abap2UI5/abap2UI5), pull the repository -with [abapGit](https://abapgit.org), then start any class by name: - -``` -?app_start=Z2UI5_CL_SMP_APP_009 -``` - -Each repository also ships an **overview app** that lists its own samples with -a search box, so once the repository is in your system you do not need the page -here at all. - -### Without a system - -Every card on the **Learn** and **Controls** pages carries a button that opens -that class in the [playground](https://abap2ui5.github.io/playground/) — the -ABAP in an editor with the app running beside it, in the browser, nothing -installed anywhere. - -**Stack** is the exception, and says so on its own cards: a Gateway service, a -RAP business object, an APC channel or a launchpad is precisely what the -playground does not have, so those samples would open there and then fail. diff --git a/package.json b/package.json index 6c4c703e..3b8ab7d3 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,9 @@ "link:samples": "node scripts/link-samples.mjs", "check:samples": "node scripts/link-samples.mjs --check", "test": "node --test test/*.test.mjs", - "check": "npm run test && npm run check:version && npm run docs:build && npm run check:examples && npm run check:samples && npm run check:counts", + "check": "npm run test && npm run check:version && npm run docs:build && npm run check:examples && npm run check:samples", "llms": "node scripts/generate-llms.mjs", - "check:version": "node scripts/check-version.mjs", - "check:counts": "node scripts/check-corpus-counts.mjs" + "check:version": "node scripts/check-version.mjs" }, "devDependencies": { "@abap2ui5/linter": "^0.2.2", diff --git a/scripts/check-corpus-counts.mjs b/scripts/check-corpus-counts.mjs deleted file mode 100644 index 68a29aca..00000000 --- a/scripts/check-corpus-counts.mjs +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env node -/* - * check-corpus-counts — the sample-catalogue page states four numbers, and - * this is what holds them to the catalogues. - * - * `resources/samples.md` is the page that answers "which of the three sample - * repositories do I search?", and it opens with a total: "614 working apps, in - * three repositories", then one count per repository in the table below. Every - * one of those is typed by hand, and every one of them describes a repository - * whose CI cannot see this page. - * - * They had drifted - the page said 431 for samples-controls and 615 in total - * while the published catalogue said 430 and the three summed to 614. Small, - * and exactly the kind of small that a reader has no way to detect: a figure - * on the page that introduces the catalogues is taken on trust. - * - * generate-llms.mjs solved the same problem for the generated file by counting - * instead of typing, and leaving the number out when the catalogue is absent. - * A prose page cannot do that - the sentence is written, not generated - so - * the number stays and this checks it. - * - * Counted through `countCatalogue`, the same parser link-samples.mjs resolves - * against, so the answer is always "what this repository can resolve" and - * never a second opinion. - * - * A catalogue that is not checked out is NOT a failure: the count is skipped - * and the run says which ones it could not take. The total needs all three, so - * it is skipped unless all three are there. A check must not go red because a - * sibling repository is absent, and must not claim to have verified something - * it did not. - * - * node scripts/check-corpus-counts.mjs (npm run check:counts) - */ -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { countCatalogue } from './lib/catalogue.mjs'; - -const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); -const PAGE = 'docs/resources/samples.md'; - -/* Each claim names the repository it is about and the pattern that carries the - * number. Declared one by one rather than scanned, so that this file has no - * opinion about "1.71" or any other figure on the page, and so that adding a - * count to the page is a decision somebody makes here. */ -const CLAIMS = [ - { repo: 'samples', find: /\/samples\/blob\/main\/SAMPLES\.md\)\s*\|\s*(\d+)\s*\|/ }, - { repo: 'samples-controls', find: /\/samples-controls\/blob\/main\/SAMPLES\.md\)\s*\|\s*(\d+)\s*\|/ }, - { repo: 'samples-stack', find: /\/samples-stack\/blob\/main\/SAMPLES\.md\)\s*\|\s*(\d+)\s*\|/ }, -]; - -const TOTAL = { find: /\*\*(\d+) working apps, in three repositories\.\*\*/ }; - -const file = path.join(ROOT, PAGE); -if (!fs.existsSync(file)) { - console.error(`${PAGE} is not here — this check names it directly`); - process.exit(1); -} -const text = fs.readFileSync(file, 'utf8'); - -const problems = []; -const notes = []; -let checked = 0; - -const truth = {}; -for (const claim of CLAIMS) { - const found = text.match(claim.find); - if (!found) { - /* The table was restructured. Failing is right: silently no longer - * checking a number that is still on the page is the outcome to avoid. */ - problems.push( - `${PAGE}: no match for ${claim.find} (${claim.repo})\n` - + ' the row carrying this count changed shape — update the pattern here,' - + ' or drop the claim if the number is gone', - ); - continue; - } - - const actual = countCatalogue(claim.repo, ROOT); - if (actual === null) { - notes.push(`${claim.repo}: catalogue not here — ${found[1]} not verified`); - continue; - } - - truth[claim.repo] = actual; - checked += 1; - if (Number(found[1]) !== actual) { - problems.push(`${PAGE}: says ${found[1]} for ${claim.repo}, its catalogue lists ${actual}`); - } -} - -const totalFound = text.match(TOTAL.find); -if (!totalFound) { - problems.push( - `${PAGE}: no match for ${TOTAL.find}\n` - + ' the opening sentence changed shape — update the pattern here', - ); -} else if (Object.keys(truth).length === CLAIMS.length) { - const sum = Object.values(truth).reduce((a, b) => a + b, 0); - checked += 1; - if (Number(totalFound[1]) !== sum) { - problems.push(`${PAGE}: opens with ${totalFound[1]} apps in total, the three catalogues list ${sum}`); - } -} else { - notes.push(`total: not verified — it needs all three catalogues`); -} - -console.log(`check-corpus-counts: ${CLAIMS.length + 1} claim(s) on ${PAGE}, ${checked} checked`); -for (const n of notes) console.log(` ${n}`); - -if (problems.length) { - console.error(`\n${problems.length} problem(s):`); - for (const p of problems) console.error(` ${p}`); - process.exit(1); -} -if (!checked) { - console.log('no catalogue reachable — not a failure, but nothing was verified'); -} else { - console.log('every count matches its catalogue - OK'); -}