@bongos/core 1.24.58 → 1.24.60
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.
- package/.bongos-core.json +48 -33
- package/docs/architecture.md +1 -1
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-readings.json +1 -1
- package/docs/recipes/ops-gotchas.md +2 -2
- package/modules/status-ui/public/style.css +5 -2
- package/modules/ui-design/public/brand/png-sources.json +10 -0
- package/modules/ui-design/public/brand.css +6 -0
- package/modules/ui-design/public/brand.html +2 -2
- package/modules/ui-design/scripts/gen-design-reference.js +2 -3
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-docs/index.html +3 -1
- package/release-notes.json +16 -0
- package/scripts/bongos/css-literal-scan.js +72 -14
- package/scripts/bongos/design-generators-fresh.js +14 -6
- package/scripts/bongos/gen-brand.js +82 -36
- package/scripts/status-mirror-sync.js +4 -1
- package/src/bongos/routes/auth.js +4 -9
- package/src/bongos/serve-internal.js +5 -70
- package/src/bongos/sign-in-pages.js +20 -4
- package/src/brand-mark.js +10 -1
- package/src/error-page.js +11 -10
- package/src/module-api.js +1 -1
- package/src/theme-markup.js +81 -0
- package/tests/brand_mark.mjs +11 -1
- package/tests/brand_surfaces.mjs +5 -2
- package/tests/design_counts_ratchet.mjs +97 -2
- package/tests/design_reference.mjs +1 -1
- package/tests/wordmark_and_faces.mjs +111 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/bongos/package-core.js",
|
|
5
|
-
"core_version": "1.24.
|
|
6
|
-
"core_contract": "1.24.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.24.60",
|
|
6
|
+
"core_contract": "1.24.60",
|
|
7
|
+
"source_commit": "fef925d217da9148be0808c73ee46288043dc2de",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-11-
|
|
9
|
+
"built_at": "2026-11-07T15:39:07.882Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 638,
|
|
13
13
|
"agent_docs_stubbed": 32,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 3900,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 4571,
|
|
20
|
+
"tree_sha256": "02fb38f9111b66794f346c5bb82422a3f315f456b1c9d73a5b3eb1c136097fc1",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2472,7 +2472,7 @@
|
|
|
2472
2472
|
{
|
|
2473
2473
|
"path": "docs/architecture.md",
|
|
2474
2474
|
"mode": "0000644",
|
|
2475
|
-
"sha256": "
|
|
2475
|
+
"sha256": "58b03efd477eb60e66022cce2e4adda65a359d20ee992c6bceb3320a995322c5"
|
|
2476
2476
|
},
|
|
2477
2477
|
{
|
|
2478
2478
|
"path": "docs/branding-contract.md",
|
|
@@ -3007,7 +3007,7 @@
|
|
|
3007
3007
|
{
|
|
3008
3008
|
"path": "docs/module-api-changelog.md",
|
|
3009
3009
|
"mode": "0000644",
|
|
3010
|
-
"sha256": "
|
|
3010
|
+
"sha256": "71913622d0d94c4120e620d5aea32ff476a6e879c5e166da3144eedc75619dda"
|
|
3011
3011
|
},
|
|
3012
3012
|
{
|
|
3013
3013
|
"path": "docs/modules-contract.md",
|
|
@@ -3097,7 +3097,7 @@
|
|
|
3097
3097
|
{
|
|
3098
3098
|
"path": "docs/page-readings.json",
|
|
3099
3099
|
"mode": "0000644",
|
|
3100
|
-
"sha256": "
|
|
3100
|
+
"sha256": "16e8909e4de1207587056fece1ee2fc2455778f569d3338043fd6bc5eb05543d"
|
|
3101
3101
|
},
|
|
3102
3102
|
{
|
|
3103
3103
|
"path": "docs/project-context.template.md",
|
|
@@ -3192,7 +3192,7 @@
|
|
|
3192
3192
|
{
|
|
3193
3193
|
"path": "docs/recipes/ops-gotchas.md",
|
|
3194
3194
|
"mode": "0000644",
|
|
3195
|
-
"sha256": "
|
|
3195
|
+
"sha256": "99193931238d13b50918ddc794136a3f5a499ef384cd5ff227c64a5cbb5dc116"
|
|
3196
3196
|
},
|
|
3197
3197
|
{
|
|
3198
3198
|
"path": "docs/recipes/overnight-builder.md",
|
|
@@ -11332,7 +11332,7 @@
|
|
|
11332
11332
|
{
|
|
11333
11333
|
"path": "modules/status-ui/public/style.css",
|
|
11334
11334
|
"mode": "0000644",
|
|
11335
|
-
"sha256": "
|
|
11335
|
+
"sha256": "84b2a0c1e49eef8a7f87a586f250afce3a7c89d54a4211a0ac52820e3de63929"
|
|
11336
11336
|
},
|
|
11337
11337
|
{
|
|
11338
11338
|
"path": "modules/ui-design/CLAUDE.md",
|
|
@@ -11702,12 +11702,12 @@
|
|
|
11702
11702
|
{
|
|
11703
11703
|
"path": "modules/ui-design/public/brand.css",
|
|
11704
11704
|
"mode": "0000644",
|
|
11705
|
-
"sha256": "
|
|
11705
|
+
"sha256": "4d80b05a7f569217a96df00e2c11a8005e540730d67ea94f0d2fa7fe66303343"
|
|
11706
11706
|
},
|
|
11707
11707
|
{
|
|
11708
11708
|
"path": "modules/ui-design/public/brand.html",
|
|
11709
11709
|
"mode": "0000644",
|
|
11710
|
-
"sha256": "
|
|
11710
|
+
"sha256": "9bd01c16060a9624f3f1e0e4467ca7b4da4df3b7527c8b005a669b331b171d1a"
|
|
11711
11711
|
},
|
|
11712
11712
|
{
|
|
11713
11713
|
"path": "modules/ui-design/public/brand.states.json",
|
|
@@ -11759,6 +11759,11 @@
|
|
|
11759
11759
|
"mode": "0000644",
|
|
11760
11760
|
"sha256": "e168fdd0f4ac94754af089e7240be7cbba46704b36a617252f2942c97e8835e2"
|
|
11761
11761
|
},
|
|
11762
|
+
{
|
|
11763
|
+
"path": "modules/ui-design/public/brand/png-sources.json",
|
|
11764
|
+
"mode": "0000644",
|
|
11765
|
+
"sha256": "6181696f80b70fab9daadc14f77963093223387ecff5d4f13b9e1f63e1c6ad6f"
|
|
11766
|
+
},
|
|
11762
11767
|
{
|
|
11763
11768
|
"path": "modules/ui-design/public/tokens.css",
|
|
11764
11769
|
"mode": "0000644",
|
|
@@ -11777,7 +11782,7 @@
|
|
|
11777
11782
|
{
|
|
11778
11783
|
"path": "modules/ui-design/scripts/gen-design-reference.js",
|
|
11779
11784
|
"mode": "0000644",
|
|
11780
|
-
"sha256": "
|
|
11785
|
+
"sha256": "d59b046a2aabda513d2d580a574c74ae43b04e97c847315c16eaa2ab50144ffb"
|
|
11781
11786
|
},
|
|
11782
11787
|
{
|
|
11783
11788
|
"path": "modules/ui-design/scripts/gen-design-tokens.js",
|
|
@@ -11897,17 +11902,17 @@
|
|
|
11897
11902
|
{
|
|
11898
11903
|
"path": "package-lock.json",
|
|
11899
11904
|
"mode": "0000644",
|
|
11900
|
-
"sha256": "
|
|
11905
|
+
"sha256": "dfea60d54c9a25b94f32d02e56aecb552db65f0a68d3ca9470db04acbd8b3fd3"
|
|
11901
11906
|
},
|
|
11902
11907
|
{
|
|
11903
11908
|
"path": "package.json",
|
|
11904
11909
|
"mode": "0000644",
|
|
11905
|
-
"sha256": "
|
|
11910
|
+
"sha256": "fe9083b4b86df7ab6427311717f99a1bba6d8c7e079e2f37c32b4722a3bc4186"
|
|
11906
11911
|
},
|
|
11907
11912
|
{
|
|
11908
11913
|
"path": "public-docs/index.html",
|
|
11909
11914
|
"mode": "0000644",
|
|
11910
|
-
"sha256": "
|
|
11915
|
+
"sha256": "6ec35589784910e09c362401b3e0468b90cbe58c56754d6e6d7e4353a8083444"
|
|
11911
11916
|
},
|
|
11912
11917
|
{
|
|
11913
11918
|
"path": "public-docs/redoc.standalone.js",
|
|
@@ -11922,7 +11927,7 @@
|
|
|
11922
11927
|
{
|
|
11923
11928
|
"path": "release-notes.json",
|
|
11924
11929
|
"mode": "0000644",
|
|
11925
|
-
"sha256": "
|
|
11930
|
+
"sha256": "2735b7f5e5d4c0bf2b24fc78d79738c5b57a9eaf4734823a79e67ea8e0fb39b2"
|
|
11926
11931
|
},
|
|
11927
11932
|
{
|
|
11928
11933
|
"path": "scripts/bongos/CLAUDE.md",
|
|
@@ -12262,7 +12267,7 @@
|
|
|
12262
12267
|
{
|
|
12263
12268
|
"path": "scripts/bongos/css-literal-scan.js",
|
|
12264
12269
|
"mode": "0000644",
|
|
12265
|
-
"sha256": "
|
|
12270
|
+
"sha256": "1dbcdb46cfd195c1080bdd37bc8337b0926cd5f6e281cd131656801f6c92b236"
|
|
12266
12271
|
},
|
|
12267
12272
|
{
|
|
12268
12273
|
"path": "scripts/bongos/cutover-codemod.js",
|
|
@@ -12297,7 +12302,7 @@
|
|
|
12297
12302
|
{
|
|
12298
12303
|
"path": "scripts/bongos/design-generators-fresh.js",
|
|
12299
12304
|
"mode": "0000644",
|
|
12300
|
-
"sha256": "
|
|
12305
|
+
"sha256": "a51d725286fa198505ff57ceceb50412ffa18e9f659c88cbe01d501bac8da9f5"
|
|
12301
12306
|
},
|
|
12302
12307
|
{
|
|
12303
12308
|
"path": "scripts/bongos/design-sync.js",
|
|
@@ -12517,7 +12522,7 @@
|
|
|
12517
12522
|
{
|
|
12518
12523
|
"path": "scripts/bongos/gen-brand.js",
|
|
12519
12524
|
"mode": "0000644",
|
|
12520
|
-
"sha256": "
|
|
12525
|
+
"sha256": "bc3ce6eebc646e7f2359ef2495a99878e060d7b41c27673833d824d428a379bd"
|
|
12521
12526
|
},
|
|
12522
12527
|
{
|
|
12523
12528
|
"path": "scripts/bongos/gen-diagrams.js",
|
|
@@ -15302,7 +15307,7 @@
|
|
|
15302
15307
|
{
|
|
15303
15308
|
"path": "scripts/status-mirror-sync.js",
|
|
15304
15309
|
"mode": "0000644",
|
|
15305
|
-
"sha256": "
|
|
15310
|
+
"sha256": "41628e240bb4f5c9840f1ce3839d1a299df8cacd54b2706f4151dcda53e7495b"
|
|
15306
15311
|
},
|
|
15307
15312
|
{
|
|
15308
15313
|
"path": "src/asset-version.js",
|
|
@@ -15672,7 +15677,7 @@
|
|
|
15672
15677
|
{
|
|
15673
15678
|
"path": "src/bongos/routes/auth.js",
|
|
15674
15679
|
"mode": "0000644",
|
|
15675
|
-
"sha256": "
|
|
15680
|
+
"sha256": "6348ee00e6e60d899f3e98bc55a75e6b3f88562fcda7a1655a4d4df1c2273393"
|
|
15676
15681
|
},
|
|
15677
15682
|
{
|
|
15678
15683
|
"path": "src/bongos/routes/backup.js",
|
|
@@ -15807,12 +15812,12 @@
|
|
|
15807
15812
|
{
|
|
15808
15813
|
"path": "src/bongos/serve-internal.js",
|
|
15809
15814
|
"mode": "0000644",
|
|
15810
|
-
"sha256": "
|
|
15815
|
+
"sha256": "0d5a45ed0f8b8f907169a886504749887a659fbd2bdff23c28fa8146c3742a05"
|
|
15811
15816
|
},
|
|
15812
15817
|
{
|
|
15813
15818
|
"path": "src/bongos/sign-in-pages.js",
|
|
15814
15819
|
"mode": "0000644",
|
|
15815
|
-
"sha256": "
|
|
15820
|
+
"sha256": "cfd8a09da90e8f2a176e94c960736bbb295c216a1d6bf1f8027f7f0ce1ceacc8"
|
|
15816
15821
|
},
|
|
15817
15822
|
{
|
|
15818
15823
|
"path": "src/bongos/software-update.js",
|
|
@@ -15832,7 +15837,7 @@
|
|
|
15832
15837
|
{
|
|
15833
15838
|
"path": "src/brand-mark.js",
|
|
15834
15839
|
"mode": "0000644",
|
|
15835
|
-
"sha256": "
|
|
15840
|
+
"sha256": "5484f9ff087a0d28d076f5079c49aaa55e704ba52e60be03a9454e3b8fc4b3c8"
|
|
15836
15841
|
},
|
|
15837
15842
|
{
|
|
15838
15843
|
"path": "src/branding.js",
|
|
@@ -15847,7 +15852,7 @@
|
|
|
15847
15852
|
{
|
|
15848
15853
|
"path": "src/error-page.js",
|
|
15849
15854
|
"mode": "0000644",
|
|
15850
|
-
"sha256": "
|
|
15855
|
+
"sha256": "ddfd55f0581a32e31b26624e0e981b1768af896f7edc962bc1779eb05f64ccba"
|
|
15851
15856
|
},
|
|
15852
15857
|
{
|
|
15853
15858
|
"path": "src/hall-look.js",
|
|
@@ -15872,7 +15877,7 @@
|
|
|
15872
15877
|
{
|
|
15873
15878
|
"path": "src/module-api.js",
|
|
15874
15879
|
"mode": "0000644",
|
|
15875
|
-
"sha256": "
|
|
15880
|
+
"sha256": "66eed53ac99b04f6c4c0b5e33b13b44c2b1d53239198bf8b41fe13a454d866d9"
|
|
15876
15881
|
},
|
|
15877
15882
|
{
|
|
15878
15883
|
"path": "src/module-loader/catalog.js",
|
|
@@ -15939,6 +15944,11 @@
|
|
|
15939
15944
|
"mode": "0000644",
|
|
15940
15945
|
"sha256": "1565fab25ca23066a460ef35f3693a56186fdc03f5461d3fc891b528d185885c"
|
|
15941
15946
|
},
|
|
15947
|
+
{
|
|
15948
|
+
"path": "src/theme-markup.js",
|
|
15949
|
+
"mode": "0000644",
|
|
15950
|
+
"sha256": "7efca13206ba049b5958bcfdbb674e14e67ff4e8c1ddb33f0729bcbd6de4624f"
|
|
15951
|
+
},
|
|
15942
15952
|
{
|
|
15943
15953
|
"path": "tests/abandon_creator_authz.mjs",
|
|
15944
15954
|
"mode": "0000644",
|
|
@@ -16662,12 +16672,12 @@
|
|
|
16662
16672
|
{
|
|
16663
16673
|
"path": "tests/brand_mark.mjs",
|
|
16664
16674
|
"mode": "0000644",
|
|
16665
|
-
"sha256": "
|
|
16675
|
+
"sha256": "68ff85560c05b7426139527cea3832429e17da4b64c96bbc26ba46c02305d97e"
|
|
16666
16676
|
},
|
|
16667
16677
|
{
|
|
16668
16678
|
"path": "tests/brand_surfaces.mjs",
|
|
16669
16679
|
"mode": "0000644",
|
|
16670
|
-
"sha256": "
|
|
16680
|
+
"sha256": "26684884f85c8ad99966ae4f7713552cc12709c0d41100b3d7a5b60b8d50c9af"
|
|
16671
16681
|
},
|
|
16672
16682
|
{
|
|
16673
16683
|
"path": "tests/branding.mjs",
|
|
@@ -17402,12 +17412,12 @@
|
|
|
17402
17412
|
{
|
|
17403
17413
|
"path": "tests/design_counts_ratchet.mjs",
|
|
17404
17414
|
"mode": "0000644",
|
|
17405
|
-
"sha256": "
|
|
17415
|
+
"sha256": "3e7457685c915d01d11ba4dd1481e726f82c83a3ce481f5190893e4b0636b7bc"
|
|
17406
17416
|
},
|
|
17407
17417
|
{
|
|
17408
17418
|
"path": "tests/design_reference.mjs",
|
|
17409
17419
|
"mode": "0000644",
|
|
17410
|
-
"sha256": "
|
|
17420
|
+
"sha256": "809766d9baedf5ed420935d3c94c7e1bcb27cfd46c307792cd556ea7eb4f24af"
|
|
17411
17421
|
},
|
|
17412
17422
|
{
|
|
17413
17423
|
"path": "tests/design_tokens_generated.mjs",
|
|
@@ -22814,6 +22824,11 @@
|
|
|
22814
22824
|
"mode": "0000644",
|
|
22815
22825
|
"sha256": "486bb5b4af30db3ab3a6a0f047edf60a9d4ec5a70cb1c19cebbd1fcd89578799"
|
|
22816
22826
|
},
|
|
22827
|
+
{
|
|
22828
|
+
"path": "tests/wordmark_and_faces.mjs",
|
|
22829
|
+
"mode": "0000644",
|
|
22830
|
+
"sha256": "bb1ac8d5fd24e2ea073b768298acbe4bcc55ca5f2e25d36d9904fdcd18037ac8"
|
|
22831
|
+
},
|
|
22817
22832
|
{
|
|
22818
22833
|
"path": "tests/work_board_live_refresh.mjs",
|
|
22819
22834
|
"mode": "0000644",
|
package/docs/architecture.md
CHANGED
|
@@ -456,7 +456,7 @@ markdown describes, the DB enforces.**
|
|
|
456
456
|
|
|
457
457
|
- **the apex root itself** — the public front door (`/`, `/projects`, `/create`, `/privacy`, `/terms`, `/contact`). **Carved to the `public-landing` module in task 1003322** ([ADR 0218](adr/0218-the-apex-root-web-surface.md)): the surface moved from repo-root `public-landing/` to `modules/public-landing/public/` and is a loader-discovered web-surface module — the THIRD, and the first that is not a subdomain. Where `hall-ui`/`status-ui` declare a Host PREFIX, this one declares `{ apexRoot: true, dir }`, because the apex is whatever host is left once the subdomains are taken (`isApexHost` = `!isStatusHost && !isBuildersHost`); `host: ""` is rejected, since `host.startsWith("")` is true for every host and would swallow the other two surfaces. Like the hall it keeps its **dedicated** serving block — in `src/platform-server.js`, now resolving its root through `moduleWebSurfaces()` by the `apexRoot` predicate rather than a hardcoded path — so the apex-only sentinel strip, the brand-token stamp and the `?v=` content stamp are unchanged. Disable the module and the front door vanishes: every route falls through to the game-less 404 tail. Served bytes are identical across the carve apart from the module's own `window.__MODULES__` entry.
|
|
458
458
|
- **`example.com`** — game (Phaser + Colyseus). Static files from `public/`. `/builders` + `/builders/*` now **301-redirect to `builders.example.com/<rest>`** ([#739](https://example.com/builders#/task/739) then promoted to permanent 301 in [#741](https://example.com/builders#/task/741), ADR 0036 cutover); the apex no longer serves the builder surface directly.
|
|
459
|
-
- **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-status/` to `modules/status-ui/public/`, now served by the loader's web-surface seam (`moduleWebSurfaces` → `serve-internal.js`, routed on the `status.` Host prefix the manifest declares) instead of a hardcoded block — no behavior change. Layout reorganized in [#726](https://example.com/builders#/task/726) (ADR 0036): Pulse / Watch(uptime) / Architects / Works / Treasury / Lately Inscribed / The World — the grade-aggregate, estimation-drift, and repo-health tablets moved to the Archon `/watch` page. **⚠ Served OFF the droplet** (ADR 0029, outage resilience): the live page is **GitHub Pages from the separate repo `example-owner/example-status`** (CNAME → Fastly), reading data cross-origin from the droplet's `/api/bongos/public/*` (CORS open) and an availability banner from the prober's `status-data` branch. The droplet still serves `modules/status-ui/public/` (on the `status.` host) as a same-origin fallback, but **DNS points at Pages, not the droplet** — so a droplet deploy does NOT update the live page. Changes to the surface publish to the mirror via `scripts/status-mirror-sync.js` (re-pointed at `modules/status-ui/public/`; status.js/style.css/cursors are byte-identical copies; index.html gets the off-box bits injected)
|
|
459
|
+
- **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-status/` to `modules/status-ui/public/`, now served by the loader's web-surface seam (`moduleWebSurfaces` → `serve-internal.js`, routed on the `status.` Host prefix the manifest declares) instead of a hardcoded block — no behavior change. Layout reorganized in [#726](https://example.com/builders#/task/726) (ADR 0036): Pulse / Watch(uptime) / Architects / Works / Treasury / Lately Inscribed / The World — the grade-aggregate, estimation-drift, and repo-health tablets moved to the Archon `/watch` page. **⚠ Served OFF the droplet** (ADR 0029, outage resilience): the live page is **GitHub Pages from the separate repo `example-owner/example-status`** (CNAME → Fastly), reading data cross-origin from the droplet's `/api/bongos/public/*` (CORS open) and an availability banner from the prober's `status-data` branch. The droplet still serves `modules/status-ui/public/` (on the `status.` host) as a same-origin fallback, but **DNS points at Pages, not the droplet** — so a droplet deploy does NOT update the live page. Changes to the surface publish to the mirror via `scripts/status-mirror-sync.js` (re-pointed at `modules/status-ui/public/`; status.js/style.css/cursors are byte-identical copies; index.html gets the off-box bits injected) ([#737](https://example.com/builders#/task/737)). **⚠ Run by hand:** no workflow runs the sync — `.github/workflows/sync-status-mirror.yml` is not in this repo — so a status-surface change reaches the live page only when someone runs `node scripts/status-mirror-sync.js --repo-dir <mirror-checkout> --push` (task 1005131).
|
|
460
460
|
- **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-builders/` to `modules/hall-ui/public/` (~13k LOC, the largest module) and is a loader-discovered web-surface module (`contributes.webSurfaces` host `builders.`). UNLIKE the generic status surface it keeps its **dedicated** serving block in `serve-internal.js` (`BUILDERS_DIR = modules/hall-ui/public/`), partitioned out of the generic web-surface loop on the `isBuildersHost` predicate. A thin rewrite shim maps every non-API path onto the existing `/builders/*` tree (so all serving + gating + asset-stamping is reused), serving the hall (`/`), the Metic+ **`/watch`** monitoring page (gated by `requireGovernmentPage`), **`/settings`** (Voices + Craft prefs), plus ranks/sessions/primer/diagrams. No behavior change — byte-identical (only `window.__MODULES__.enabled` gains `hall-ui:true`). **Additive** — until its DNS A record + cert are live, the whole surface stays reachable at `example.com/builders/*`. No `.github/workflows/*` follow-up: unlike R84, no workflow path-trigger watches `public-builders/**`.
|
|
461
461
|
- The `/api/bongos/*` surface is reachable from every host. **Cross-subdomain sign-in:** the `gds_session` cookie is scoped to `.example.com` on the production hosts (apex/www/builders/status) and host-only on localhost/staging (no cross-env token bleed); the OAuth handshake runs on the canonical origin with a validated `?return=` (open-redirect-guarded) so the subdomain can land a builder back on itself.
|
|
462
462
|
- Caddy gets a site block per host (`infra/Caddyfile` (instance-side)), all reverse-proxying to `127.0.0.1:3000`.
|
|
@@ -3370,5 +3370,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
3370
3370
|
landed since 1.24.56 with no explicit bump. run 42379442367. (task 1002620)
|
|
3371
3371
|
1.24.58 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3372
3372
|
landed since 1.24.57 with no explicit bump. run 42380593295. (task 1002620)
|
|
3373
|
+
1.24.59 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3374
|
+
landed since 1.24.58 with no explicit bump. run 42385816081. (task 1002620)
|
|
3375
|
+
1.24.60 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3376
|
+
landed since 1.24.59 with no explicit bump. run 42387285187. (task 1002620)
|
|
3373
3377
|
---------------------------------------------------------------------------
|
|
3374
3378
|
```
|
package/docs/page-readings.json
CHANGED
|
@@ -5031,7 +5031,7 @@
|
|
|
5031
5031
|
"surface": "status",
|
|
5032
5032
|
"title": "{{productName}} — build status",
|
|
5033
5033
|
"states_read": ["loaded"],
|
|
5034
|
-
"files_hash": "
|
|
5034
|
+
"files_hash": "5b546389375906c5",
|
|
5035
5035
|
"reading_hash": "5abba39cf5ec9226",
|
|
5036
5036
|
"counts": {"lines":66,"placed":47,"shared":9,"unplaced":10},
|
|
5037
5037
|
"omitted": {"data":90},
|
|
@@ -276,11 +276,11 @@ Inside the namespace the file lists as `---------- 1 root root 0`. The runner un
|
|
|
276
276
|
|
|
277
277
|
### The live status page is NOT served by the droplet — editing the status surface + deploying does nothing
|
|
278
278
|
|
|
279
|
-
> **Path note (BV1.R84):** the status surface moved from `public-status/` to `modules/status-ui/public/` (carved to the `status-ui` web-surface module). Everything below applies at the new path; `scripts/status-mirror-sync.js` was re-pointed. **
|
|
279
|
+
> **Path note (BV1.R84):** the status surface moved from `public-status/` to `modules/status-ui/public/` (carved to the `status-ui` web-surface module). Everything below applies at the new path; `scripts/status-mirror-sync.js` was re-pointed. **No auto-sync:** `.github/workflows/sync-status-mirror.yml` is not in this repo and nothing in CI runs the sync — you must run the script by hand (task 1005131).
|
|
280
280
|
|
|
281
281
|
- **Symptom:** you change `modules/status-ui/public/`, deploy to the droplet, the origin serves the new page (verified via `curl` on the box), but `status.example.com` keeps showing the old version. Purging Cloudflare doesn't help.
|
|
282
282
|
- **Root cause:** the off-box move (ADR 0029) repointed `status.example.com` DNS at **GitHub Pages from the separate repo `example-owner/example-status`** (served by Fastly — headers say `server: GitHub.com`, `via: varnish`, **no `cf-*` headers** → Cloudflare isn't even in the path). The droplet still serves `modules/status-ui/public/` as a same-origin fallback, but the public DNS goes to Pages. There was no sync, so droplet edits never reached the live page.
|
|
283
|
-
- **Fix:** publish to the mirror with `node scripts/status-mirror-sync.js --repo-dir <mirror-checkout> --push`
|
|
283
|
+
- **Fix:** publish to the mirror with `node scripts/status-mirror-sync.js --repo-dir <mirror-checkout> --push` (by hand — no workflow runs it, see the path note above). `status.js`/`style.css`/`cursors/` are byte-identical copies (the one off-box difference, the API base, is injected via `window.STATUS_API_BASE` in the mirror's `index.html`); the sync injects the off-box banner + API-base script into `index.html` at fixed anchors and **throws if an anchor is missing** rather than mis-publishing. GitHub Pages purges its own Fastly cache on deploy, so the live page updates ~1 min after the Pages build goes green (`gh api repos/example-owner/example-status/pages/builds/latest`). ([#737](https://example.com/builders#/task/737))
|
|
284
284
|
- **Why it bites:** the origin looks correct at every layer you can `curl` from the box, so you chase a phantom cache on the wrong CDN. The tell is the response headers — `server: GitHub.com` + Fastly, not `cloudflare`.
|
|
285
285
|
|
|
286
286
|
---
|
|
@@ -250,11 +250,14 @@ a:hover { text-decoration-color: currentColor; }
|
|
|
250
250
|
/* drawn from the one mark (modules/ui-design/public/brand/mark.svg, task 1005088) */
|
|
251
251
|
--mark-ink: var(--ink);
|
|
252
252
|
}
|
|
253
|
+
/* the wordmark: the pack's productName, lowercase and light, as the hall's lockup
|
|
254
|
+
(DESIGN.md "Naming"; task 1005135) */
|
|
253
255
|
.topbar__name {
|
|
254
256
|
font-family: var(--font-display);
|
|
255
|
-
font-size: var(--ds-text-
|
|
256
|
-
font-weight:
|
|
257
|
+
font-size: var(--ds-text-lg);
|
|
258
|
+
font-weight: 300;
|
|
257
259
|
letter-spacing: -0.01em;
|
|
260
|
+
text-transform: lowercase;
|
|
258
261
|
color: var(--ink);
|
|
259
262
|
white-space: nowrap;
|
|
260
263
|
overflow: hidden;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apple-touch-icon.png": {
|
|
3
|
+
"page": "b665654a1cdfa7fb91f9aef0ab4a06831922c2e12bd7eb3dea572dd0db4988a2",
|
|
4
|
+
"png": "953557984586881b25452b8642f595dfad39d17b86459cee5c5b080b74165362"
|
|
5
|
+
},
|
|
6
|
+
"og-card.png": {
|
|
7
|
+
"page": "5f7d738dd440ed4760017fe4e468ec8a593745536336f819d4a3bd2c32a5c38d",
|
|
8
|
+
"png": "e168fdd0f4ac94754af089e7240be7cbba46704b36a617252f2942c97e8835e2"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -15,6 +15,11 @@ body[data-page="brand"] {
|
|
|
15
15
|
font-family: var(--font-body);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/* The hall's sheet paints its plate veil as a fixed body::after over the page
|
|
19
|
+
(black in dark); the hall lifts its shell above it, and so does this page —
|
|
20
|
+
otherwise the whole reference reads through the veil, dimmed (task 1005135). */
|
|
21
|
+
body[data-page="brand"] > * { position: relative; z-index: 1; }
|
|
22
|
+
|
|
18
23
|
/* ---- the bar: the mark, the name, the sections ---- */
|
|
19
24
|
.ref-head {
|
|
20
25
|
box-sizing: border-box;
|
|
@@ -134,6 +139,7 @@ body[data-page="brand"] {
|
|
|
134
139
|
font-weight: 300;
|
|
135
140
|
font-size: var(--ds-text-headline);
|
|
136
141
|
letter-spacing: -0.01em;
|
|
142
|
+
text-transform: lowercase;
|
|
137
143
|
color: var(--ink);
|
|
138
144
|
}
|
|
139
145
|
.ref-lockup__mark { width: 72px; height: 72px; }
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
</head>
|
|
14
14
|
<body data-page="brand">
|
|
15
15
|
<header class="ref-head">
|
|
16
|
-
<a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg><span>
|
|
16
|
+
<a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg><span>{{productName}}</span></a>
|
|
17
17
|
</header>
|
|
18
18
|
<main class="ref-main">
|
|
19
19
|
<h1 class="ref-title">Design system</h1>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
<div class="ref-lockup">
|
|
29
29
|
<svg class="ref-lockup__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg>
|
|
30
|
-
<span class="ref-lockup__name">
|
|
30
|
+
<span class="ref-lockup__name">{{productName}}</span>
|
|
31
31
|
</div>
|
|
32
32
|
<div class="ref-naming">
|
|
33
33
|
<p><strong>The wordmark is lowercase; the name in a sentence is capitalised</strong> (owner, 2026-11-06):</p>
|
|
@@ -152,7 +152,6 @@ function build(src = read()) {
|
|
|
152
152
|
for (const cls of NEEDS) {
|
|
153
153
|
if (!new RegExp(cls.replace(/[.[\]-]/g, '\\$&') + '(?![a-z0-9_-])').test(allCss)) throw new Error(`the hall's sheets no longer define ${cls}`);
|
|
154
154
|
}
|
|
155
|
-
const product = (src.pack.identity && src.pack.identity.productName) || '';
|
|
156
155
|
const naming = readNaming(src.design);
|
|
157
156
|
const files = readBrandFiles(src.genBrand, SRC.brandDir);
|
|
158
157
|
const OTB = src.otb;
|
|
@@ -199,7 +198,7 @@ function build(src = read()) {
|
|
|
199
198
|
parts.push(section('ref-logo', 'Logo and name', 'The mark is one file every page draws from. The ring and the planet take the ink; the moon takes the accent.', `
|
|
200
199
|
<div class="ref-lockup">
|
|
201
200
|
<svg class="ref-lockup__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="${BRAND_URL}mark.svg#mark"/></svg>
|
|
202
|
-
<span class="ref-lockup__name"
|
|
201
|
+
<span class="ref-lockup__name">{{productName}}</span>
|
|
203
202
|
</div>
|
|
204
203
|
<div class="ref-naming">
|
|
205
204
|
${naming.lead.map((p) => `<p>${p}</p>`).join('\n ')}
|
|
@@ -315,7 +314,7 @@ function build(src = read()) {
|
|
|
315
314
|
</head>
|
|
316
315
|
<body data-page="brand">
|
|
317
316
|
<header class="ref-head">
|
|
318
|
-
<a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="${BRAND_URL}mark.svg#mark"/></svg><span
|
|
317
|
+
<a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="${BRAND_URL}mark.svg#mark"/></svg><span>{{productName}}</span></a>
|
|
319
318
|
</header>
|
|
320
319
|
<main class="ref-main">
|
|
321
320
|
<h1 class="ref-title">Design system</h1>
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.24.
|
|
3
|
+
"version": "1.24.60",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.24.
|
|
9
|
+
"version": "1.24.60",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.24.
|
|
3
|
+
"version": "1.24.60",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/public-docs/index.html
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
}
|
|
55
55
|
#topbar .mark { width: 28px; height: 28px; flex-shrink: 0; --mark-ink: var(--ink); }
|
|
56
56
|
#topbar strong { font-family: var(--font-display); font-size: var(--ds-text-xl); font-weight: 500; }
|
|
57
|
+
/* the wordmark: the pack's productName, lowercase and light (DESIGN.md "Naming"; task 1005135) */
|
|
58
|
+
#topbar .wordmark { font-size: var(--ds-text-lg); font-weight: 300; letter-spacing: -0.01em; text-transform: lowercase; }
|
|
57
59
|
#topbar .muted {
|
|
58
60
|
font-family: var(--font-mono); font-size: var(--ds-text-2xs); letter-spacing: .12em;
|
|
59
61
|
text-transform: uppercase; color: var(--ink-soft);
|
|
@@ -72,7 +74,7 @@
|
|
|
72
74
|
<body>
|
|
73
75
|
<div id="topbar">
|
|
74
76
|
<svg class="mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg>
|
|
75
|
-
<strong>{{productName}} — API</strong>
|
|
77
|
+
<strong><span class="wordmark">{{productName}}</span> — API</strong>
|
|
76
78
|
<span class="muted">OpenAPI 3.1</span>
|
|
77
79
|
<span class="spacer"></span>
|
|
78
80
|
<a href="/docs/openapi.json" download>Download spec</a>
|
package/release-notes.json
CHANGED
|
@@ -11319,5 +11319,21 @@
|
|
|
11319
11319
|
"id": "1005128",
|
|
11320
11320
|
"text": "A project's owner now takes a new Bongos version with one Update button; the \"ask the team for this upgrade\" step is gone for every hosted project."
|
|
11321
11321
|
}
|
|
11322
|
+
],
|
|
11323
|
+
"1.24.59": [
|
|
11324
|
+
{
|
|
11325
|
+
"id": "1005135",
|
|
11326
|
+
"text": "The name beside the logo now reads 'cloud bongos' in lowercase everywhere, taken from the project's branding, and the sign-in and error pages use the same fonts and colours as the rest of the site."
|
|
11327
|
+
},
|
|
11328
|
+
{
|
|
11329
|
+
"id": "1005133",
|
|
11330
|
+
"text": "The logo files and the link-preview pictures are now checked automatically, so a logo change can no longer ship with out-of-date copies; the docs now say plainly that the off-site status page is updated by hand."
|
|
11331
|
+
}
|
|
11332
|
+
],
|
|
11333
|
+
"1.24.60": [
|
|
11334
|
+
{
|
|
11335
|
+
"id": "1005134",
|
|
11336
|
+
"text": "The automatic check that stops pages from typing in their own colours and sizes now also catches colours given a custom name and styles written directly inside a page, so those shortcuts can no longer slip new colours past it."
|
|
11337
|
+
}
|
|
11322
11338
|
]
|
|
11323
11339
|
}
|
|
@@ -21,16 +21,28 @@
|
|
|
21
21
|
// tokens; the count stops the set of breakpoints sprawling).
|
|
22
22
|
// Sizes, radii, shadows and breakpoints are counted per DECLARATION / RULE.
|
|
23
23
|
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
24
|
+
// CUSTOM PROPERTIES (task 1005134). A colour typed into a custom-property
|
|
25
|
+
// declaration (`:root{--mine:#123456}`, `body{--x:rgb(…)}`) COUNTS as a colour,
|
|
26
|
+
// so a new sheet cannot dodge its zero start by naming its colours. Only the
|
|
27
|
+
// shared token definitions are exempt, because they are exactly where literals
|
|
28
|
+
// belong: the whole of the shared token sheet and the hall's token block (its
|
|
29
|
+
// :root and the two byte-identical dark twins) — TOKEN_SHEETS. The pack splice
|
|
30
|
+
// (serve-internal.js themeMarkup) is built in JavaScript at serve time and is
|
|
31
|
+
// never scanned. A custom property's sizes/radii/shadows are not counted — those
|
|
32
|
+
// kinds are read off the property that SPENDS a value, and a --x is not one.
|
|
33
|
+
// Page-private palettes are also guarded by tests/hall_private_palettes.mjs.
|
|
34
|
+
//
|
|
35
|
+
// WHAT IT DOES NOT COUNT. Custom-property NAMES are removed from a value before
|
|
36
|
+
// it is read (so --ds-space-12 is not a "12"), and url(...) bodies are emptied (a
|
|
37
|
+
// data URI is not a colour). A literal inside a var() fallback DOES count: a
|
|
38
|
+
// fallback is a typed-in value.
|
|
31
39
|
//
|
|
32
40
|
// Scope: every tracked *.css outside docs/ (the design mocks there are not
|
|
33
|
-
// served), node_modules and vendor
|
|
41
|
+
// served), node_modules and vendor/; the inline <style> blocks of every served
|
|
42
|
+
// .html (one under a public/, public-docs/, views/ or content/ folder); and the
|
|
43
|
+
// <style> blocks a server file writes as a string (STYLE_STRING_SOURCES: the
|
|
44
|
+
// branded error page). Task 1005134: a page could otherwise type its colours into
|
|
45
|
+
// a <style> tag and never be counted.
|
|
34
46
|
//
|
|
35
47
|
// Print the counts: node scripts/bongos/css-literal-scan.js [--all]
|
|
36
48
|
|
|
@@ -42,6 +54,18 @@ const ROOT = path.resolve(__dirname, '..', '..');
|
|
|
42
54
|
const KINDS = ['colours', 'font_sizes', 'radii', 'shadows', 'breakpoints'];
|
|
43
55
|
|
|
44
56
|
const EXCLUDE_RE = /^docs\/|(^|\/)(node_modules|vendor)\//;
|
|
57
|
+
// A served page: an .html under a folder the server serves or renders from.
|
|
58
|
+
const SERVED_HTML_RE = /(^|\/)(public|public-docs|views|content)\/.*\.html$/;
|
|
59
|
+
// Server files that write a page's <style> block as a string.
|
|
60
|
+
const STYLE_STRING_SOURCES = ['src/error-page.js'];
|
|
61
|
+
const STYLE_BLOCK_RE = /<style\b[^>]*>([\s\S]*?)<\/style>/gi;
|
|
62
|
+
// The shared token definitions, where a typed-in colour belongs: `true` exempts
|
|
63
|
+
// every custom property in the sheet; a RegExp exempts those in a rule whose
|
|
64
|
+
// selector matches it (the hall's token block: :root and the two dark twins).
|
|
65
|
+
const TOKEN_SHEETS = {
|
|
66
|
+
'modules/ui-design/public/tokens.css': true,
|
|
67
|
+
'modules/hall-ui/public/style.css': /^(?::root|html\[data-theme="dark"\]|html:not\(\[data-theme\]\))$/,
|
|
68
|
+
};
|
|
45
69
|
const COMMENT_RE = /\/\*[\s\S]*?\*\//g;
|
|
46
70
|
const URL_RE = /url\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\)/gi;
|
|
47
71
|
const VAR_NAME_RE = /--[\w-]+/g;
|
|
@@ -84,17 +108,43 @@ function hasLength(value) {
|
|
|
84
108
|
return false;
|
|
85
109
|
}
|
|
86
110
|
|
|
87
|
-
|
|
88
|
-
|
|
111
|
+
// The selector of the innermost rule around a position, read by walking the text
|
|
112
|
+
// forward (positions must be asked in increasing order). '' at the top level.
|
|
113
|
+
function selectorWalker(css) {
|
|
114
|
+
const stack = [];
|
|
115
|
+
let pos = 0;
|
|
116
|
+
let segStart = 0;
|
|
117
|
+
return (idx) => {
|
|
118
|
+
for (; pos < idx; pos += 1) {
|
|
119
|
+
const ch = css[pos];
|
|
120
|
+
if (ch === '{') { stack.push(css.slice(segStart, pos).replace(/\s+/g, ' ').trim()); segStart = pos + 1; }
|
|
121
|
+
else if (ch === '}') { stack.pop(); segStart = pos + 1; }
|
|
122
|
+
else if (ch === ';') segStart = pos + 1;
|
|
123
|
+
}
|
|
124
|
+
return stack.length ? stack[stack.length - 1] : '';
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The five counts for one stylesheet's text. `tokens` marks the shared token
|
|
130
|
+
* definitions: true (the whole sheet) or a RegExp over a rule's selector.
|
|
131
|
+
*/
|
|
132
|
+
function countSheet(text, { tokens = false } = {}) {
|
|
89
133
|
const counts = Object.fromEntries(KINDS.map((k) => [k, 0]));
|
|
90
134
|
const css = String(text).replace(COMMENT_RE, ' ').replace(URL_RE, 'url()');
|
|
91
135
|
AT_RULE_RE.lastIndex = 0;
|
|
92
136
|
let m;
|
|
93
137
|
while ((m = AT_RULE_RE.exec(css))) if (MEDIA_LENGTH_RE.test(m[2])) counts.breakpoints += 1;
|
|
138
|
+
const selectorAt = selectorWalker(css);
|
|
94
139
|
DECL_RE.lastIndex = 0;
|
|
95
140
|
while ((m = DECL_RE.exec(css))) {
|
|
96
141
|
const prop = m[1].toLowerCase();
|
|
97
|
-
if (prop.startsWith('--'))
|
|
142
|
+
if (prop.startsWith('--')) {
|
|
143
|
+
// A custom property: its colours count unless it is a shared token definition.
|
|
144
|
+
const exempt = tokens === true || (tokens instanceof RegExp && tokens.test(selectorAt(m.index + m[0].indexOf(m[1]))));
|
|
145
|
+
if (!exempt) counts.colours += colourCount(m[2].replace(VAR_NAME_RE, ' '));
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
98
148
|
const value = m[2].replace(VAR_NAME_RE, ' ');
|
|
99
149
|
counts.colours += colourCount(value);
|
|
100
150
|
if ((prop === 'font-size' || prop === 'font') && hasLength(value)) counts.font_sizes += 1;
|
|
@@ -106,8 +156,16 @@ function countSheet(text) {
|
|
|
106
156
|
}
|
|
107
157
|
|
|
108
158
|
function trackedStylesheets(root = ROOT) {
|
|
109
|
-
const out = execFileSync('git', ['ls-files', '-z', '--', '*.css'], { cwd: root, encoding: 'utf8' });
|
|
110
|
-
return out.split('\0').filter((f) => f && !EXCLUDE_RE.test(f)
|
|
159
|
+
const out = execFileSync('git', ['ls-files', '-z', '--', '*.css', '*.html', ...STYLE_STRING_SOURCES], { cwd: root, encoding: 'utf8' });
|
|
160
|
+
return out.split('\0').filter((f) => f && !EXCLUDE_RE.test(f)
|
|
161
|
+
&& (f.endsWith('.css') || SERVED_HTML_RE.test(f) || STYLE_STRING_SOURCES.includes(f))).sort();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// The CSS a file carries: a stylesheet is all CSS; a page or a server file
|
|
165
|
+
// carries only what sits inside its <style> blocks.
|
|
166
|
+
function cssOf(file, text) {
|
|
167
|
+
if (file.endsWith('.css')) return text;
|
|
168
|
+
return [...String(text).matchAll(STYLE_BLOCK_RE)].map((b) => b[1]).join('\n');
|
|
111
169
|
}
|
|
112
170
|
|
|
113
171
|
/**
|
|
@@ -123,7 +181,7 @@ function scanCssLiterals({ root = ROOT, files = null, read = null } = {}) {
|
|
|
123
181
|
let text;
|
|
124
182
|
try { text = reader(f); } catch { continue; }
|
|
125
183
|
scanned += 1;
|
|
126
|
-
const c = countSheet(text);
|
|
184
|
+
const c = countSheet(cssOf(f, text), { tokens: TOKEN_SHEETS[f] || false });
|
|
127
185
|
if (KINDS.some((k) => c[k] > 0)) sheets[f] = c;
|
|
128
186
|
}
|
|
129
187
|
return { sheets, scanned };
|