markuplint-setup
Set up Markuplint in a project from scratch.
When to Use
- "Set up markuplint" / "Add markuplint to this project"
- "I want to lint my HTML"
- "Install markuplint"
Steps
1. Check Existing Installation
- Check for and packages
- Check for config files (, )
- If already installed, tell the user and suggest instead
2. Detect Project Type
Scan the project:
- Package manager: check for / /
- Framework: check dependencies for , , , , , etc. Also check file extensions (, , , , , , )
- Monorepo: check for in or / /
3. Choose Preset and Packages
Use
to get the latest supported syntaxes and preset information:
Use AskUserQuestion to confirm:
- Detected framework — is it correct?
- Which preset to use? (recommend based on framework)
4. Install Packages
Install using the detected package manager. Example:
shell
npm install -D markuplint @markuplint/jsx-parser @markuplint/react-spec
Do NOT use — it requires interactive terminal input.
5. Create Configuration File
Write
directly. Keep it minimal — only include what's needed for the detected framework.
Static HTML needs no
or
:
json
{
"extends": ["markuplint:recommended"]
}
Framework projects need parser and spec:
json
{
"extends": ["markuplint:recommended-react"],
"parser": {
"\\.[jt]sx$": "@markuplint/jsx-parser"
},
"specs": {
"\\.[jt]sx$": "@markuplint/react-spec"
}
}
Refer to
https://markuplint.dev/docs/guides/beyond-html for the exact parser/spec package names and file patterns for each framework.
When to use JavaScript/TypeScript config
If the project uses external config plugins or shared configs that require fine-grained merging, recommend
(or
) with spread syntax — similar to ESLint's flat config pattern:
ts
import type { Config } from '@markuplint/ml-config';
import reactConfig from '@example/markuplint-config-react';
const config: Config = {
...reactConfig,
rules: {
...reactConfig.rules,
'class-naming': '/^[a-z][a-z0-9-]*$/',
},
};
export default config;
This gives full control over merge order and avoids the limitations of JSON
(which uses a fixed merge strategy). Use JSON for simple setups; use JS/TS when composing multiple configs.
6. Run Initial Lint
Run Markuplint and capture the results:
shell
npx markuplint "$ARGUMENTS" --format JSON
If
is empty, ask the user for the target glob (e.g.,
).
Summarize:
- Total violation count
- Breakdown by rule (which rules have the most violations)
- Whether violations are concentrated in specific files/directories
7. Rule-by-Rule Adoption Decision
Use AskUserQuestion for each rule that has violations. Present rules one at a time (or batch related rules).
For each rule, explain what it checks (fetch the rule page if needed:
https://markuplint.dev/docs/rules/{rule-id}
) and offer options:
- Keep as error — fix all violations now
- Downgrade to warning — keep but don't block CI
- Bulk suppress — record current violations, enforce only on new code
- Disable — turn off the rule
When to recommend Bulk Suppressions:
- Many violations in legacy code that won't be touched soon
- The rule is valuable for new code
When to recommend disabling:
- The rule doesn't fit the project's architecture or conventions
- The rule conflicts with a template engine being used
8. Apply Decisions
- Update with disabled/warning rules
- If Bulk Suppressions were chosen, run:
npx markuplint "$TARGET" --suppress
- Tell the user to commit
markuplint-suppressions.json
9. Add npm Script
json
{
"scripts": {
"lint:html": "markuplint \"src/**/*.html\""
}
}
Adjust the glob to match the project's source files and framework extensions.