comark-linter
Vite Doctor
Lint a project's Markdown as part of Vite Doctor, with one code per rule.
comark-linter/doctor is a Vite Doctor extension. Vite Doctor loads extensions from an executable config, so register it in doctor.config.ts:
// doctor.config.ts
import comark from "comark-linter/doctor";
import { defineDoctorConfig } from "vite-doctor/config";
export default defineDoctorConfig({
extends: ["comark/recommended"],
extensions: [comark({ components: ["duck-count"] })],
});pnpm vite-doctor . --config doctor.config.tsIt runs whenever the extension is registered, and the comark/recommended preset turns every rule on. It needs vite-doctor 0.1 or later.
Options
Section titled "Options"It takes the same options as the command line's config, plus two of its own:
| Option | |
|---|---|
include |
The Markdown to check, relative to the project root. Default **/*.{md,mdc}. |
exclude |
Globs to skip. Default **/node_modules/** and **/dist/**. |
Links resolve from the project root, and files are read through Vite Doctor's read-only ctx.fs, so its cache knows which files a result depends on. comark/dead-url is marked env-dependent, since its result depends on the network; the URL cache is still written to node_modules/.cache/comark-linter/ with node:fs, because ctx.fs can't write.
This site lints its own pages this way. Its docs/build.ts renders a few components itself, so the config names them, and its routes mirror the pages' URLs:
// doctor.config.ts
export default defineDoctorConfig({
extends: ["comark/recommended"],
extensions: [
comark({
include: "{docs/pages,packages/*/docs}/**/*.md",
components: ["demo", "drop", "example", "examples", "hero", "matrix", "packages"],
links: {
// A package's pages come from its docs/, the rest from docs/pages, and files from docs/public.
routes(path) {
const [first = "", ...rest] = path.split("/").filter(Boolean);
if (first === "play") return true;
if (existsSync(`packages/${first}/docs/index.md`))
return `packages/${first}/docs/${rest.join("/")}`;
return /\.\w+$/.test(path) ? `docs/public${path}` : `docs/pages${path}`;
},
},
}),
],
});Each rule reports with its own code, and the code links to the rule's page in Doctor. The core rules start at COMARK0001, and each package's rules get a hundred codes of their own. comark-annotate's start at COMARK0101, comark-cards' at COMARK0201, and so on.
Frontmatter Comark can't read and unsafe URLs are errors. The rest are warnings. Doctor's overview lists every code.