Skip to content

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

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

v2.0.0: Update rules to match HTML Academy codeguide#28
meritt merged 21 commits into
mainfrom
next

Conversation

@meritt

@meritt meritt commented Jan 25, 2026

Copy link
Copy Markdown
Member

Synchronised with linthtml-rules-htmlacademy#115 and codeguide#75. This is the config side of the joint 2.0.0 release — what the default preset now expects from HTML.

The package has been migrated to ESM (type: "module", configuration file renamed index.jslinthtml.config.js). Node.js requirement is now >=24. Everything below describes how the default preset has changed.

Newly activated rules

Ten plugin rules joined the preset, expanding its coverage of forms, accessibility, and modern HTML:

  • htmlacademy/a-target-rel<a target="_blank"> must declare rel="noreferrer". Per the HTML spec, noreferrer implicitly enables noopener, so one keyword covers both privacy (no Referer header) and security (no window.opener).
  • htmlacademy/attr-order — enforces the codeguide attribute order `class → src/href → data-* → others`.
  • htmlacademy/boolean-attr-no-value — boolean attributes (disabled, checked, required, autofocus, hidden, open, async, defer, autoplay, controls, loop, muted, …) must be written without a value. <input disabled> — yes, <input disabled="disabled"> — no.
  • htmlacademy/heading-level — heading levels must not skip (<h1><h3> is flagged) and the document must start with <h1>.
  • htmlacademy/icon-button-aria-label<button> without visible text must declare an accessible name via aria-label, aria-labelledby, or title.
  • htmlacademy/input-name-unique — duplicate <input name> within the same <form> is flagged; radio and checkbox groups are exempt.
  • htmlacademy/label-req-for — every <label> must be associated with a form control either through for/id or through a nested control.
  • htmlacademy/label-req-text<label> must contain visible text content (or aria-label). Closes the <label for="x"><input id="x"></label> no-text loophole.
  • htmlacademy/req-submit-button — every <form> must contain a submit button.
  • htmlacademy/svg-role-img — inline <svg> must declare itself either as content (role="img" + aria-label/aria-labelledby) or as decorative (aria-hidden="true").
  • htmlacademy/tag-forbid-attr activated with the redundant-type rule: <link type="text/css"> and <script type="text/javascript"> are flagged (these HTML4 defaults have not been required since HTML5).

Replaced / removed

  • htmlacademy/img-svg-req-dimensionshtmlacademy/replaced-elements-req-dimensions — the renamed rule now covers <img>, <svg>, <video>, and <iframe>.
  • htmlacademy/class-first removed from the preset — fully subsumed by htmlacademy/attr-order (which checks the full attribute order, not only the position of class).
  • button-req-content (base linthtml rule) removed from the preset — replaced by htmlacademy/icon-button-aria-label, which is broader: it recognises aria-label, aria-labelledby, and title, not just text content or aria-label. Eliminates the duplicate report on empty/icon-only buttons.

Configuration adjustments to existing rules

  • htmlacademy/attribute-allowed-values.input.type — whitelist expanded from 11 to 22 entries, covering every HTML5 <input type> value. The previous list was effectively a no-op because the rule itself was broken in the previous release (see linthtml-rules-htmlacademy#115); now that the rule actually executes, the policy is to allow every spec value and rely on other rules for narrower constraints.
  • htmlacademy/tag-req-attr.form — added requirement for the method attribute on <form>. Forms must now declare method="get" or method="post".
  • htmlacademy/tag-self-close — set to [true, 'never']. In the previous release the rule was activated as true (no option), which left it silent due to a missing-option early return in the rule body. The preset now actually flags <br/>, <img/>, and similar void self-closers.
  • htmlacademy/no-px-size — extended to <video> and <iframe> (was <img> and <svg> only).
  • htmlacademy/charset-position — fixed so it actually requires the first <head> child to be <meta charset>. Previously any first <meta> (e.g. <meta name="viewport">) passed silently because of inverted logic.
  • htmlacademy/aria-label-misusearia-label on <svg role="img"> is no longer flagged. Content SVG legitimately uses this pattern.
  • attr-name-ignore-regex (top-level option) — expanded to cover 42 camelCase SVG attributes (viewBox, preserveAspectRatio, xlink:href, gradientTransform, patternUnits, markerWidth, attributeName, stdDeviation, baseFrequency, …). Without this, the attr-name-style: dash rule reports valid SVG markup. Closes Актуализировать список атрибутов исключений SVG #19.
  • htmlacademy/tag-name-lowercase.ignore — expanded to all SVG filter primitives (feBlend, feColorMatrix, feGaussianBlur, …) and other camelCase SVG tags (foreignObject, animateTransform, animateMotion).

Behavioural summary

What used to pass on main but no longer passes:

<a href="/x" target="_blank">External</a>            <!-- needs rel="noreferrer" -->
<form action="/api"><input type="text"></form>      <!-- needs method + submit -->
<button type="button"><svg></svg></button>           <!-- needs aria-label -->
<h1>x</h1><h3>y</h3>                                <!-- no heading-level skip -->
<input type="checkbox" checked="checked">            <!-- write just "checked" -->
<label for="q"><input id="q"></label>               <!-- label needs visible text -->
<svg width="20" height="20"></svg>                    <!-- needs role or aria-hidden -->
<input type="text" name="q"><input name="q">      <!-- duplicate non-radio name -->
<br/>                                               <!-- void elements must not self-close -->
<link rel="stylesheet" href="s.css" type="text/css"> <!-- redundant type -->

What used to fail on main but now passes:

<picture><source type="image/avif" srcset="p.avif"><img src="p.jpg"></picture>
<!-- AVIF is now an accepted modern alternative to WebP in <picture> -->

Cleanup

linthtml.config.js was rewritten as a clean default preset. Dead *: false entries for base rules that simply are not listed (linthtml ignores unlisted rules), redundant top-level options (id-class-ignore-regex, line-max-len-ignore-regex, stray spec-char-escape), and explanatory comments were removed. SVG tag/attribute lists and the input-type whitelist were extracted into named constants. Rules are sorted alphabetically inside each block. The file went from 180 to 116 lines.

Closes

@meritt

meritt commented Jan 25, 2026

Copy link
Copy Markdown
Member Author

@nikolai-shabalin ну гулять дк гулять

Comment thread index.js Outdated
'rules': {
'htmlacademy/space-between-comments': [true, 'space'],
'htmlacademy/a-target-rel': true,
'htmlacademy/a-target-rel': false, // browsers add rel="noopener" automatically since 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вернуть как было

Comment thread .github/ISSUE_TEMPLATE/bugreport.yml Outdated
Comment thread .github/ISSUE_TEMPLATE/config.yml Outdated
Comment thread .github/ISSUE_TEMPLATE/new-rule.yml Outdated
Comment thread linthtml.config.js Outdated
Comment thread package.json
"linthtml"
],
"license": "MIT",
"author": {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Авторов можно указать несколько в массиве через запятую

@meritt meritt merged commit a4c992c into main May 20, 2026
1 check passed
@meritt meritt deleted the next branch May 20, 2026 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Актуализировать список атрибутов исключений SVG

2 participants