{"_id":"@redocly/recheck","_rev":"17-5ff25926b7b1ee9059c5a94d4f5fc96a","name":"@redocly/recheck","dist-tags":{"latest":"0.14.0"},"versions":{"0.1.0":{"name":"@redocly/recheck","version":"0.1.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.1.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"},{"name":"slavikbezkorovainyi","email":"slavik@redocly.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"4523774b60ea4c7eaf9f8983c148f8ca857beed0","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.1.0.tgz","fileCount":182,"integrity":"sha512-slqUn0nom28+/8T3JMwF8bNopWNbkf0SnVR+SLq98fy3QbPh0iI1uS4pTVznueU7A+gGwnGrVhToJiqsG9sHYQ==","signatures":[{"sig":"MEUCIDeOTXv3cbenlnF97MfWO+PHiYvyp2dSkOw5wC/UV9M6AiEAoUYleXZl4Lk1PDQe5ai7RAUylyoyscod7VRJQmXNILM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":253173},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.1.0.tgz","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","start":"node dist/cli.js","validate":"node dist/cli.js validate","test:watch":"vitest"},"_npmUser":{"name":"adamaltman","email":"adam@rebilly.com"},"_resolved":"/private/var/folders/7_/cgg9kk4977987pv5x6nt90280000gn/T/db588d6d46bac4c2475abd9215ba016d/redocly-recheck-0.1.0.tgz","_integrity":"sha512-slqUn0nom28+/8T3JMwF8bNopWNbkf0SnVR+SLq98fy3QbPh0iI1uS4pTVznueU7A+gGwnGrVhToJiqsG9sHYQ==","_npmVersion":"10.9.4","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"22.21.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.1.0","colorette":"2.0.20","picomatch":"2.3.1","ajv-formats":"^2.1.1","@redocly/ajv":"8.11.4"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.1.1","typescript":"5.9.3","@types/node":"22.18.13","@types/yargs":"^17.0.32","@types/js-yaml":"^4.0.9","@types/picomatch":"2.3.4","@vitest/coverage-v8":"^3.1.1"},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.1.0_1765887049501_0.8122589797569268","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@redocly/recheck","version":"0.2.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.2.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"a42df69ceea440cf4647bbcc7836ad84298e142b","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.2.0.tgz","fileCount":578,"integrity":"sha512-q33AXl46yf4DCN2YVh25I8uKstFfG7ngInWvWyK+wp6UrHU2SFbYsQ0z21m0vHJqHOXee1iayJ7qTVc0roYiZQ==","signatures":[{"sig":"MEUCIQCrUcHpQBoFcnnGoJLmpUfQDq2Ic+8oWtSrgMK5nK6OeQIgW11YnR+QSNoihqLLuQnedKKYnINEtNB4L/ALVH4aTjM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2198548},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.2.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/cfa511c3b487123a7e05fa8d55c09044/redocly-recheck-0.2.0.tgz","_integrity":"sha512-q33AXl46yf4DCN2YVh25I8uKstFfG7ngInWvWyK+wp6UrHU2SFbYsQ0z21m0vHJqHOXee1iayJ7qTVc0roYiZQ==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.0","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.68.0-next.5","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.2.0_1785979925811_0.5974523629364346","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@redocly/recheck","version":"0.3.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.3.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"72887bdd9207b2658f873c3fceae76e828f0e44f","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.3.0.tgz","fileCount":578,"integrity":"sha512-nG77AuOa/omwq+WLLfvg/407jGB2vUjYiS8GZ8yK/GE7nNYumZkgi9svqXDLJ9jFYTc5v9hRn8I6DLuVRH8yHQ==","signatures":[{"sig":"MEYCIQD/LcHuywGdOa5NPbeCmCSq7bA1cUBBWNh3tEE6SKHXlAIhAOnSNFvyHiT1x8pUIX+GMBShfDavMZRn7+vSNXRmZwst","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2199267},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.3.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/9f9d402201cb7fc3bedf581e00e4dcd7/redocly-recheck-0.3.0.tgz","_integrity":"sha512-nG77AuOa/omwq+WLLfvg/407jGB2vUjYiS8GZ8yK/GE7nNYumZkgi9svqXDLJ9jFYTc5v9hRn8I6DLuVRH8yHQ==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.0","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.68.0-next.8","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.3.0_1786434444778_0.20595655831464166","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@redocly/recheck","version":"0.4.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.4.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"61d382b04d0078592d3b85b9df04fbd1e880160c","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.4.0.tgz","fileCount":578,"integrity":"sha512-e1pV3NQRsbGgaogiMqKZA+Ibcv5qfA1Mi5iu7ewY0KqjLE5AlvX1r+BdlbrV+hVsxbk/BJ/yJiMwOpJgotVmvA==","signatures":[{"sig":"MEQCIBSJhBkh6emAHGDfnHVVMtD2sXsfvCV9CXT3toqqgp+NAiBlY+sltZZB/ke3Ia4ab5zLB2GL5UHtD3M6wrUOUOle0Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2204519},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.4.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/9e1bd2853af8990e8dac5a3983499086/redocly-recheck-0.4.0.tgz","_integrity":"sha512-e1pV3NQRsbGgaogiMqKZA+Ibcv5qfA1Mi5iu7ewY0KqjLE5AlvX1r+BdlbrV+hVsxbk/BJ/yJiMwOpJgotVmvA==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.68.0","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.4.0_1786632579895_0.8237892719078701","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@redocly/recheck","version":"0.4.1","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.4.1","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"c8ae0fef63f81f596e19ef2f733542b5012f0baa","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.4.1.tgz","fileCount":578,"integrity":"sha512-9v4QDxRJHKaLJUdFzN8lsmUXIUZDtXdI6VWM7S1BE05+YQIy+o7t8QOSovovWfjPa0xGf5YgQAWoZMKmX6kDuA==","signatures":[{"sig":"MEQCIH05y2KeDBuZoj6cmXVCDSQZ4dmPfa00kvv+2B6wQkroAiAOADOd46bifJI4EY/3L6mFUh6vE35NJCIg/OzQ7rINGw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2207300},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.4.1.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/b6bcf6cff84bc73a7c5d00d43176aabd/redocly-recheck-0.4.1.tgz","_integrity":"sha512-9v4QDxRJHKaLJUdFzN8lsmUXIUZDtXdI6VWM7S1BE05+YQIy+o7t8QOSovovWfjPa0xGf5YgQAWoZMKmX6kDuA==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.0","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.4.1_1786957629625_0.24193104336263604","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@redocly/recheck","version":"0.5.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.5.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"ad84c42aa4b1ef1b25b3c80cde93fa49ad16a7dd","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.5.0.tgz","fileCount":598,"integrity":"sha512-PGLOqpWENg7EXMJEn6cQxjP5Jzo5uknnuQaUsUuX4W4Oc0y+E7TsPAuXbM1pM/dRHdaGcMTwQPTZ1z0RdCe4Ow==","signatures":[{"sig":"MEUCIQCeB3gsWlRzP56Gt0q33Qa6mmxorHOWXZYH2ZDjywwtMAIgZAOa7IS7sqkS+Yq2LZuAYUThnwvXvDunDHYtM9tQ6wM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2264012},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.5.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/e8888c92afd4e7c52a48ee840be0cbc5/redocly-recheck-0.5.0.tgz","_integrity":"sha512-PGLOqpWENg7EXMJEn6cQxjP5Jzo5uknnuQaUsUuX4W4Oc0y+E7TsPAuXbM1pM/dRHdaGcMTwQPTZ1z0RdCe4Ow==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.0","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.5.0_1787011098319_0.21046696982421453","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@redocly/recheck","version":"0.6.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.6.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"e4b6f2dbb8e32f6bcfc0a6354088d1b1f16acb96","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.6.0.tgz","fileCount":598,"integrity":"sha512-1VwbzmHmzjgedmkSYbwsjRJTBxeEM9zY2wvE62buYwPvtPj3gWudvDdugy2JazdtdmkkBICOUNGdPoYrT7oLNg==","signatures":[{"sig":"MEQCIGh1drSBo0M8LeBOQUEcosrqsvTdHT57yiTtQT9sm9gEAiB1mvUMsGo+jI85uwNb8aB9BlbX7+FmHrnvUHLk8EEyjw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2266585},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.6.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/5804aa1fdd3d772a22abb9f58557f6d5/redocly-recheck-0.6.0.tgz","_integrity":"sha512-1VwbzmHmzjgedmkSYbwsjRJTBxeEM9zY2wvE62buYwPvtPj3gWudvDdugy2JazdtdmkkBICOUNGdPoYrT7oLNg==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.1","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.6.0_1787110067506_0.26718474628971034","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@redocly/recheck","version":"0.7.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.7.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"1b9baed1b0750b898bf90f632baf6bc14a5e7fb3","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.7.0.tgz","fileCount":602,"integrity":"sha512-bKRncSLv2/UrsaGQb30tNb59s/4BuR0BUgqk9R5y6p2eSwfb6cSXDrvbw5Kklq7vCfI35RglvEHzYbKFvgVXNg==","signatures":[{"sig":"MEQCIC9p7wajfjz3NVyxFq2yyq/GVzRYBcId+Kn9l5pSCSSPAiAembUeUZtLPum5TEOCCUdFa/SL0Ha2ZgQEPMK5Egn7gA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2280259},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.7.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/e067ba720bebca07e93da9fe8a2db358/redocly-recheck-0.7.0.tgz","_integrity":"sha512-bKRncSLv2/UrsaGQb30tNb59s/4BuR0BUgqk9R5y6p2eSwfb6cSXDrvbw5Kklq7vCfI35RglvEHzYbKFvgVXNg==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.1","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.7.0_1787123375904_0.45646369660615504","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@redocly/recheck","version":"0.8.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.8.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"c0468bbc04aed6fb500406b5cf4a864acaaf6be2","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.8.0.tgz","fileCount":604,"integrity":"sha512-nNrJUiqSEun7W1humBGMqnzjbuCn1oXVro75vZNxVcbTjQhtdDEafDun0WHceApwJFbg0nSRkSLi1vjsNbDvCQ==","signatures":[{"sig":"MEQCIBAs+CyqqUhAHkzNqhSWHTYLjuJLUQZT7VK7TscADKdGAiBllIIGxX85Egf2Uc2DQxjOnzFYrIko44j9klSDJqO/Fw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2292501},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.8.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/8037f2673e12cf1e9cbbd099226d1116/redocly-recheck-0.8.0.tgz","_integrity":"sha512-nNrJUiqSEun7W1humBGMqnzjbuCn1oXVro75vZNxVcbTjQhtdDEafDun0WHceApwJFbg0nSRkSLi1vjsNbDvCQ==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.2","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.8.0_1787201417363_0.043016086179250346","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"@redocly/recheck","version":"0.9.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.9.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"05a218513174e0b8c8f4ebd2b7cd050fc19a15c9","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.9.0.tgz","fileCount":611,"integrity":"sha512-5equ45Yc/qBcd/gK4Rch5u7o17kzHcHR2mCnbOONhlZo1JMkgpV0PfI+S5TsrzTA80VuVnhw08bZ3iIPN/0PTA==","signatures":[{"sig":"MEYCIQDt2hIoklBMIzpAflWDsoFGx2CF0gb3BBqrW9ebPBTkAwIhAKKD8Y6lzhg0Akb8al+lcR/0Q9Y7OtnkqbRCBgaA6/OX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2313462},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.9.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js validate","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/196568b2f7908343c8e347b77897ed0b/redocly-recheck-0.9.0.tgz","_integrity":"sha512-5equ45Yc/qBcd/gK4Rch5u7o17kzHcHR2mCnbOONhlZo1JMkgpV0PfI+S5TsrzTA80VuVnhw08bZ3iIPN/0PTA==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.2","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.9.0_1787240182834_0.47865883142370835","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"@redocly/recheck","version":"0.10.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.10.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"nx":{"targets":{"vitest:test":{"dependsOn":["build"]}}},"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"15e34a9e9974b80f7b9dfaca08d64f9ae410e751","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.10.0.tgz","fileCount":611,"integrity":"sha512-lpjPssA2mQqsHw26rK4U9Sf75lFi2E+TXOhlsi6YzgDRcHSzQSUz4Foqpn+gNm70gWOZqLujjh0Jqp6T4DGHtQ==","signatures":[{"sig":"MEUCIBUvaZA+PTiJlEGZ0S0FvS4c52KAWcZ0QVXAWpHvpQlHAiEAiF8yCk3ONiL9Cb4YY9EHx/jxasLqWqhYK9LvDFOuR20=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2326603},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.10.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js --validate-config","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/0f160cab60842d9f0522e01b33933144/redocly-recheck-0.10.0.tgz","_integrity":"sha512-lpjPssA2mQqsHw26rK4U9Sf75lFi2E+TXOhlsi6YzgDRcHSzQSUz4Foqpn+gNm70gWOZqLujjh0Jqp6T4DGHtQ==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.4","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.10.0_1787763682329_0.25173988480570975","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"@redocly/recheck","version":"0.11.0","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.11.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"nx":{"targets":{"vitest:test":{"dependsOn":["build"]}}},"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"c7641e9efe4ea0ef73d627083e5c820fd989384e","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.11.0.tgz","fileCount":615,"integrity":"sha512-JYzPvU/e9IiljFuaQLsC8DHxVsYv5d4YAlyg9XRX8ta3mZUQNajSUHEgy/Y4XalbNJFyCyg5uUaNC5BwKvE3sg==","signatures":[{"sig":"MEUCICKryWV65YL6LXh/7vvau7bMubNbnvXw2t+8q4zq0artAiEA57pDdsOSLG0To3Qu2F9O84Iosmi7zovrAsFVMKn70r8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2337849},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.11.0.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js --validate-config","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/dc9cd21c4e06e8567e15944b0eaa86f9/redocly-recheck-0.11.0.tgz","_integrity":"sha512-JYzPvU/e9IiljFuaQLsC8DHxVsYv5d4YAlyg9XRX8ta3mZUQNajSUHEgy/Y4XalbNJFyCyg5uUaNC5BwKvE3sg==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.5","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.11.0_1787839155805_0.5175467501612601","host":"s3://npm-registry-packages-npm-production"}},"0.11.1":{"name":"@redocly/recheck","version":"0.11.1","keywords":["content","linting","markdown","documentation"],"author":{"name":"Redocly"},"license":"MIT","_id":"@redocly/recheck@0.11.1","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"nx":{"targets":{"vitest:test":{"dependsOn":["build"]}}},"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"9bcdd8220ff79e69ec4660aa84a03450edcc5631","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.11.1.tgz","fileCount":615,"integrity":"sha512-FBe78GY4wF7BM8HZnl6oFNSeI+38dTQLZtPcZu1MyQ4wuB3MvOdZLeKtmqAakOWHek+V1Won9j2J+KiqdXjvMA==","signatures":[{"sig":"MEQCIFL5tQEYfiPAWjx9afncSgilGtCOep22c8l3Liv3YxqOAiBV2S6SP5VMq+4A9+JjI4cVGetnitTiycNKSkGY+KaBVw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2338827},"main":"dist/index.js","type":"module","_from":"file:redocly-recheck-0.11.1.tgz","types":"./dist/index.d.ts","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js --validate-config","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"_resolved":"/tmp/c7ce196a4dd55abebb0963a83441ab2d/redocly-recheck-0.11.1.tgz","_integrity":"sha512-FBe78GY4wF7BM8HZnl6oFNSeI+38dTQLZtPcZu1MyQ4wuB3MvOdZLeKtmqAakOWHek+V1Won9j2J+KiqdXjvMA==","_npmVersion":"11.16.0","description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.5","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.10","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.11.1_1788201263205_0.53740361562908","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"@redocly/recheck","version":"0.12.0","keywords":["content","linting","markdown","documentation"],"author":"Redocly","license":"MIT","_id":"@redocly/recheck@0.12.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"nx":{"targets":{"vitest:test":{"dependsOn":["build"]}}},"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"ce40226d02c70409622e1c1dc4470dd27074fafd","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.12.0.tgz","fileCount":619,"integrity":"sha512-nXhNKrntJl7+17EJyQkPUFsysRLCfAr4FCwom8xzM0Za9P0DJz/o5HPU9Tv1hYyb04vDJyD472wKa7CWQ8GzLA==","signatures":[{"sig":"MEYCIQCWVAWSh3ouq/2DSuNk8MGhEpvCYBt8C7moXmz3WV4Q6QIhAI/6iuL/6/MFBwVKiVn5scyV/Ch2CrVr0cyyNX7e6zb0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2342851},"main":"dist/index.js","type":"module","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js --validate-config","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.11","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.7","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.11","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.12.0_1788366180501_0.8843726098061255","host":"s3://npm-registry-packages-npm-production"}},"0.13.0":{"name":"@redocly/recheck","version":"0.13.0","keywords":["content","linting","markdown","documentation"],"author":"Redocly","license":"MIT","_id":"@redocly/recheck@0.13.0","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"nx":{"targets":{"vitest:test":{"dependsOn":["build"]}}},"bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"31f70f8ab47460110eb079c29798194597cd92f9","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.13.0.tgz","fileCount":619,"integrity":"sha512-82hLBp/8wM/d8QN34kd22ZPs+GwHcS3h53V9M6fjawQaLSGWVPAhULgXyAdOp+NvtsXhU65yO4sjyK1dhkiK1A==","signatures":[{"sig":"MEYCIQCoWXD/rSOjZ3PscPNdqPZmqRn4UtX9YD7d9/5wZ73tFAIhAMmEcAHkNzBFKWWyN2JxX0O0c4J8XWRzgAM9sBfACXFB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2342579},"main":"dist/index.js","type":"module","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js --validate-config","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"description":"Content linting (configurable + built-in rules)","directories":{},"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.1","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.11","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0-next.7","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.11","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/recheck_0.13.0_1788449444723_0.26328589225396515","host":"s3://npm-registry-packages-npm-production"}},"0.14.0":{"nx":{"targets":{"vitest:test":{"dependsOn":["build"]}}},"_id":"@redocly/recheck@0.14.0","bin":{"recheck":"dist/cli.js"},"dist":{"shasum":"cb25788409c4ba5154e68836fa92c4465aba4dbc","tarball":"https://registry.npmjs.org/@redocly/recheck/-/recheck-0.14.0.tgz","fileCount":619,"integrity":"sha512-22owJPr2ntdqqzAyrXoVvVb2DpIDqE+PknKfbCV2EfByZtjjcxJCOHqSj35hu94KWDVwlI9Hn2v54AyAdTn6rw==","signatures":[{"sig":"MEYCIQCW2+ptoLdIgedoLjxUyPARu69Xqppj2W4dQVE+MFJ2NgIhANibObhzlFGEnspcnXfZ+/5FvdRrNwKJ5R4EgZbE3LkP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC21FI7k6tjQvcZHeuPmqOnE5812vA1KEMS6G1Q48W0JwIhAPlfGr1xhDAOTNwTOH2LXm3Kxsydu7NEOqYs/kVfuPmx"}],"unpackedSize":2342832},"main":"dist/index.js","name":"@redocly/recheck","type":"module","author":"Redocly","license":"MIT","scripts":{"dev":"tsgo --watch","test":"nx run vitest:test","bench":"node benchmarks/bench.mjs","build":"tsgo && tsgo --noEmit -p tsconfig.typecheck.json","start":"node dist/cli.js","parity":"node benchmarks/parity/run-parity.mjs","validate":"node dist/cli.js --validate-config","clone-corpora":"bash benchmarks/clone-corpora.sh","examples:generate":"node scripts/generate-examples.mjs","markdoc-schema:generate":"tsx scripts/generate-markdoc-schema.mjs"},"version":"0.14.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b4d302b3-a2d3-4cd9-a7f4-d7a12f800136"}},"keywords":["content","linting","markdown","documentation"],"description":"Content linting (configurable + built-in rules)","directories":{},"maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"_nodeVersion":"24.18.0","dependencies":{"yargs":"^17.7.2","js-yaml":"4.3.2","colorette":"2.0.20","micromark":"4.0.2","picomatch":"2.3.2","ajv-formats":"^3.0.1","@redocly/ajv":"8.18.0","string-width":"^8.2.1","micromark-util-symbol":"2.0.0","micromark-extension-math":"3.1.0","micromark-extension-directive":"4.0.0","micromark-extension-gfm-table":"2.1.1","micromark-extension-frontmatter":"2.0.0","micromark-extension-gfm-footnote":"2.1.0","micromark-extension-gfm-autolink-literal":"2.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.1","nspell":"2.1.5","vitest":"4.1.11","typescript":"6.0.3","@types/node":"24.1.0","@types/yargs":"17.0.32","markdownlint":"0.41.0","dictionary-en":"4.0.0","@redocly/theme":"0.69.0","@types/js-yaml":"4.0.9","@redocly/portal":"0.68.3","@markdoc/markdoc":"0.5.2","@types/picomatch":"2.3.4","@vitest/coverage-v8":"4.1.11","micromark-util-types":"2.0.2"},"peerDependencies":{"nspell":"^2.1.5","dictionary-en":"^4.0.0"},"peerDependenciesMeta":{"nspell":{"optional":true},"dictionary-en":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/recheck_0.14.0_1789548952565_0.5538598950684386"}}},"time":{"created":"2025-12-16T12:10:49.365Z","modified":"2026-09-16T08:55:53.003Z","0.1.0":"2025-12-16T12:10:49.650Z","0.2.0":"2026-08-06T01:32:05.975Z","0.3.0":"2026-08-11T07:47:24.969Z","0.4.0":"2026-08-13T14:49:40.141Z","0.4.1":"2026-08-17T09:07:09.802Z","0.5.0":"2026-08-17T23:58:18.519Z","0.6.0":"2026-08-19T03:27:47.666Z","0.7.0":"2026-08-19T07:09:36.101Z","0.8.0":"2026-08-20T04:50:17.577Z","0.9.0":"2026-08-20T15:36:23.038Z","0.10.0":"2026-08-26T17:01:22.479Z","0.11.0":"2026-08-27T13:59:15.966Z","0.11.1":"2026-08-31T18:34:23.379Z","0.12.0":"2026-09-02T16:23:00.753Z","0.13.0":"2026-09-03T15:30:44.943Z","0.14.0":"2026-09-16T08:55:52.664Z"},"author":"Redocly","license":"MIT","keywords":["content","linting","markdown","documentation"],"description":"Content linting (configurable + built-in rules)","maintainers":[{"name":"romanhotsiy","email":"gotsijroman@gmail.com"},{"name":"alawar","email":"olexandr.varchuk@gmail.com"},{"name":"adamaltman","email":"adam@rebilly.com"},{"name":"marshevskyy","email":"marshevskyy@gmail.com"},{"name":"volodymyr-rutskyi","email":"rutskyi.v@gmail.com"}],"readme":"# Recheck\n\nRecheck combines a **markdown linter** (structure/format — full markdownlint rule parity: 53 built-in rules with auto-fix) and a **prose linter** (style/voice — Vale-style scopes like `sentence`/`paragraph`/`heading` with `swap`/`pattern`/`repetition`/`consistency`/`capitalization` rules) in **one tool with one simple YAML config** — replacing a markdownlint + Vale combo with one line:\n\n```yaml\nextends: [recheck/markdown, recheck/prose]\n```\n\nRecheck is also built to be **embedded by other tools**: it exposes a library-first API (`parseMarkdown`, `extractScopes`, `lintContent`, `lintFiles`, `runRules` — see [Library API](#library-api)) so tools like Redocly CLI's `lint` command can add markdown and prose linting too, including linting markdown strings embedded inside API descriptions.\n\n## Features\n\n✅ **Modern Scope-Based Architecture**\n- File-first processing: each file is parsed once into a [micromark](https://github.com/micromark/micromark) AST, then segmented into scopes\n- Full scope vocabulary: `all`, `raw`, `summary` (alias: `default`), `sentence`, `paragraph`, `heading` (+ `heading.h1`-`h6`), `code`, `list-item`, `blockquote`, `table.header`, `table.cell`, `markdoc.tag`, `frontmatter`, `html`, `comment`, `alt`, `link`\n- Selector syntax for precise targeting: `~` negates a term, `&` joins terms into a conjunction — e.g. `scope: ['~blockquote & ~heading']`\n- Vale-compatible scope notation (e.g., `heading.h1`, `heading.h2`)\n- Efficient rule indexing for fast processing at scale\n\n✅ **Flexible Configuration Format**\n- Modern `assertions`-based rule definitions\n- `severity` levels: `off`, `info`, `warn`, `error`\n- Array-based scope targeting for precise control\n- Comprehensive JSON Schema validation\n\n✅ **Production-Ready Engine**\n- High-performance JavaScript engine optimized for large repositories\n- Successfully processes 300+ files with 1,000+ issues efficiently\n- Built-in rules for common content quality checks\n- Safe auto-fix capabilities for appropriate rules\n\n✅ **Developer-Friendly CLI**\n- Table, JSON, SARIF, and GitHub Actions output formats for CI/CD integration\n- Universal output-path option for file export\n- Inline PR annotations with GitHub Actions format\n- Severity filtering and detailed statistics\n- Auto-fix with granular control\n- Comprehensive error reporting\n\n## Installation\n\n```bash\n# Navigate to the recheck package\ncd packages/recheck\n\n# Install dependencies\npnpm install\n\n# Build the project\npnpm build\n```\n\n**Contributing to Recheck itself** (build-cache problems, `pnpm parity`'s required `--corpus` flag, the `generate-examples.mjs`/`oxfmt` coupling) is covered in [CONTRIBUTING.md](CONTRIBUTING.md), not here — this README is for people adopting Recheck as a linter.\n\n## Usage\n\n### Validate Configuration\n\n```bash\n# Validate with explicit config file\nnode dist/cli.js --validate-config --config recheck.example.yaml\n\n# Auto-discover config file in current directory\nnode dist/cli.js --validate-config\n```\n\n### Run content linting\n\n```bash\n# Run on current directory\nnode dist/cli.js . --config recheck.example.yaml\n\n# Run on specific file\nnode dist/cli.js README.md --config recheck.example.yaml\n\n# Filter by severity (only show errors)\nnode dist/cli.js . --severity error\n\n# Show all enabled rules (info and above)\nnode dist/cli.js . --severity info\n\n# Work one rule at a time. This helps you clear a large list of findings.\n# Give the name that the report shows, or the full config key. Use the flag\n# more than one time for more than one rule. A rule from a namespace other\n# than `recheck/` keeps that namespace: use `google/passive-voice`.\nnode dist/cli.js . --rule semantic-line-breaks\nnode dist/cli.js . -r us-spelling -r recheck/oxford-comma\n\n# ...and its inverse, to silence a rule you have already triaged\nnode dist/cli.js . --exclude-rule semantic-line-breaks\n\n# Use --rule with --fix to clear one rule's findings across all documents\nnode dist/cli.js . --rule semantic-line-breaks --fix\n\n# A name that matches no rule in your config is an error, not an empty run:\n# a misspelled filter that reported \"no issues\" would look the same as a\n# clean document set. The error message lists the rules your config loaded.\n\n# Output formats (table is default)\nnode dist/cli.js . --output table           # Human-readable table (default)\nnode dist/cli.js . --output json            # Structured JSON for CI\nnode dist/cli.js . --output sarif           # SARIF format for security tools\nnode dist/cli.js . --output github-actions  # GitHub Actions annotations (inline PR comments)\n\n# Show detailed statistics\nnode dist/cli.js . --stats\n\n# Auto-fix safe issues (35 fixable rules total: swap + semantic-line-breaks\n# natively, plus 33 of the 53 markdownlint-parity rules — see the rule table\n# under \"Markdownlint parity\" below for the full per-rule breakdown)\nnode dist/cli.js . --fix\n\n# Combine auto-fix with statistics\nnode dist/cli.js . --fix --stats\n\n# Limit annotations for CI (applies to file output, default: 20)\nnode dist/cli.js . --annotations-limit 50\n\n# Output to file (works with all formats)\nnode dist/cli.js . --output json --output-path report.json\nnode dist/cli.js . --output sarif --output-path recheck.sarif\nnode dist/cli.js . --output json --output-path limited.json --annotations-limit 50\n\n# Emit run summary to a file (json or text)\nnode dist/cli.js . --summary json --summary-path recheck-summary.json\n\n# Scan only changed files (via file list or stdin)\n# From file:\nnode dist/cli.js . --changed-only --changed-list changed.txt\n# Or with stdin:\ngit diff --name-only origin/main... | node dist/cli.js . --changed-only\n```\n\n## Library API\n\nThe CLI is a thin wrapper around a public library API, published from `packages/recheck`'s `dist/index.js`.\nThis is the intended integration point for embedding Recheck in another tool (a build step, an editor extension, or another CLI like Redocly CLI's `lint`) rather than shelling out:\n\n```ts\nimport { lintContent, lintFiles } from '@redocly/recheck';\n\n// A config is a flat map of `recheck/<rule>` -> rule definition — the same\n// shape a YAML config file resolves to once `extends` presets are expanded.\n// Load from YAML (via `loadConfig`, which resolves `extends` for you) or\n// build one programmatically, as here:\nconst config = {\n  'recheck/no-hard-tabs': {\n    severity: 'error' as const,\n    message: 'Hard tabs',\n    assertions: { 'no-hard-tabs': {} },\n  },\n};\n\n// Lint an in-memory string — no file I/O. Useful for linting markdown that\n// isn't on disk, e.g. a `description` field pulled out of an OpenAPI document.\nconst problems = await lintContent('# Title\\n\\nSome *text*.\\n', config);\n\n// Lint files from disk, optionally writing auto-fixes back:\nconst { problems: fileProblems, fixedFiles } = await lintFiles(['README.md'], config, {\n  fix: true,\n});\n```\n\nKey exports:\n\n- **`parseMarkdown(content, options?)`** — parses a markdown string into a micromark-based token tree, once.\n  Every other API in this list builds on this tree rather than re-parsing.\n  `options.markdoc` is a boolean here: `true` also tokenizes `{% ... %}` Markdoc tag spans into `markdocTag` tokens, and `false` or omitted gives you the same tree as passing no options at all.\n  The [object form](#markdoc-aware-linting-markdoc-true) (`{ schema, extend }`) is a config-file concept only — it resolves down to this boolean before any file is parsed, and `ParseOptions.markdoc` does not accept it.\n- **`extractScopes(tree, content)`** — segments a parsed token tree into Vale-style scopes (`sentence`, `paragraph`, `heading`, `list-item`, `blockquote`, `table.cell`, etc.) for prose/style rules to run against.\n- **`lintContent(content, config, opts?)`** — lints a single in-memory markdown string against a config; no disk access.\n  Rules that need on-disk facts (e.g. `max-image-size`) require `opts.metadata` to be supplied by the caller.\n- **`lintFiles(paths, config, opts?)`** — lints markdown files from disk; pass `{ fix: true }` to also write auto-fixes back, looping lint → fix → re-lint until the file converges.\n  Files that can't be read are skipped (with a console warning) and reported in the returned `skippedFiles` (`{ path, reason }[]`), so callers can detect incomplete coverage programmatically.\n  `opts.root` sets the lint root that image-metadata loading is confined to (default `process.cwd()`) — image refs resolving outside it are treated as missing without touching the disk.\n  `opts.maxProblems` caps the total problems collected: once a file's lint pushes the run to the cap, later files aren't linted at all and the returned `truncated` flag is set.\n- **`runRules(files, rules)`** — the lower-level engine entry point for callers that already have a `NormalizedRule[]` (e.g. from `loadConfig`) and want to run against an explicit in-memory file list, bypassing `lintFiles`'s own config loading/validation.\n  Under `{ fix: true }` its `RunResult` separates the fixes that genuinely landed (`fixes`) from proposals dropped by overlap resolution (`skippedFixes`).\n- **`applyFixesToContent(content, fixes)`** — applies `Fix` edits to a string, preserving the file's own line endings (CRLF files stay CRLF).\n  Returns `{ content, applied, skipped }`: every input fix is classified as genuinely applied or skipped (overlapping edits, out-of-range lines), so callers can report what actually changed rather than every proposal.\n- **`computeTextStatistics(prose)`** — computes word/sentence/syllable/character/complex-word counts for a plain prose string (not markdown — extract prose from a scope first).\n  Sentence counting reuses `splitSentences` internally, so it agrees with the rest of the engine on sentence boundaries.\n  Tokenization is ASCII-only by design (accented or non-Latin letters don't count as word characters), so readability scores are meaningful for English prose.\n- **`computeReadability(formula, stats)`** — scores a `TextStatistics` object with one of six standard readability formulas: `flesch-reading-ease`, `flesch-kincaid-grade`, `gunning-fog`, `smog`, `coleman-liau`, `automated-readability`.\n  Returns `0` (rather than `NaN`/`Infinity`) when `stats.words` or `stats.sentences` is `0`.\n- **`TECHNICAL_PROPER_NOUNS`** — the [built-in technical proper-noun vocabulary](#built-in-technical-proper-noun-vocabulary) `capitalization`/`spelling` consume by default; re-exported so you can read it or build your own tooling around the same list.\n\nThis is exactly the surface a host tool needs to add both markdown-structure linting and prose/style linting to content it already has in memory — for example, linting the markdown inside an OpenAPI `description` field without writing it to a temp file first.\n\n## Configuration Format\n\nConfiguration uses a modern `assertions`-based format with `severity` levels and flexible scope targeting.\n\nA top-level `excludes` applies to every rule, so a path you never lint is stated once rather than repeated on each rule.\nIt is merged ahead of a rule's own `excludes`, which still apply:\n\n```yaml\nexcludes:\n  - \"**/_partials/**\"\n  - \"CHANGELOG.md\"\n```\n\n```yaml\nrecheck/us-spelling:\n  scope: all # default\n  severity: error\n  message: 'Use the US spelling \"%s\" instead of British \"%s\".'\n  link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-us-spelling-avoid-non-english-words\n  appliesTo:\n    - \"docs/**\"              # Only apply to documentation\n  assertions:\n    swap:\n      ignoreCase: true\n      wordBoundary: true\n      pairs:\n        color: colour\n        behavior: behaviour\n        organize: organise\n  exceptions:\n    files: [docs/style-guide.md]\n    lines:\n      - \"British spellings such as 'color'\"\n\nrecheck/no-gerund-headings:\n  severity: error\n  scope: \n    - heading.h1\n    - heading.h2\n    - heading.h3\n  message: 'Do not start headings with a gerund.'\n  excludes:\n    - \"**/drafts/**\"         # Exclude draft documents\n  assertions:\n    pattern:\n      ignoreCase: true\n      tokens:\n        - '^\\\\w*ing.*'\n\nrecheck/config-line-length:\n  severity: error\n  message: 'Config docs: keep lines under %s characters.'\n  appliesTo:\n    - \"docs/config/**\"       # Only apply to config documentation\n  assertions:\n    line-length:\n      lineLength: 100\n      codeBlocks: false\n\nrecheck/ul-style-dash:\n  severity: error\n  message: \"Use '-' for unordered list bullets.\"\n  excludes:\n    - \"**/examples/**\"       # Allow mixed styles in examples\n  assertions:\n    ul-style:\n      style: dash\n```\n\n## Baseline\n\nA baseline lets a team adopt recheck on a large document set with no cleanup project first: record the findings that exist today, then fail only on new ones.\n\n```bash\nrecheck --generate-baseline            # writes recheck-baseline.yaml next to your config\n```\n\nActivate it with one config line:\n\n```yaml\nbaseline: ./recheck-baseline.yaml\n```\n\nThe file stores one count per file per rule, errors only, sorted for stable diffs:\n\n```yaml\nversion: 1\nfiles:\n  docs/index.md:\n    recheck/semantic-line-breaks: 3\n```\n\nWith the baseline active, `recheck`:\n\n- **suppresses** findings whose (file, rule) count matches the baseline, and reports how many matched;\n- **fails** when a count rises — the group's findings are printed with `(baseline 3, found 5)` context;\n- **fails** when a count falls, because the baseline is stale — the message says to run `recheck --generate-baseline` and commit the result.\n  Counts only step down, so the file equals reality at every green commit.\n\nWarnings are never baselined; they do not affect exit codes.\nPartial runs (`--rule`, `--changed-only`, a narrower path) compare only the files they scanned and the rules they ran, so they never false-alarm about what they did not see.\nLine numbers are deliberately not stored: counts survive unrelated edits, and a baseline diff in review reads as \"this PR pays down 4 findings.\"\nA renamed file is a new path with no budget, so its pre-existing findings report as new until you regenerate — the baseline diff then shows the counts moving from the old path to the new one.\n\n## Readability\n\n`recheck --readability` reports scores per file: Flesch reading ease, Flesch-Kincaid grade, Automated Readability Index (ARI), words, and sentences, plus medians.\nARI is a grade level computed from exact character counts, with no syllable heuristic, which makes it steadier on technical vocabulary.\nIt is score-shaped, not rule-shaped: it never gates and always exits 0 when it ran.\nTo gate on a bound, use the `metric` assertion — both read the same prose and the same formulas, so they can never disagree.\n\n```bash\nrecheck docs --readability\nrecheck docs --readability --output json\nrecheck docs --readability --changed-only < changed.txt   # score only listed files\n```\n\nThe score reads flowing prose the way standard readability tools do: headings, code, and Markdoc tags are excluded, and every block ends a sentence.\nA file with no prose reports `—` (null in JSON) rather than a fake zero.\nIn CI, run it twice — once on the PR head and once on the merge-base worktree — and join on file to show each changed page's score change.\n\n## Agent skills\n\nAgents write a growing share of markdown, and a skill makes each one a recheck user with no person in the loop.\nTwo skills ship in the npm package under `skills/`:\n\n- **`recheck-lint`** — run recheck on touched markdown before committing or outputting it, fix errors, and never suppress findings to pass.\n- **`recheck-config`** — write and tune `recheck.yaml`: measure the corpus, set severities from counts, prefer fixes over exceptions, and adopt a baseline for large corpora.\n\nTo use them with Claude Code, copy them into your project:\n\n```bash\ncp -r node_modules/@redocly/recheck/skills/recheck-lint .claude/skills/\ncp -r node_modules/@redocly/recheck/skills/recheck-config .claude/skills/\n```\n\nEach skill is one `SKILL.md` with a trigger description and instructions, so other agent runtimes can adapt them with a rename.\n\n## Exceptions\n\nRules can be configured with exceptions to skip specific files or lines:\n\n### File Exceptions\n\nSkip entire files using glob patterns or exact matches:\n\n```yaml\nrecheck/us-spelling:\n  # ... other config\n  exceptions:\n    files:\n      - \"docs/style-guide.md\"      # Exact filename\n      - \"docs/api/*.md\"            # Glob pattern\n      - \"**/CHANGELOG.md\"          # Recursive glob\n```\n\n**File matching supports:**\n- **Basename matching**: `style-guide.md` matches any file with that name\n- **Relative path matching**: `docs/style-guide.md` matches the specific path\n- **Glob patterns**: `docs/*.md` matches all markdown files in docs directory\n\n### Line Exceptions\n\nSkip specific lines using fragment matching:\n\n```yaml\nrecheck/no-trailing-spaces:\n  # ... other config\n  exceptions:\n    lines:\n      - \"British spellings such as\"    # Fragment match\n      - \"Code example:\"                # Beginning of line\n      - \"// ignore-lint\"               # Comment-based exception\n```\n\n**Line matching behavior:**\n- **Fragment matching**: If the line contains the exception text anywhere, it's skipped\n- **Case-sensitive**: `\"Code Example\"` does not match `\"code example\"`\n- **Multiple patterns**: Any matching pattern will skip the line\n\n### Exception Examples\n\n```yaml\n# Skip documentation style guides for spelling rules\nrecheck/us-spelling:\n  exceptions:\n    files: [\"docs/style-guide.md\", \"**/*style*\"]\n    lines: [\"British spellings such as 'colour'\"]\n\n# Skip auto-generated files and code blocks\nrecheck/no-trailing-spaces:\n  exceptions:\n    files: [\"**/generated/**\", \"CHANGELOG.md\"]\n    lines: [\"```\", \"Code example:\", \"// formatter-ignore\"]\n```\n\n## Inline Directives\n\nBeyond config-level `exceptions`, individual Markdown files can silence rules\ninline with HTML comments — the same mechanism ESLint/Vale users expect.\nA\ndirective names rules by their **short name** (`oxford-comma`) or **full\nname** (`recheck/oxford-comma`) — both work.\nA directive is inert inside a\nfenced code block (it has to be real, parsed HTML, not just matching text).\n\n```markdown\n<!-- recheck-disable -->\nEverything below this point is unchecked, for every rule.\n<!-- recheck-enable -->\nChecking resumes here.\n\n<!-- recheck-disable oxford-comma us-spelling -->\nOnly these two rules are off from here on.\n<!-- recheck-enable oxford-comma -->\nus-spelling is still off; oxford-comma is back on.\n\n<!-- recheck-disable-next-line oxford-comma -->\nThis one line is exempt from oxford-comma; the rest of the file isn't.\n\n<!-- recheck-disable-file -->\nNothing in this file is linted at all, no matter where this comment sits.\n```\n\nThe five forms:\n\n| Directive | Effect |\n| --- | --- |\n| `<!-- recheck-disable -->` | Disables **all** rules from this line to the end of the file, or until a matching `recheck-enable`. |\n| `<!-- recheck-disable rule… -->` | Disables only the **listed** rules from this line on (same end conditions). |\n| `<!-- recheck-enable -->` | Re-enables all rules (or, with rule names, only the listed ones) from this line on. |\n| `<!-- recheck-disable-next-line -->` | Disables all rules (or, with rule names, only the listed ones) for exactly the next line. |\n| `<!-- recheck-disable-file -->` | Disables every rule for the whole file, regardless of where the comment appears. |\n\nRule naming: list one or more rules space-separated, by short name\n(`oxford-comma`) or full name (`recheck/oxford-comma`) — both work on every\nform that accepts names; omitting names targets every rule.\nNaming a rule\nthat isn't configured produces a warning (`recheck-directive`, severity\n`warn`) pointing at the directive's line — useful for catching a typo in\nthe disabled rule name — but disables nothing.\n\n## Rule Types and Assertions\n\n### Assertion Types\n\nRules are defined using `assertions` that specify their behavior:\n\n#### Swap Assertions (`swap`)\nText replacement with configurable options.\n**Fixable**: each match is replaced with its pair's value, with the matched text's own casing applied to the replacement --\nan all-lowercase match inserts the replacement as configured, a Capitalized match capitalizes just the replacement's first word,\nand an ALL-CAPS match (2+ letters) uppercases the whole replacement;\nany other (mixed-case) casing is left as configured, since it carries no reliable intent to infer.\nThis matters most with `ignoreCase: true`: without it, a sentence-initial `'Behaviour'` would be fixed to literal `'behavior'`, silently lowercasing the start of the sentence -- with it, it fixes to `'Behavior'`.\n(With `keysAreRegex: true`, casing is inferred from the MATCHED text, not the regex key, so this applies uniformly to regex keys too.)\nWhen two pairs' matches overlap in the source (a compound key together with the shorter keys it contains), the longest match wins and is reported and fixed as one span.\n\n```yaml\nassertions:\n  swap:\n    ignoreCase: true\n    wordBoundary: true\n    pairs:\n      color: colour\n      behavior: behaviour\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `pairs` | `object` | Yes | Find → replace entries: each key is searched for in the segment's content and reported/fixed with its value. Keys must be non-empty strings; values must be strings. |\n| `ignoreCase` | `boolean` | No | Matches keys case-insensitively. Default `false`. |\n| `wordBoundary` | `boolean` | No | Wraps each key in `\\b...\\b` so only whole words match. Default `false`. |\n| `keysAreRegex` | `boolean` | No | Keys are literal text by default; set `true` to treat each key as a regex (for example, `favou?rite` matches both spellings). An invalid regex key is ignored and matches nothing; the rule's other pairs still apply. Default `false`. |\n| `includeCode` | `boolean` | No | Matches inside inline code spans (`` `like this` ``) are skipped by default, so a pair like `master: primary` doesn't fire inside `` `git checkout master` ``. Set `true` to scan inline code too. Default `false`. |\n\nA missing or empty `pairs`, an empty-string key, a non-string replacement value, or an unknown option key under `swap` is a validation error.\n\nThe rule's `message` gets two positional `%s` substitutions, in this order: **1st = the replacement, 2nd = the matched text** — with the pair `utilize: use`, the message `'Use \"%s\" instead of \"%s\".'` renders as `'Use \"use\" instead of \"utilize\".'`\n\n#### Pattern Assertions (`pattern`)\nRegex-based pattern matching:\n```yaml\nassertions:\n  pattern:\n    ignoreCase: true\n    tokens:\n      - '^\\\\w*ing.*'\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `tokens` | `string[]` | Yes | Regex patterns matched against each segment's content. An invalid regex is caught and silently produces zero problems rather than crashing the run. |\n| `ignoreCase` | `boolean` | No | Matches every token case-insensitively. Default `false`. |\n| `includeCode` | `boolean` | No | Matches inside inline code spans (`` `like this` ``) are skipped by default, so a token like `master` doesn't fire inside `` `git checkout master` ``. Set `true` to scan inline code too. Default `false`. |\n\n#### Occurrence Assertions (`occurrence`)\nVale-parity `occurrence` check: counts regex matches within each scoped segment and flags the segment when the count falls outside `[min, max]`.\n`min: 1` with no `max` acts as an existence check — it flags a segment where the pattern is missing entirely.\n\n```yaml\nassertions:\n  occurrence:\n    pattern: '[.!?]'\n    max: 3\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `pattern` | `string` | Yes | Regex matched against each segment's content (whole segment, not per-line). |\n| `min` | `number` | At least one of `min`/`max` | Minimum allowed match count; fewer matches is a violation. `min: 1` with no `max` reads as \"the pattern must be present\". |\n| `max` | `number` | At least one of `min`/`max` | Maximum allowed match count; more matches is a violation. |\n| `ignoreCase` | `boolean` | No | Matches `pattern` case-insensitively. Default `false`. |\n\nOmitting both `min` and `max` is a validation error — an occurrence assertion with no bound can never report anything.\nAn unknown option key under `occurrence` is likewise a validation error.\n\nThe rule's `message` gets two positional `%s` substitutions, in this order: **1st = the actual match count, 2nd = the bound that was violated** (`min` or `max`, whichever applied), e.g. `'Too many sentences (%s found, max %s).'` → `'Too many sentences (4 found, max 3).'`.\nNot fixable (detection-only): a count-based violation has no single match position to anchor an edit to.\n\n#### Repetition Assertions (`repetition`)\nVale-parity `repetition` check: flags an adjacent repeated word — two tokens matching `pattern`, separated only by whitespace (which may include a single hard-wrap newline), so `'the theory'` is not flagged (different words) but `'the the'` and a hard-wrapped `'the\\nthe rest'` are.\n**Fixable**: collapses the pair back to one occurrence, keeping the FIRST token's casing/text (so `'The the'` fixes to `'The'`, not `'the'`).\n\n```yaml\nassertions:\n  repetition:\n    ignoreCase: true # default\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `pattern` | `string` | No | Regex used to tokenize each segment's content. Default `\\w+`. |\n| `ignoreCase` | `boolean` | No | Compares adjacent tokens case-insensitively. Default **`true`** — unlike every other assertion's case-sensitive default, since `'The the'` is the overwhelmingly common typo this check exists to catch. Set `false` to require an exact-case repeat. |\n\nAn unknown option key under `repetition` is a validation error, as is a non-string `pattern` or a non-boolean `ignoreCase`; both options are optional, so an empty `repetition: {}` is valid.\n\nThe rule's `message` gets one positional `%s` substitution: the repeated word itself, e.g. `'Repeated word \"%s\".'` → `'Repeated word \"the\".'`.\nFix idempotency holds under repeated `--fix` passes: `'the the the'` converges to `'the'`.\n\n#### Consistency Assertions (`consistency`)\nVale-parity `consistency` check: each `either` entry declares one alternative group — the key and the value are the two variants (both matched as literals with word boundaries, like `swap` keys).\nWhichever variant appears **first in the file (by source order)** wins file-wide; every later occurrence of the other variant is flagged.\n**Fixable**: each later occurrence is replaced with the winning variant **literally as written in `either`** — unlike `swap`, the losing match's own casing is not preserved here (with `ignoreCase: true`, a later `'Behaviour'` in a `behavior`-first document fixes to `'behavior'`).\n\n```yaml\nassertions:\n  consistency:\n    either:\n      behavior: behaviour\n      color: colour\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `either` | `object` | Yes | Map of variant pairs; key and value are the two alternatives of one group. Each pair gets its own independent first-seen winner. Must be non-empty. |\n| `ignoreCase` | `boolean` | No | Matches variants case-insensitively (so `'Behaviour'` counts as an occurrence of `behaviour`). Default `false`. |\n\nOmitting `either`, leaving it empty, or giving it non-string or empty-string keys or values is a validation error — a consistency assertion with no variant pairs can never report anything, and an empty-string key would otherwise reach the scan loop as a zero-width regex that never terminates.\nAn unknown option key under `consistency` is likewise a validation error.\n\nMatches from overlapping scopes (e.g. `scope: [paragraph, sentence]`, where every sentence segment sits inside its paragraph segment) are deduplicated by source position before the winner is decided, so each occurrence is counted — and fixed — exactly once.\n\nThe rule's `message` gets two positional `%s` substitutions, in this order: **1st = the offending (later) match, 2nd = the first-seen winner**, e.g. `'Inconsistent spelling: \"%s\" conflicts with first-seen \"%s\".'` → `'Inconsistent spelling: \"behaviour\" conflicts with first-seen \"behavior\".'`.\n\n#### Conditional Assertions (`conditional`)\nVale-parity `conditional` check: if `first` (a regex pattern) matches anywhere within the rule's scoped segments, `second` (a regex pattern) must exist **somewhere in the whole file** — checked against the full raw file content, not just the rule's own scope, so a `second` match sitting inside a code block still satisfies a rule scoped to `paragraph`.\nWhen `second` is absent file-wide, every `first` match becomes its own problem, at its exact source position.\n**Detection-only** (not fixable) — there is no single well-defined edit that would \"introduce\" `second`.\n\n```yaml\nassertions:\n  conditional:\n    first: '\\bTODO\\b'\n    second: '\\bDONE\\b'\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `first` | `string` | Yes | Regex; if it matches anywhere in the rule's scoped segments, `second` is required. Non-empty. |\n| `second` | `string` | Yes | Regex; must match somewhere in the whole file content once `first` has matched. Non-empty. |\n| `ignoreCase` | `boolean` | No | Matches both `first` and `second` case-insensitively. Default `false`. |\n\nUnlike `swap`/`consistency`'s escaped-literal variants, `first` and `second` are raw user regex patterns (like `pattern`'s `tokens`).\nMissing, empty, or non-string `first`/`second` is a validation error, as is an unknown option key or a non-boolean `ignoreCase` — but `first`/`second` are **not** validated as compilable regexes at config-load time; an invalid regex in either one silently produces zero problems at runtime instead (same convention as `pattern`).\n\nMatches from overlapping scopes (e.g. `scope: [paragraph, sentence]`) are deduplicated by source position, so each occurrence of `first` is reported exactly once.\n\nThe rule's `message` gets two positional `%s` substitutions, in this order: **1st = the offending `first` match, 2nd = the `second` pattern that was never introduced**, e.g. `'\"%s\" appears but \"%s\" was never introduced.'` → `'\"TODO\" appears but \"DONE\" was never introduced.'`.\n\n#### Capitalization Assertions (`capitalization`)\nVale-parity `capitalization` check: flags (and — for four of its `match` values — fixes) a scoped segment whose text doesn't already match the required casing.\n`match` is one of `$title`, `$sentence`, `$lower`, `$upper`, or else a **custom regex** the whole segment text must satisfy.\n\n```yaml\nassertions:\n  capitalization:\n    match: $title\n    style: chicago # optional, default 'ap' — only affects $title\n    exceptions: [GitHub, iPhone]\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `match` | `string` | Yes | `$title`, `$sentence`, `$lower`, `$upper`, or a regex the whole segment text must satisfy. Non-empty. |\n| `style` | `'ap' \\| 'chicago'` | No | Stopword list `$title` uses (see below). Default `'ap'`. Accepted alongside any `match`, but only has an effect on `$title` — a documented no-op elsewhere, not a validation error. |\n| `exceptions` | `string[]` | No | Words (or phrases — see below) kept in their EXACT as-written casing from this list, everywhere they appear — including the first/last word — overriding every other rule. Unioned with the [built-in technical proper-noun vocabulary](#built-in-technical-proper-noun-vocabulary) unless `builtinVocabulary: false`. |\n| `builtinVocabulary` | `boolean` | No | Default `true`. Whether [`TECHNICAL_PROPER_NOUNS`](#built-in-technical-proper-noun-vocabulary) is unioned into `exceptions`. Set `false` for a closed vocabulary of only this rule's own `exceptions`. |\n\nAn `exceptions` entry containing whitespace or a dot (e.g. `Node.js`, `VS Code`) is matched as a whole PHRASE against the segment text — case-insensitively but otherwise literally, longest-match-first when phrases overlap — and preserved verbatim, instead of being looked up per word.\n\nUnknown option keys, a missing/empty `match`, an invalid `style`, a non-string-array `exceptions`, or a non-boolean `builtinVocabulary` are all validation errors.\n\n**`$title`** — AP or Chicago title case, implemented in `rules/scope/title-case.ts`'s `apTitleCase`/`chicagoTitleCase`:\n- The first and last word are **always** capitalized, regardless of any stopword list.\n- A hyphenated compound (e.g. `well-known`) runs **each hyphen part** through the same stopword test a standalone word gets for the active style — `well-known` → `Well-Known`, but `editor-in-chief` → `Editor-in-Chief` (`in` is a stopword in both styles).\n  The compound's first part always capitalizes when the compound opens the title, and its last part always capitalizes when the compound closes the title — e.g. `the new state-of-the-art` → `The New State-of-the-Art` (changed from the original simplification by product decision during execution, 2026-07-27).\n- A word already in ALL-CAPS (2+ letters, e.g. an acronym like `API`) is left exactly as written.\n- **AP** (default) lowercases articles (`a`, `an`, `the`), coordinating conjunctions (`and`, `but`, `or`, `nor`, `for`, `so`, `yet`), and prepositions of **3 letters or fewer** (`at`, `by`, `in`, `of`, `off`, `on`, `out`, `to`, `up`, `via`).\n- **Chicago** lowercases the same articles/conjunctions, plus **every** preposition regardless of length (the short ones above, plus `about`, `above`, `across`, `after`, `against`, `along`, `among`, `around`, `before`, `behind`, `below`, `between`, `during`, `through`, `toward`, `under`, `until`, `with`, `within`, `without`) —\n  e.g. Chicago lowercases `'...walking through the park'` → `'...walking through the Park'`, where AP capitalizes `Through`.\n\n**`$sentence`** — only the first word is capitalized; every other word is lowercased unless it's an `exceptions` entry (as-written) or already ALL-CAPS (left alone).\n\n**Word position counts a phrase exception as one word.**\nA *phrase* exception (one containing whitespace or a dot, like `Node.js` or `VS Code` — see the phrase-matching note above) is a single atomic token in the word sequence the `$`-styles case: it's emitted in its exact as-written form, and it **occupies a position**, so it never changes which word counts as first or last.\nWith `exceptions: [VS Code]`, the already-correctly-cased heading `## VS Code actions for teams` produces no finding under `$sentence` (`actions` is the second word, not the first), and `## a guide to Node.js` becomes `## A Guide to Node.js` under `$title`/AP (`Node.js` is the last word, so `to` is a mid-title stopword and stays lowercase).\nSingle-word exceptions (e.g. `GitHub`) behave as they always have — resolved by lookup rather than position.\n\nThis used to be a bug, tracked as [Redocly/redocly#25610](https://github.com/Redocly/redocly/issues/25610) and fixed since:\nphrase exceptions were previously *masked out* of the text before word position was computed, which made a leading phrase promote the next word to sentence-initial under `$sentence`\n(`## VS Code actions for teams` was flagged, and under `fix: true` rewritten to `## VS Code Actions for teams`)\nand made a trailing phrase promote the preceding word to last-word position under `$title` (`a guide to Node.js` → `A Guide To Node.js`).\nIf you had worked around it by rephrasing headings or by swapping in a custom regex `match`, neither is needed any more.\nSee `rules/scope/title-case.ts`'s `recaseWords` for the tokenization that replaced the masking.\n\n**`$lower`** / **`$upper`** — the whole segment must be all-lowercase / all-uppercase respectively; no exceptions/ALL-CAPS carve-out (unconditional, matching Vale's own `$lower`/`$upper`).\n\n**Custom regex** — the whole segment text must satisfy the pattern.\n**Detection-only**: unlike the four `$`-styles, a failing regex is flagged but never auto-fixed, even though the rule itself is registered fixable.\nLike `pattern`'s `tokens`, an invalid regex is caught and silently produces zero problems rather than crashing the run.\n\n**Inline code is frozen.**\nA backtick-delimited span in the segment text (e.g. a heading like ``'the `configFile` option'``) is treated like an exception: its content is never flagged or rewritten by any of the four `$`-styles, even if it would otherwise land on the first/last word.\n\n**Fixable** for `$title`/`$sentence`/`$lower`/`$upper` only, one segment-wide edit per flagged segment.\nA **multi-line** segment (e.g. a soft-wrapped paragraph) is skipped entirely under these four styles — neither a problem nor a fix — since a `Fix` can only rewrite a single line; a custom regex `match` has no such restriction and still checks (and reports) multi-line segments, since it never produces a fix regardless of segment span.\n\nThe rule's `message` gets two positional `%s` substitutions, in this order: **1st = the segment's own text (first line only), 2nd = the `match` value itself** (e.g. `'$title'`, or the literal regex source for custom-regex mode), e.g. `'\"%s\" should use %s capitalization.'` → `'\"the great escape\" should use $title capitalization.'`.\n\n#### Metric Assertions (`metric`)\nScores the document's prose with one of six published readability formulas and flags the file once when the score falls outside `[min, max]`.\n\n```yaml\nassertions:\n  metric:\n    formula: flesch-reading-ease\n    min: 30\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `formula` | `string` | Yes | One of `flesch-reading-ease`, `flesch-kincaid-grade`, `gunning-fog`, `smog`, `coleman-liau`, `automated-readability`. |\n| `min` | `number` | At least one of `min`/`max` | Minimum acceptable score; a lower score is a violation. |\n| `max` | `number` | At least one of `min`/`max` | Maximum acceptable score; a higher score is a violation. |\n\nOmitting both `min` and `max`, an unrecognized `formula`, or an unknown option key are all validation errors — a metric assertion with no bound can never report anything, and an unrecognized formula would otherwise reach the scoring engine's own exhaustive-switch failure at lint time instead of at config validation.\n\n**Always summary-scoped.**\nUnlike every other assertion above, `metric` does not honor a configurable `scope:` — readability is a property of the WHOLE document's prose, not something a selector could sensibly narrow (a readability score isn't meaningful for one paragraph in isolation the way an `occurrence` count is).\nConfig validation forces every `metric` rule to `scope: summary`.\nOmit `scope` on a `metric` rule (or write `scope: summary` explicitly); configuring any other scope prints a warning (`metric is always summary-scoped; ignoring configured scope ...`) and applies `summary` behavior anyway.\nText from overlapping segments (e.g. a list nested inside a blockquote) is deduplicated by source position, same as `consistency`/`conditional` above.\n\n**What the score reads.**\nThe metric scores flowing prose the way standard readability tools do: `paragraph`, `list-item`, `blockquote`, `table.cell`, and `table.header` text counts; **headings are excluded**, and `code`, `frontmatter`, `html`, `comment`, `alt`, and `link` content is never counted.\nEvery block that does not end in terminal punctuation ends a sentence — an unpunctuated list item is one sentence, not a fragment fused into its neighbors.\nWithout that rule, a run of bullets scored as one enormous \"sentence\" and pushed Flesch reading ease far below zero; with it, scores line up with other readability tools within syllable-heuristic differences.\n\n**Non-prose stripping.**\nBefore scoring, each segment's text also has Markdoc tag-marker spans (`{% tag attr=\"x\" %}`, `{% /tag %}`, and the `{%- ... -%}` trim variant) and backtick-delimited inline code spans stripped out — neither is readable prose, and both otherwise skew word/syllable counts.\nProse between two block-tag markers still counts (only the marker spans themselves are removed); a paragraph consisting only of tag markers contributes nothing.\nMulti-backtick delimiters (`` ``like this`` ``) are handled conservatively as a simple open-run/close-run pair match, not a full CommonMark-correct implementation.\n\n**Detection-only** (not fixable) — there is no single edit that would \"fix\" a readability score.\nReports at most **one** problem per file, always at `line: 1, column: 1` (there is no single source position a whole-document score belongs to) — never divided by zero: a file with no prose at all (empty, or only code/frontmatter) is never flagged, regardless of `min`/`max`.\n\nThe rule's `message` is substituted against up to **four** values, in this order: **1st = the formula name, 2nd = the computed score, 3rd = `min` (or `-∞` if unset), 4th = `max` (or `∞` if unset)** — e.g. the internal fallback `'Readability (%s) is %s; expected between %s and %s.'` → `'Readability (flesch-reading-ease) is 42.1; expected between 60 and ∞.'`.\nThe `message` validation cap is per-assertion: a `metric` rule's `message` may use up to **4** `%s` placeholders (one per value above), while every other assertion stays capped at 2.\nFewer placeholders than values is fine — substitution is positional, so a 2-slot message receives the leading values (formula name, then score).\n\n<!-- recheck-disable-next-line no-gerund-headings -->\n#### Spelling Assertions (`spelling`)\nVale-parity `spelling` check (detection-only): tokenizes each scoped segment's text into words and flags any word an [nspell](https://github.com/wooorm/nspell)/Hunspell speller doesn't recognize, with up to three suggested corrections.\n\n```yaml\nassertions:\n  spelling:\n    vocab: [Redocly, Reunite]\n    ignore: ['\\bAcme\\w*']\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `dictionary` | `string` | No | Base path (WITHOUT the `.aff`/`.dic` extension) to a custom Hunspell dictionary pair, e.g. `dictionary: dict/custom` reads `dict/custom.aff` and `dict/custom.dic`. Resolved relative to `process.cwd()` (where the CLI is invoked from) unless absolute. Omit to use the bundled default English dictionary. |\n| `vocab` | `string[]` | No | Extra known-good words, matched case-insensitively; never flagged even when the speller itself doesn't recognize them (product names, jargon, etc.). Unioned with the [built-in technical proper-noun vocabulary](#built-in-technical-proper-noun-vocabulary) unless `builtinVocabulary: false`. |\n| `ignore` | `string[]` | No | Regex patterns; a token matching ANY of them is never flagged, e.g. `['\\bAcme\\w*']` to allow every inflection of a brand name. An invalid pattern is silently ignored, same convention as `pattern`'s `tokens`. |\n| `builtinVocabulary` | `boolean` | No | Default `true`. Whether [`TECHNICAL_PROPER_NOUNS`](#built-in-technical-proper-noun-vocabulary) is unioned into the accepted-word set alongside `vocab`. A multi-token entry (`Node.js`, `VS Code`) is split into its individual words, each accepted separately — correct for a per-word spell check, unlike `capitalization`'s whole-phrase matching. Set `false` for a closed vocabulary of only this rule's own `vocab`. |\n\nAll options are optional — an empty `spelling: {}` is valid (default dictionary, no extra vocabulary, no ignore patterns, built-in vocabulary on).\nUnknown option keys, a non-string/empty-string `dictionary`, a `vocab`/`ignore` entry that isn't a non-empty string, or a non-boolean `builtinVocabulary` are all validation errors.\n\n**Optional peer dependencies — install to enable.**\n`nspell` and its default dictionary (`dictionary-en`) are **optional peer dependencies**: installing `@redocly/recheck` itself pulls in **neither**.\nEnable `spelling` with:\n\n```bash\nnpm i nspell dictionary-en\n```\n\n...or, if every `spelling` rule in your config sets its own `dictionary` path, you only need the speller itself (the bundled dictionary is never touched):\n\n```bash\nnpm i nspell\n```\n\nIf a config enables `spelling` without the required peer(s) installed, `recheck --validate-config` fails with an actionable error naming the exact command above — never a bare `Cannot find module 'nspell'` surfacing for the first time at lint time.\n\n**Dictionaries load lazily.**\nNeither `nspell` nor `dictionary-en` is imported unless some rule in your config actually has a `spelling` assertion — a config without one never touches either package, at either `validate` or lint time.\nThe loaded speller (including the ~500KB parsed dictionary) is cached per dictionary source for the process's lifetime, so every file/rule sharing the same `dictionary` (or the shared default) reuses one instance rather than reloading it per call.\n\n**Word tokenization.**\nWords are matched with `/\\p{L}+(?:['’]\\p{L}+)?/gu` — Unicode letter runs, with an optional apostrophe-joined suffix so contractions (`don't`, `it's`) tokenize as one word.\nA token is skipped (never checked) when it's in `vocab` (case-insensitively), matches any `ignore` pattern, is ALL-CAPS (2+ letters, e.g. an acronym) — matching the same ALL-CAPS carve-out `$title`/`$sentence` capitalization use — or is digit-adjacent (see below).\nBecause `\\p{L}` can never match a digit, a token touching one is never captured WHOLE by the tokenizer in the first place: a digit-adjacent identifier like `config2` still splits into a letter-only fragment (`config`) as its own regex match.\nRather than checking that fragment like any other word, a digit-adjacency guard looks at the character immediately before and after each match and skips it when either neighbor is a digit — so common digit-bearing identifiers (`sha256` → `sha`, `utf8` → `utf`, `oauth2` → `oauth`, `es6` → `es`, `log4j` → both `log` and `j`, `2fast` → `fast`) are no longer flagged as false-positive misspellings.\nThis mitigates, but doesn't eliminate, every false positive from the tokenizer's inability to capture digits at all — a token entirely surrounded by non-digit characters is still checked normally, so a genuine misspelling elsewhere in the same sentence is still flagged.\n\n**Code is never spell-checked, by construction of scope segmentation — not something this assertion special-cases.**\nA fenced or indented code block is its own `scope: 'code'` segment, entirely distinct from `paragraph`/`heading`/etc.; scoping `spelling` to prose (the common case, e.g. `scope: paragraph` or an array of prose scopes) means `ctx.segments` never contains one.\nA backtick-delimited **inline** code span, though, remains embedded as raw text inside a prose segment's own content (verified directly against the extractor) — those spans are masked out before tokenizing, the same length-preserving technique `capitalization`'s backtick-span freezing uses, so positions of any remaining flagged word stay exact.\nScoping `spelling` to `all`/`raw` (or leaving `scope` at its default) checks the whole raw file, literal code included — same default-scope behavior every other native assertion (`swap`, `pattern`, ...) has.\n\n**Detection-only** — no `fix`.\nThe rule's `message` gets two positional `%s` substitutions, in this order: **1st = the unrecognized word, 2nd = a suggestion suffix** — either `''` (zero suggestions) or `' — did you mean: a, b, c?'` (one to three, comma-joined) — e.g. the internal fallback `'Unknown word \"%s\"%s'` → `'Unknown word \"wrold\" — did you mean: wold, world?'`.\n\n#### Built-in technical proper-noun vocabulary\n\n`capitalization` and `spelling` both ship a built-in list of common technical/product proper nouns — `TECHNICAL_PROPER_NOUNS`, exported from `@redocly/recheck`'s public API (`import { TECHNICAL_PROPER_NOUNS } from '@redocly/recheck'`) so you can read or extend it yourself.\nIt exists so a config that turns on sentence-case headings or spelling doesn't immediately need to hand-list the same 15+ mixed-case technology names every project already has to deal with (`OpenAPI`, `npm`, `Node.js`, `VS Code`, ...).\n\n**On by default**, per rule:\n- `capitalization` unions it into `exceptions` (so a listed name keeps its as-written casing under every `$`-style, including `$sentence`).\n- `spelling` unions it into `vocab` (so those words are never reported as misspellings), splitting any multi-token entry into its individual words first — a per-word spell check has no way to accept a whole phrase atomically the way `capitalization`'s phrase matching does.\n- Either union is opted out of independently with that rule's own `builtinVocabulary: false`, restoring strict pre-built-in behavior (a closed vocabulary of only what you list yourself).\n- Your own `exceptions`/`vocab` on the same rule **compose** with the built-ins rather than replacing them — unlike a preset-shipped list on the same rule key, which a same-key override *would* replace entirely (see [`extends` presets](#extends-presets) above).\n  This is exactly how [`recheck/prose`](#extends-presets)'s `capitalization` rule gets its protection for common technical nouns without shipping any `exceptions` of its own.\n\n**Multi-token entries work.**\nAn entry containing a dot or whitespace (`Node.js`, `VS Code`, `Visual Studio Code`, `GitHub Actions`, `Google Cloud`, `Azure DevOps`) is matched by `capitalization` as a whole phrase against the segment text (longest-match-first, case-insensitive but otherwise literal) and preserved verbatim — not looked up per word, which is what a single-token entry like `GitHub` still gets.\n\n**Inclusion bar** (why an entry is — or isn't — in the list, and the bar to clear before proposing one): an entry qualifies if it's an unambiguous technology, product, or company name whose exception listing wouldn't *weaken* capitalization/spelling checks — concretely, its lowercase form must not be a legitimate English word in its own right.\nThat covers ordinary Title-Case brand names (`Android`, `Kubernetes`, `Redocly`) just as much as entries with an internal capital (`OpenAPI`, `GraphQL`), a dot (`Node.js`), or forced lowercase (`npm`) — `$sentence` lowercases every non-first word regardless of how \"ordinary\" its casing looks, so plain Title-Case names need protection too.\nExcluded, deliberately:\n- **Pure ALL-CAPS acronyms** (`JWT`, `YAML`) — already handled structurally by the ALL-CAPS carve-out both `capitalization` and `spelling` apply, so listing them adds maintenance for no behavior change.\n  Note this is narrower than \"looks like an acronym\": `OAuth` and `AsyncAPI` are mixed-case, not pure ALL-CAPS, and are in the list.\n- **Terms with legitimate lowercase prose usage** — generic English (`cloud`, `apps`),\n  words that are ALSO ordinary English words even though they're Redocly product names too (`Realm`, `Replay`, `Respect` — listing them would force-capitalize ordinary usage like \"we respect your privacy\"; `Node` — the common technical noun, superseded by the `Node.js` phrase entry for the platform specifically),\n  and — caught by a later audit, not the original pass — ordinary brand-shaped words with a real dictionary meaning (`Chrome`, `Markdown`, `Postman`, `Prettier`, `Safari`, `Swagger`, `Windows`; see `src/data/proper-nouns.ts`'s header for each one's disqualifying lowercase usage).\n  A few real dictionary words (`Android`, `Docker`, `TypeScript`) were judged rare enough in ordinary lowercase usage to keep anyway — a documented, deliberate risk-acceptance, not an oversight.\n  List your own such names in your rule's own `exceptions`/`vocab`, which compose with this list as described above.\n\nTwo automated tests in `src/data/__tests__/proper-nouns.test.ts` enforce this:\none checks every entry's shape against the bar above — no pure ALL-CAPS, and, mechanically, no single-token entry whose lowercase form the REAL spelling dictionary (`dictionary-en`/`nspell`, the same pair `spelling` loads at runtime) accepts as a legitimate English word, unless it's named in an explicit accepted-risk allowlist —\nplus alphabetization and no duplicates.\nA round-trip guard separately drives every entry through the real `capitalization` and `spelling` rules and fails the suite if any entry can't actually be protected — the list can't silently regress into decoration.\n\n#### Length Assertions (`length`)\nRecheck-original, detection-only check: measures each scoped segment's size — in characters, words, or sentences — and flags a segment whose measurement falls outside `[min, max]`.\nUnlike `metric` (always whole-document), `length` honors whatever `scope` the rule configures — e.g. `scope: alt` to cap image alt text, or `scope: sentence` to cap sentence length in words.\n[`recheck/google`](#extends-presets) ships this for the guide's stated \"fewer than 26 words per sentence\" limit (`google/sentence-length`); Microsoft's 150-character alt-text cap is the other published example of this shape.\n\n```yaml\nassertions:\n  length:\n    unit: characters\n    max: 150\n```\n\n| Option | Type | Required | Description |\n| --- | --- | --- | --- |\n| `unit` | `'characters' \\| 'words' \\| 'sentences'` | Yes | What `min`/`max` count: raw character length, whitespace-delimited words (the same tokenizer `metric` uses for its own word counts — see `metrics/statistics.ts`'s `tokenizeWords`), or sentences via the shared `splitSentences` sentence-boundary logic (`scopes/sentences.ts`). |\n| `min` | `number` | At least one of `min`/`max` | Minimum allowed size; a smaller segment is a violation. |\n| `max` | `number` | At least one of `min`/`max` | Maximum allowed size; a larger segment is a violation. |\n\nOmitting both `min` and `max`, a missing/unrecognized `unit`, or an unknown option key are all validation errors — same reasoning as `occurrence`/`metric` above.\nAn inverted range (`min` > `max`) is also an error.\n\n**Detection-only** (not fixable) — there is no single edit that would resize a segment to fit.\nReports at most one problem per flagged segment, at the segment's own `startLine`/`startColumn`.\n\nThe rule's `message` gets three positional `%s` substitutions, in this order: **1st = the segment's measured size, 2nd = the unit name, 3rd = the bound that was violated** (`min` or `max`, whichever applied), e.g. the internal fallback `'Segment is %s %s; at most %s allowed'` → `'Segment is 151 characters; at most 150 allowed'`.\nThe message validation cap for `length` is **3** placeholders (one per value above), same reasoning as `metric`'s 4-cap.\n\n#### Built-in Prose Assertions\nBeyond `swap`, `pattern`, `occurrence`, `repetition`, `consistency`, `conditional`, `capitalization`, `metric`, `spelling`, and `length` above, Recheck ships a small set of native prose/format checks:\n- `semantic-line-breaks` - Semantic line break validation ✅ **Fixable**\n- `max-image-size` - Oversized image detection\n\nThree of the assertions above (`repetition`, `consistency`, `capitalization`) are bundled, pre-configured, in the [`recheck/prose`](#extends-presets) preset,\nand `capitalization`/`length` are also used by [`recheck/google`](#extends-presets) (sentence-case headings and list items, and a sentence-length cap);\nthe remaining four (`occurrence`, `conditional`, `metric`, `spelling`) are documented [opt-ins](#opt-in-prose-assertions) with copy-paste snippets, not shipped in any preset by default.\n\n### Recheck-original structural rules\n\nSeven rules have no markdownlint counterpart, so they sit outside the 53-rule parity set\n(and outside the parity comparison).\nAll seven are **detection-only** (`fix: false`).\nThe\ncanonical list is `RECHECK_ORIGINAL_TOKEN_RULE_NAMES` in `src/rules/token/index.ts`.\n\nThe table below covers five of them.\nThe other two — `markdoc-unknown-tag` and\n`markdoc-attributes` — need a tag schema to check anything, so they are documented with\nthe [`recheck/markdoc`](#extends-presets) preset instead.\n\n| Rule | Flags | Why |\n| --- | --- | --- |\n| `no-empty-headings` | A heading whose text content is empty (a bare `#`, or markup that renders to nothing such as `## <span></span>`) | An empty heading still lands in the document outline and in screen-reader heading navigation. Inline code counts as content, so `` # `config.yaml` `` is fine. |\n| `no-duplicate-link-destinations` | The second and later links to one destination when the link **text** differs from the first occurrence's | Screen-reader users listing a page's links hear one target described inconsistently; the texts also drift apart over time. Repeating the *same* text for the same destination is ordinary prose and is not flagged. Resolves reference links through their definition. |\n| `list-length` | A list (ordered or unordered) with fewer than `min` items (default 2) or more than `max` items (no default — unbounded unless set) | A single-item list usually reads better as a plain sentence, and a very long list asks readers to hold too many parallel items in mind. Every list is evaluated independently, including nested sublists — a short sublist is flagged even when its parent list is long enough. |\n| `markdoc-syntax` | A grammar-level Markdoc tag error — a malformed span, an unquoted \"bareword\" attribute/primary value, or a close tag carrying attributes | These are invalid under real Markdoc's own grammar regardless of any tag schema, so the rule fires on custom/unknown tags and under `schema: false` alike. See the [`recheck/markdoc`](#extends-presets) preset bullet below for the full behavior and a config example. |\n| `markdoc-pairing` | An unclosed, orphaned, or interleaved (crossed) Markdoc tag pair, or a schema-declared self-closing tag written with a close it must not have | Same grammar-level scope as `markdoc-syntax` — see the [`recheck/markdoc`](#extends-presets) preset bullet below. |\n\nThe first three rules are **opt-in — not shipped in any preset**; configure them\nindividually as shown below.\n\n`markdoc-syntax` and `markdoc-pairing` work the other way around: they ship only inside\nthe [`recheck/markdoc`](#extends-presets) preset, and both need `markdoc: true` (or the\nobject form) to ever see a Markdoc tag token.\nNaming either rule key on its own, without\nthe flag, validates but can never report anything — and you get no warning about it,\nbecause the stale-config warning fires on `extends` containing `\"recheck/markdoc\"`\n(`warnStaleMarkdocPreset` in `config/validate.ts`), not on individual rule keys.\nThe\npreset bullet below covers both rules' full behavior with the flag on, plus a config\nexample.\n\n```yaml\nrecheck/empty-headings:\n  severity: error\n  message: 'Headings should have text content.'\n  assertions:\n    no-empty-headings: {}\n\nrecheck/link-text-consistency:\n  severity: warn\n  message: 'Link destination \"%s\" is already linked by different text.'\n  assertions:\n    no-duplicate-link-destinations: {}\n\nrecheck/list-length:\n  severity: warn\n  message: 'List has %s item(s).'\n  assertions:\n    list-length: { min: 2, max: 10 }\n```\n\nFor markdown structure/format rules (headings, lists, links, tables, whitespace, and 49 more), see [Markdownlint parity](#markdownlint-parity) below — `no-trailing-spaces`, `no-hard-tabs`, `line-length`, `ul-style` (bullet style), `no-duplicate-heading`, and `link-fragments` are all part of that 53-rule set, not this native list.\n(`max-line-length`, `bullet-style`, `no-duplicate-headings`, and `no-broken-fragment-links` were pre-parity native ids for those same rules; they were removed rather than kept as aliases — see [Migrate from markdownlint](#migrate-from-markdownlint).)\n\n### Enhanced Scope Support\n\nThe `scope` field supports a string, an array (OR'd together), and a `~negation` / `&`-conjunction\nselector syntax:\n```yaml\nscope: all              # Apply to all content (default)\nscope: raw              # Apply to raw file content, bypassing scope segmentation\nscope: summary          # Apply to the document's prose: paragraph, heading, list-item, blockquote, and table-cell text (alias: default)\nscope: sentence         # Apply to sentences only\nscope: paragraph        # Apply to paragraphs only\nscope: heading          # Apply to all headings\nscope: code             # Apply to code blocks only\nscope: list-item        # Apply to list item text\nscope: blockquote       # Apply to blockquote text\nscope: table.header     # Apply to table header cells\nscope: table.cell       # Apply to table body cells\nscope: markdoc.tag      # Apply to Markdoc tag spans (`{% ... %}`), requires markdoc: true\nscope: frontmatter      # Apply to YAML frontmatter\nscope: html             # Apply to raw HTML blocks\nscope: comment          # Apply to HTML comments\nscope: alt              # Apply to image alt text\nscope: link             # Apply to link text\nscope:                  # Apply to specific heading levels\n  - heading.h1\n  - heading.h2\n  - heading.h3\nscope:                  # Selector syntax: '~' negates, '&' conjoins\n  - \"~blockquote & ~heading\"\n```\n\n### Markdoc-aware linting (`markdoc: true`)\n\nOpt-in — off by default, since Liquid/Jinja templates use the same `{% %}` delimiters and would otherwise get mistokenized as Markdoc:\n\n```yaml\nmarkdoc: true   # shorthand for `{ schema: 'realm' }`\n```\n\nWriting *about* Markdoc syntax rather than using it (docs like this one, a tutorial, a changelog entry)?\nWrap the literal `{% ... %}` in a code span — `` `{% partial /%}` `` — instead of leaving it bare in prose.\nCode spans never tokenize as Markdoc tags whether the flag is on or off, so that's the escape hatch.\n\n#### Object form: choosing or extending the tag schema\n\n`markdoc: true` is shorthand for the common case.\nThe object form adds two things the\nboolean can't express: turning the schema-aware checks off while keeping tag tokenization,\nand layering a project's own custom tags over the built-in schema.\n\n```yaml\nmarkdoc:\n  schema: realm        # required -- 'realm' (the built-in schema below) or `false`; there is no default if this key is omitted\n  extend:               # optional: your own tags, merged over the base schema\n    tags:\n      myCustomTag:\n        selfClosing: true\n        attributes:\n          level:\n            type: string\n            enum: [info, warning, danger]\n            required: true\n```\n\n- **`schema: realm`** — the same built-in schema `markdoc: true` uses: `@markdoc/markdoc`'s\n  own built-in tags composed with `@redocly/theme`'s tag definitions.\n  It's generated from a\n  theme build rather than hand-written, and a test fails if it drifts out of sync (see\n  [CONTRIBUTING.md](CONTRIBUTING.md) for the regeneration command).\n  This is what most\n  projects want, and what the four [`recheck/markdoc`](#extends-presets) rules validate\n  against by default.\n- **`schema: false`** — tokenization and tag **pairing** still run, so `markdoc.tag` scope,\n  prose-scope exclusion, fix protection, and `markdoc-syntax`/`markdoc-pairing`'s\n  grammar-level checks all still work.\n  Only the two schema-dependent rules\n  (`markdoc-unknown-tag`, `markdoc-attributes`) go inert, since there's no schema left for\n  \"unknown tag\" or \"missing required attribute\" to mean anything against.\n  Use this if you\n  write Markdoc tags but don't have (or don't want) a schema to validate them against.\n- **`extend.tags`** — merges your own tag definitions over the base schema.\n  On a name\n  collision the merge is a **whole-tag replace**, matching how Markdoc's own config\n  composition works, not a per-attribute deep merge.\n  Declare your project's custom tags\n  here (for example, a docs site's own `@theme/markdoc/schema.ts` overrides) so\n  `markdoc-unknown-tag` and `markdoc-attributes` validate against your real tag surface\n  instead of flagging every custom tag as unknown.\n  Under `schema: false` there is no base\n  to merge over, so `extend` does nothing.\n- **`extend.tagsFile`** — the same tag-definition surface as `extend.tags`, but sourced from\n  a separate YAML file instead of written inline into `recheck.yaml`.\n  This is the shape\n  [`recheck --generate-markdoc-schema`](#generate-a-tagsfile-recheck---generate-markdoc-schema) below generates,\n  so a project with tags defined in TypeScript (a `@theme/markdoc/schema.ts` module, say)\n  never hand-transcribes them into YAML.\n  ```yaml\n  markdoc:\n    schema: realm\n    extend:\n      tagsFile: ./recheck-markdoc-tags.yaml\n  ```\n  - **Resolution**: the path is resolved relative to the directory containing the\n    `recheck.yaml`/`recheck.yml` that names it — never the process's current working\n    directory — so `tagsFile: ./tags.yaml` always reads the file next to that config,\n    wherever `recheck` is invoked from.\n  - **Precedence**: tags merge in the order built-in schema → `tagsFile` → inline\n    `extend.tags`, each layer a whole-tag replace on a name collision (same rule as\n    `extend.tags` above).\n    `tags` and `tagsFile` can both be set on the same `extend` block;\n    `extend` with neither key is rejected by config validation as a likely no-op.\n  - **Errors are fatal to the whole run, not a silent markdoc downgrade.**\n    A `tagsFile` that\n    doesn't exist, isn't valid YAML, isn't a YAML map, or contains a tag entry with an\n    invalid shape all fail `recheck`/`recheck --validate-config` outright\n    (`Configuration validation failed!`, the same failure every other structurally-invalid\n    config produces) — markdoc checking is never quietly switched off while the rest of the\n    config keeps running.\n\nTurning `markdoc` on (either form) changes how every prose rule sees a Markdoc tag, not just `markdoc.tag` (above):\n\n- **Prose scopes exclude the tag itself.**\n  `paragraph`, `heading`, `list-item`, `blockquote`, and `table.header`/`table.cell` all blank a tag's own `{% ... %}` span out of their content before any rule runs — a `swap`/`pattern`/`capitalization` match can't fire on the tag's syntax, and a `length`/`metric` count doesn't include it.\n  The blanking is position-preserving (same-width spaces, never a deletion), so real text on either side of a tag keeps its exact line and column.\n- **A segment with no prose left isn't emitted at all.**\n  A heading or table cell whose entire text IS a tag (`# {% #","readmeFilename":""}