mosaic-headless 1.2.0 → 1.3.0
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/README.ja.md +19 -4
- package/README.ko.md +111 -0
- package/README.md +30 -5
- package/README.zh-TW.md +17 -4
- package/SKILL.md +79 -7
- package/assets/templates/platforms/claude-ai.json +1 -1
- package/assets/templates/platforms/claude-code.json +1 -1
- package/assets/templates/platforms/codex-cli.json +1 -1
- package/assets/templates/platforms/copilot.json +1 -1
- package/assets/templates/platforms/gemini-cli.json +1 -1
- package/bin/check-release.mjs +29 -2
- package/data/animatable-properties.csv +23 -23
- package/data/browser-verification.csv +2238 -0
- package/data/condition-comparators.csv +13 -13
- package/data/condition-subjects.csv +60 -60
- package/data/data-class-hierarchy.csv +122 -0
- package/data/db-columns.csv +207 -207
- package/data/default-children.csv +11 -11
- package/data/design-audit.csv +1 -0
- package/data/dynamic-variables.csv +75 -75
- package/data/element-classes.csv +152 -152
- package/data/evaluator-functions.csv +20 -20
- package/data/interaction-types.csv +13 -13
- package/data/node-properties.csv +182 -182
- package/data/node-property-verification.csv +182 -182
- package/data/node-types.csv +123 -123
- package/data/node-verification.csv +123 -123
- package/data/placement-rules.csv +123 -123
- package/data/pluggables.csv +208 -208
- package/data/property-verification.csv +171 -171
- package/data/rest-routes.csv +115 -115
- package/data/rwd-verification.csv +577 -570
- package/data/style-properties.csv +99 -99
- package/data/style-states.csv +54 -54
- package/data/style-value-shapes.csv +23 -23
- package/data/style-verification.csv +99 -99
- package/package.json +59 -59
- package/references/failure-modes.md +74 -0
- package/sites/_moksa.py +106 -44
- package/sites/moksa.json +9075 -8684
- package/tools/build_page.py +34 -1
- package/tools/extract_node_types.py +26 -1
- package/tools/mo.py +686 -0
- package/tools/sweep_node_properties.py +41 -2
- package/tools/verify_browser.py +589 -0
- package/tools/verify_rwd.py +14 -1
- package/README.zh-CN.md +0 -87
- package/tools/build_all.py +0 -55
- package/tools/build_report.py +0 -221
package/README.ja.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[Mosaic Pro](https://mosaicbuilder.com)(Nextend)のサイトを、データモデルを直接書いて
|
|
4
4
|
構築・変更する — ビジュアルエディタも DOM も使わない。
|
|
5
5
|
|
|
6
|
-
*他の言語:[English](README.md) · [繁體中文](README.zh-TW.md) · [
|
|
6
|
+
*他の言語:[English](README.md) · [繁體中文](README.zh-TW.md) · [한국어](README.ko.md)*
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -20,6 +20,17 @@ fractional-index の文字列。エディタはこのモデルの一クライア
|
|
|
20
20
|
**ノードタイプ、プロパティ名、列挙値、スタイルキー、Free/Pro の判断を記憶で書かないこと。
|
|
21
21
|
`data/` を引くこと。**
|
|
22
22
|
|
|
23
|
+
しかも grep ではなく `mo.py` で引く。grep は打った質問には答えるが、本当に抱えている
|
|
24
|
+
質問には答えない。`accordion-content` を grep すればその型が存在することは分かるが、
|
|
25
|
+
それを置くと commit は綺麗に通り、そのあと公開ページ全体が 54 バイトのエラー文字列に
|
|
26
|
+
なることは教えてくれない。
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python tools/mo.py type accordion-content # 1 つの型を、全ライブスイープに接続して表示
|
|
30
|
+
python tools/mo.py check div text button # 危険な型・未知の型があれば exit 1
|
|
31
|
+
python tools/mo.py style --grouped # 単独設定では必ず効かない 20 個
|
|
32
|
+
```
|
|
33
|
+
|
|
23
34
|
そのうえでページを見る。Mosaic の失敗の仕方は 4 通りあり、
|
|
24
35
|
**HTTP ステータスが変わるのはそのうち 1 つだけ**:
|
|
25
36
|
|
|
@@ -29,10 +40,12 @@ commit 中の PHP fatal HTTP 500 (122 タイプ中 15、素の div の
|
|
|
29
40
|
構造的に不正なノード HTTP 200、コミット済み、DB に行もある。そして
|
|
30
41
|
公開ページ全体が 54 バイトのエラー文字列になる
|
|
31
42
|
値の「形」が違う HTTP 200、保存される。ただし CSS ルールが存在しない
|
|
43
|
+
ルールは正しいが結果が違う HTTP 200、スタイルシートにあり、内容も正しい。それでも
|
|
44
|
+
ブラウザは別の値を計算する
|
|
32
45
|
URL に対応するテンプレなし HTTP 406、未ログインには空の body
|
|
33
46
|
```
|
|
34
47
|
|
|
35
|
-
**commit
|
|
48
|
+
**commit の成功も、正しいスタイルシートも、ページが動いている証拠にはならない。**
|
|
36
49
|
|
|
37
50
|
## 何を、どう検証したか
|
|
38
51
|
|
|
@@ -45,7 +58,9 @@ URL に対応するテンプレなし HTTP 406、未ログインには空の b
|
|
|
45
58
|
| **ノードタイプ** | 122 / 122。1 ドキュメントにつき 1 タイプで commit → 描画 → 断言 → 削除。70 RENDERED、30 COMMITTED、15 COMMIT_5xx、7 BROKE_PAGE |
|
|
46
59
|
| **スタイルプロパティ** | 98 / 98 を実ページに書き、コンパイル済み CSS と照合:58 COMPILED、18 ABSENT、21 SKIPPED |
|
|
47
60
|
| **ノードプロパティ** | 181 / 181 を、各プロパティ自身の validator chain から導いた値で再測定:35 APPLIED、42 NO_EFFECT、55 NO_HOST、47 SKIPPED |
|
|
48
|
-
| **レスポンシブ** | 2 サイト計
|
|
61
|
+
| **レスポンシブ** | 2 サイト計 576 件の `_t`/`_m` 宣言を、サイトが実際に配信したスタイルシートに対して 1 件ずつ断言 — 全件検証済み |
|
|
62
|
+
| **ブラウザ** | 配信されたページを Chromium の 3 つのビューポートで計算スタイル 2,237 件読み取り:1,661 件が一致、576 件は比較不能として明示、**上書き 0 件** |
|
|
63
|
+
| **デザイン監査** | コントラスト、フォントフォールバック、CJK の字送り、横溢れ、テキストの切れ、1 行の文字数 — ブラウザ上で実行、**指摘 0 件** |
|
|
49
64
|
| **テーマの書き出し/読み込み** | 往復検証済み:テーマ全体を書き出し、コピーとして読み込み、そのコピーがバイト単位で同一のページを配信 |
|
|
50
65
|
| **実測** | REST ルート 114、element class 151、条件サブジェクト 59、23 テーブル / 206 カラム |
|
|
51
66
|
|
|
@@ -77,7 +92,7 @@ wp eval-file tools/theme_import.php theme.json "名前" rebind activate
|
|
|
77
92
|
|
|
78
93
|
`sites/_moksa.py` が完全な実例:実在するスタジオのトップページ — マストヘッド、仕様ブロック、
|
|
79
94
|
サービス、9 行の実績テーブル、プロセス、技術スタック、プロダクト、推薦の声、連絡先 —
|
|
80
|
-
**
|
|
95
|
+
**618 ノードをすべてテーブル経由で commit**。名前付き view timeline で作った、スクロールに
|
|
81
96
|
追随する条項インデックスも含め、JavaScript は一切使っていない。
|
|
82
97
|
|
|
83
98
|
## どこから読むか
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# mosaic-headless
|
|
2
|
+
|
|
3
|
+
[Mosaic Pro](https://mosaicbuilder.com)(Nextend) 사이트를 데이터 모델에 직접 써서
|
|
4
|
+
구축하고 수정한다 — 비주얼 에디터도, DOM도 쓰지 않는다.
|
|
5
|
+
|
|
6
|
+
*다른 언어: [English](README.md) · [繁體中文](README.zh-TW.md) · [日本語](README.ja.md)*
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Mosaic은 페이지를 **23개의 커스텀 테이블**에 보관한다. `post_content`도 아니고
|
|
11
|
+
`postmeta`도 아니다. 요소 하나당 한 행, 트리 구조는 `parentID` 컬럼, 형제 순서는
|
|
12
|
+
fractional-index 문자열이다. 에디터는 이 모델의 한 클라이언트일 뿐이다.
|
|
13
|
+
포맷 그 자체가 아니며, 반드시 쓸 필요도 없다.
|
|
14
|
+
|
|
15
|
+
이 skill은 그 모델의 지도이며, **소스를 읽은 것이 아니라 실제 설치본을 상대로
|
|
16
|
+
측정한 것**이다.
|
|
17
|
+
|
|
18
|
+
## 모든 것에 우선하는 단 하나의 규칙
|
|
19
|
+
|
|
20
|
+
**노드 타입, 속성 이름, 열거값, 스타일 키, Free/Pro 판단을 기억으로 쓰지 말 것.
|
|
21
|
+
`data/`에서 찾아볼 것.**
|
|
22
|
+
|
|
23
|
+
그리고 grep이 아니라 `mo.py`로 찾을 것. grep은 입력한 질문에 답할 뿐, 실제로 품고 있는
|
|
24
|
+
질문에는 답하지 않는다. `accordion-content`를 grep하면 그 타입이 존재한다는 것은 알 수
|
|
25
|
+
있지만, 그것을 배치하면 commit은 깨끗하게 통과하고 그다음 공개 페이지 전체가 54바이트
|
|
26
|
+
에러 문자열이 된다는 사실은 알려주지 않는다.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python tools/mo.py type accordion-content # 타입 하나를 모든 라이브 스윕과 연결해 출력
|
|
30
|
+
python tools/mo.py check div text button # 위험하거나 존재하지 않는 타입이면 exit 1
|
|
31
|
+
python tools/mo.py style --grouped # 단독으로 설정하면 반드시 무효인 20개
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
그리고 페이지를 확인한다. Mosaic의 실패 방식은 네 가지이고,
|
|
35
|
+
**그중 HTTP 상태 코드가 바뀌는 것은 하나뿐이다**:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
검증기의 정상적인 거부 HTTP 200 + body에 exceptions 배열
|
|
39
|
+
commit 중 PHP fatal HTTP 500 (122개 타입 중 15개, 맨 div 안에서도 발생)
|
|
40
|
+
구조적으로 잘못된 노드 HTTP 200, 커밋됨, DB에 행도 있음. 그리고
|
|
41
|
+
공개 페이지 전체가 54바이트 에러 문자열이 된다
|
|
42
|
+
값의 "모양"이 틀림 HTTP 200, 저장됨. 다만 CSS 규칙이 존재하지 않는다
|
|
43
|
+
규칙은 맞는데 결과가 다름 HTTP 200, 스타일시트에 있고 내용도 맞다. 그런데 브라우저가
|
|
44
|
+
계산해내는 값은 다른 것이다
|
|
45
|
+
URL에 맞는 템플릿 없음 HTTP 406, 로그인하지 않은 사용자에게는 빈 body
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**commit 성공도, 올바른 스타일시트도 페이지가 동작한다는 증거가 아니다.**
|
|
49
|
+
|
|
50
|
+
## 무엇을, 어떻게 검증했는가
|
|
51
|
+
|
|
52
|
+
전부 실제 설치본에서 실행 — WordPress 7.1, WooCommerce 11.1, Mosaic Pro 1.0.7,
|
|
53
|
+
**라이선스 없음**: 라이선스가 제한하는 것은 테마 라이브러리와 업데이트이지
|
|
54
|
+
노드 팩토리가 아니므로 Pro 타입도 등록되고 렌더링된다.
|
|
55
|
+
|
|
56
|
+
| 항목 | 결과 |
|
|
57
|
+
|---|---|
|
|
58
|
+
| **노드 타입** | 122 / 122. 문서 하나당 타입 하나로 commit → 렌더 → 단언 → 삭제. 70 RENDERED, 30 COMMITTED, 15 COMMIT_5xx, 7 BROKE_PAGE |
|
|
59
|
+
| **스타일 속성** | 98 / 98을 실제 페이지에 쓰고 컴파일된 CSS와 대조: 58 COMPILED, 18 ABSENT, 21 SKIPPED |
|
|
60
|
+
| **노드 속성** | 181 / 181을 각 속성 자신의 validator chain에서 도출한 값으로 재측정: 35 APPLIED, 42 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
|
|
61
|
+
| **반응형** | 두 사이트 합쳐 576개의 `_t`/`_m` 선언을, 사이트가 실제로 내보낸 스타일시트에 대해 하나씩 단언 — 전부 검증됨 |
|
|
62
|
+
| **브라우저** | 전달된 페이지를 Chromium의 세 가지 뷰포트에서 계산 스타일 2,237건 판독: 1,661건 일치, 576건은 비교 불가로 명시, **덮어쓰기 0건** |
|
|
63
|
+
| **디자인 감사** | 명암비, 폰트 폴백, CJK 자간, 가로 넘침, 텍스트 잘림, 한 줄 글자 수 — 브라우저에서 실행, **지적 0건** |
|
|
64
|
+
| **테마 내보내기/가져오기** | 왕복 검증: 테마 전체를 내보내 사본으로 가져왔고, 사본이 바이트 단위로 동일한 페이지를 제공 |
|
|
65
|
+
| **실측** | REST 라우트 114개, element class 151개, 조건 주체 59개, 23개 테이블 / 206개 컬럼 |
|
|
66
|
+
|
|
67
|
+
`SKIPPED`, `NO_HOST`, `INCONCLUSIVE`를 합격률에 섞는 일은 결코 없다.
|
|
68
|
+
**자신의 사각지대를 성공으로 세는 스윕이야말로 이 skill이 반대하는 것이다.**
|
|
69
|
+
|
|
70
|
+
### 쓰기 시작하기 전에 알아둘 가치가 있는 두 가지 결과
|
|
71
|
+
|
|
72
|
+
**`group`을 가진 속성은 단독으로 설정하면 동작하지 않는다.** 양방향 모두 정확하다:
|
|
73
|
+
group이 없는 78개는 58 COMPILED / 0 ABSENT, group이 있는 20개는 전부 0 COMPILED.
|
|
74
|
+
즉 `borderLeftWidth`, `outlineColor`, `gridColumnStart`는 서로 다른 세 개의 기벽이
|
|
75
|
+
아니라 **하나의 규칙의 세 가지 사례**다. 그룹 형태를 쓰거나(`border`는
|
|
76
|
+
`{width, style, color}`를 받는다) `customStyles`로 내려간다.
|
|
77
|
+
|
|
78
|
+
**브레이크포인트 오버라이드는 속성을 "바꿀" 수는 있어도 "없앨" 수는 없다.**
|
|
79
|
+
좁은 화면의 `customStyles`가 단지 테두리를 쓰지 않았을 뿐이라면 넓은 화면의 테두리는
|
|
80
|
+
살아남아, 한 칼럼으로 접힌 레이아웃 한가운데에 선을 긋는다.
|
|
81
|
+
**`border-left:0`이라고 명시적으로 말해야 한다.**
|
|
82
|
+
|
|
83
|
+
## 도구
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
wp eval-file tools/bootstrap_probe_theme.php # 라이선스 없이 쓰는 작업용 테마
|
|
87
|
+
python tools/build_site.py --config c.json --site sites/moksa.json
|
|
88
|
+
python tools/verify_rwd.py --config c.json --site sites/moksa.json --csv rwd.csv
|
|
89
|
+
python tools/copy_styles.py --config c.json --from a --to-prefix b- --only "&._m"
|
|
90
|
+
wp eval-file tools/theme_export.php active > theme.json
|
|
91
|
+
wp eval-file tools/theme_import.php theme.json "이름" rebind activate
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`sites/_moksa.py`가 완전한 예제다. 실재하는 스튜디오의 홈페이지 — 머리기사, 사양 블록,
|
|
95
|
+
서비스, 9행짜리 작업 테이블, 프로세스, 기술 스택, 제품, 고객 추천사, 연락처 —
|
|
96
|
+
**618개의 노드를 전부 테이블을 통해 commit**했고, 이름 붙인 view timeline으로 만든
|
|
97
|
+
스크롤 추적 조항 인덱스까지 JavaScript는 한 줄도 쓰지 않았다.
|
|
98
|
+
|
|
99
|
+
## 어디부터 읽을 것인가
|
|
100
|
+
|
|
101
|
+
1. `references/data-model.md` — 페이지가 실제로 어디에 있는가.
|
|
102
|
+
2. `references/write-protocol.md` — checkout / check / commit.
|
|
103
|
+
3. `references/failure-modes.md` — Mosaic이 깨지는 방식, 전부 실측. **쓰기 전에 읽을 것.**
|
|
104
|
+
4. `references/responsive.md` — state / breakpoint / property 축.
|
|
105
|
+
5. `references/styling.md` — 스타일 값이 CSS가 되기까지.
|
|
106
|
+
6. `references/design-system.md` — element class와 디자인 토큰.
|
|
107
|
+
|
|
108
|
+
## 라이선스
|
|
109
|
+
|
|
110
|
+
MIT. Mosaic Pro 자체는 라이선스가 있는 서드파티 소프트웨어이며 이 repo에
|
|
111
|
+
**포함되어 있지 않다**.
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Build and modify [Mosaic Pro](https://mosaicbuilder.com) (Nextend) sites by writing
|
|
4
4
|
the data model directly — no visual editor, no DOM.
|
|
5
5
|
|
|
6
|
-
*Read this in [繁體中文](README.zh-TW.md) · [
|
|
6
|
+
*Read this in [繁體中文](README.zh-TW.md) · [日本語](README.ja.md) · [한국어](README.ko.md)*
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -20,6 +20,17 @@ read off the source.
|
|
|
20
20
|
**Never write a node type, property name, enum value, style key or Free/Pro claim
|
|
21
21
|
from memory. Look it up in `data/`.**
|
|
22
22
|
|
|
23
|
+
And look it up with `mo.py`, not grep. Grep answers the question you typed; it does
|
|
24
|
+
not answer the question you have. Ask grep about `accordion-content` and it confirms
|
|
25
|
+
the type exists. It does not mention that placing one commits cleanly and then
|
|
26
|
+
reduces the whole public page to a 54-byte error string.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python tools/mo.py type accordion-content # one type, joined to every live sweep
|
|
30
|
+
python tools/mo.py check div text button # exits 1 on an unsafe or unknown type
|
|
31
|
+
python tools/mo.py style --grouped # the 20 that are inert set on their own
|
|
32
|
+
```
|
|
33
|
+
|
|
23
34
|
Then check the page. Mosaic has four failure modes and **only one of them changes the
|
|
24
35
|
HTTP status code**:
|
|
25
36
|
|
|
@@ -29,10 +40,13 @@ PHP fatal during commit HTTP 500 (15 of 122 types do this from a plain div)
|
|
|
29
40
|
structurally invalid node HTTP 200, committed, row in the DB, and the whole
|
|
30
41
|
public page becomes a 54-byte error string
|
|
31
42
|
wrong value SHAPE HTTP 200, stored, and the CSS rule is simply absent
|
|
43
|
+
right rule, wrong result HTTP 200, in the stylesheet, correct, and the BROWSER
|
|
44
|
+
computes something else
|
|
32
45
|
no template for the URL HTTP 406 with an EMPTY BODY for anyone not logged in
|
|
33
46
|
```
|
|
34
47
|
|
|
35
|
-
A successful commit is not evidence of a working page
|
|
48
|
+
A successful commit is not evidence of a working page, and neither is a correct
|
|
49
|
+
stylesheet.
|
|
36
50
|
|
|
37
51
|
## What was verified, and how
|
|
38
52
|
|
|
@@ -45,7 +59,9 @@ factories, so Pro types register and render regardless.
|
|
|
45
59
|
| **node types** | 122 / 122 swept one per document, committed → rendered → asserted → deleted: 70 RENDERED, 30 COMMITTED, 15 COMMIT_5xx, 7 BROKE_PAGE |
|
|
46
60
|
| **style properties** | 98 / 98 written to a live page and checked against the compiled CSS: 58 COMPILED, 18 ABSENT, 21 SKIPPED |
|
|
47
61
|
| **node properties** | 181 / 181 re-probed with a value shaped by each property's own validator chain: 35 APPLIED, 42 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
|
|
48
|
-
| **responsive** |
|
|
62
|
+
| **responsive** | 576 `_t`/`_m` declarations across two sites asserted against the stylesheet the site actually served — all verified |
|
|
63
|
+
| **browser** | 2,237 computed-style readings on the delivered page in Chromium at three viewports: 1,661 compared and agreed, 576 not-comparable and labelled, **0 overridden** |
|
|
64
|
+
| **design audit** | contrast, font fallback, CJK tracking, overflow, clipped text, line measure — run in the browser, **0 findings** |
|
|
49
65
|
| **theme export/import** | round-tripped: a full theme exported, re-imported as a copy, and the copy served byte-identical pages |
|
|
50
66
|
| **measured live** | 114 REST routes, 151 element classes, 59 condition subjects, 23 tables / 206 columns |
|
|
51
67
|
|
|
@@ -77,7 +93,7 @@ wp eval-file tools/theme_import.php theme.json "Name" rebind activate
|
|
|
77
93
|
|
|
78
94
|
`sites/_moksa.py` is the worked example: a real studio homepage — masthead, spec
|
|
79
95
|
block, services, a nine-row work table, process, stack, products, testimonials,
|
|
80
|
-
contact —
|
|
96
|
+
contact — 618 nodes committed entirely through the tables, with a scroll-tracking
|
|
81
97
|
clause index built on named view timelines and no JavaScript.
|
|
82
98
|
|
|
83
99
|
## Where to start
|
|
@@ -126,7 +142,16 @@ wrong rather than the things that are easy to check:
|
|
|
126
142
|
or not. Listing `sites/` once put a real client's generator and content into the
|
|
127
143
|
tarball — gitignored, and about to be published anyway.
|
|
128
144
|
|
|
129
|
-
|
|
145
|
+
Publishing runs on npm trusted publishing (OIDC): npm trusts this repository's
|
|
146
|
+
`release.yml` directly, so there is no token in the repository's secrets and
|
|
147
|
+
nothing to rotate. Provenance is attached automatically.
|
|
148
|
+
|
|
149
|
+
One-time setup, on npmjs.com under the package's Settings → Trusted Publisher:
|
|
150
|
+
publisher `GitHub Actions`, organisation `Moksa1123`, repository
|
|
151
|
+
`mosaic-headless`, workflow filename `release.yml`, environment name left
|
|
152
|
+
**empty** — the workflow declares no environment, and a value here that the run
|
|
153
|
+
does not match is refused. The connection cannot be edited afterwards, only
|
|
154
|
+
deleted and recreated.
|
|
130
155
|
|
|
131
156
|
## Licence
|
|
132
157
|
|
package/README.zh-TW.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
直接寫入資料模型來建置與修改 [Mosaic Pro](https://mosaicbuilder.com)(Nextend)網站——
|
|
4
4
|
不開視覺編輯器,不碰 DOM。
|
|
5
5
|
|
|
6
|
-
*其他語言:[English](README.md) · [
|
|
6
|
+
*其他語言:[English](README.md) · [日本語](README.ja.md) · [한국어](README.ko.md)*
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -17,6 +17,16 @@ Mosaic 把一個頁面放在 **23 張自訂資料表**裡,不在 `post_content
|
|
|
17
17
|
|
|
18
18
|
**絕不憑印象寫節點型別、屬性名稱、列舉值、樣式鍵或 Free/Pro 的判斷。到 `data/` 裡查。**
|
|
19
19
|
|
|
20
|
+
而且要用 `mo.py` 查,不要用 grep。grep 回答你打出來的問題,不回答你真正的問題:
|
|
21
|
+
問它 `accordion-content`,它確認這個型別存在,但不會提到放一個下去會乾淨地寫入、
|
|
22
|
+
然後把整個公開頁面變成一段 54 bytes 的錯誤字串。
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
python tools/mo.py type accordion-content # 一個型別,接上所有線上掃描結果
|
|
26
|
+
python tools/mo.py check div text button # 型別不安全或不存在就 exit 1
|
|
27
|
+
python tools/mo.py style --grouped # 那 20 個單獨設定必然無效的屬性
|
|
28
|
+
```
|
|
29
|
+
|
|
20
30
|
然後去看頁面。Mosaic 有四種失效模式,**其中只有一種會改變 HTTP 狀態碼**:
|
|
21
31
|
|
|
22
32
|
```
|
|
@@ -25,10 +35,11 @@ commit 時 PHP fatal HTTP 500 (122 種型別裡有 15 種,光放在 div
|
|
|
25
35
|
結構無效的節點 HTTP 200、已寫入、資料庫有那一列,然後整個公開頁面
|
|
26
36
|
變成一段 54 bytes 的錯誤字串
|
|
27
37
|
值的「形狀」錯誤 HTTP 200、已儲存,而那條 CSS 規則就是不存在
|
|
38
|
+
規則對,結果不對 HTTP 200、在樣式表裡、內容正確,而瀏覽器算出來是另一回事
|
|
28
39
|
該網址沒有對應範本 HTTP 406,而且對未登入者是空白 body
|
|
29
40
|
```
|
|
30
41
|
|
|
31
|
-
**commit
|
|
42
|
+
**commit 成功不能當作頁面正常的證據,樣式表正確也不能。**
|
|
32
43
|
|
|
33
44
|
## 驗證了什麼,怎麼驗的
|
|
34
45
|
|
|
@@ -40,7 +51,9 @@ commit 時 PHP fatal HTTP 500 (122 種型別裡有 15 種,光放在 div
|
|
|
40
51
|
| **節點型別** | 122 / 122,一份文件一種型別:寫入 → 渲染 → 斷言 → 刪除。70 RENDERED、30 COMMITTED、15 COMMIT_5xx、7 BROKE_PAGE |
|
|
41
52
|
| **樣式屬性** | 98 / 98 寫進真實頁面並對照編譯後的 CSS:58 COMPILED、18 ABSENT、21 SKIPPED |
|
|
42
53
|
| **節點屬性** | 181 / 181,用每個屬性自己的 validator chain 推導出的值重測:35 APPLIED、42 NO_EFFECT、55 NO_HOST、47 SKIPPED |
|
|
43
|
-
| **響應式** | 兩個站共
|
|
54
|
+
| **響應式** | 兩個站共 576 條 `_t`/`_m` 宣告,對照網站實際送出的樣式表逐條斷言——全數通過 |
|
|
55
|
+
| **瀏覽器** | 在 Chromium 三個視窗寬度上對交付頁面做 2,237 次計算樣式讀取:1,661 條比對相符、576 條標為無法比對、**0 條被覆蓋** |
|
|
56
|
+
| **設計稽核** | 對比度、字體回退、CJK 字距、水平溢出、文字裁切、每行字數——在瀏覽器裡跑,**0 項發現** |
|
|
44
57
|
| **主題匯出/匯入** | 完整來回驗證:匯出整個主題、以副本身分匯入,副本送出的頁面逐位元組相同 |
|
|
45
58
|
| **線上量測** | 114 條 REST 路由、151 個 element class、59 個條件主體、23 張表 / 206 個欄位 |
|
|
46
59
|
|
|
@@ -70,7 +83,7 @@ wp eval-file tools/theme_import.php theme.json "名稱" rebind activate
|
|
|
70
83
|
```
|
|
71
84
|
|
|
72
85
|
`sites/_moksa.py` 是完整範例:一個真實工作室的首頁——刊頭、規格區塊、服務、九列作品表格、
|
|
73
|
-
流程、技術堆疊、產品、客戶見證、聯絡——**
|
|
86
|
+
流程、技術堆疊、產品、客戶見證、聯絡——**618 個節點全部透過資料表寫入**,
|
|
74
87
|
還有一個用具名 view timeline 做的、會跟著捲動的條款索引,完全沒有 JavaScript。
|
|
75
88
|
|
|
76
89
|
## 從哪裡開始讀
|
package/SKILL.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "mosaic-headless"
|
|
3
3
|
description: |
|
|
4
|
-
Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 properties, 98 style properties with 20 structured value shapes pinned down, 53 style states, 151 element classes, 74 dynamic variables, 12 interaction triggers, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, the design-token and element-class layers verified against compiled CSS, the @VAR() dynamic language verified against rendered output,
|
|
4
|
+
Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface with `mo.py`, which joins every source table to the live sweeps so a lookup leads with the measured verdict rather than the declaration (122 node types, 181 properties, 98 style properties with 20 structured value shapes pinned down, 53 style states, 151 element classes, 74 dynamic variables, 12 interaction triggers, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, the design-token and element-class layers verified against compiled CSS, the @VAR() dynamic language verified against rendered output, nine designed pages built through the tables themselves, and the delivered page re-read in Chromium at three viewports so a rule that is present, correct and still wrong cannot pass.
|
|
5
5
|
license: "MIT"
|
|
6
6
|
author: "moksa (https://moksaweb.com)"
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.3.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Headless Mosaic
|
|
@@ -21,6 +21,34 @@ apply — `references/vs-elementor-gutenberg.md` says which skill does.
|
|
|
21
21
|
**Never write a node type, property name, enum value, style key or Free/Pro claim
|
|
22
22
|
from memory. Look it up in `data/`.**
|
|
23
23
|
|
|
24
|
+
And look it up with `mo.py`, not with grep. Grep answers the question you typed;
|
|
25
|
+
it does not answer the question you have. Ask grep about `accordion-content` and it
|
|
26
|
+
confirms the type exists. It does not mention that placing one commits cleanly and
|
|
27
|
+
then reduces the entire public page to a 54-byte error string - which is the only
|
|
28
|
+
thing about that type worth knowing.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python tools/mo.py stats # the surface, and what is unsafe
|
|
32
|
+
python tools/mo.py type accordion-content # ONE type, joined to every sweep
|
|
33
|
+
python tools/mo.py types --edition pro --safe
|
|
34
|
+
python tools/mo.py check div text button # exits 1 on an unsafe or unknown type
|
|
35
|
+
python tools/mo.py placement accordion-item # what goes inside what, both directions
|
|
36
|
+
python tools/mo.py prop tagName # one node property + how it was probed
|
|
37
|
+
python tools/mo.py props --shared # the ones every element carries
|
|
38
|
+
python tools/mo.py style --grouped # the 20 that are inert set on their own
|
|
39
|
+
python tools/mo.py css border-radius # which Mosaic key drives this CSS
|
|
40
|
+
python tools/mo.py states --grep hover # state IDs and their selector templates
|
|
41
|
+
python tools/mo.py vars --namespace post # the @VAR() surface
|
|
42
|
+
python tools/mo.py classes --grep Heading # element classes (theme-global)
|
|
43
|
+
python tools/mo.py routes --grep template
|
|
44
|
+
python tools/mo.py tables wp_mosaic_nodes
|
|
45
|
+
python tools/mo.py skeleton # a minimal valid page spec
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`--json` on any of them for machine-readable output. Every answer leads with the
|
|
49
|
+
measured verdict rather than the declaration, because on this platform the two
|
|
50
|
+
disagree for 52 of the 122 types.
|
|
51
|
+
|
|
24
52
|
Then check the page. Mosaic has four failure modes and **only one of them changes the
|
|
25
53
|
HTTP status code**:
|
|
26
54
|
|
|
@@ -31,6 +59,10 @@ structurally invalid node HTTP 200, committed, row in the DB, and the whole
|
|
|
31
59
|
public page becomes a 54-byte error string
|
|
32
60
|
wrong value SHAPE HTTP 200, stored, and the CSS rule is simply absent -
|
|
33
61
|
or worse, compiles to `transform:none`
|
|
62
|
+
right rule, wrong result HTTP 200, in the stylesheet, correct, and the BROWSER
|
|
63
|
+
computes something else: a unit that resolves against
|
|
64
|
+
something you forgot, a font that cannot render the
|
|
65
|
+
text, a property the layout mode overrides
|
|
34
66
|
no template for the URL HTTP 406 with an EMPTY BODY for anyone not logged in
|
|
35
67
|
```
|
|
36
68
|
|
|
@@ -65,8 +97,10 @@ that looks like a server problem. Two things make it easy to hit:
|
|
|
65
97
|
is 406 - and if the build fails, it stays that way. Never activate a new theme
|
|
66
98
|
as a step that can be separated from the commit that fills it.
|
|
67
99
|
|
|
68
|
-
A successful commit is not evidence of a working page
|
|
69
|
-
|
|
100
|
+
A successful commit is not evidence of a working page, and neither is a correct
|
|
101
|
+
stylesheet. Fetch the page and check its size; then run `verify_browser.py` and let
|
|
102
|
+
the element say what it actually got. `references/failure-modes.md` has all of them,
|
|
103
|
+
measured.
|
|
70
104
|
|
|
71
105
|
## What was verified, and how
|
|
72
106
|
|
|
@@ -105,7 +139,15 @@ PROPERTIES 170 probes over the declared property surface, each value asserted
|
|
|
105
139
|
against the delivered markup and the compiled CSS separately.
|
|
106
140
|
data/property-verification.csv
|
|
107
141
|
|
|
108
|
-
|
|
142
|
+
BROWSER 2,237 computed-style readings on the delivered page in Chromium, at
|
|
143
|
+
three viewports: every declared property vs `getComputedStyle` on the
|
|
144
|
+
node it targets. 1,661 compared and agreed, 576 not-comparable and
|
|
145
|
+
labelled as such, 0 overridden. Plus a design audit that only a browser
|
|
146
|
+
can run - font fallback, tracking against script, text contrast,
|
|
147
|
+
horizontal overflow, clipped text, line measure - currently 0 findings.
|
|
148
|
+
data/browser-verification.csv, data/design-audit.csv
|
|
149
|
+
|
|
150
|
+
RWD 576 responsive declarations across two sites asserted against the
|
|
109
151
|
stylesheet the site actually served - each `_t`/`_m` property matched
|
|
110
152
|
to its element's generated class inside that breakpoint's own media
|
|
111
153
|
query. All verified; the checker is itself checked against a poisoned
|
|
@@ -134,7 +176,7 @@ node types 122 / 122 swept live, one per document
|
|
|
134
176
|
node properties 181 / 181 re-probed with a value shaped by each property's
|
|
135
177
|
own validator chain: 35 APPLIED, 42 NO_EFFECT,
|
|
136
178
|
2 EDITOR_ONLY, 55 NO_HOST (no rendering type
|
|
137
|
-
declares them),
|
|
179
|
+
declares them), 2 INSTRUMENT, 45 SKIPPED
|
|
138
180
|
style properties 98 / 98 swept live; 58 COMPILED, 18 ABSENT, 1 NO_ELEMENT,
|
|
139
181
|
21 SKIPPED (no test value could be synthesised, and
|
|
140
182
|
SKIPPED is never counted as a pass)
|
|
@@ -148,6 +190,15 @@ validator chain - array for `ValidatorArray`, boolean for `ValidatorBoolean`, a
|
|
|
148
190
|
enum member for `ValidatorAcceptedValues` - six of those NO_EFFECTs turn out to work:
|
|
149
191
|
`tagName`, `target`, `rel`, `height`, `size`, `insertLocation`.
|
|
150
192
|
|
|
193
|
+
**A sweep cannot be its own subject.** `attrID` and `style` came back SKIPPED
|
|
194
|
+
because the property sweep finds each probe node BY its `attrID` and reads its
|
|
195
|
+
`style` back out of the compiled CSS - asking it to probe those is asking a ruler to
|
|
196
|
+
measure itself. But SKIPPED reads as "nobody checked", and they are in fact the two
|
|
197
|
+
most heavily asserted properties here: every row of `style-verification.csv` is a
|
|
198
|
+
`style` assertion and every row of `rwd-verification.csv` is a `style` assertion
|
|
199
|
+
located by `attrID`. They are labelled **INSTRUMENT**, which is not a pass either,
|
|
200
|
+
and the label carries the file and row count that does cover them.
|
|
201
|
+
|
|
151
202
|
**Some properties are gated by a companion.** `target` and `rel` did nothing until
|
|
152
203
|
the node also carried a `url`: `button` and `menu-link` render a `<span>` without one
|
|
153
204
|
and an `<a href>` with it, so an anchor-only attribute has nothing to attach to. A
|
|
@@ -228,7 +279,10 @@ so the pattern is in the data, not just in this paragraph.
|
|
|
228
279
|
| `data/property-verification.csv` | 170 | **probed live** — per-property effect on markup vs CSS, with unprovable enums marked INCONCLUSIVE |
|
|
229
280
|
| `data/node-property-verification.csv` | 181 | **swept live** — each property probed with a value shaped by its own validator chain, on a type that declares it |
|
|
230
281
|
| `data/style-verification.csv` | 98 | **swept live** — every style property written to a page and checked against the compiled CSS, with its group beside the result |
|
|
231
|
-
| `data/rwd-verification.csv` |
|
|
282
|
+
| `data/rwd-verification.csv` | 576 | **checked live** - every `_t`/`_m` declaration vs the served stylesheet, with status per row |
|
|
283
|
+
| `data/browser-verification.csv` | 2237 | **computed in Chromium** - declared vs `getComputedStyle` at three viewports, `not-comparable` labelled per row |
|
|
284
|
+
| `data/design-audit.csv` | 0 | **computed in Chromium** - contrast, font fallback, CJK tracking, overflow, measure. Empty means it ran and found nothing |
|
|
285
|
+
| `data/data-class-hierarchy.csv` | 121 | source - every data class and its parent, so a type's inherited properties can be resolved |
|
|
232
286
|
| `data/element-classes.csv` | 151 | **live** — the built-in class metas; their IDs are what an `elementClass` record must use |
|
|
233
287
|
| `data/dynamic-variables.csv` | 74 | source — every `@VAR('ns/name')` expression, by namespace |
|
|
234
288
|
| `data/evaluator-functions.csv` | 19 | source — the `@` functions with their arity |
|
|
@@ -320,6 +374,23 @@ post — `build_all.py` resets first for that reason.
|
|
|
320
374
|
friends. A selector written against `div`/`nav` misses all of them.
|
|
321
375
|
- **`icon` renders inline `<svg>`.**
|
|
322
376
|
|
|
377
|
+
## Tools
|
|
378
|
+
|
|
379
|
+
| tool | does |
|
|
380
|
+
|---|---|
|
|
381
|
+
| `mo.py` | query the measured surface - **the front door** |
|
|
382
|
+
| `build_page.py` | commit one page spec through the verified write path |
|
|
383
|
+
| `build_site.py` | a whole site: one master with the shell, one document per page |
|
|
384
|
+
| `verify_rwd.py` | does every `_t`/`_m` declaration reach the served stylesheet? |
|
|
385
|
+
| `verify_browser.py` | does the **browser** compute what the stylesheet promised - and does the result pass a design audit? |
|
|
386
|
+
| `sweep_node_types.py` | commit every node type one per document and assert the delivered HTML |
|
|
387
|
+
| `sweep_style_properties.py` | write every style property and check the compiled CSS |
|
|
388
|
+
| `sweep_node_properties.py` | probe every node property with a value from its own validator chain |
|
|
389
|
+
| `theme_export.php` / `theme_import.php` | move a whole theme across installs, ids intact |
|
|
390
|
+
| `copy_styles.py` | push one node's style onto others, by attrID or prefix |
|
|
391
|
+
| `bootstrap_probe_theme.php` | a licence-free scratch theme |
|
|
392
|
+
| `mint_session.php` | a matching cookie + `wp_rest` nonce from WP-CLI |
|
|
393
|
+
|
|
323
394
|
## Regenerating everything
|
|
324
395
|
|
|
325
396
|
```bash
|
|
@@ -339,6 +410,7 @@ python tools/sweep_node_types.py --config sweep.json --setup
|
|
|
339
410
|
python tools/sweep_node_types.py --config sweep.json --sweep --edition all
|
|
340
411
|
python tools/sweep_properties.py --config sweep.json
|
|
341
412
|
python tools/verify_rwd.py --config sweep.json --site sites/moksa.json --csv data/rwd-verification.csv
|
|
413
|
+
python tools/verify_browser.py --config sweep.json --site sites/moksa.json --csv data/browser-verification.csv --audit data/design-audit.csv
|
|
342
414
|
python tools/sweep_style_properties.py --config sweep.json --page moksa --csv data/style-verification.csv
|
|
343
415
|
python tools/sweep_node_properties.py --config sweep.json --page moksa --csv data/node-property-verification.csv
|
|
344
416
|
wp eval-file tools/theme_export.php active > theme.json
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.
|
|
23
|
+
"version": "1.3.0"
|
|
24
24
|
},
|
|
25
25
|
"loaderBehaviour": "Upload via Settings -> Skills -> Upload. Claude.ai parses SKILL.md frontmatter and surfaces the skill in your library. The extraction tool (extract-block-schema.php) needs a live WP-CLI connection and won't run in the sandbox; use it from a local terminal against your own site instead.",
|
|
26
26
|
"uploadSteps": [
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.
|
|
23
|
+
"version": "1.3.0"
|
|
24
24
|
},
|
|
25
25
|
"loaderBehaviour": "Auto-loads on session start when SKILL.md frontmatter parses successfully.",
|
|
26
26
|
"verified": true,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.
|
|
23
|
+
"version": "1.3.0"
|
|
24
24
|
},
|
|
25
25
|
"loaderBehaviour": "Confirmed (2026-07-11): Codex CLI natively supports the SKILL.md spec. Place SKILL.md under .codex/skills/<name>/ (project) or ~/.codex/skills/<name>/ (personal) and Codex loads the name+description at session start, then the full body on demand. A parallel, broader convention .agents/skills/ (searched from cwd up to repo root, then ~/.agents/skills/) also exists across multiple tools - if your Codex CLI version prioritizes that path instead, mirror the same SKILL.md there.",
|
|
26
26
|
"verified": true,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.
|
|
23
|
+
"version": "1.3.0"
|
|
24
24
|
},
|
|
25
25
|
"loaderBehaviour": "CHANGED as of 2026-07-11: GitHub Copilot added a proper '.github/skills/' Agent Skills directory (December 2025), alongside the older single-file .github/copilot-instructions.md convention. This config targets the new skills-directory form. If your Copilot version predates this (pre Dec 2025), use the instructions-append fallback instead (see fallback below).",
|
|
26
26
|
"fallback": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.
|
|
23
|
+
"version": "1.3.0"
|
|
24
24
|
},
|
|
25
25
|
"loaderBehaviour": "CHANGED as of 2026-07-11: Gemini CLI now natively supports the same SKILL.md standard as Claude Code and Codex CLI - the same directory-based skill works unmodified. Gemini CLI discovers skills in this precedence order: built-in, extension skills, ~/.gemini/skills/ (personal), .gemini/skills/ (project, shared via version control). At session start Gemini injects each discovered skill's name+description into the system prompt and calls activate_skill when a task matches.",
|
|
26
26
|
"verified": true,
|
package/bin/check-release.mjs
CHANGED
|
@@ -78,7 +78,9 @@ const counts = {
|
|
|
78
78
|
"data/node-verification.csv": 122,
|
|
79
79
|
"data/style-verification.csv": 98,
|
|
80
80
|
"data/node-property-verification.csv": 181,
|
|
81
|
-
"data/rwd-verification.csv":
|
|
81
|
+
"data/rwd-verification.csv": 576,
|
|
82
|
+
"data/browser-verification.csv": 2237,
|
|
83
|
+
"data/data-class-hierarchy.csv": 121,
|
|
82
84
|
};
|
|
83
85
|
for (const [file, expected] of Object.entries(counts)) {
|
|
84
86
|
if (!fs.existsSync(path.join(ROOT, file))) { fail(`${file} missing`); continue; }
|
|
@@ -94,6 +96,24 @@ const style = read("data/style-verification.csv");
|
|
|
94
96
|
if (!style.includes("SKIPPED")) fail("style-verification.csv has no SKIPPED rows - "
|
|
95
97
|
+ "blind spots should be labelled, not dropped");
|
|
96
98
|
|
|
99
|
+
// The browser pass has the same obligation, under a different word: a declaration it
|
|
100
|
+
// cannot soundly compare must say so rather than be counted as agreement.
|
|
101
|
+
const browser = read("data/browser-verification.csv");
|
|
102
|
+
if (!browser.includes("not-comparable"))
|
|
103
|
+
fail("browser-verification.csv has no not-comparable rows - a computed-value check "
|
|
104
|
+
+ "that claims to compare everything is comparing things it cannot");
|
|
105
|
+
if (browser.includes("OVERRIDDEN"))
|
|
106
|
+
fail("browser-verification.csv still contains OVERRIDDEN rows - the shipped example "
|
|
107
|
+
+ "must render what it declares");
|
|
108
|
+
|
|
109
|
+
// The design audit ships even when it is empty, and empty has to mean "ran and found
|
|
110
|
+
// nothing" rather than "was never run", so the header alone is the proof.
|
|
111
|
+
const audit = read("data/design-audit.csv");
|
|
112
|
+
if (!audit.startsWith("url,breakpoints,check,level"))
|
|
113
|
+
fail("data/design-audit.csv is not the audit table verify_browser.py writes");
|
|
114
|
+
if (audit.includes(",error,"))
|
|
115
|
+
fail("data/design-audit.csv carries unresolved design errors");
|
|
116
|
+
|
|
97
117
|
// ---------- nothing private ships -------------------------------------------
|
|
98
118
|
|
|
99
119
|
// npm's `files` allowlist OVERRIDES .gitignore: naming a directory there ships
|
|
@@ -113,7 +133,14 @@ try {
|
|
|
113
133
|
if (packed) {
|
|
114
134
|
let files = [];
|
|
115
135
|
try {
|
|
116
|
-
|
|
136
|
+
// npm 11 returns an array of packed packages; npm 12 returns an object keyed
|
|
137
|
+
// by package name. Reading only the array shape against npm 12 yields zero
|
|
138
|
+
// files, and a leak check over zero files passes - which is the blind spot
|
|
139
|
+
// scored as a success that this whole file exists to prevent. The
|
|
140
|
+
// `files.length === 0` assertion below is the backstop that caught it.
|
|
141
|
+
const parsed = JSON.parse(packed);
|
|
142
|
+
const packs = Array.isArray(parsed) ? parsed : Object.values(parsed);
|
|
143
|
+
files = (packs[0]?.files || []).map((f) => f.path.split("\\").join("/"));
|
|
117
144
|
} catch { fail("could not parse `npm pack --json` output"); }
|
|
118
145
|
|
|
119
146
|
const forbidden = [
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
property,kind,animates_via
|
|
2
|
-
transform,Transform,(the CSS property)
|
|
3
|
-
translateX,Move,--mosaic-translate-x
|
|
4
|
-
translateY,Move,--mosaic-translate-y
|
|
5
|
-
translateZ,Move,--mosaic-translate-z
|
|
6
|
-
scale,Scale,--mosaic-scale
|
|
7
|
-
scaleX,Scale,--mosaic-scale-x
|
|
8
|
-
scaleY,Scale,--mosaic-scale-y
|
|
9
|
-
scaleZ,Scale,--mosaic-scale-z
|
|
10
|
-
rotateX,Rotate,--mosaic-rotate-x
|
|
11
|
-
rotateY,Rotate,--mosaic-rotate-y
|
|
12
|
-
rotateZ,Rotate,--mosaic-rotate-z
|
|
13
|
-
opacity,Opacity,(the CSS property)
|
|
14
|
-
color,Color,(the CSS property)
|
|
15
|
-
backgroundColor,Color,(the CSS property)
|
|
16
|
-
borderColor,Color,(the CSS property)
|
|
17
|
-
boxShadow,BoxShadow,(the CSS property)
|
|
18
|
-
textShadow,TextShadow,(the CSS property)
|
|
19
|
-
width,Size,(the CSS property)
|
|
20
|
-
height,Size,(the CSS property)
|
|
21
|
-
filter,Filter,(the CSS property)
|
|
22
|
-
backdropFilter,Filter,(the CSS property)
|
|
23
|
-
transformOrigin,TransformOrigin,(the CSS property)
|
|
1
|
+
property,kind,animates_via
|
|
2
|
+
transform,Transform,(the CSS property)
|
|
3
|
+
translateX,Move,--mosaic-translate-x
|
|
4
|
+
translateY,Move,--mosaic-translate-y
|
|
5
|
+
translateZ,Move,--mosaic-translate-z
|
|
6
|
+
scale,Scale,--mosaic-scale
|
|
7
|
+
scaleX,Scale,--mosaic-scale-x
|
|
8
|
+
scaleY,Scale,--mosaic-scale-y
|
|
9
|
+
scaleZ,Scale,--mosaic-scale-z
|
|
10
|
+
rotateX,Rotate,--mosaic-rotate-x
|
|
11
|
+
rotateY,Rotate,--mosaic-rotate-y
|
|
12
|
+
rotateZ,Rotate,--mosaic-rotate-z
|
|
13
|
+
opacity,Opacity,(the CSS property)
|
|
14
|
+
color,Color,(the CSS property)
|
|
15
|
+
backgroundColor,Color,(the CSS property)
|
|
16
|
+
borderColor,Color,(the CSS property)
|
|
17
|
+
boxShadow,BoxShadow,(the CSS property)
|
|
18
|
+
textShadow,TextShadow,(the CSS property)
|
|
19
|
+
width,Size,(the CSS property)
|
|
20
|
+
height,Size,(the CSS property)
|
|
21
|
+
filter,Filter,(the CSS property)
|
|
22
|
+
backdropFilter,Filter,(the CSS property)
|
|
23
|
+
transformOrigin,TransformOrigin,(the CSS property)
|