Skip to main content

Rule renames and splits

Master reference for rule-name changes with a stable v4 lineage (v4.18.3). Option-format changes beyond a rename or split are on the per-rule pages under rules/. ARIA version and wai-aria option mapping: ARIA.

v5 redoes the catalog: verb-prefix names, one rule per independent check, and spec-conformance metadata. v4's 38 built-in rules become 106 in v5. Of that: 12 were renamed, 10 were split, wai-aria became 21 independent rules, and the rest are new checks with no v4 predecessor.

Old names that were renamed or split keep working: Markuplint reports a deprecation warning and expands the config. Those aliases are removed in v6. Names that did not change have no alias — see Known migration gap.

Categories​

v4 used five categories (validation, a11y, naming-convention, maintainability, style). v5 uses nine, from each rule's meta.ts category. Categories are a browsing aid on the rules index; they do not appear in config files.

CategoryWhat it covers
syntaxParse-level conformance
structureContent model, ancestors, doctype, table model
attributesAttribute name/value conformance
referencesID and fragment references
formsForm-control checks
a11yARIA and accessibility
styleOpinionated formatting/naming
maintainabilityProject hygiene
compatbrowserslist × BCD, experimental/non-standard flags

naming-convention (only class-naming) folds into style.

1:1 renames​

These 12 names existed in stable v4 and map 1:1:

Old name (v4)New name
attr-duplicationno-duplicate-attr
id-duplicationno-duplicate-id
required-attrrequire-attr
required-elementrequire-element
ineffective-attrno-ineffective-attr
end-tagrequire-end-tag
disallowed-elementno-restricted-element
heading-levelsno-skipped-heading-level
neighbor-popoversrequire-adjacent-popover
no-hard-code-idno-hardcoded-id
no-use-event-handler-attrno-event-handler-attr
use-listno-pseudo-list

required-attr → require-attr keeps { name, value } matching. See Scope changes.

Splits​

These 10 names existed in stable v4. Each split is independently configurable.

Old name (v4)Split intoWhat each checks
invalid-attrno-unknown-attrName not defined by the spec
no-disallowed-attrName defined but disallowed here (noUse, unmet condition, is on an autonomous custom element)
no-invalid-attr-valueValue type/grammar
no-restricted-attrUser disallowAttrs only — omitted from the alias unless disallowAttrs was set
doctyperequire-doctypeMissing DOCTYPE
no-obsolete-doctypeLegacy public/system identifier (about:legacy-compat still allowed). Omitted if denyObsoleteType was false
character-referenceno-malformed-character-referenceMalformed character references
no-unescaped-charUnescaped < / ambiguous &
deprecated-attrno-obsolete-attrHTML LS obsolete attributes (error)
no-deprecated-attrMDN/BCD deprecated attributes (warning)
deprecated-elementno-obsolete-elementObsolete elements (error)
no-deprecated-elementDeprecated elements (warning)
landmark-rolesno-nested-top-level-landmarkNested banner / main / contentinfo (ignoreRoles carried over)
require-landmark-labelDuplicate landmark without an accessible name. Omitted if labelEachArea was false
no-refer-to-non-existent-idno-refer-to-non-existent-idDOMID / ARIA ID-reference (name unchanged — gap)
no-broken-fragment-linka[href] / area[href] fragment (fragmentRefersNameAttr moved here)
permitted-contentspermitted-contentsChild content model (name unchanged — gap)
no-disallowed-ancestorforbiddenAncestors
require-ancestordescendantOf
no-duplicate-sibling-attrSibling-unique attributes (e.g. track[default])
required-h1require-h1Missing <h1>
no-duplicate-h1Duplicate <h1>. Omitted if expected-once was false
table-row-column-alignmentno-table-cell-overlapCell overlap (error)
no-table-span-overflowSpan past row-group/table (error)
no-empty-table-trackRow/column with no anchored cell (error)
consistent-table-row-lengthRagged column count (warning)

aria-* and role are exempt from the three spec-checking invalid-attr successors; ARIA rules own them.

Option-routed splits​

Most splits copy the old setting to every successor. These do not:

  • doctype: drop no-obsolete-doctype when denyObsoleteType was false.
  • landmark-roles: drop require-landmark-label when labelEachArea was false.
  • required-h1: drop no-duplicate-h1 when expected-once was false.
  • invalid-attr: add no-restricted-attr only when disallowAttrs was set. Option routing: invalid-attr.

The alias does this automatically. Hand-written configs should match that routing.

New in v5 (no v4 equivalent)​

These checks have no v4 rule to migrate from. Presets may enable some of them (see Preset changes).

attr-order, form-attr-references-form, head-element-order, input-list-references-datalist, itemprop-requires-itemscope, label-for-references-labelable, label-no-multiple-controls, link-types, map-id-name-match, meta-charset-position, meter-value-bounds, no-always-matching-source, no-aria-hidden-on-hidden-until-found, no-content-after-body, no-duplicate-autofocus, no-duplicate-visible-main, no-experimental-features, no-extra-selected-options, no-input-file-value, no-mismatched-aspect-ratio, no-mixed-srcset-descriptors, no-nonstandard-features, no-redundant-accessible-name, no-stray-head-or-body-tag, no-unclosed-element-at-eof, no-unpaired-srcset-sizes, no-unsupported-browser-features, progress-value-bounds, require-dialog-autofocus, sizes-auto-requires-lazy-loading, usemap-references-map, valid-importmap, valid-speculation-rules.

label-no-multiple-controls is new as a rule name, but the check lived inside v4 label-has-control — Known migration gap.

Two ARIA rules (require-parent-role, tab-requires-tabpanel) are also new relative to the v4 wai-aria implementation; they still receive the wai-aria alias. See ARIA.

Deletions​

Only wai-aria is removed as a rule name. The alias expands it to 21 successors until v6. There is no other v4 built-in rule deletion.

Scope changes​

  • require-attr: full v4 required-attr scope, including { name, value } patterns.
  • label-has-control: only reports a <label> with no associated control. Reporting a second descendant control is label-no-multiple-controls.

Known migration gap​

danger

These old names are not deprecated (they still exist), so there is no alias warning. A raw config that enabled only the old name silently drops the split-off check.

v4 name you still useSplit-off rules you must add yourself
permitted-contentsno-disallowed-ancestor, require-ancestor, no-duplicate-sibling-attr
no-refer-to-non-existent-idno-broken-fragment-link
label-has-controllabel-no-multiple-controls

Preset users: markuplint:html-standard already enables the permitted-contents siblings and label-no-multiple-controls. markuplint:a11y enables no-broken-fragment-link and label-has-control. markuplint:recommended extends both.

Gaps that remain even with presets:

  • Extending markuplint:html-standard alone does not enable no-broken-fragment-link (it is only in a11y), while it does enable no-refer-to-non-existent-id.
  • Extending markuplint:a11y alone does not enable label-no-multiple-controls (it is only in html-standard), while v4 a11y ran that check inside label-has-control.

Severity changes​

Compared to the v4 default (createRule defaults to error unless defaultSeverity is set):

Rulev4v5
no-table-cell-overlap / no-table-span-overflow / no-empty-table-trackwarning (as table-row-column-alignment)error
consistent-table-row-lengthwarning (same compound rule)warning
no-duplicate-dterrorwarning
no-obsolete-attr / no-obsolete-elementerror (as deprecated-attr / deprecated-element)error
no-deprecated-attr / no-deprecated-elementerror (same compound rules)warning
no-broken-fragment-linkerror (as part of no-refer-to-non-existent-id)warning
require-h1 / no-duplicate-h1error (as required-h1)warning
require-adjacent-popovererror (as neighbor-popovers)warning

no-consecutive-br stays warning (false positives on legitimate line breaks).

caution

The three table-model errors can fail CI that treats errors as fatal, on markup that only warned in v4.

Preset changes​

Verified against v4.18.3 preset JSON and current preset.*.jsonc.

  • markuplint:code-styles was {} in v4. It now enables case-sensitive-attr-name and case-sensitive-tag-name.
  • markuplint:security was {} in v4. It now enables no-event-handler-attr.
  • markuplint:compat did not exist in v4. v5's markuplint:recommended extends it, enabling no-unsupported-browser-features and no-nonstandard-features (no-experimental-features stays opt-in).
  • markuplint:performance gains head-element-order and no-mismatched-aspect-ratio. Its nodeRules (charset, defer, img dimensions, iframe loading) are unchanged in substance.
  • markuplint:html-standard drops no-duplicate-dt and no-ineffective-attr (both were on in v4). It adds no-unknown-attr / no-disallowed-attr / no-invalid-attr-value — v4's html-standard did not include invalid-attr. It also adds many new MUST checks (parse structure, srcset, forms, itemprop-requires-itemscope, and the permitted-contents siblings).
  • markuplint:a11y still includes wai-aria coverage, now as named groups. That enables checks the v4 umbrella left off by default, plus two checks the v4 umbrella never ran. See ARIA.
  • no-refer-to-non-existent-id and no-duplicate-id remain in both a11y and html-standard.
  • markuplint:recommended still extends code-styles, html-standard, a11y, performance, security, and rdfa, and now also compat.

Rules intentionally in no preset: attr-order, attr-value-quotes, class-naming, no-boolean-attr-value, no-default-value, no-empty-palpable-content, no-duplicate-dt, no-ineffective-attr, no-experimental-features.