@expressivecss/mcp-server 0.4.0 → 0.4.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/contract.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generatedBy": "scripts/gen-expressivecss-skill.mjs",
4
- "frameworkVersion": "0.14.1",
5
- "skillVersion": "0.10.0",
6
- "matchingTag": "v0.14.1",
4
+ "frameworkVersion": "0.15.0",
5
+ "skillVersion": "0.11.0",
6
+ "matchingTag": "v0.15.0",
7
7
  "releaseTags": [
8
8
  "v0.10.0",
9
9
  "v0.10.1",
@@ -13,6 +13,7 @@
13
13
  "v0.13.1",
14
14
  "v0.14.0",
15
15
  "v0.14.1",
16
+ "v0.15.0",
16
17
  "v0.5.0",
17
18
  "v0.6.0",
18
19
  "v0.7.0",
@@ -29,5 +30,5 @@
29
30
  "package.json",
30
31
  "CHANGELOG.md"
31
32
  ],
32
- "sourceHash": "80d854b3978953f2491c292c4c9c0fe32f72842a9d9a03e4e0b8aff409314463"
33
+ "sourceHash": "e1c777a1bcd53d5a6ed4615075a7a500fb6f488050e727487804f8cc421b5902"
33
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressivecss/mcp-server",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "ExpressiveCSS MCP server with Design→QA workflow tools.",
5
5
  "homepage": "https://www.expressivecss.com",
6
6
  "repository": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generatedBy": "mcp/expressivecss/scripts/sync-guides.mjs",
4
- "frameworkVersion": "0.14.1",
4
+ "frameworkVersion": "0.15.0",
5
5
  "semantics": {
6
6
  "about": "Normative HTML semantics for ExpressiveCSS. This data file is the single source of truth: SEMANTICS.md is generated from it by scripts/gen-semantics.mjs, and tests/semantics.test.js enforces it. One row per roster entry, each stating its kind - component, foundation or behavior, as CONTEXT.md defines them. CONTEXT.md defines the rest of the vocabulary.",
7
7
  "scope": "Element choice, landmark structure, and the ARIA that element choice implies. Keyboard interaction, focus management and colour contrast are deliberately out of scope.",
@@ -1264,6 +1264,35 @@
1264
1264
  }
1265
1265
  ]
1266
1266
  },
1267
+ "keypad": {
1268
+ "status": "enforced",
1269
+ "note": "Added with the keypad and keyboard component. The container is a named group, and every key is a native button that must not submit the form around it.",
1270
+ "rules": [
1271
+ {
1272
+ "id": "keypad-is-group",
1273
+ "kind": "require-attr",
1274
+ "selector": ":is(.keypad, .keyboard)",
1275
+ "attr": "role",
1276
+ "equals": "group",
1277
+ "message": "A keypad or keyboard is a set of related keys. Give it role=\"group\" and an aria-label so its keys are announced together."
1278
+ },
1279
+ {
1280
+ "id": "keypad-is-labelled",
1281
+ "kind": "require-attr",
1282
+ "selector": ":is(.keypad, .keyboard)",
1283
+ "attr": "aria-label",
1284
+ "message": "Name the keypad or keyboard with aria-label, for example \"PIN keypad\"."
1285
+ },
1286
+ {
1287
+ "id": "keypad-key-type",
1288
+ "kind": "require-attr",
1289
+ "selector": ":is(.keypad, .keyboard) button",
1290
+ "attr": "type",
1291
+ "equals": "button",
1292
+ "message": "A <button> inside a form defaults to type=submit, so every key would submit it. Give each key type=\"button\"."
1293
+ }
1294
+ ]
1295
+ },
1267
1296
  "tree": {
1268
1297
  "status": "enforced",
1269
1298
  "note": "Added with the tree component. Nested lists of native disclosures and links: every row is a Tab stop and the browser opens a branch, so no tree role is promised.",
package/smoke.mjs CHANGED
@@ -299,10 +299,13 @@ async function verifyResponseBudgets(matchingDir, versionedDir) {
299
299
  assert.equal(result.structuredContent.skipped, true);
300
300
  assert.equal(result.structuredContent.contractCompatibility, 'unknown');
301
301
  }
302
- await assert.rejects(peer.callTool(request('component_syntax_expert', { components: Array(400).fill(1) })), (error) => error.code === -32001);
303
302
  }, { env: { SKIP_SETUP_EXPERT: 'true', SKIP_CREATIVE_DIRECTOR: 'true', SKIP_PAGE_ARCHITECT: 'true', SKIP_COMPONENT_SYNTAX_EXPERT: 'true' } });
304
303
  await withServer(1, async ({ peer }) => {
305
304
  await assert.rejects(peer.callTool(request('component_syntax_expert', { components: ['cards'] })), (error) => error.code === -32001);
305
+ // A validation error is budgeted like any result. Its size is zod's to
306
+ // decide (4.6.6 stops at the array's maxItems), so only a 1-byte budget
307
+ // overflows it on every version.
308
+ await assert.rejects(peer.callTool(request('component_syntax_expert', { components: Array(400).fill(1) })), (error) => error.code === -32001);
306
309
  }, { env: { SKIP_COMPONENT_SYNTAX_EXPERT: 'true' } });
307
310
  for (const invalid of ['', '0', '-1', '+1', '1.5', 'NaN', 'Infinity', '1e4', ' 64', '9007199254740992']) {
308
311
  const child = spawnSync(process.execPath, [path.join(packageDir, 'server.js')], { env: { ...process.env, [setting]: invalid }, encoding: 'utf8', timeout: 10_000 });