Skip to content

v2.0.0: Update custom rules to match HTML Academy codeguide#115

Merged
meritt merged 18 commits into
mainfrom
next
May 20, 2026
Merged

v2.0.0: Update custom rules to match HTML Academy codeguide#115
meritt merged 18 commits into
mainfrom
next

Conversation

@meritt

@meritt meritt commented Jan 25, 2026

Copy link
Copy Markdown
Member

Synchronised with linthtml-config-htmlacademy#28 and codeguide#75. This is the rules side of the joint 2.0.0 release.

The package has been migrated to ESM (type: "module", top-level await, import everywhere). Node.js requirement is now >=24. Everything below describes changes to the rules themselves.

New rules

Nine new rules cover gaps in form accessibility and SVG semantics:

  • htmlacademy/req-submit-button — every <form> must contain a submit button (<button type="submit">, default-type <button>, <input type="submit">, or an external submitter linked via form="<id>"). Closes Правило: req-submit-button #40.
  • htmlacademy/input-name-unique<input> elements within the same <form> must have unique name attributes; radio and checkbox groups are exempt because they legitimately share a name. Closes Правило: input-name-unique #46.
  • htmlacademy/heading-level — disallows skipping heading levels (<h1><h3> is flagged) and requires the document to start with <h1>. Returning to a higher level (<h3><h2>) is allowed. Closes Правило: heading-level #41.
  • htmlacademy/label-req-for — every <label> must be associated with a labelable control either through a for/id reference or by containing the control inline. Empty for="" is explicitly allowed.
  • htmlacademy/label-req-text<label> must contain visible text content (or carry an aria-label); <label><input></label> without any text is flagged. Closes Правило: label-req-text #67.
  • htmlacademy/icon-button-aria-label — a <button> without visible text content must declare an accessible name via aria-label, aria-labelledby, or title. Covers icon-only buttons that would otherwise be invisible to screen readers. Addresses Проблема: button-req-content не видит aria-labelledby #80 (the upstream button-req-content does not recognise aria-labelledby).
  • htmlacademy/svg-role-img — inline <svg> must opt in either as content (role="img" + aria-label/aria-labelledby) or as decorative (aria-hidden="true"). Bare <svg> with content is flagged. Closes Правило: svg-role-img #53.
  • htmlacademy/boolean-attr-no-value — disallows assigning a value to HTML boolean attributes (disabled, required, checked, readonly, multiple, selected, autofocus, hidden, open, async, defer, autoplay, controls, loop, muted, inert, …). Uses is_boolean_attribute from @linthtml/dom-utils so the list stays accurate.
  • htmlacademy/attr-order — enforces attribute order via configurable groups. The default order matches the codeguide policy `class → src/href → data-* → others` and supports glob patterns like `data-`, `aria-`, and the catch-all `*`. Order inside a group is free.

Renamed

  • htmlacademy/img-svg-req-dimensionshtmlacademy/replaced-elements-req-dimensions — the renamed rule now covers <img>, <svg>, <video>, and <iframe> (was <img> and <svg> only).

Behaviour changes in existing rules

  • htmlacademy/a-target-rel — now requires only rel="noreferrer". Per the HTML spec, noreferrer implicitly enables noopener behaviour, so a single keyword covers both the privacy concern (no `Referer` header) and the security concern (no `window.opener`). Previously the rule required `rel="noopener noreferrer"`.
  • htmlacademy/req-webp-in-picture — now accepts image/avif as a modern alternative to image/webp inside <picture>.
  • htmlacademy/tag-forbid-attr — each forbidden entry now supports an optional value (string or RegExp). Attributes can now be forbidden only when their value matches a specific pattern (e.g. disallow type="text/css" on <link> while allowing other type values).
  • htmlacademy/no-px-size — extended to cover <video> and <iframe> in addition to <img> and <svg>. The error message now includes the offending tag name.
  • htmlacademy/aria-label-misusearia-label on <svg role="img"> (or role="image") is no longer flagged. Content SVG legitimately uses this pattern to expose its accessible name. Closes Проблема: aria-label-misuse не учитывает роли у svg #79.

Bug fixes in existing rules

The following rules existed in the previous release but were effectively non-functional. They were activated in the published config yet never reported anything — fixed in this release:

  • htmlacademy/attribute-allowed-values — the body accessed node.name.chars while node.name is a plain string. The condition node.name.chars in rule_config was always false, so the rule never executed. Now uses node.name.
  • htmlacademy/charset-position — the predicate !hasMeta && !hasUtf && !hasCharset reported only when all three flags were false, which meant <meta name="viewport"> (or any non-charset <meta>) was silently accepted as the first child of <head>. The rule now correctly requires the first element to be <meta> with a charset attribute.
  • htmlacademy/attr-req-value — crashed with a TypeError when activated without the ignore option. Empty ignore list is now assumed.
  • htmlacademy/input-req-label — issues reported via end() used the bare name input-req-label instead of the namespaced htmlacademy/input-req-label. Both code paths now use the namespaced name consistently.

Closes

@meritt

meritt commented Jan 25, 2026

Copy link
Copy Markdown
Member Author

@nikolai-shabalin ку-ку

Comment thread docs/CONTRIBUTING.md Outdated
Comment thread docs/list-of-rules.md Outdated
Comment thread rules/a-target-rel/index.js Outdated
Comment thread rules/a-target-rel/README.md Outdated
Comment thread rules/replaced-elements-req-dimensions/index.js
Comment thread rules/replaced-elements-req-dimensions/README.md
Comment thread rules/req-webp-in-picture/index.js
Comment thread CHANGELOG.md Outdated
Comment thread index.js Outdated
@meritt meritt merged commit 5ed204c into main May 20, 2026
1 check passed
@meritt meritt deleted the next branch May 20, 2026 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants