@markuplint/rules 5.0.0-rc.7 → 5.0.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/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [5.0.1](https://github.com/markuplint/markuplint/compare/v5.0.0...v5.0.1) (2026-09-22)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **rules:** skip framework directives in no-event-handler-attr ([1da97ed](https://github.com/markuplint/markuplint/commit/1da97ed5ff6a17aeabd9dbe7077ebe057a3b674d)), closes [#4044](https://github.com/markuplint/markuplint/issues/4044)
11
+
12
+ # [5.0.0](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.7...v5.0.0) (2026-09-11)
13
+
14
+ ### Bug Fixes
15
+
16
+ - **rules:** add role predefined group to attr-order ([ed07019](https://github.com/markuplint/markuplint/commit/ed07019cafaf5dc85ce5c5e6f4ac56f908b93b54)), closes [#4033](https://github.com/markuplint/markuplint/issues/4033)
17
+
6
18
  # [5.0.0-rc.7](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.6...v5.0.0-rc.7) (2026-08-31)
7
19
 
8
20
  ### Bug Fixes
package/CLAUDE.md CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  ## Adding a New Rule (checklist — steps 2–4 have NO enforcing test; forgetting them fails silently)
4
4
 
5
- 1. `src/<rule-name>/`: `index.ts`, `meta.ts`, `schema.json`, spec file(s), `README.md` **and** `README.ja.md` — both languages are website source and MUST stay in sync; updating only one is a recurring mistake
5
+ 1. `src/<rule-name>/`: `index.ts`, `meta.ts`, `schema.json`, spec file(s), `README.md` **and** `README.ja.md` — both languages are website source and must stay in sync; updating only one is a recurring mistake
6
6
  - `meta.ts`'s `category` must be one of the v5 9-category scheme: `syntax`, `structure`, `attributes`, `references`, `forms`, `a11y`, `style`, `maintainability`, `compat` (see the [Categories section](https://markuplint.dev/docs/migration/v4-to-v5/rules/rule-names#categories) of the website's rule-names guide for what each covers)
7
7
  - `meta.ts` should also declare `specConformance` (`sources`/`level`/`cites`) once you know the rule's governing spec and requirement strength — `level: 'must'` or `'should'` requires a non-empty `cites`. The rollout across pre-existing rules is incremental and partial by design (enforced only for rules that declare it — see `spec-conformance.spec.ts` and `@markuplint/config-presets`'s `html-standard-entries.spec.ts`), but a **new** rule should declare it from the start
8
8
  2. Register the rule in `src/index.ts` (import + registry entry)
9
9
  3. Add a `$ref` entry to `packages/@markuplint/rules/schema.json` — this file is a **manually maintained registry** (no generator produces it, despite looking generated)
10
10
  4. If the rule belongs in a preset, update `packages/@markuplint/config-presets/src/`
11
11
 
12
- ## Test ID Convention (MANDATORY)
12
+ ## Test ID Convention
13
13
 
14
- Every `test()` block in rule spec files — `src/<rule-name>/**/*.spec.ts` — MUST have a unique ID prefix:
14
+ Every `test()` block in rule spec files — `src/<rule-name>/**/*.spec.ts` — has a unique ID prefix:
15
15
 
16
16
  ```
17
17
  [rule-name-category-NNN] description
@@ -37,7 +37,42 @@ Repo-wide meta specs directly under `src/` (e.g. `mirrors-parse-error-codes.spec
37
37
  - When adding a new test, assign the next available number in the appropriate category
38
38
  - Run `/list-rule-test` (or `node .claude/skills/list-rule-test/scripts/list-rule-test.mjs --no-id`) to check for missing IDs — the only expected hits are the exempt meta specs noted above
39
39
 
40
- ## Assertion Convention (MANDATORY)
40
+ ## Sample identifiers in specs
41
+
42
+ <!-- cspell:ignore myform mymap -->
43
+
44
+ Sample `id` / `name` values in test markup must be kebab-case (`my-form`), suffixed with a digit
45
+ (`form1`), or a plain dictionary word (`target`). Never a camelCase coinage (`myform`, `mymap`,
46
+ `targetEl`): CSpell decomposes compound words only when every part is at least three characters,
47
+ so a two-letter prefix glued to a word is looked up whole, misses the dictionary, and fails the
48
+ lint — on the `dev` line the same one-line fix has been made in four separate PRs (#3826, #3831,
49
+ #3833, #3932). The v6 line has no CSpell, so a coinage introduced there surfaces only once the
50
+ branch merges somewhere that does.
51
+
52
+ ## Writing a rule's README and `schema.json` description
53
+
54
+ Both files feed the website build (`website/scripts/prebuild/rule-content.mts` injects the
55
+ description into MDX), which breaks in two ways that no rule test catches:
56
+
57
+ - **An attribute-bearing tag must be wrapped in backticks.** `escapeMdx` only escapes bare tags
58
+ (`<head>`); `<input type="button">` reaches the MDX parser as unclosed JSX and crashes the
59
+ Docusaurus build.
60
+ - **A YAML `description:` may not start with a backtick** — `gray-matter` fails with "stream/document
61
+ separator expected". Wrap the whole value in single quotes instead:
62
+
63
+ ```yaml
64
+ description: '`<input type="button">` must not have a value attribute'
65
+ ```
66
+
67
+ Deliberately malformed markup in an ❌ example needs `<!-- prettier-ignore -->` immediately before
68
+ the fence: oxfmt formats ` ```html ` blocks as real HTML and will close the tag you left open,
69
+ turning the incorrect example into a copy of the correct one. Apply it to `README.md` and
70
+ `README.ja.md` separately, and read the diff after `yarn lint` to confirm the breakage survived.
71
+
72
+ The CI website check only runs when a PR already touches `website/`, so a new rule can land with a
73
+ broken description and detonate in someone else's PR. Run `yarn site:build` before pushing.
74
+
75
+ ## Assertion Convention
41
76
 
42
77
  When asserting reported violations in rule specs, use `toStrictEqual` with the exact violation object `{ severity, line, col, message, raw }`. Never loose or partial matchers for violation objects. (Assertions on other values — counts, fixed code strings, registry invariants — use whatever matcher fits.)
43
78
 
@@ -1,4 +1,4 @@
1
- type PredefinedGroup = 'global' | 'event' | 'aria' | 'data' | 'spread';
1
+ type PredefinedGroup = 'global' | 'event' | 'aria' | 'role' | 'data' | 'spread';
2
2
  type SortOrder = 'alphabetical' | 'source-order' | string[];
3
3
  type OrderEntry = string | {
4
4
  name?: string;
@@ -112,6 +112,13 @@ eventAttrs) {
112
112
  match: (name) => /^aria-.+$/.test(name),
113
113
  };
114
114
  }
115
+ case 'role': {
116
+ return {
117
+ entryIndex,
118
+ order: groupOrder,
119
+ match: (name) => name === 'role',
120
+ };
121
+ }
115
122
  case 'data': {
116
123
  return {
117
124
  entryIndex,
package/lib/index.d.ts CHANGED
@@ -16,7 +16,7 @@ declare const rules: {
16
16
  readonly 'attr-order': Readonly<import("@markuplint/ml-core").RuleSeed<(string | {
17
17
  name?: string;
18
18
  pattern?: string;
19
- group?: "data" | "aria" | "global" | "event" | "spread";
19
+ group?: "data" | "aria" | "global" | "event" | "role" | "spread";
20
20
  order?: string[] | "alphabetical" | "source-order";
21
21
  })[], {
22
22
  alphabetical?: boolean;
@@ -29,6 +29,13 @@ export default createRule({
29
29
  if (attr.ownerElement.elementType !== 'html') {
30
30
  return;
31
31
  }
32
+ // Framework directives that resolve to an `onXxx` name (Vue `@click`, Alpine
33
+ // `x-on:click`, htmx `hx-on:click`, Svelte `on:click`) are excluded: they never
34
+ // reach the DOM as a literal inline-handler attribute, and each framework
35
+ // documents them as its recommended event-binding idiom.
36
+ if (attr.isDirective) {
37
+ return;
38
+ }
32
39
  const ignoreList = Array.isArray(attr.rule.options.ignore)
33
40
  ? attr.rule.options.ignore
34
41
  : attr.rule.options.ignore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/rules",
3
- "version": "5.0.0-rc.7",
3
+ "version": "5.0.1",
4
4
  "description": "Built-in rules of markuplint",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,13 +31,13 @@
31
31
  "./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
32
32
  },
33
33
  "dependencies": {
34
- "@markuplint/html-spec": "5.0.0-rc.7",
35
- "@markuplint/ml-config": "5.0.0-rc.7",
36
- "@markuplint/ml-core": "5.0.0-rc.7",
37
- "@markuplint/ml-spec": "5.0.0-rc.7",
38
- "@markuplint/selector": "5.0.0-rc.7",
39
- "@markuplint/shared": "5.0.0-rc.7",
40
- "@markuplint/types": "5.0.0-rc.7",
34
+ "@markuplint/html-spec": "5.0.1",
35
+ "@markuplint/ml-config": "5.0.1",
36
+ "@markuplint/ml-core": "5.0.1",
37
+ "@markuplint/ml-spec": "5.0.1",
38
+ "@markuplint/selector": "5.0.1",
39
+ "@markuplint/shared": "5.0.1",
40
+ "@markuplint/types": "5.0.1",
41
41
  "@mdn/browser-compat-data": "^7.3.2",
42
42
  "@types/debug": "4.1.13",
43
43
  "ansi-colors": "4.1.3",
@@ -47,5 +47,5 @@
47
47
  "image-size": "^2.0.2",
48
48
  "type-fest": "5.6.0"
49
49
  },
50
- "gitHead": "8d7a3b801e0f5f88438c003e7eee2bd45e6aedd0"
50
+ "gitHead": "edbaeedca5588fb291ea9d4e21a4ab2bf41fc9cb"
51
51
  }