Runs automated HTML linting using axe-core (WCAG accessibility) and markuplint (HTML standards) CLI tools. Use when user asks to "lint HTML", "run automated checks", "validate HTML", "check accessibility with CLI", or mentions "axe-core", "markuplint", "automated audit".
This skill inherits all available tools. When active, it can use any tool Claude has access to.
configs/markuplintrc.jsonpackage.jsonscripts/lint-html.shscripts/run-axe.shscripts/run-markuplint.shAutomated HTML linting using axe-core and markuplint CLI tools with JSON output.
| Tool | Focus | Output |
|---|---|---|
| axe-core | WCAG 2.1 AA accessibility | JSON with violations |
| markuplint | HTML standards, semantics | JSON with problems |
Run the combined lint script:
bash scripts/lint-html.sh path/to/file.html
Or run tools separately:
# axe-core only (accessibility)
bash scripts/run-axe.sh path/to/file.html
# markuplint only (HTML standards)
bash scripts/run-markuplint.sh path/to/file.html
Tools are installed automatically via npx, but for better performance:
# Basic installation
npm install -g @axe-core/cli markuplint
# For JSX/TSX support (React projects)
npm install -D @markuplint/jsx-parser @markuplint/react-spec
| Extension | Parser | Notes |
|---|---|---|
.html | Built-in | No additional setup |
.jsx | @markuplint/jsx-parser | Requires react-spec |
.tsx | @markuplint/jsx-parser | Requires react-spec |
.vue | @markuplint/vue-parser | Requires vue-spec |
Copy this checklist:
Lint Progress:
- [ ] Step 1: Run combined lint script
- [ ] Step 2: Parse JSON results
- [ ] Step 3: Prioritize issues (critical → serious → moderate)
- [ ] Step 4: Apply fixes
- [ ] Step 5: Re-run to verify
bash scripts/lint-html.sh target.html
Output structure:
{
"file": "target.html",
"timestamp": "2025-01-01T00:00:00Z",
"axe": {
"violations": [...],
"passes": [...],
"incomplete": [...]
},
"markuplint": {
"problems": [...],
"passed": [...]
},
"summary": {
"axe_violations": 3,
"markuplint_problems": 5,
"total_issues": 8
}
}
{
"id": "color-contrast",
"impact": "serious",
"description": "Elements must have sufficient color contrast",
"nodes": [
{
"html": "<p class=\"light\">...</p>",
"failureSummary": "Fix: Increase contrast ratio to 4.5:1"
}
]
}
Impact levels: critical > serious > moderate > minor
{
"severity": "error",
"ruleId": "required-attr",
"message": "The \"alt\" attribute is required",
"line": 15,
"col": 5,
"raw": "<img src=\"photo.jpg\">"
}
Severity levels: error > warning
Common fix patterns:
<!-- Before -->
<img src="photo.jpg">
<!-- After -->
<img src="photo.jpg" alt="Description of image">
/* Before: #999 on #fff = 2.85:1 */
.text { color: #999; }
/* After: #595959 on #fff = 7:1 */
.text { color: #595959; }
<!-- Before -->
<div role="hamburger">
<!-- After -->
<button aria-label="Menu" aria-expanded="false">
bash scripts/lint-html.sh target.html
Goal: total_issues: 0 or only minor warnings.
# Specific WCAG tags
npx @axe-core/cli file.html --tags wcag21aa
# With rules
npx @axe-core/cli file.html --rules color-contrast,image-alt
# Disable rules
npx @axe-core/cli file.html --disable frame-title
# With config
npx markuplint file.html --config .markuplintrc
# Problem only (no passes)
npx markuplint file.html --problem-only
# JSON format
npx markuplint file.html --format JSON
Use configs/markuplintrc.json as a starting point:
{
"parser": {
"\\.[jt]sx$": "@markuplint/jsx-parser"
},
"specs": {
"\\.[jt]sx$": "@markuplint/react-spec"
},
"rules": {
"required-attr": true,
"deprecated-element": true,
"character-reference": true,
"no-refer-to-non-existent-id": true,
"class-naming": false,
"attr-duplication": true,
"id-duplication": true
}
}
Copy to your project root:
cp configs/markuplintrc.json .markuplintrc
{
"rules": {
"color-contrast": { "enabled": true },
"image-alt": { "enabled": true }
}
}
If a tool fails:
# Debug axe-core
npx @axe-core/cli file.html --verbose
# Debug markuplint
npx markuplint file.html --verbose
Sources: