stylegallery 0.1.0 → 0.1.1
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/AGENTS.md +4 -1
- package/DOMAINS.md +2 -6
- package/GOVERNANCE.md +10 -9
- package/README.md +23 -127
- package/consumer-reference/agent-native/v2/admission-policy.json +646 -0
- package/consumer-reference/agent-native/v2/material-registry.json +1 -0
- package/consumer-reference/agent-native/v2/schema/admission-policy.schema.json +50 -0
- package/consumer-reference/agent-native/v2/schema/material-manifest.schema.json +17 -0
- package/consumer-reference/agent-native/v2/schema/material-record.schema.json +20 -0
- package/consumer-reference/contract.md +1 -1
- package/consumer-reference/index.md +5 -3
- package/layout/index.md +124 -0
- package/log.md +51 -0
- package/package.json +181 -22
- package/scripts/agent-native/v2/experimental-extension-registry.mjs +143 -0
- package/scripts/agent-native/v2/extensions/a2a-projection.mjs +264 -0
- package/scripts/agent-native/v2/extensions/agui-projection.mjs +191 -0
- package/scripts/agent-native/v2/material-admission.mjs +295 -0
- package/scripts/agent-native/v2/material-cli-adapter.mjs +134 -0
- package/scripts/agent-native/v2/material-context.mjs +251 -0
- package/scripts/agent-native/v2/material-identity.mjs +71 -0
- package/scripts/agent-native/v2/material-mcp-adapter.mjs +253 -0
- package/scripts/agent-native/v2/material-operation-registry.mjs +123 -0
- package/scripts/agent-native/v2/material-queries.mjs +398 -0
- package/scripts/agent-native/v2/material-registry.mjs +319 -0
- package/scripts/sg-material-mcp.mjs +98 -0
- package/scripts/sg-material.mjs +27 -0
- package/consumer-reference/adapters/style-dictionary.config.mjs +0 -36
- package/consumer-reference/baselines/calibration.json +0 -260
- package/consumer-reference/baselines/manifest.json +0 -21
- package/consumer-reference/fixtures/consumer-conformance/e2e-fixture.mjs +0 -282
- package/consumer-reference/fixtures/consumer-conformance/manifest.json +0 -102
- package/consumer-reference/fixtures/consumer-conformance/runtime-proof.mjs +0 -32
- package/consumer-reference/fixtures/consumer-conformance/valid-migration-result.json +0 -18
- package/consumer-reference/fixtures/consumer-conformance/valid-migration.json +0 -142
- package/consumer-reference/fixtures/invalid-stable-ended-support.json +0 -19
- package/consumer-reference/fixtures/promotion/invalid-blocking-evidence.json +0 -26
- package/consumer-reference/fixtures/promotion/invalid-count-only.json +0 -29
- package/consumer-reference/fixtures/promotion/invalid-missing-owner-migration.json +0 -25
- package/consumer-reference/fixtures/promotion/invalid-normative-bypass-no-regression.json +0 -25
- package/consumer-reference/fixtures/promotion/invalid-related-counted-independent.json +0 -45
- package/consumer-reference/fixtures/promotion/invalid-stable-ended-support.json +0 -26
- package/consumer-reference/fixtures/promotion/manifest.json +0 -15
- package/consumer-reference/fixtures/promotion/valid-deferred-example.json +0 -67
- package/consumer-reference/fixtures/promotion/valid-normative-bypass.json +0 -67
- package/consumer-reference/fixtures/token-portability/invalid-cycle.json +0 -7
- package/consumer-reference/fixtures/token-portability/invalid-dangling-alias.json +0 -6
- package/consumer-reference/fixtures/token-portability/invalid-extends.json +0 -4
- package/consumer-reference/fixtures/token-portability/invalid-json-pointer.json +0 -7
- package/consumer-reference/fixtures/token-portability/invalid-resolver.json +0 -9
- package/consumer-reference/fixtures/token-portability/invalid-type-mismatch.json +0 -10
- package/consumer-reference/fixtures/token-portability/invalid-unknown-reserved.json +0 -6
- package/consumer-reference/fixtures/token-portability/invalid-untested-type.json +0 -6
- package/consumer-reference/fixtures/token-portability/valid-border.json +0 -14
- package/consumer-reference/fixtures/token-portability/valid-reference.json +0 -32
- package/consumer-reference/fixtures/token-portability/valid-whole-alias.json +0 -7
- package/consumer-reference/fixtures/valid-deprecated.json +0 -21
- package/consumer-reference/fixtures/valid-experimental.json +0 -19
- package/consumer-reference/generated/manifest.json +0 -40
- package/consumer-reference/generated/tokens.css +0 -12
- package/consumer-reference/policies/shared-experimental.json +0 -37
- package/consumer-reference/schema/ax-evidence.schema.json +0 -30
- package/consumer-reference/schema/baseline-manifest.schema.json +0 -55
- package/consumer-reference/schema/calibration-record.schema.json +0 -190
- package/consumer-reference/schema/capture-session.schema.json +0 -161
- package/consumer-reference/schema/component-state.schema.json +0 -150
- package/consumer-reference/schema/consumer-conformance-record.schema.json +0 -365
- package/consumer-reference/schema/dom-evidence.schema.json +0 -38
- package/consumer-reference/schema/evidence-record.schema.json +0 -81
- package/consumer-reference/schema/fixture-manifest.schema.json +0 -32
- package/consumer-reference/schema/item.schema.json +0 -188
- package/consumer-reference/schema/page-evidence-manifest.schema.json +0 -216
- package/consumer-reference/schema/page-evidence-session.schema.json +0 -119
- package/consumer-reference/schema/portable-tokens.schema.json +0 -104
- package/consumer-reference/schema/promotion-rfc.schema.json +0 -219
- package/consumer-reference/schema/runtime-evidence-manifest.schema.json +0 -33
- package/consumer-reference/schema/visual-evidence.schema.json +0 -31
- package/design-engineering/consumer-migration-readiness.md +0 -124
- package/design-engineering/interface-craft.md +0 -107
- package/design-engineering/reference-profiles/external-adaptation/index.md +0 -12
- package/design-engineering/reference-profiles/governed-local/editorial/components/button.component.json +0 -125
- package/design-engineering/reference-profiles/governed-local/editorial/evidence/button.evidence.json +0 -3504
- package/design-engineering/reference-profiles/governed-local/editorial/fixtures/button.fixture.json +0 -65
- package/design-engineering/reference-profiles/governed-local/editorial/generated/evidence-coverage.md +0 -23
- package/design-engineering/reference-profiles/governed-local/editorial/generated/keyboard-matrix.md +0 -19
- package/design-engineering/reference-profiles/governed-local/editorial/generated/state-matrix.md +0 -21
- package/design-engineering/reference-profiles/governed-local/editorial/local-foundations.json +0 -12
- package/design-engineering/reference-profiles/governed-local/editorial/states/button.states.json +0 -195
- package/design-engineering/reference-profiles/governed-local/editorial/tokens.dtcg.json +0 -17
- package/design-engineering/reference-profiles/governed-local/terminal/components/button.component.json +0 -125
- package/design-engineering/reference-profiles/governed-local/terminal/evidence/button.evidence.json +0 -3504
- package/design-engineering/reference-profiles/governed-local/terminal/fixtures/button.fixture.json +0 -65
- package/design-engineering/reference-profiles/governed-local/terminal/generated/evidence-coverage.md +0 -23
- package/design-engineering/reference-profiles/governed-local/terminal/generated/keyboard-matrix.md +0 -19
- package/design-engineering/reference-profiles/governed-local/terminal/generated/state-matrix.md +0 -21
- package/design-engineering/reference-profiles/governed-local/terminal/local-foundations.json +0 -12
- package/design-engineering/reference-profiles/governed-local/terminal/profile.json +0 -43
- package/design-engineering/reference-profiles/governed-local/terminal/states/button.states.json +0 -195
- package/design-engineering/reference-profiles/governed-local/terminal/tokens.dtcg.json +0 -17
- package/game-ui/classification.md +0 -82
- package/game-ui/reference-record.md +0 -62
- package/game-ui/screen-hierarchy.md +0 -107
- package/game-ui/unity/architecture.md +0 -166
- package/game-ui/unity/cli-loop.md +0 -84
- package/game-ui/unity/data/unity-technologies-public-repositories.json +0 -26654
- package/game-ui/unity/org-wiki.md +0 -146
- package/game-ui/unity/repository-map.md +0 -102
- package/game-ui/unity/ui-systems.md +0 -85
- package/motion/practice-reference.md +0 -145
- package/motion/review-workflow.md +0 -86
- package/motion/vocabulary.md +0 -82
- package/platform-guides/apple-interaction.md +0 -89
- package/scripts/agent-native/events.mjs +0 -113
- package/scripts/agent-native/immutable-store.mjs +0 -102
- package/scripts/artifact-metadata.mjs +0 -20
- package/scripts/audit-evidence-freshness.mjs +0 -308
- package/scripts/baseline-contract.mjs +0 -189
- package/scripts/baseline-schema-parity.mjs +0 -40
- package/scripts/build-reference-artifacts.mjs +0 -127
- package/scripts/calibration-raw-contract.mjs +0 -172
- package/scripts/capture-session-contract.mjs +0 -187
- package/scripts/component-state-artifact-fixture.mjs +0 -44
- package/scripts/component-state-contract.mjs +0 -99
- package/scripts/component-state-semantics.mjs +0 -128
- package/scripts/component-state-workflow-contract.mjs +0 -67
- package/scripts/component-state-workflow-negative-cases.mjs +0 -64
- package/scripts/consumer-conformance-contract.mjs +0 -198
- package/scripts/consumer-evidence-governance-contract.mjs +0 -210
- package/scripts/consumer-reference-case-runner.mjs +0 -93
- package/scripts/consumer-reference-schema.mjs +0 -155
- package/scripts/create-component-state-session.mjs +0 -100
- package/scripts/create-page-evidence-session.mjs +0 -139
- package/scripts/domain-document-boundaries.mjs +0 -40
- package/scripts/domain-validation-checks.mjs +0 -141
- package/scripts/evidence-artifact-contract.mjs +0 -191
- package/scripts/finalize-component-state-evidence.mjs +0 -165
- package/scripts/finalize-page-evidence.mjs +0 -197
- package/scripts/generate-consumer-reference-evidence.mjs +0 -154
- package/scripts/generate-patterns.mjs +0 -218
- package/scripts/governance-matrix-contract.mjs +0 -73
- package/scripts/governance-matrix-negative-cases.mjs +0 -114
- package/scripts/governance-policy-contract.mjs +0 -49
- package/scripts/governance-test-fixture.mjs +0 -321
- package/scripts/governance-workflow-negative-cases.mjs +0 -241
- package/scripts/governed-profile-registry.mjs +0 -125
- package/scripts/json-schema-formats.mjs +0 -31
- package/scripts/markdown-structure.mjs +0 -45
- package/scripts/page-artifact-metadata.mjs +0 -124
- package/scripts/page-evidence-contract.mjs +0 -297
- package/scripts/page-evidence-fixture.mjs +0 -271
- package/scripts/pattern-data.mjs +0 -325
- package/scripts/profile-record-contract.mjs +0 -140
- package/scripts/promotion-attestation-contract.mjs +0 -91
- package/scripts/promotion-boundary-test-contract.mjs +0 -92
- package/scripts/promotion-fixture-inventory.mjs +0 -109
- package/scripts/promotion-governance-contract.mjs +0 -28
- package/scripts/reference-artifact-path-contract.mjs +0 -28
- package/scripts/reference-profile-contract.mjs +0 -114
- package/scripts/reference-token-contract.mjs +0 -156
- package/scripts/run-consumer-page-evidence-ci.mjs +0 -170
- package/scripts/summarize-sentinel-calibration.mjs +0 -98
- package/scripts/test-agent-adapter-conformance.mjs +0 -250
- package/scripts/test-agent-conformance-receipt.mjs +0 -106
- package/scripts/test-agent-events.mjs +0 -81
- package/scripts/test-agent-execution-effects.mjs +0 -114
- package/scripts/test-agent-execution-fixtures.mjs +0 -140
- package/scripts/test-agent-execution-kernel.mjs +0 -39
- package/scripts/test-agent-execution-learning.mjs +0 -130
- package/scripts/test-agent-execution-lifecycle.mjs +0 -143
- package/scripts/test-agent-execution-safety.mjs +0 -158
- package/scripts/test-agent-execution-views.mjs +0 -117
- package/scripts/test-agent-identity-integrity-cases.mjs +0 -160
- package/scripts/test-agent-knowledge-kernel.mjs +0 -183
- package/scripts/test-agent-learning.mjs +0 -246
- package/scripts/test-agent-mcp.mjs +0 -246
- package/scripts/test-agent-native-schemas.mjs +0 -215
- package/scripts/test-agent-projections.mjs +0 -249
- package/scripts/test-agent-registry-mcp-integrity.mjs +0 -215
- package/scripts/test-agent-registry-mutations.mjs +0 -110
- package/scripts/test-audit-evidence-freshness.mjs +0 -177
- package/scripts/test-component-state-sentinel.mjs +0 -35
- package/scripts/test-component-state-source-contract.mjs +0 -83
- package/scripts/test-consumer-conformance-sentinel.mjs +0 -165
- package/scripts/test-consumer-reference-sentinel.mjs +0 -31
- package/scripts/test-generate-consumer-reference-evidence.mjs +0 -124
- package/scripts/test-json-cli-output.mjs +0 -151
- package/scripts/test-json-schema-formats.mjs +0 -40
- package/scripts/test-reference-adapters.mjs +0 -199
- package/scripts/test-renderer-purity.mjs +0 -34
- package/scripts/test-sg-cli.mjs +0 -129
- package/scripts/test-summarize-sentinel-calibration.mjs +0 -226
- package/scripts/test-validate-baseline-manifest.mjs +0 -234
- package/scripts/test-validate-component-state-artifacts.mjs +0 -243
- package/scripts/test-validate-component-state.mjs +0 -106
- package/scripts/test-validate-consumer-conformance.mjs +0 -427
- package/scripts/test-validate-consumer-reference-cli.mjs +0 -69
- package/scripts/test-validate-consumer-reference.mjs +0 -263
- package/scripts/test-validate-domains.mjs +0 -357
- package/scripts/test-validate-governance.mjs +0 -292
- package/scripts/test-validate-ia.mjs +0 -262
- package/scripts/test-validate-okf.mjs +0 -73
- package/scripts/test-validate-page-evidence.mjs +0 -302
- package/scripts/test-validate-patterns.mjs +0 -157
- package/scripts/test-validate-promotion-rfc.mjs +0 -250
- package/scripts/test-validate-reference-profiles.mjs +0 -170
- package/scripts/test-validate-unity-org-wiki.mjs +0 -57
- package/scripts/test-validate-unity-source-contracts.mjs +0 -67
- package/scripts/test-validate-vocabulary.mjs +0 -174
- package/scripts/test-validate-webpage-workflow.mjs +0 -293
- package/scripts/validate-baseline-manifest.mjs +0 -44
- package/scripts/validate-catalog.mjs +0 -65
- package/scripts/validate-component-state.mjs +0 -141
- package/scripts/validate-consumer-conformance.mjs +0 -477
- package/scripts/validate-consumer-reference.mjs +0 -288
- package/scripts/validate-domains.mjs +0 -237
- package/scripts/validate-governance.mjs +0 -248
- package/scripts/validate-ia.mjs +0 -136
- package/scripts/validate-links.mjs +0 -66
- package/scripts/validate-okf.mjs +0 -104
- package/scripts/validate-page-evidence.mjs +0 -191
- package/scripts/validate-patterns.mjs +0 -246
- package/scripts/validate-promotion-rfc.mjs +0 -224
- package/scripts/validate-reference-artifacts.mjs +0 -125
- package/scripts/validate-renderer-purity.mjs +0 -56
- package/scripts/validate-unity-org-wiki.mjs +0 -146
- package/scripts/validate-unity-source-contracts.mjs +0 -107
- package/scripts/validate-vocabulary.mjs +0 -115
- package/scripts/validate-webpage-workflow.mjs +0 -254
- package/scripts/visual-expectation-contract.mjs +0 -20
- package/scripts/workflow-action-contract.mjs +0 -163
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { execFileSync, spawnSync } from "node:child_process";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { canonicalSourceManifest, digest, metadata } from "./page-evidence-contract.mjs";
|
|
7
|
-
|
|
8
|
-
const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
9
|
-
export const creator = path.join(repositoryRoot, "scripts/create-page-evidence-session.mjs");
|
|
10
|
-
export const finalizer = path.join(repositoryRoot, "scripts/finalize-page-evidence.mjs");
|
|
11
|
-
export const validator = path.join(repositoryRoot, "scripts/validate-page-evidence.mjs");
|
|
12
|
-
export const semanticEnvironment = Object.freeze({
|
|
13
|
-
browser: "Chromium 140.0.0",
|
|
14
|
-
browser_revision: "chromium-1400",
|
|
15
|
-
color_scheme: "light",
|
|
16
|
-
locale: "en-US",
|
|
17
|
-
page_scale_factor: 1,
|
|
18
|
-
platform: "linux/amd64",
|
|
19
|
-
reduced_motion: "no-preference",
|
|
20
|
-
viewport: { height: 720, width: 320 },
|
|
21
|
-
});
|
|
22
|
-
const png = Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=", "base64");
|
|
23
|
-
const crcTable = Uint32Array.from({ length: 256 }, (_, index) => {
|
|
24
|
-
let value = index;
|
|
25
|
-
for (let bit = 0; bit < 8; bit += 1) value = (value >>> 1) ^ (0xedb88320 & -(value & 1));
|
|
26
|
-
return value >>> 0;
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
function pngChunk(type, data) {
|
|
30
|
-
const name = Buffer.from(type, "ascii");
|
|
31
|
-
const chunk = Buffer.alloc(12 + data.length);
|
|
32
|
-
chunk.writeUInt32BE(data.length, 0);
|
|
33
|
-
name.copy(chunk, 4);
|
|
34
|
-
data.copy(chunk, 8);
|
|
35
|
-
let crc = 0xffffffff;
|
|
36
|
-
for (const byte of chunk.subarray(4, 8 + data.length)) crc = crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8);
|
|
37
|
-
chunk.writeUInt32BE((crc ^ 0xffffffff) >>> 0, 8 + data.length);
|
|
38
|
-
return chunk;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function truncatedPng() {
|
|
42
|
-
return Buffer.from(png.subarray(0, 24));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function corruptPngCrc() {
|
|
46
|
-
const bytes = Buffer.from(png);
|
|
47
|
-
bytes[bytes.length - 1] ^= 0xff;
|
|
48
|
-
return bytes;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function pngWithTrailingBytes() {
|
|
52
|
-
return Buffer.concat([png, Buffer.from("trailing bytes")]);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function pngWithInvalidImageData() {
|
|
56
|
-
return Buffer.concat([png.subarray(0, 33), pngChunk("IDAT", Buffer.alloc(0)), png.subarray(png.length - 12)]);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function pngWithTrailingImageData() {
|
|
60
|
-
const length = png.readUInt32BE(33);
|
|
61
|
-
const data = png.subarray(41, 41 + length);
|
|
62
|
-
return Buffer.concat([png.subarray(0, 33), pngChunk("IDAT", Buffer.concat([data, Buffer.from("trailing")])), png.subarray(45 + length)]);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function git(root, ...args) {
|
|
66
|
-
return execFileSync("git", ["-c", `safe.directory=${root}`, ...args], { cwd: root, encoding: "utf8" }).trim();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function writeJson(file, value) {
|
|
70
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
71
|
-
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function runCli(file, args, root, env = {}) {
|
|
75
|
-
const fixtureEnv = Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.startsWith("GITHUB_")));
|
|
76
|
-
const child = spawnSync(process.execPath, [file, ...args, "--json"], { cwd: repositoryRoot, encoding: "utf8", env: { ...fixtureEnv, ...env } });
|
|
77
|
-
let report = { failures: [{ code: "child_output_invalid", message: child.stdout || child.stderr, path: file }], ok: false };
|
|
78
|
-
try { report = JSON.parse(child.stdout); } catch (error) { if (!(error instanceof SyntaxError)) throw error; }
|
|
79
|
-
return { report, root, status: child.status };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function initializeConsumer() {
|
|
83
|
-
const root = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), "stylegallery-page-evidence-")));
|
|
84
|
-
execFileSync("git", ["init", "-b", "main"], { cwd: root, stdio: "ignore" });
|
|
85
|
-
git(root, "config", "user.email", "fixture@example.com");
|
|
86
|
-
git(root, "config", "user.name", "StyleGallery fixture");
|
|
87
|
-
git(root, "remote", "add", "origin", "https://github.com/example/consumer.git");
|
|
88
|
-
fs.mkdirSync(path.join(root, "src"), { recursive: true });
|
|
89
|
-
fs.mkdirSync(path.join(root, "tests"), { recursive: true });
|
|
90
|
-
fs.writeFileSync(path.join(root, "src/page.js"), "export const page = 'ready';\n");
|
|
91
|
-
fs.writeFileSync(path.join(root, "tests/page.spec.js"), "const scenario = 'responsive-layout';\nvoid scenario;\n");
|
|
92
|
-
git(root, "add", "src/page.js", "tests/page.spec.js");
|
|
93
|
-
git(root, "commit", "-m", "fixture sources");
|
|
94
|
-
return {
|
|
95
|
-
relevantSources: ["src/page.js", "tests/page.spec.js"],
|
|
96
|
-
repository: "example/consumer",
|
|
97
|
-
revision: git(root, "rev-parse", "HEAD"),
|
|
98
|
-
root,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function createConformance(fixture, { artifactName = "session-a", recordName = artifactName, runId = `run-${artifactName}`, scenarioId = "responsive-layout", sessionId = `session-${artifactName}` } = {}) {
|
|
103
|
-
const sourceFailures = [];
|
|
104
|
-
const source = canonicalSourceManifest(fixture.root, fixture.relevantSources, sourceFailures);
|
|
105
|
-
if (!source || sourceFailures.length > 0) throw new Error(`fixture source manifest failed: ${JSON.stringify(sourceFailures)}`);
|
|
106
|
-
const artifactRoot = path.join(fixture.root, "evidence", artifactName);
|
|
107
|
-
const recordFile = path.join(fixture.root, "records", `${recordName}.json`);
|
|
108
|
-
writeJson(recordFile, {
|
|
109
|
-
claim_boundary: "Synthetic conformance fixture; not product certification.",
|
|
110
|
-
consumer: { relevant_sources: fixture.relevantSources, repository: fixture.repository, revision: fixture.revision },
|
|
111
|
-
id: `${recordName}-conformance`,
|
|
112
|
-
page_evidence: { manifest: path.relative(fixture.root, path.join(artifactRoot, "page-evidence-manifest.json")), status: "applicable" },
|
|
113
|
-
record_kind: "consumer_migration_conformance",
|
|
114
|
-
scenarios: [{
|
|
115
|
-
assertions: ["No document overflow."],
|
|
116
|
-
argv: ["node", "tests/page.spec.js"],
|
|
117
|
-
evidence_method: "browser",
|
|
118
|
-
exit_code: 0,
|
|
119
|
-
id: scenarioId,
|
|
120
|
-
observable_actions: ["Render the page."],
|
|
121
|
-
result_artifact: path.relative(fixture.root, path.join(artifactRoot, "runner", `${scenarioId}.json`)),
|
|
122
|
-
run_id: runId,
|
|
123
|
-
session_id: sessionId,
|
|
124
|
-
source_digest: source.sha256,
|
|
125
|
-
}],
|
|
126
|
-
schema_version: "1.0",
|
|
127
|
-
});
|
|
128
|
-
return { artifactRoot, recordFile, runId, scenarioId, sessionId, source };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function startSession(fixture, session, env = {}) {
|
|
132
|
-
return runCli(creator, ["--root", fixture.root, "--record", session.recordFile, "--artifact-root", session.artifactRoot], fixture.root, env);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function receiptFor(session) {
|
|
136
|
-
const file = path.join(session.artifactRoot, "page-evidence-session.json");
|
|
137
|
-
const bytes = fs.readFileSync(file);
|
|
138
|
-
return { bytes, file, sha256: digest(bytes), value: JSON.parse(bytes) };
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function writeRunner(fixture, session, overrides = {}) {
|
|
142
|
-
const receipt = receiptFor(session);
|
|
143
|
-
const scenarioId = overrides.scenarioId ?? session.scenarioId;
|
|
144
|
-
const runnerReference = `runner/${scenarioId}.json`;
|
|
145
|
-
const artifactReference = overrides.artifactPath ?? `captures/${scenarioId}-320.png`;
|
|
146
|
-
if (overrides.writeArtifact !== false) {
|
|
147
|
-
const artifactFile = path.join(session.artifactRoot, artifactReference);
|
|
148
|
-
fs.mkdirSync(path.dirname(artifactFile), { recursive: true });
|
|
149
|
-
fs.writeFileSync(artifactFile, overrides.artifactBytes ?? png);
|
|
150
|
-
}
|
|
151
|
-
const evidence = overrides.evidence ?? (overrides.status === "failed"
|
|
152
|
-
? { kind: "failed", reason: "synthetic runner failure" }
|
|
153
|
-
: { artifacts: [{ media_type: "image/png", path: artifactReference }], kind: "captured" });
|
|
154
|
-
const runner = {
|
|
155
|
-
evidence,
|
|
156
|
-
nonce: overrides.nonce ?? receipt.value.nonce,
|
|
157
|
-
receipt_sha256: overrides.receiptSha256 ?? receipt.sha256,
|
|
158
|
-
recorded_at: overrides.recordedAt ?? receipt.value.started_at,
|
|
159
|
-
record_kind: "page_evidence_runner_result",
|
|
160
|
-
repository: overrides.repository ?? fixture.repository,
|
|
161
|
-
revision: overrides.revision ?? fixture.revision,
|
|
162
|
-
run: {
|
|
163
|
-
attempt: receipt.value.attempt,
|
|
164
|
-
id: overrides.runId ?? session.runId,
|
|
165
|
-
repository: overrides.runRepository ?? fixture.repository,
|
|
166
|
-
revision: overrides.runRevision ?? fixture.revision,
|
|
167
|
-
source: "local",
|
|
168
|
-
},
|
|
169
|
-
scenario_id: scenarioId,
|
|
170
|
-
schema_version: "1.0",
|
|
171
|
-
semantic_environment: overrides.semanticEnvironment ?? semanticEnvironment,
|
|
172
|
-
session_id: overrides.sessionId ?? session.sessionId,
|
|
173
|
-
source_sha256: overrides.sourceSha256 ?? receipt.value.source.sha256,
|
|
174
|
-
status: overrides.status ?? "passed",
|
|
175
|
-
};
|
|
176
|
-
const runnerFile = path.join(session.artifactRoot, runnerReference);
|
|
177
|
-
writeJson(runnerFile, runner);
|
|
178
|
-
return { artifactReference, runner, runnerFile, runnerReference };
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export function declareCapturedArtifact(session, runnerRecord, artifactReference) {
|
|
182
|
-
if (runnerRecord.artifactReference !== artifactReference) {
|
|
183
|
-
fs.rmSync(path.join(session.artifactRoot, runnerRecord.artifactReference), { force: true });
|
|
184
|
-
}
|
|
185
|
-
const runner = {
|
|
186
|
-
...runnerRecord.runner,
|
|
187
|
-
evidence: { artifacts: [{ media_type: "application/json", path: artifactReference }], kind: "captured" },
|
|
188
|
-
};
|
|
189
|
-
writeJson(runnerRecord.runnerFile, runner);
|
|
190
|
-
return { ...runnerRecord, artifactReference, runner };
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function rewriteCompletedCapture(session, runnerRecord, artifactReference) {
|
|
194
|
-
const declared = declareCapturedArtifact(session, runnerRecord, artifactReference);
|
|
195
|
-
const manifestFile = path.join(session.artifactRoot, "page-evidence-manifest.json");
|
|
196
|
-
const manifest = JSON.parse(fs.readFileSync(manifestFile));
|
|
197
|
-
const runnerResult = metadata(fs.readFileSync(declared.runnerFile), "application/json", declared.runnerReference);
|
|
198
|
-
const artifact = metadata(fs.readFileSync(path.join(session.artifactRoot, artifactReference)), "application/json", artifactReference);
|
|
199
|
-
const [scenario, ...remaining] = manifest.scenarios;
|
|
200
|
-
writeJson(manifestFile, {
|
|
201
|
-
...manifest,
|
|
202
|
-
scenarios: [{ ...scenario, evidence: { artifacts: [artifact], kind: "captured" }, runner_result: runnerResult }, ...remaining],
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function rewriteCompletedArtifact(session, runnerRecord, bytes) {
|
|
207
|
-
const artifactFile = path.join(session.artifactRoot, runnerRecord.artifactReference);
|
|
208
|
-
fs.writeFileSync(artifactFile, bytes);
|
|
209
|
-
const artifact = { ...metadata(bytes, "image/png", runnerRecord.artifactReference), height: 1, width: 1 };
|
|
210
|
-
const manifestFile = path.join(session.artifactRoot, "page-evidence-manifest.json");
|
|
211
|
-
const manifest = JSON.parse(fs.readFileSync(manifestFile));
|
|
212
|
-
const runnerResult = metadata(fs.readFileSync(runnerRecord.runnerFile), "application/json", runnerRecord.runnerReference);
|
|
213
|
-
const [scenario, ...remaining] = manifest.scenarios;
|
|
214
|
-
writeJson(manifestFile, {
|
|
215
|
-
...manifest,
|
|
216
|
-
scenarios: [{ ...scenario, evidence: { artifacts: [artifact], kind: "captured" }, runner_result: runnerResult }, ...remaining],
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export function finalizeSession(fixture, session, runner, priorManifest) {
|
|
221
|
-
const args = ["--root", fixture.root, "--artifact-root", session.artifactRoot, "--runner-result", runner.runnerReference, "--review-by", "2030-01-01T00:00:00Z"];
|
|
222
|
-
if (priorManifest) args.push("--prior-manifest", priorManifest);
|
|
223
|
-
return runCli(finalizer, args, fixture.root);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export function validateSession(fixture, session, priorManifest) {
|
|
227
|
-
const args = ["--root", fixture.root, "--artifact-root", session.artifactRoot];
|
|
228
|
-
if (priorManifest) args.push("--prior-manifest", priorManifest);
|
|
229
|
-
return runCli(validator, args, fixture.root);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export function completeSession(fixture, session = createConformance(fixture)) {
|
|
233
|
-
const start = startSession(fixture, session);
|
|
234
|
-
if (start.status !== 0) return { fixture, session, start };
|
|
235
|
-
const runner = writeRunner(fixture, session);
|
|
236
|
-
const finalize = finalizeSession(fixture, session, runner);
|
|
237
|
-
const validate = finalize.status === 0 ? validateSession(fixture, session) : undefined;
|
|
238
|
-
return { finalize, fixture, runner, session, start, validate };
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export function isolated(run) {
|
|
242
|
-
const fixture = initializeConsumer();
|
|
243
|
-
try { return run(fixture); }
|
|
244
|
-
finally { cleanupFixture(fixture); }
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export function started(fixture, options) {
|
|
248
|
-
const session = createConformance(fixture, options);
|
|
249
|
-
const start = startSession(fixture, session);
|
|
250
|
-
if (start.status !== 0) throw new Error(`fixture start failed: ${JSON.stringify(start.report)}`);
|
|
251
|
-
return session;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export function reuseSetup(fixture, { beforeCurrent, currentOptions } = {}) {
|
|
255
|
-
const prior = completeSession(fixture, createConformance(fixture, { artifactName: "prior" }));
|
|
256
|
-
beforeCurrent?.(fixture);
|
|
257
|
-
const current = started(fixture, { artifactName: "current", ...currentOptions });
|
|
258
|
-
const priorManifest = path.join(prior.session.artifactRoot, "page-evidence-manifest.json");
|
|
259
|
-
const evidence = {
|
|
260
|
-
kind: "reused",
|
|
261
|
-
prior_manifest_sha256: digest(fs.readFileSync(priorManifest)),
|
|
262
|
-
prior_run_id: prior.session.runId,
|
|
263
|
-
prior_scenario_id: prior.session.scenarioId,
|
|
264
|
-
prior_session_id: prior.session.sessionId,
|
|
265
|
-
};
|
|
266
|
-
return { current, evidence, prior, priorManifest };
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
export function cleanupFixture(fixture) {
|
|
270
|
-
fs.rmSync(fixture.root, { force: true, recursive: true });
|
|
271
|
-
}
|
package/scripts/pattern-data.mjs
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
// allow: SIZE_OK - explicit 46-pattern sample and rule data table; generation logic stays separate.
|
|
2
|
-
export const sources = {
|
|
3
|
-
carbonGrid: "https://carbondesignsystem.com/elements/2x-grid/overview/",
|
|
4
|
-
everyLayout: "https://every-layout.dev/layouts/",
|
|
5
|
-
everySidebar: "https://every-layout.dev/layouts/sidebar/",
|
|
6
|
-
everyStack: "https://every-layout.dev/layouts/stack/",
|
|
7
|
-
govukLayout: "https://design-system.service.gov.uk/styles/layout/",
|
|
8
|
-
materialCanonical: "https://m3.material.io/foundations/adaptive-design/canonical-layouts",
|
|
9
|
-
mdnCookbook: "https://developer.mozilla.org/en-US/docs/Web/CSS/How_to/Layout_cookbook",
|
|
10
|
-
mdnGrid: "https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Grids",
|
|
11
|
-
mdnOverflow: "https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/overflow",
|
|
12
|
-
mdnPosition: "https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/position",
|
|
13
|
-
webOneLine: "https://web.dev/articles/one-line-layouts",
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const samples = {
|
|
17
|
-
"stack": `
|
|
18
|
-
<section class="stack" aria-labelledby="stack-heading">
|
|
19
|
-
<h2 id="stack-heading">Release checklist</h2>
|
|
20
|
-
<p>Review copy, verify forms, and publish the notes in order.</p>
|
|
21
|
-
<button>Start review</button>
|
|
22
|
-
</section>`,
|
|
23
|
-
"box": `
|
|
24
|
-
<aside class="box" aria-labelledby="box-heading">
|
|
25
|
-
<h2 id="box-heading">Support window</h2>
|
|
26
|
-
<p>Responses resume Monday at 09:00.</p>
|
|
27
|
-
</aside>`,
|
|
28
|
-
"center": `
|
|
29
|
-
<article class="center" aria-labelledby="center-heading">
|
|
30
|
-
<h2 id="center-heading">Editorial policy</h2>
|
|
31
|
-
<p>Long-form guidance stays readable while the page around it remains fluid.</p>
|
|
32
|
-
</article>`,
|
|
33
|
-
"cluster": `
|
|
34
|
-
<nav class="cluster" aria-label="Project actions">
|
|
35
|
-
<a href="#">Backlog</a>
|
|
36
|
-
<a href="#">Milestones</a>
|
|
37
|
-
<a href="#">Roadmap</a>
|
|
38
|
-
</nav>`,
|
|
39
|
-
"content-limiter": `
|
|
40
|
-
<article class="content_limiter" aria-labelledby="limiter-heading">
|
|
41
|
-
<h2 id="limiter-heading">Incident summary</h2>
|
|
42
|
-
<p>The report keeps a comfortable measure even inside a wide dashboard shell.</p>
|
|
43
|
-
</article>`,
|
|
44
|
-
"super-center": `
|
|
45
|
-
<section class="super_center" aria-labelledby="centered-dialog-title">
|
|
46
|
-
<form aria-labelledby="centered-dialog-title">
|
|
47
|
-
<h2 id="centered-dialog-title">Confirm archive</h2>
|
|
48
|
-
<button>Archive project</button>
|
|
49
|
-
</form>
|
|
50
|
-
</section>`,
|
|
51
|
-
"icon-frame": `
|
|
52
|
-
<span class="icon_frame" aria-label="Calendar">
|
|
53
|
-
<svg aria-hidden="true" viewBox="0 0 24 24"></svg>
|
|
54
|
-
</span>`,
|
|
55
|
-
"frame": `
|
|
56
|
-
<figure class="frame">
|
|
57
|
-
<img alt="Product walkthrough still" class="frame_media">
|
|
58
|
-
</figure>`,
|
|
59
|
-
"cover": `
|
|
60
|
-
<section class="cover" aria-labelledby="cover-title">
|
|
61
|
-
<header><p>Step 2 of 4</p></header>
|
|
62
|
-
<main><h1 id="cover-title">Choose a billing profile</h1></main>
|
|
63
|
-
<footer><button>Continue</button></footer>
|
|
64
|
-
</section>`,
|
|
65
|
-
"sidebar": `
|
|
66
|
-
<section class="sidebar" aria-labelledby="sidebar-title">
|
|
67
|
-
<article class="sidebar_primary">
|
|
68
|
-
<h2 id="sidebar-title">Quarterly planning notes</h2>
|
|
69
|
-
<p>The main article keeps priority when the available inline space changes.</p>
|
|
70
|
-
</article>
|
|
71
|
-
<aside class="sidebar_secondary">Meeting agenda and owners</aside>
|
|
72
|
-
</section>`,
|
|
73
|
-
"switcher": `
|
|
74
|
-
<section class="switcher" aria-label="Pricing tiers">
|
|
75
|
-
<article class="switcher_item">Starter plan</article>
|
|
76
|
-
<article class="switcher_item">Team plan</article>
|
|
77
|
-
<article class="switcher_item">Enterprise plan</article>
|
|
78
|
-
</section>`,
|
|
79
|
-
"media-object": `
|
|
80
|
-
<article class="media_object">
|
|
81
|
-
<figure class="media_object_media"><img alt="Speaker portrait"></figure>
|
|
82
|
-
<div class="media_object_content">
|
|
83
|
-
<h2>Design systems briefing</h2>
|
|
84
|
-
<p>Speaker details align beside the portrait without squeezing the text.</p>
|
|
85
|
-
</div>
|
|
86
|
-
</article>`,
|
|
87
|
-
"split-nav": `
|
|
88
|
-
<nav class="split_nav" aria-label="Documentation">
|
|
89
|
-
<section class="split_nav_primary"><a href="#">Guides</a><a href="#">API</a></section>
|
|
90
|
-
<section class="split_nav_secondary"><a href="#">Sign in</a></section>
|
|
91
|
-
</nav>`,
|
|
92
|
-
"holy-grail": `
|
|
93
|
-
<section class="holy_grail" aria-label="News page">
|
|
94
|
-
<header class="holy_grail_header">Daily briefing</header>
|
|
95
|
-
<aside class="holy_grail_left">Topic navigation</aside>
|
|
96
|
-
<main class="holy_grail_main">Lead story and article stream</main>
|
|
97
|
-
<aside class="holy_grail_right">Market snapshot</aside>
|
|
98
|
-
<footer class="holy_grail_footer">Edition links</footer>
|
|
99
|
-
</section>`,
|
|
100
|
-
"sticky-footer": `
|
|
101
|
-
<section class="sticky_footer" aria-label="Account setup">
|
|
102
|
-
<header>Account setup</header>
|
|
103
|
-
<main class="sticky_footer_main">Profile fields and preferences</main>
|
|
104
|
-
<footer><button>Save profile</button></footer>
|
|
105
|
-
</section>`,
|
|
106
|
-
"sticky-header": `
|
|
107
|
-
<header class="sticky_header">
|
|
108
|
-
<nav aria-label="Repository"><a href="#">Code</a><a href="#">Issues</a><a href="#">Pull requests</a></nav>
|
|
109
|
-
</header>`,
|
|
110
|
-
"scroll-body-shell": `
|
|
111
|
-
<section class="scroll_body_shell" aria-label="Inbox">
|
|
112
|
-
<header>Inbox filters</header>
|
|
113
|
-
<main class="scroll_body_shell_body">Message list owns vertical scrolling</main>
|
|
114
|
-
<footer>Selected message actions</footer>
|
|
115
|
-
</section>`,
|
|
116
|
-
"fixed-sidenav-shell": `
|
|
117
|
-
<section class="fixed_sidenav_shell" aria-label="Settings">
|
|
118
|
-
<nav class="fixed_sidenav_shell_list"><a href="#">Profile</a><a href="#">Billing</a></nav>
|
|
119
|
-
<main class="fixed_sidenav_shell_main">Editable settings form scrolls independently</main>
|
|
120
|
-
</section>`,
|
|
121
|
-
"sticky-aside": `
|
|
122
|
-
<section class="sticky_aside" aria-label="Long article">
|
|
123
|
-
<main class="sticky_aside_main">Article sections continue down the page.</main>
|
|
124
|
-
<aside class="sticky_aside_side">Table of contents</aside>
|
|
125
|
-
</section>`,
|
|
126
|
-
"ram-grid": `
|
|
127
|
-
<section class="ram_grid" aria-label="Photo albums">
|
|
128
|
-
<article>Spring launch album</article>
|
|
129
|
-
<article>Customer meetup album</article>
|
|
130
|
-
<article>Workshop album</article>
|
|
131
|
-
</section>`,
|
|
132
|
-
"card-grid": `
|
|
133
|
-
<section class="card_grid" aria-label="Project cards">
|
|
134
|
-
<article>Design audit</article>
|
|
135
|
-
<article>Analytics migration</article>
|
|
136
|
-
<article>Onboarding rewrite</article>
|
|
137
|
-
</section>`,
|
|
138
|
-
"twelve-span-grid": `
|
|
139
|
-
<section class="twelve_span_grid" aria-label="Dashboard modules">
|
|
140
|
-
<article class="twelve_span_grid_item">Revenue module</article>
|
|
141
|
-
<article class="twelve_span_grid_item">Retention module</article>
|
|
142
|
-
<article class="twelve_span_grid_item">Pipeline module</article>
|
|
143
|
-
</section>`,
|
|
144
|
-
"page-grid": `
|
|
145
|
-
<section class="page_grid" aria-label="Article page">
|
|
146
|
-
<main class="page_grid_content">Centered article track with fluid outer gutters</main>
|
|
147
|
-
</section>`,
|
|
148
|
-
"grid-wrapper": `
|
|
149
|
-
<section class="grid_wrapper" aria-label="Marketing page">
|
|
150
|
-
<main class="grid_wrapper_main">Centered campaign copy</main>
|
|
151
|
-
</section>`,
|
|
152
|
-
"columns": `
|
|
153
|
-
<article class="columns" aria-labelledby="columns-heading">
|
|
154
|
-
<h2 id="columns-heading">Release notes</h2>
|
|
155
|
-
<p>Several short updates can flow into balanced columns when there is room.</p>
|
|
156
|
-
<p>When the container narrows, the same content returns to a single column.</p>
|
|
157
|
-
</article>`,
|
|
158
|
-
"deconstructed-pancake": `
|
|
159
|
-
<section class="deconstructed_pancake" aria-label="Plan comparison">
|
|
160
|
-
<article class="deconstructed_pancake_item">Solo plan</article>
|
|
161
|
-
<article class="deconstructed_pancake_item">Studio plan</article>
|
|
162
|
-
<article class="deconstructed_pancake_item">Agency plan</article>
|
|
163
|
-
</section>`,
|
|
164
|
-
"line-up": `
|
|
165
|
-
<article class="line_up" aria-labelledby="line-up-title">
|
|
166
|
-
<section class="line_up_body"><h2 id="line-up-title">Implementation proposal</h2><p>Variable-length summary copy sits above the aligned action row.</p></section>
|
|
167
|
-
<footer class="line_up_footer"><button>Review proposal</button></footer>
|
|
168
|
-
</article>`,
|
|
169
|
-
"clamped-card": `
|
|
170
|
-
<article class="clamped_card" aria-labelledby="clamped-title">
|
|
171
|
-
<h2 id="clamped-title">Invite teammate</h2>
|
|
172
|
-
<p>The card grows with the viewport but stops at the intended reading width.</p>
|
|
173
|
-
</article>`,
|
|
174
|
-
"fluid-styles": `
|
|
175
|
-
<section class="fluid_styles" aria-labelledby="fluid-title">
|
|
176
|
-
<h2 id="fluid-title">Operations overview</h2>
|
|
177
|
-
<p>The region fills the parent without exceeding the shared page measure.</p>
|
|
178
|
-
</section>`,
|
|
179
|
-
"split-screen": `
|
|
180
|
-
<section class="split_screen" aria-label="Compare documents">
|
|
181
|
-
<section class="split_screen_pane">Draft contract</section>
|
|
182
|
-
<section class="split_screen_pane">Reviewed contract</section>
|
|
183
|
-
</section>`,
|
|
184
|
-
"list-detail": `
|
|
185
|
-
<section class="list_detail" aria-label="Customer records">
|
|
186
|
-
<nav class="list_detail_list"><a href="#">Acme Co.</a><a href="#">Northwind</a></nav>
|
|
187
|
-
<section class="list_detail_detail">Selected customer timeline</section>
|
|
188
|
-
</section>`,
|
|
189
|
-
"supporting-pane": `
|
|
190
|
-
<section class="supporting_pane" aria-label="Invoice editor">
|
|
191
|
-
<main class="supporting_pane_main">Invoice line-item editor</main>
|
|
192
|
-
<aside class="supporting_pane_summary">Payment summary</aside>
|
|
193
|
-
</section>`,
|
|
194
|
-
"feed": `
|
|
195
|
-
<section class="feed" aria-label="Activity feed">
|
|
196
|
-
<article>Build completed</article>
|
|
197
|
-
<article>Review requested</article>
|
|
198
|
-
<article>Deployment approved</article>
|
|
199
|
-
</section>`,
|
|
200
|
-
"breadcrumb": `
|
|
201
|
-
<nav class="breadcrumb" aria-label="Breadcrumb">
|
|
202
|
-
<a href="#">Workspace</a>
|
|
203
|
-
<a href="#">Projects</a>
|
|
204
|
-
<span>Layout gallery</span>
|
|
205
|
-
</nav>`,
|
|
206
|
-
"pagination": `
|
|
207
|
-
<nav class="pagination" aria-label="Search results pages">
|
|
208
|
-
<a href="#">Previous</a>
|
|
209
|
-
<a href="#">Page 4</a>
|
|
210
|
-
<a href="#">Next</a>
|
|
211
|
-
</nav>`,
|
|
212
|
-
"badge-list": `
|
|
213
|
-
<section class="badge_list" aria-label="Repository counts">
|
|
214
|
-
<div class="badge_list_item"><span>Open issues</span><span>12</span></div>
|
|
215
|
-
<div class="badge_list_item"><span>Pull requests</span><span>4</span></div>
|
|
216
|
-
<div class="badge_list_item"><span>Reviews waiting</span><span>7</span></div>
|
|
217
|
-
</section>`,
|
|
218
|
-
"step-nav": `
|
|
219
|
-
<nav class="step_nav" aria-label="Checkout steps">
|
|
220
|
-
<a href="#">Shipping address</a>
|
|
221
|
-
<a href="#">Payment method</a>
|
|
222
|
-
<a href="#">Order review</a>
|
|
223
|
-
</nav>`,
|
|
224
|
-
"tab-strip": `
|
|
225
|
-
<nav class="tab_strip" aria-label="Report views">
|
|
226
|
-
<a href="#">Summary</a>
|
|
227
|
-
<a href="#">Cohorts</a>
|
|
228
|
-
<a href="#">Exports</a>
|
|
229
|
-
</nav>`,
|
|
230
|
-
"reel": `
|
|
231
|
-
<section class="reel" aria-label="Upcoming events">
|
|
232
|
-
<article>Design critique</article>
|
|
233
|
-
<article>Planning workshop</article>
|
|
234
|
-
<article>Launch review</article>
|
|
235
|
-
</section>`,
|
|
236
|
-
"imposter": `
|
|
237
|
-
<section class="imposter_anchor" aria-label="Draft editor">
|
|
238
|
-
<p>Draft body text stays in normal document flow.</p>
|
|
239
|
-
<section class="imposter" aria-label="Modal placement">
|
|
240
|
-
<dialog open>Unsaved changes confirmation</dialog>
|
|
241
|
-
</section>
|
|
242
|
-
</section>`,
|
|
243
|
-
"panel-layout": `
|
|
244
|
-
<section class="panel_layout" aria-label="Console workspace">
|
|
245
|
-
<main class="panel_layout_main">Query editor</main>
|
|
246
|
-
<aside class="panel_layout_side">Execution history</aside>
|
|
247
|
-
</section>`,
|
|
248
|
-
"overlay-stack": `
|
|
249
|
-
<section class="overlay_stack" aria-label="Map with controls">
|
|
250
|
-
<figure class="overlay_stack_item">Transit map</figure>
|
|
251
|
-
<form class="overlay_stack_item">Route search controls</form>
|
|
252
|
-
</section>`,
|
|
253
|
-
"wrap-row": `
|
|
254
|
-
<form class="wrap_row" aria-label="Filter tickets">
|
|
255
|
-
<label>Status <select></select></label>
|
|
256
|
-
<label>Owner <select></select></label>
|
|
257
|
-
<button>Apply filters</button>
|
|
258
|
-
</form>`,
|
|
259
|
-
"dense-grid": `
|
|
260
|
-
<section class="dense_grid" aria-label="Keyboard shortcuts">
|
|
261
|
-
<kbd>Cmd K</kbd>
|
|
262
|
-
<kbd>Cmd Shift P</kbd>
|
|
263
|
-
<kbd>Esc</kbd>
|
|
264
|
-
</section>`,
|
|
265
|
-
"masonry-approx": `
|
|
266
|
-
<section class="masonry_approx" aria-label="Research notes">
|
|
267
|
-
<article>Interview excerpt with a longer observation.</article>
|
|
268
|
-
<article>Short survey result.</article>
|
|
269
|
-
<article>Workshop synthesis note.</article>
|
|
270
|
-
</section>`,
|
|
271
|
-
"main-with-rail": `
|
|
272
|
-
<section class="main_with_rail" aria-label="Documentation page">
|
|
273
|
-
<main class="main_with_rail_main">API reference article</main>
|
|
274
|
-
<aside class="main_with_rail_side">On this page links</aside>
|
|
275
|
-
</section>`,
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
export const patterns = [
|
|
279
|
-
["stack", "Stacking", "Create consistent vertical rhythm between direct children.", "block", "fluid", sources.everyStack, [[".stack", { display: "grid", gap: "1rem" }]]],
|
|
280
|
-
["box", "Containment", "Wrap content with predictable internal spacing.", "block", "fixed", sources.everyLayout, [[".box", { "box-sizing": "border-box", display: "block", padding: "1rem" }]]],
|
|
281
|
-
["center", "Centering", "Center a block while respecting a maximum measure.", "inline", "fluid", sources.everyLayout, [[".center", { "margin-inline": "auto", "max-inline-size": "64rem", "padding-inline": "1rem" }]]],
|
|
282
|
-
["cluster", "In-line grouping", "Keep related items together while allowing wrapping.", "inline", "wrap", sources.everyLayout, [[".cluster", { display: "flex", "flex-wrap": "wrap", gap: "0.75rem", "justify-content": "flex-start" }]]],
|
|
283
|
-
["content-limiter", "Containment", "Keep prose width readable inside fluid containers.", "inline", "fluid", sources.govukLayout, [[".content_limiter", { "margin-inline": "auto", "max-inline-size": "70ch", "padding-inline": "1rem" }]]],
|
|
284
|
-
["super-center", "Centering", "Center one region along both axes.", "both", "fluid", sources.webOneLine, [[".super_center", { display: "grid", "min-block-size": "100dvh", "place-items": "center" }]]],
|
|
285
|
-
["icon-frame", "Media / Fit", "Keep an icon aligned inside a fixed square slot.", "both", "fixed", sources.everyLayout, [[".icon_frame", { "block-size": "2.5rem", display: "grid", "inline-size": "2.5rem", "place-items": "center" }]]],
|
|
286
|
-
["frame", "Media / Fit", "Preserve media aspect ratio in a responsive slot.", "both", "fluid", sources.everyLayout, [[".frame", { "aspect-ratio": "16 / 9", display: "grid", "inline-size": "100%", overflow: "clip" }], [".frame_media", { "block-size": "100%", "inline-size": "100%", "min-block-size": "0", "min-inline-size": "0", "object-fit": "cover" }]]],
|
|
287
|
-
["cover", "Viewport / Shell", "Keep a central region balanced between optional header and footer.", "block", "fluid", sources.everyLayout, [[".cover", { display: "grid", gap: "1rem", "grid-template-rows": "auto 1fr auto", "min-block-size": "100dvh", padding: "1rem" }]]],
|
|
288
|
-
["sidebar", "Split / Sidebar", "Let a narrow sidebar and wider content wrap when space is tight.", "inline", "wrap", sources.everySidebar, [[".sidebar", { display: "flex", "flex-wrap": "wrap", gap: "1rem" }], [".sidebar_primary", { "flex-basis": "0", "flex-grow": "999", "min-inline-size": "16rem" }], [".sidebar_secondary", { "flex-basis": "18rem", "flex-grow": "1" }]]],
|
|
289
|
-
["switcher", "Split / Sidebar", "Switch equal regions from row to stack without a viewport breakpoint.", "inline", "wrap", sources.everyLayout, [[".switcher", { display: "flex", "flex-wrap": "wrap", gap: "1rem" }], [".switcher_item", { "flex-basis": "calc((40rem - 100%) * 999)", "flex-grow": "1" }]]],
|
|
290
|
-
["media-object", "Split / Sidebar", "Align media and descriptive content as a stable pair.", "inline", "reflow", sources.mdnCookbook, [[".media_object", { "align-items": "start", display: "flex", "flex-wrap": "wrap", gap: "1rem" }], [".media_object_media", { "flex-basis": "6rem", "flex-grow": "0" }], [".media_object_content", { "flex-basis": "min(20rem, 100%)", "flex-grow": "1", "min-inline-size": "0" }]]],
|
|
291
|
-
["split-nav", "In-line grouping", "Separate primary and secondary nav actions in one row.", "inline", "wrap", sources.mdnCookbook, [[".split_nav", { "align-items": "center", display: "flex", "flex-wrap": "wrap", gap: "0.75rem" }], [".split_nav_primary", { display: "flex", gap: "0.75rem" }], [".split_nav_secondary", { "margin-inline-start": "auto" }]]],
|
|
292
|
-
["holy-grail", "Viewport / Shell", "Place header, footer, sidebars, and main content in a resilient shell.", "both", "breakpointed", sources.webOneLine, [[".holy_grail", { display: "grid", gap: "1rem", "grid-template": '"header header header" auto "left main right" 1fr "footer footer footer" auto / minmax(12rem, auto) 1fr minmax(12rem, auto)', "min-block-size": "100dvh" }], [".holy_grail_header", { "grid-area": "header" }], [".holy_grail_left", { "grid-area": "left" }], [".holy_grail_main", { "grid-area": "main", "min-inline-size": "0" }], [".holy_grail_right", { "grid-area": "right" }], [".holy_grail_footer", { "grid-area": "footer" }]]],
|
|
293
|
-
["sticky-footer", "Viewport / Shell", "Keep footer at the bottom when content is short.", "block", "fluid", sources.mdnCookbook, [[".sticky_footer", { display: "grid", "grid-template-rows": "auto 1fr auto", "min-block-size": "100dvh" }], [".sticky_footer_main", { "min-block-size": "0" }]]],
|
|
294
|
-
["sticky-header", "Viewport / Shell", "Keep a header visible above a scrolling content region.", "block", "fluid", sources.mdnPosition, [[".sticky_header", { "inset-block-start": "0", position: "sticky", "z-index": "1" }]]],
|
|
295
|
-
["scroll-body-shell", "Viewport / Shell", "Keep shell regions fixed while only the body scrolls.", "block", "fluid", sources.mdnOverflow, [[".scroll_body_shell", { display: "grid", "grid-template-rows": "auto minmax(0, 1fr) auto", "max-block-size": "100dvh" }], [".scroll_body_shell_body", { "min-block-size": "0", overflow: "auto" }]], "Pattern owns the named scroll container."],
|
|
296
|
-
["fixed-sidenav-shell", "Viewport / Shell", "Keep side navigation stable while main content scrolls.", "both", "fluid", sources.carbonGrid, [[".fixed_sidenav_shell", { display: "grid", "grid-template-columns": "16rem minmax(0, 1fr)", "grid-template-rows": "minmax(0, 1fr)", "max-block-size": "100dvh" }], [".fixed_sidenav_shell_list", { "min-block-size": "0" }], [".fixed_sidenav_shell_main", { "min-block-size": "0", overflow: "auto" }]], "Pattern owns the named scroll container."],
|
|
297
|
-
["sticky-aside", "Split / Sidebar", "Keep related aside content visible during long reads.", "block", "fluid", sources.mdnPosition, [[".sticky_aside", { "align-items": "start", display: "grid", gap: "1rem", "grid-template-columns": "minmax(0, 1fr) 16rem" }], [".sticky_aside_main", { "min-inline-size": "0" }], [".sticky_aside_side", { "inset-block-start": "1rem", position: "sticky" }]]],
|
|
298
|
-
["ram-grid", "Grid / Repetition", "Repeat items into as many useful columns as space allows.", "both", "fluid", sources.webOneLine, [[".ram_grid", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(auto-fit, minmax(min(16rem, 100%), 1fr))" }]]],
|
|
299
|
-
["card-grid", "Grid / Repetition", "Align repeating cards in rows and columns.", "both", "fluid", sources.mdnCookbook, [[".card_grid", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(auto-fit, minmax(min(18rem, 100%), 1fr))" }]]],
|
|
300
|
-
["twelve-span-grid", "Grid / Repetition", "Provide a twelve-column placement scaffold.", "both", "fluid", sources.webOneLine, [[".twelve_span_grid", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(12, minmax(0, 1fr))" }], [".twelve_span_grid_item", { "grid-column": "span 4" }]]],
|
|
301
|
-
["page-grid", "Grid / Repetition", "Align page content to margins, gutters, and a central track.", "inline", "fluid", sources.carbonGrid, [[".page_grid", { display: "grid", gap: "1rem", "grid-template-columns": "minmax(1rem, 1fr) minmax(0, 72rem) minmax(1rem, 1fr)" }], [".page_grid_content", { "grid-column": "2" }]]],
|
|
302
|
-
["grid-wrapper", "Grid / Repetition", "Center grid tracks while allowing full-width breakout tracks.", "inline", "fluid", sources.mdnCookbook, [[".grid_wrapper", { display: "grid", "grid-template-columns": "1fr minmax(0, 64rem) 1fr" }], [".grid_wrapper_main", { "grid-column": "2" }]]],
|
|
303
|
-
["columns", "Grid / Repetition", "Flow long content into balanced text columns.", "inline", "fluid", sources.mdnCookbook, [[".columns", { "column-gap": "2rem", columns: "18rem" }]]],
|
|
304
|
-
["deconstructed-pancake", "In-line grouping", "Let equal cards stretch in a row and stack naturally when narrow.", "inline", "wrap", sources.webOneLine, [[".deconstructed_pancake", { display: "flex", "flex-wrap": "wrap", gap: "1rem" }], [".deconstructed_pancake_item", { flex: "1 1 16rem" }]]],
|
|
305
|
-
["line-up", "Stacking", "Keep card footer actions aligned at the bottom.", "block", "fluid", sources.webOneLine, [[".line_up", { display: "flex", "flex-direction": "column", gap: "1rem" }], [".line_up_body", { "min-block-size": "0" }], [".line_up_footer", { "margin-block-start": "auto" }]]],
|
|
306
|
-
["clamped-card", "Containment", "Constrain a card to a readable fluid width.", "inline", "fluid", sources.webOneLine, [[".clamped_card", { "inline-size": "clamp(16rem, 50vw, 28rem)", "margin-inline": "auto" }]]],
|
|
307
|
-
["fluid-styles", "Containment", "Let a region fill available width without exceeding a readable max.", "inline", "fluid", sources.carbonGrid, [[".fluid_styles", { "inline-size": "min(100%, 72rem)", "margin-inline": "auto" }]]],
|
|
308
|
-
["split-screen", "Split / Sidebar", "Split a viewport or region into two balanced panes.", "inline", "reflow", sources.materialCanonical, [[".split_screen", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(auto-fit, minmax(min(20rem, 100%), 1fr))", "min-block-size": "100dvh" }], [".split_screen_pane", { "min-inline-size": "0" }]]],
|
|
309
|
-
["list-detail", "Split / Sidebar", "Place an explorable list beside its detail region.", "inline", "reflow", sources.materialCanonical, [[".list_detail", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(auto-fit, minmax(min(18rem, 100%), 1fr))" }], [".list_detail_list", { "min-inline-size": "0" }], [".list_detail_detail", { "min-inline-size": "0" }]]],
|
|
310
|
-
["supporting-pane", "Split / Sidebar", "Keep supplemental information beside a primary task.", "inline", "reflow", sources.materialCanonical, [[".supporting_pane", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(auto-fit, minmax(min(20rem, 100%), 1fr))" }], [".supporting_pane_main", { "min-inline-size": "0" }], [".supporting_pane_summary", { "min-inline-size": "0" }]]],
|
|
311
|
-
["feed", "Stacking", "Stack repeated content items with stable rhythm.", "block", "fluid", sources.materialCanonical, [[".feed", { display: "grid", gap: "1rem", "grid-auto-rows": "minmax(min-content, auto)" }]]],
|
|
312
|
-
["breadcrumb", "In-line grouping", "Lay out hierarchy links compactly with wrapping.", "inline", "wrap", sources.mdnCookbook, [[".breadcrumb", { "align-items": "center", display: "flex", "flex-wrap": "wrap", gap: "0.5rem" }]]],
|
|
313
|
-
["pagination", "In-line grouping", "Lay out page controls as a bounded wrapping row.", "inline", "wrap", sources.mdnCookbook, [[".pagination", { display: "flex", "flex-wrap": "wrap", gap: "0.5rem", "justify-content": "center" }]]],
|
|
314
|
-
["badge-list", "In-line grouping", "Align item labels with trailing counts.", "inline", "fluid", sources.mdnCookbook, [[".badge_list", { display: "grid", gap: "0.5rem" }], [".badge_list_item", { "align-items": "center", display: "flex", gap: "0.75rem", "justify-content": "space-between" }]]],
|
|
315
|
-
["step-nav", "Stacking", "Present sequential steps with consistent vertical rhythm.", "block", "fluid", sources.govukLayout, [[".step_nav", { display: "grid", gap: "0.75rem", "margin-block": "1rem" }]]],
|
|
316
|
-
["tab-strip", "In-line grouping", "Keep peer tabs in one stable row that can wrap.", "inline", "wrap", sources.govukLayout, [[".tab_strip", { display: "flex", "flex-wrap": "wrap", gap: "0.75rem" }]]],
|
|
317
|
-
["reel", "In-line grouping", "Let a row scroll horizontally instead of wrapping.", "inline", "scroll", sources.everyLayout, [[".reel", { display: "grid", gap: "1rem", "grid-auto-columns": "minmax(14rem, 35%)", "grid-auto-flow": "column", "overflow-x": "auto" }]], "Pattern owns the named scroll container."],
|
|
318
|
-
["imposter", "Overlay / Exception", "Place an overlay region over a parent without changing document order.", "both", "fixed", sources.everyLayout, [[".imposter_anchor", { position: "relative" }], [".imposter", { display: "grid", inset: "0", "place-items": "center", position: "absolute", "z-index": "1" }]]],
|
|
319
|
-
["panel-layout", "Viewport / Shell", "Create predictable main and utility panels.", "inline", "reflow", sources.carbonGrid, [[".panel_layout", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(auto-fit, minmax(min(22rem, 100%), 1fr))" }], [".panel_layout_main", { "min-inline-size": "0" }], [".panel_layout_side", { "min-inline-size": "0" }]]],
|
|
320
|
-
["overlay-stack", "Overlay / Exception", "Stack several regions into the same grid cell.", "both", "fluid", sources.webOneLine, [[".overlay_stack", { display: "grid" }], [".overlay_stack_item", { "grid-area": "1 / 1" }]]],
|
|
321
|
-
["wrap-row", "In-line grouping", "Wrap controls into rows with stable gaps.", "inline", "wrap", sources.mdnCookbook, [[".wrap_row", { "align-items": "center", display: "flex", "flex-wrap": "wrap", gap: "0.75rem" }]]],
|
|
322
|
-
["dense-grid", "Grid / Repetition", "Fill a compact grid with repeated small items.", "both", "fluid", sources.mdnGrid, [[".dense_grid", { display: "grid", gap: "0.5rem", "grid-template-columns": "repeat(auto-fill, minmax(8rem, 1fr))" }]]],
|
|
323
|
-
["masonry-approx", "Grid / Repetition", "Approximate staggered content with columns when exact row alignment is not needed.", "block", "fluid", sources.mdnCookbook, [[".masonry_approx", { "column-gap": "1rem", "column-width": "14rem" }]]],
|
|
324
|
-
["main-with-rail", "Split / Sidebar", "Keep primary content dominant with a narrow secondary rail.", "inline", "reflow", sources.govukLayout, [[".main_with_rail", { display: "grid", gap: "1rem", "grid-template-columns": "repeat(auto-fit, minmax(min(18rem, 100%), 1fr))" }], [".main_with_rail_main", { "min-inline-size": "0" }], [".main_with_rail_side", { "min-inline-size": "0" }]]],
|
|
325
|
-
];
|