@redocly/recheck 0.15.0 → 2.58.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -1886
- package/examples/appendices/google.appendix.yaml +1 -1
- package/examples/appendices/inclusive-language.appendix.yaml +1 -1
- package/examples/appendices/microsoft.appendix.yaml +1 -1
- package/examples/appendices/plain-language.appendix.yaml +1 -1
- package/examples/appendices/technical-english.appendix.yaml +1 -1
- package/examples/google.yaml +7 -7
- package/examples/inclusive-language.yaml +7 -7
- package/examples/microsoft.yaml +7 -7
- package/examples/plain-language.yaml +7 -7
- package/examples/technical-english.yaml +7 -7
- package/lib/actions/baseline.d.ts +15 -0
- package/lib/actions/baseline.d.ts.map +1 -0
- package/lib/actions/baseline.js +51 -0
- package/lib/actions/baseline.js.map +1 -0
- package/lib/actions/lint.d.ts +51 -0
- package/lib/actions/lint.d.ts.map +1 -0
- package/lib/actions/lint.js +123 -0
- package/lib/actions/lint.js.map +1 -0
- package/lib/actions/markdoc-schema.d.ts +34 -0
- package/lib/actions/markdoc-schema.d.ts.map +1 -0
- package/lib/actions/markdoc-schema.js +106 -0
- package/lib/actions/markdoc-schema.js.map +1 -0
- package/lib/actions/readability.d.ts +25 -0
- package/lib/actions/readability.d.ts.map +1 -0
- package/lib/actions/readability.js +47 -0
- package/lib/actions/readability.js.map +1 -0
- package/lib/actions/roots.d.ts +7 -0
- package/lib/actions/roots.d.ts.map +1 -0
- package/lib/actions/roots.js +36 -0
- package/lib/actions/roots.js.map +1 -0
- package/lib/config/presets/api-descriptions.d.ts +8 -0
- package/lib/config/presets/api-descriptions.d.ts.map +1 -0
- package/lib/config/presets/api-descriptions.js +24 -0
- package/lib/config/presets/api-descriptions.js.map +1 -0
- package/lib/config/presets/google.d.ts +3 -0
- package/lib/config/presets/google.d.ts.map +1 -0
- package/lib/config/presets/google.js +1086 -0
- package/lib/config/presets/google.js.map +1 -0
- package/lib/config/presets/inclusive-language.d.ts +3 -0
- package/lib/config/presets/inclusive-language.d.ts.map +1 -0
- package/lib/config/presets/inclusive-language.js +151 -0
- package/lib/config/presets/inclusive-language.js.map +1 -0
- package/lib/config/presets/index.d.ts +16 -0
- package/lib/config/presets/index.d.ts.map +1 -0
- package/lib/config/presets/index.js +38 -0
- package/lib/config/presets/index.js.map +1 -0
- package/lib/config/presets/markdoc.d.ts +3 -0
- package/lib/config/presets/markdoc.d.ts.map +1 -0
- package/lib/config/presets/markdoc.js +45 -0
- package/lib/config/presets/markdoc.js.map +1 -0
- package/lib/config/presets/markdown-relaxed.d.ts +3 -0
- package/lib/config/presets/markdown-relaxed.d.ts.map +1 -0
- package/lib/config/presets/markdown-relaxed.js +34 -0
- package/lib/config/presets/markdown-relaxed.js.map +1 -0
- package/lib/config/presets/markdown.d.ts +11 -0
- package/lib/config/presets/markdown.d.ts.map +1 -0
- package/lib/config/presets/markdown.js +73 -0
- package/lib/config/presets/markdown.js.map +1 -0
- package/lib/config/presets/microsoft.d.ts +3 -0
- package/lib/config/presets/microsoft.d.ts.map +1 -0
- package/lib/config/presets/microsoft.js +1260 -0
- package/lib/config/presets/microsoft.js.map +1 -0
- package/lib/config/presets/minimal.d.ts +3 -0
- package/lib/config/presets/minimal.d.ts.map +1 -0
- package/lib/config/presets/minimal.js +13 -0
- package/lib/config/presets/minimal.js.map +1 -0
- package/lib/config/presets/plain-language.d.ts +3 -0
- package/lib/config/presets/plain-language.d.ts.map +1 -0
- package/lib/config/presets/plain-language.js +175 -0
- package/lib/config/presets/plain-language.js.map +1 -0
- package/lib/config/presets/prose.d.ts +3 -0
- package/lib/config/presets/prose.d.ts.map +1 -0
- package/lib/config/presets/prose.js +60 -0
- package/lib/config/presets/prose.js.map +1 -0
- package/lib/config/presets/technical-english.d.ts +22 -0
- package/lib/config/presets/technical-english.d.ts.map +1 -0
- package/lib/config/presets/technical-english.js +61 -0
- package/lib/config/presets/technical-english.js.map +1 -0
- package/lib/config/resolve.d.ts +36 -0
- package/lib/config/resolve.d.ts.map +1 -0
- package/lib/config/resolve.js +106 -0
- package/lib/config/resolve.js.map +1 -0
- package/lib/config/schema.d.ts +215 -0
- package/lib/config/schema.d.ts.map +1 -0
- package/lib/config/schema.js +152 -0
- package/lib/config/schema.js.map +1 -0
- package/lib/config/validate.d.ts +19 -0
- package/lib/config/validate.d.ts.map +1 -0
- package/lib/config/validate.js +1049 -0
- package/lib/config/validate.js.map +1 -0
- package/lib/core/auto-fix.d.ts.map +1 -0
- package/lib/core/auto-fix.js +94 -0
- package/lib/core/auto-fix.js.map +1 -0
- package/lib/core/baseline.d.ts +43 -0
- package/lib/core/baseline.d.ts.map +1 -0
- package/lib/core/baseline.js +142 -0
- package/lib/core/baseline.js.map +1 -0
- package/lib/core/case-preserve.d.ts +11 -0
- package/lib/core/case-preserve.d.ts.map +1 -0
- package/lib/core/case-preserve.js +22 -0
- package/lib/core/case-preserve.js.map +1 -0
- package/lib/core/directives.d.ts.map +1 -0
- package/lib/core/directives.js +66 -0
- package/lib/core/directives.js.map +1 -0
- package/lib/core/files.d.ts +31 -0
- package/lib/core/files.d.ts.map +1 -0
- package/lib/core/files.js +184 -0
- package/lib/core/files.js.map +1 -0
- package/lib/core/inline-code.d.ts +33 -0
- package/lib/core/inline-code.d.ts.map +1 -0
- package/lib/core/inline-code.js +50 -0
- package/lib/core/inline-code.js.map +1 -0
- package/lib/core/line-endings.d.ts +13 -0
- package/lib/core/line-endings.d.ts.map +1 -0
- package/lib/core/line-endings.js +39 -0
- package/lib/core/line-endings.js.map +1 -0
- package/lib/core/markdoc-tags.d.ts +48 -0
- package/lib/core/markdoc-tags.d.ts.map +1 -0
- package/lib/core/markdoc-tags.js +102 -0
- package/lib/core/markdoc-tags.js.map +1 -0
- package/lib/core/prose-extract.d.ts +6 -0
- package/lib/core/prose-extract.d.ts.map +1 -0
- package/lib/core/prose-extract.js +71 -0
- package/lib/core/prose-extract.js.map +1 -0
- package/lib/core/readability.d.ts +17 -0
- package/lib/core/readability.d.ts.map +1 -0
- package/lib/core/readability.js +34 -0
- package/lib/core/readability.js.map +1 -0
- package/lib/core/rule-filters.d.ts +29 -0
- package/lib/core/rule-filters.d.ts.map +1 -0
- package/lib/core/rule-filters.js +88 -0
- package/lib/core/rule-filters.js.map +1 -0
- package/lib/core/runner.d.ts +60 -0
- package/lib/core/runner.d.ts.map +1 -0
- package/lib/core/runner.js +305 -0
- package/lib/core/runner.js.map +1 -0
- package/lib/core/summary.d.ts +4 -0
- package/lib/core/summary.d.ts.map +1 -0
- package/lib/core/summary.js +37 -0
- package/lib/core/summary.js.map +1 -0
- package/lib/core/timing.d.ts +9 -0
- package/lib/core/timing.d.ts.map +1 -0
- package/lib/core/timing.js +19 -0
- package/lib/core/timing.js.map +1 -0
- package/lib/data/markdoc-realm-schema.d.ts.map +1 -0
- package/lib/data/markdoc-realm-schema.js +782 -0
- package/lib/data/markdoc-realm-schema.js.map +1 -0
- package/lib/data/proper-nouns.d.ts.map +1 -0
- package/lib/data/proper-nouns.js +42 -0
- package/lib/data/proper-nouns.js.map +1 -0
- package/lib/data/realm-front-matter-schema.d.ts +12 -0
- package/lib/data/realm-front-matter-schema.d.ts.map +1 -0
- package/lib/data/realm-front-matter-schema.js +51 -0
- package/lib/data/realm-front-matter-schema.js.map +1 -0
- package/lib/index.d.ts +81 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +114 -0
- package/lib/index.js.map +1 -0
- package/lib/metrics/formulas.d.ts +9 -0
- package/lib/metrics/formulas.d.ts.map +1 -0
- package/lib/metrics/formulas.js +59 -0
- package/lib/metrics/formulas.js.map +1 -0
- package/lib/metrics/statistics.d.ts +14 -0
- package/lib/metrics/statistics.d.ts.map +1 -0
- package/lib/metrics/statistics.js +35 -0
- package/lib/metrics/statistics.js.map +1 -0
- package/lib/parser/index.d.ts +13 -0
- package/lib/parser/index.d.ts.map +1 -0
- package/lib/parser/index.js +123 -0
- package/lib/parser/index.js.map +1 -0
- package/lib/parser/markdoc/extract-statics.d.ts +28 -0
- package/lib/parser/markdoc/extract-statics.d.ts.map +1 -0
- package/lib/parser/markdoc/extract-statics.js +80 -0
- package/lib/parser/markdoc/extract-statics.js.map +1 -0
- package/lib/parser/markdoc/pairing.d.ts +38 -0
- package/lib/parser/markdoc/pairing.d.ts.map +1 -0
- package/lib/parser/markdoc/pairing.js +77 -0
- package/lib/parser/markdoc/pairing.js.map +1 -0
- package/lib/parser/markdoc/schema.d.ts +56 -0
- package/lib/parser/markdoc/schema.d.ts.map +1 -0
- package/lib/parser/markdoc/schema.js +60 -0
- package/lib/parser/markdoc/schema.js.map +1 -0
- package/lib/parser/markdoc/span.d.ts +52 -0
- package/lib/parser/markdoc/span.d.ts.map +1 -0
- package/lib/parser/markdoc/span.js +577 -0
- package/lib/parser/markdoc/span.js.map +1 -0
- package/lib/parser/markdoc/structure.d.ts +17 -0
- package/lib/parser/markdoc/structure.d.ts.map +1 -0
- package/lib/parser/markdoc/structure.js +121 -0
- package/lib/parser/markdoc/structure.js.map +1 -0
- package/lib/parser/markdoc/syntax.d.ts +17 -0
- package/lib/parser/markdoc/syntax.d.ts.map +1 -0
- package/lib/parser/markdoc/syntax.js +262 -0
- package/lib/parser/markdoc/syntax.js.map +1 -0
- package/lib/parser/types.d.ts.map +1 -0
- package/lib/presets.d.ts +6 -0
- package/lib/presets.d.ts.map +1 -0
- package/lib/presets.js +12 -0
- package/lib/presets.js.map +1 -0
- package/lib/rules/registry.d.ts +13 -0
- package/lib/rules/registry.d.ts.map +1 -0
- package/lib/rules/registry.js +54 -0
- package/lib/rules/registry.js.map +1 -0
- package/lib/rules/scope/capitalization.d.ts.map +1 -0
- package/lib/rules/scope/capitalization.js +128 -0
- package/lib/rules/scope/capitalization.js.map +1 -0
- package/lib/rules/scope/conditional.d.ts.map +1 -0
- package/lib/rules/scope/conditional.js +93 -0
- package/lib/rules/scope/conditional.js.map +1 -0
- package/lib/rules/scope/consistency.d.ts.map +1 -0
- package/lib/rules/scope/consistency.js +118 -0
- package/lib/rules/scope/consistency.js.map +1 -0
- package/lib/rules/scope/length.d.ts.map +1 -0
- package/lib/rules/scope/length.js +50 -0
- package/lib/rules/scope/length.js.map +1 -0
- package/lib/rules/scope/max-image-size.d.ts.map +1 -0
- package/lib/rules/scope/max-image-size.js +55 -0
- package/lib/rules/scope/max-image-size.js.map +1 -0
- package/lib/rules/scope/metric.d.ts +3 -0
- package/lib/rules/scope/metric.d.ts.map +1 -0
- package/lib/rules/scope/metric.js +59 -0
- package/lib/rules/scope/metric.js.map +1 -0
- package/lib/rules/scope/occurrence.d.ts.map +1 -0
- package/lib/rules/scope/occurrence.js +41 -0
- package/lib/rules/scope/occurrence.js.map +1 -0
- package/lib/rules/scope/pattern.d.ts.map +1 -0
- package/lib/rules/scope/pattern.js +58 -0
- package/lib/rules/scope/pattern.js.map +1 -0
- package/lib/rules/scope/repetition.d.ts.map +1 -0
- package/lib/rules/scope/repetition.js +134 -0
- package/lib/rules/scope/repetition.js.map +1 -0
- package/lib/rules/scope/semantic-line-breaks.d.ts.map +1 -0
- package/lib/rules/scope/semantic-line-breaks.js +180 -0
- package/lib/rules/scope/semantic-line-breaks.js.map +1 -0
- package/lib/rules/scope/spelling.d.ts +11 -0
- package/lib/rules/scope/spelling.d.ts.map +1 -0
- package/lib/rules/scope/spelling.js +146 -0
- package/lib/rules/scope/spelling.js.map +1 -0
- package/lib/rules/scope/swap.d.ts.map +1 -0
- package/lib/rules/scope/swap.js +111 -0
- package/lib/rules/scope/swap.js.map +1 -0
- package/lib/rules/scope/title-case.d.ts +24 -0
- package/lib/rules/scope/title-case.d.ts.map +1 -0
- package/lib/rules/scope/title-case.js +216 -0
- package/lib/rules/scope/title-case.js.map +1 -0
- package/lib/rules/token/blanks-around-fences.d.ts.map +1 -0
- package/lib/rules/token/blanks-around-fences.js.map +1 -0
- package/lib/rules/token/blanks-around-headings.d.ts.map +1 -0
- package/lib/rules/token/blanks-around-headings.js +96 -0
- package/lib/rules/token/blanks-around-headings.js.map +1 -0
- package/lib/rules/token/blanks-around-lists.d.ts.map +1 -0
- package/lib/rules/token/blanks-around-lists.js +48 -0
- package/lib/rules/token/blanks-around-lists.js.map +1 -0
- package/lib/rules/token/blanks-around-tables.d.ts.map +1 -0
- package/lib/rules/token/blanks-around-tables.js +40 -0
- package/lib/rules/token/blanks-around-tables.js.map +1 -0
- package/lib/rules/token/code-block-style.d.ts.map +1 -0
- package/lib/rules/token/code-block-style.js.map +1 -0
- package/lib/rules/token/code-fence-style.d.ts.map +1 -0
- package/lib/rules/token/code-fence-style.js.map +1 -0
- package/lib/rules/token/commands-show-output.d.ts.map +1 -0
- package/lib/rules/token/commands-show-output.js.map +1 -0
- package/lib/rules/token/descriptive-link-text.d.ts.map +1 -0
- package/lib/rules/token/descriptive-link-text.js +46 -0
- package/lib/rules/token/descriptive-link-text.js.map +1 -0
- package/lib/rules/token/fenced-code-language.d.ts.map +1 -0
- package/lib/rules/token/fenced-code-language.js.map +1 -0
- package/lib/rules/token/first-line-h1.d.ts.map +1 -0
- package/lib/rules/token/first-line-h1.js +83 -0
- package/lib/rules/token/first-line-h1.js.map +1 -0
- package/lib/rules/token/front-matter.d.ts.map +1 -0
- package/lib/rules/token/front-matter.js +169 -0
- package/lib/rules/token/front-matter.js.map +1 -0
- package/lib/rules/token/heading-increment.d.ts.map +1 -0
- package/lib/rules/token/heading-increment.js +26 -0
- package/lib/rules/token/heading-increment.js.map +1 -0
- package/lib/rules/token/heading-start-left.d.ts.map +1 -0
- package/lib/rules/token/heading-start-left.js.map +1 -0
- package/lib/rules/token/heading-style.d.ts.map +1 -0
- package/lib/rules/token/heading-style.js.map +1 -0
- package/lib/rules/token/helpers.d.ts +115 -0
- package/lib/rules/token/helpers.d.ts.map +1 -0
- package/lib/rules/token/helpers.js +502 -0
- package/lib/rules/token/helpers.js.map +1 -0
- package/lib/rules/token/hr-style.d.ts.map +1 -0
- package/lib/rules/token/hr-style.js.map +1 -0
- package/lib/rules/token/index.d.ts +65 -0
- package/lib/rules/token/index.d.ts.map +1 -0
- package/lib/rules/token/index.js +157 -0
- package/lib/rules/token/index.js.map +1 -0
- package/lib/rules/token/line-length.d.ts.map +1 -0
- package/lib/rules/token/line-length.js +96 -0
- package/lib/rules/token/line-length.js.map +1 -0
- package/lib/rules/token/link-fragments.d.ts.map +1 -0
- package/lib/rules/token/link-fragments.js +398 -0
- package/lib/rules/token/link-fragments.js.map +1 -0
- package/lib/rules/token/link-image-reference-definitions.d.ts.map +1 -0
- package/lib/rules/token/link-image-reference-definitions.js.map +1 -0
- package/lib/rules/token/link-image-style.d.ts.map +1 -0
- package/lib/rules/token/link-image-style.js +138 -0
- package/lib/rules/token/link-image-style.js.map +1 -0
- package/lib/rules/token/list-indent.d.ts.map +1 -0
- package/lib/rules/token/list-indent.js.map +1 -0
- package/lib/rules/token/list-length.d.ts.map +1 -0
- package/lib/rules/token/list-length.js +31 -0
- package/lib/rules/token/list-length.js.map +1 -0
- package/lib/rules/token/list-marker-space.d.ts.map +1 -0
- package/lib/rules/token/list-marker-space.js.map +1 -0
- package/lib/rules/token/markdoc-attributes.d.ts.map +1 -0
- package/lib/rules/token/markdoc-attributes.js +198 -0
- package/lib/rules/token/markdoc-attributes.js.map +1 -0
- package/lib/rules/token/markdoc-pairing.d.ts.map +1 -0
- package/lib/rules/token/markdoc-pairing.js +65 -0
- package/lib/rules/token/markdoc-pairing.js.map +1 -0
- package/lib/rules/token/markdoc-syntax.d.ts.map +1 -0
- package/lib/rules/token/markdoc-syntax.js +84 -0
- package/lib/rules/token/markdoc-syntax.js.map +1 -0
- package/lib/rules/token/markdoc-unknown-tag.d.ts.map +1 -0
- package/lib/rules/token/markdoc-unknown-tag.js +44 -0
- package/lib/rules/token/markdoc-unknown-tag.js.map +1 -0
- package/lib/rules/token/no-alt-text.d.ts.map +1 -0
- package/lib/rules/token/no-alt-text.js +43 -0
- package/lib/rules/token/no-alt-text.js.map +1 -0
- package/lib/rules/token/no-bare-urls.d.ts.map +1 -0
- package/lib/rules/token/no-bare-urls.js +74 -0
- package/lib/rules/token/no-bare-urls.js.map +1 -0
- package/lib/rules/token/no-blanks-blockquote.d.ts.map +1 -0
- package/lib/rules/token/no-blanks-blockquote.js.map +1 -0
- package/lib/rules/token/no-duplicate-heading.d.ts.map +1 -0
- package/lib/rules/token/no-duplicate-heading.js +89 -0
- package/lib/rules/token/no-duplicate-heading.js.map +1 -0
- package/lib/rules/token/no-duplicate-link-destinations.d.ts.map +1 -0
- package/lib/rules/token/no-duplicate-link-destinations.js +54 -0
- package/lib/rules/token/no-duplicate-link-destinations.js.map +1 -0
- package/lib/rules/token/no-emphasis-as-heading.d.ts.map +1 -0
- package/lib/rules/token/no-emphasis-as-heading.js +39 -0
- package/lib/rules/token/no-emphasis-as-heading.js.map +1 -0
- package/lib/rules/token/no-empty-headings.d.ts.map +1 -0
- package/lib/rules/token/no-empty-headings.js +21 -0
- package/lib/rules/token/no-empty-headings.js.map +1 -0
- package/lib/rules/token/no-empty-links.d.ts.map +1 -0
- package/lib/rules/token/no-empty-links.js.map +1 -0
- package/lib/rules/token/no-hard-tabs.d.ts.map +1 -0
- package/lib/rules/token/no-hard-tabs.js.map +1 -0
- package/lib/rules/token/no-inline-html.d.ts.map +1 -0
- package/lib/rules/token/no-inline-html.js +41 -0
- package/lib/rules/token/no-inline-html.js.map +1 -0
- package/lib/rules/token/no-multiple-blanks.d.ts.map +1 -0
- package/lib/rules/token/no-multiple-blanks.js.map +1 -0
- package/lib/rules/token/no-multiple-space-atx.d.ts +9 -0
- package/lib/rules/token/no-multiple-space-atx.d.ts.map +1 -0
- package/lib/rules/token/no-multiple-space-atx.js +46 -0
- package/lib/rules/token/no-multiple-space-atx.js.map +1 -0
- package/lib/rules/token/no-multiple-space-closed-atx.d.ts.map +1 -0
- package/lib/rules/token/no-multiple-space-closed-atx.js.map +1 -0
- package/lib/rules/token/no-reversed-links.d.ts.map +1 -0
- package/lib/rules/token/no-reversed-links.js.map +1 -0
- package/lib/rules/token/no-space-in-code.d.ts.map +1 -0
- package/lib/rules/token/no-space-in-code.js.map +1 -0
- package/lib/rules/token/no-space-in-emphasis.d.ts.map +1 -0
- package/lib/rules/token/no-space-in-emphasis.js +72 -0
- package/lib/rules/token/no-space-in-emphasis.js.map +1 -0
- package/lib/rules/token/no-space-in-links.d.ts.map +1 -0
- package/lib/rules/token/no-space-in-links.js.map +1 -0
- package/lib/rules/token/no-trailing-punctuation.d.ts.map +1 -0
- package/lib/rules/token/no-trailing-punctuation.js.map +1 -0
- package/lib/rules/token/no-trailing-spaces.d.ts.map +1 -0
- package/lib/rules/token/no-trailing-spaces.js.map +1 -0
- package/lib/rules/token/ol-prefix.d.ts.map +1 -0
- package/lib/rules/token/ol-prefix.js.map +1 -0
- package/lib/rules/token/proper-names.d.ts.map +1 -0
- package/lib/rules/token/proper-names.js +87 -0
- package/lib/rules/token/proper-names.js.map +1 -0
- package/lib/rules/token/reference-links-images.d.ts.map +1 -0
- package/lib/rules/token/reference-links-images.js.map +1 -0
- package/lib/rules/token/required-headings.d.ts.map +1 -0
- package/lib/rules/token/required-headings.js +73 -0
- package/lib/rules/token/required-headings.js.map +1 -0
- package/lib/rules/token/single-h1.d.ts.map +1 -0
- package/lib/rules/token/single-h1.js +43 -0
- package/lib/rules/token/single-h1.js.map +1 -0
- package/lib/rules/token/table-column-count.d.ts.map +1 -0
- package/lib/rules/token/table-column-count.js.map +1 -0
- package/lib/rules/token/table-column-style.d.ts.map +1 -0
- package/lib/rules/token/table-column-style.js +162 -0
- package/lib/rules/token/table-column-style.js.map +1 -0
- package/lib/rules/token/table-pipe-style.d.ts.map +1 -0
- package/lib/rules/token/table-pipe-style.js.map +1 -0
- package/lib/rules/token/ul-indent.d.ts.map +1 -0
- package/lib/rules/token/ul-indent.js.map +1 -0
- package/lib/rules/token/ul-style.d.ts.map +1 -0
- package/lib/rules/token/ul-style.js +70 -0
- package/lib/rules/token/ul-style.js.map +1 -0
- package/lib/rules/types.d.ts +62 -0
- package/lib/rules/types.d.ts.map +1 -0
- package/lib/rules/utils.d.ts +18 -0
- package/lib/rules/utils.d.ts.map +1 -0
- package/lib/rules/utils.js +75 -0
- package/lib/rules/utils.js.map +1 -0
- package/lib/scopes/extractor.d.ts +6 -0
- package/lib/scopes/extractor.d.ts.map +1 -0
- package/lib/scopes/extractor.js +398 -0
- package/lib/scopes/extractor.js.map +1 -0
- package/lib/scopes/selector.d.ts +26 -0
- package/lib/scopes/selector.d.ts.map +1 -0
- package/lib/scopes/selector.js +78 -0
- package/lib/scopes/selector.js.map +1 -0
- package/lib/scopes/sentences.d.ts +13 -0
- package/lib/scopes/sentences.d.ts.map +1 -0
- package/lib/scopes/sentences.js +237 -0
- package/lib/scopes/sentences.js.map +1 -0
- package/lib/scopes/types.d.ts +35 -0
- package/lib/scopes/types.d.ts.map +1 -0
- package/lib/scopes/vocabulary.d.ts +12 -0
- package/lib/scopes/vocabulary.d.ts.map +1 -0
- package/lib/scopes/vocabulary.js +56 -0
- package/lib/scopes/vocabulary.js.map +1 -0
- package/lib/types/assertions.d.ts +97 -0
- package/lib/types/assertions.d.ts.map +1 -0
- package/lib/types/reporting.d.ts +23 -0
- package/lib/types/reporting.d.ts.map +1 -0
- package/lib/types/rules.d.ts +53 -0
- package/lib/types/rules.d.ts.map +1 -0
- package/lib/types/validation.d.ts +5 -0
- package/lib/types/validation.d.ts.map +1 -0
- package/lib/utils/is-plain-object.d.ts +2 -0
- package/lib/utils/is-plain-object.d.ts.map +1 -0
- package/lib/utils/is-plain-object.js +5 -0
- package/lib/utils/is-plain-object.js.map +1 -0
- package/package.json +58 -61
- package/presets/google/PROVENANCE.md +217 -221
- package/presets/inclusive-language/PROVENANCE.md +20 -19
- package/presets/microsoft/PROVENANCE.md +242 -243
- package/presets/plain-language/PROVENANCE.md +66 -60
- package/presets/technical-english/PROVENANCE.md +5 -5
- package/skills/recheck-config/SKILL.md +70 -20
- package/skills/recheck-lint/SKILL.md +37 -13
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -228
- package/dist/cli.js.map +0 -1
- package/dist/commands/baseline.d.ts +0 -10
- package/dist/commands/baseline.d.ts.map +0 -1
- package/dist/commands/baseline.js +0 -59
- package/dist/commands/baseline.js.map +0 -1
- package/dist/commands/markdoc-schema.d.ts +0 -17
- package/dist/commands/markdoc-schema.d.ts.map +0 -1
- package/dist/commands/markdoc-schema.js +0 -127
- package/dist/commands/markdoc-schema.js.map +0 -1
- package/dist/commands/readability.d.ts +0 -10
- package/dist/commands/readability.d.ts.map +0 -1
- package/dist/commands/readability.js +0 -90
- package/dist/commands/readability.js.map +0 -1
- package/dist/commands/run.d.ts +0 -21
- package/dist/commands/run.d.ts.map +0 -1
- package/dist/commands/run.js +0 -236
- package/dist/commands/run.js.map +0 -1
- package/dist/commands/validate.d.ts +0 -8
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/validate.js +0 -43
- package/dist/commands/validate.js.map +0 -1
- package/dist/config/load.d.ts +0 -33
- package/dist/config/load.d.ts.map +0 -1
- package/dist/config/load.js +0 -98
- package/dist/config/load.js.map +0 -1
- package/dist/config/presets/api-descriptions.d.ts +0 -8
- package/dist/config/presets/api-descriptions.d.ts.map +0 -1
- package/dist/config/presets/api-descriptions.js +0 -24
- package/dist/config/presets/api-descriptions.js.map +0 -1
- package/dist/config/presets/google.d.ts +0 -3
- package/dist/config/presets/google.d.ts.map +0 -1
- package/dist/config/presets/google.js +0 -1671
- package/dist/config/presets/google.js.map +0 -1
- package/dist/config/presets/inclusive-language.d.ts +0 -3
- package/dist/config/presets/inclusive-language.d.ts.map +0 -1
- package/dist/config/presets/inclusive-language.js +0 -321
- package/dist/config/presets/inclusive-language.js.map +0 -1
- package/dist/config/presets/index.d.ts +0 -67
- package/dist/config/presets/index.d.ts.map +0 -1
- package/dist/config/presets/index.js +0 -141
- package/dist/config/presets/index.js.map +0 -1
- package/dist/config/presets/markdoc.d.ts +0 -21
- package/dist/config/presets/markdoc.d.ts.map +0 -1
- package/dist/config/presets/markdoc.js +0 -101
- package/dist/config/presets/markdoc.js.map +0 -1
- package/dist/config/presets/markdown-relaxed.d.ts +0 -3
- package/dist/config/presets/markdown-relaxed.d.ts.map +0 -1
- package/dist/config/presets/markdown-relaxed.js +0 -98
- package/dist/config/presets/markdown-relaxed.js.map +0 -1
- package/dist/config/presets/markdown.d.ts +0 -43
- package/dist/config/presets/markdown.d.ts.map +0 -1
- package/dist/config/presets/markdown.js +0 -132
- package/dist/config/presets/markdown.js.map +0 -1
- package/dist/config/presets/microsoft.d.ts +0 -3
- package/dist/config/presets/microsoft.d.ts.map +0 -1
- package/dist/config/presets/microsoft.js +0 -2268
- package/dist/config/presets/microsoft.js.map +0 -1
- package/dist/config/presets/minimal.d.ts +0 -3
- package/dist/config/presets/minimal.d.ts.map +0 -1
- package/dist/config/presets/minimal.js +0 -21
- package/dist/config/presets/minimal.js.map +0 -1
- package/dist/config/presets/plain-language.d.ts +0 -3
- package/dist/config/presets/plain-language.d.ts.map +0 -1
- package/dist/config/presets/plain-language.js +0 -351
- package/dist/config/presets/plain-language.js.map +0 -1
- package/dist/config/presets/prose.d.ts +0 -52
- package/dist/config/presets/prose.d.ts.map +0 -1
- package/dist/config/presets/prose.js +0 -138
- package/dist/config/presets/prose.js.map +0 -1
- package/dist/config/presets/technical-english.d.ts +0 -34
- package/dist/config/presets/technical-english.d.ts.map +0 -1
- package/dist/config/presets/technical-english.js +0 -79
- package/dist/config/presets/technical-english.js.map +0 -1
- package/dist/config/schema.d.ts +0 -226
- package/dist/config/schema.d.ts.map +0 -1
- package/dist/config/schema.js +0 -196
- package/dist/config/schema.js.map +0 -1
- package/dist/config/validate.d.ts +0 -22
- package/dist/config/validate.d.ts.map +0 -1
- package/dist/config/validate.js +0 -1315
- package/dist/config/validate.js.map +0 -1
- package/dist/core/auto-fix.d.ts.map +0 -1
- package/dist/core/auto-fix.js +0 -101
- package/dist/core/auto-fix.js.map +0 -1
- package/dist/core/baseline.d.ts +0 -49
- package/dist/core/baseline.d.ts.map +0 -1
- package/dist/core/baseline.js +0 -0
- package/dist/core/baseline.js.map +0 -1
- package/dist/core/case-preserve.d.ts +0 -46
- package/dist/core/case-preserve.d.ts.map +0 -1
- package/dist/core/case-preserve.js +0 -57
- package/dist/core/case-preserve.js.map +0 -1
- package/dist/core/directives.d.ts.map +0 -1
- package/dist/core/directives.js +0 -73
- package/dist/core/directives.js.map +0 -1
- package/dist/core/files.d.ts +0 -69
- package/dist/core/files.d.ts.map +0 -1
- package/dist/core/files.js +0 -260
- package/dist/core/files.js.map +0 -1
- package/dist/core/inline-code.d.ts +0 -87
- package/dist/core/inline-code.d.ts.map +0 -1
- package/dist/core/inline-code.js +0 -104
- package/dist/core/inline-code.js.map +0 -1
- package/dist/core/line-endings.d.ts +0 -32
- package/dist/core/line-endings.d.ts.map +0 -1
- package/dist/core/line-endings.js +0 -65
- package/dist/core/line-endings.js.map +0 -1
- package/dist/core/markdoc-tags.d.ts +0 -79
- package/dist/core/markdoc-tags.d.ts.map +0 -1
- package/dist/core/markdoc-tags.js +0 -131
- package/dist/core/markdoc-tags.js.map +0 -1
- package/dist/core/prose-extract.d.ts +0 -6
- package/dist/core/prose-extract.d.ts.map +0 -1
- package/dist/core/prose-extract.js +0 -79
- package/dist/core/prose-extract.js.map +0 -1
- package/dist/core/readability.d.ts +0 -17
- package/dist/core/readability.d.ts.map +0 -1
- package/dist/core/readability.js +0 -37
- package/dist/core/readability.js.map +0 -1
- package/dist/core/rule-filters.d.ts +0 -45
- package/dist/core/rule-filters.d.ts.map +0 -1
- package/dist/core/rule-filters.js +0 -118
- package/dist/core/rule-filters.js.map +0 -1
- package/dist/core/runner.d.ts +0 -98
- package/dist/core/runner.d.ts.map +0 -1
- package/dist/core/runner.js +0 -401
- package/dist/core/runner.js.map +0 -1
- package/dist/core/timing.d.ts +0 -24
- package/dist/core/timing.d.ts.map +0 -1
- package/dist/core/timing.js +0 -39
- package/dist/core/timing.js.map +0 -1
- package/dist/data/markdoc-realm-schema.d.ts.map +0 -1
- package/dist/data/markdoc-realm-schema.js +0 -798
- package/dist/data/markdoc-realm-schema.js.map +0 -1
- package/dist/data/proper-nouns.d.ts.map +0 -1
- package/dist/data/proper-nouns.js +0 -47
- package/dist/data/proper-nouns.js.map +0 -1
- package/dist/data/realm-front-matter-schema.d.ts +0 -28
- package/dist/data/realm-front-matter-schema.d.ts.map +0 -1
- package/dist/data/realm-front-matter-schema.js +0 -73
- package/dist/data/realm-front-matter-schema.js.map +0 -1
- package/dist/index.d.ts +0 -90
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -152
- package/dist/index.js.map +0 -1
- package/dist/metrics/formulas.d.ts +0 -17
- package/dist/metrics/formulas.d.ts.map +0 -1
- package/dist/metrics/formulas.js +0 -70
- package/dist/metrics/formulas.js.map +0 -1
- package/dist/metrics/statistics.d.ts +0 -27
- package/dist/metrics/statistics.d.ts.map +0 -1
- package/dist/metrics/statistics.js +0 -56
- package/dist/metrics/statistics.js.map +0 -1
- package/dist/parser/index.d.ts +0 -19
- package/dist/parser/index.d.ts.map +0 -1
- package/dist/parser/index.js +0 -174
- package/dist/parser/index.js.map +0 -1
- package/dist/parser/markdoc/extract-statics.d.ts +0 -45
- package/dist/parser/markdoc/extract-statics.d.ts.map +0 -1
- package/dist/parser/markdoc/extract-statics.js +0 -139
- package/dist/parser/markdoc/extract-statics.js.map +0 -1
- package/dist/parser/markdoc/pairing.d.ts +0 -63
- package/dist/parser/markdoc/pairing.d.ts.map +0 -1
- package/dist/parser/markdoc/pairing.js +0 -94
- package/dist/parser/markdoc/pairing.js.map +0 -1
- package/dist/parser/markdoc/schema.d.ts +0 -85
- package/dist/parser/markdoc/schema.d.ts.map +0 -1
- package/dist/parser/markdoc/schema.js +0 -86
- package/dist/parser/markdoc/schema.js.map +0 -1
- package/dist/parser/markdoc/span.d.ts +0 -64
- package/dist/parser/markdoc/span.d.ts.map +0 -1
- package/dist/parser/markdoc/span.js +0 -729
- package/dist/parser/markdoc/span.js.map +0 -1
- package/dist/parser/markdoc/structure.d.ts +0 -28
- package/dist/parser/markdoc/structure.d.ts.map +0 -1
- package/dist/parser/markdoc/structure.js +0 -153
- package/dist/parser/markdoc/structure.js.map +0 -1
- package/dist/parser/markdoc/syntax.d.ts +0 -44
- package/dist/parser/markdoc/syntax.d.ts.map +0 -1
- package/dist/parser/markdoc/syntax.js +0 -317
- package/dist/parser/markdoc/syntax.js.map +0 -1
- package/dist/parser/types.d.ts.map +0 -1
- package/dist/reporter/fixes.d.ts +0 -3
- package/dist/reporter/fixes.d.ts.map +0 -1
- package/dist/reporter/fixes.js +0 -41
- package/dist/reporter/fixes.js.map +0 -1
- package/dist/reporter/formats/github-actions.d.ts +0 -6
- package/dist/reporter/formats/github-actions.d.ts.map +0 -1
- package/dist/reporter/formats/github-actions.js +0 -20
- package/dist/reporter/formats/github-actions.js.map +0 -1
- package/dist/reporter/formats/json.d.ts +0 -10
- package/dist/reporter/formats/json.d.ts.map +0 -1
- package/dist/reporter/formats/json.js +0 -25
- package/dist/reporter/formats/json.js.map +0 -1
- package/dist/reporter/formats/sarif.d.ts +0 -10
- package/dist/reporter/formats/sarif.d.ts.map +0 -1
- package/dist/reporter/formats/sarif.js +0 -66
- package/dist/reporter/formats/sarif.js.map +0 -1
- package/dist/reporter/formats/table.d.ts +0 -6
- package/dist/reporter/formats/table.d.ts.map +0 -1
- package/dist/reporter/formats/table.js +0 -43
- package/dist/reporter/formats/table.js.map +0 -1
- package/dist/reporter/index.d.ts +0 -10
- package/dist/reporter/index.d.ts.map +0 -1
- package/dist/reporter/index.js +0 -42
- package/dist/reporter/index.js.map +0 -1
- package/dist/reporter/prioritize-problems.d.ts +0 -7
- package/dist/reporter/prioritize-problems.d.ts.map +0 -1
- package/dist/reporter/prioritize-problems.js +0 -29
- package/dist/reporter/prioritize-problems.js.map +0 -1
- package/dist/reporter/statistics.d.ts +0 -10
- package/dist/reporter/statistics.d.ts.map +0 -1
- package/dist/reporter/statistics.js +0 -52
- package/dist/reporter/statistics.js.map +0 -1
- package/dist/reporter/summary.d.ts +0 -10
- package/dist/reporter/summary.d.ts.map +0 -1
- package/dist/reporter/summary.js +0 -49
- package/dist/reporter/summary.js.map +0 -1
- package/dist/rules/registry.d.ts +0 -15
- package/dist/rules/registry.d.ts.map +0 -1
- package/dist/rules/registry.js +0 -81
- package/dist/rules/registry.js.map +0 -1
- package/dist/rules/scope/capitalization.d.ts.map +0 -1
- package/dist/rules/scope/capitalization.js +0 -164
- package/dist/rules/scope/capitalization.js.map +0 -1
- package/dist/rules/scope/conditional.d.ts.map +0 -1
- package/dist/rules/scope/conditional.js +0 -112
- package/dist/rules/scope/conditional.js.map +0 -1
- package/dist/rules/scope/consistency.d.ts.map +0 -1
- package/dist/rules/scope/consistency.js +0 -179
- package/dist/rules/scope/consistency.js.map +0 -1
- package/dist/rules/scope/length.d.ts.map +0 -1
- package/dist/rules/scope/length.js +0 -73
- package/dist/rules/scope/length.js.map +0 -1
- package/dist/rules/scope/max-image-size.d.ts.map +0 -1
- package/dist/rules/scope/max-image-size.js +0 -65
- package/dist/rules/scope/max-image-size.js.map +0 -1
- package/dist/rules/scope/metric.d.ts +0 -5
- package/dist/rules/scope/metric.d.ts.map +0 -1
- package/dist/rules/scope/metric.js +0 -74
- package/dist/rules/scope/metric.js.map +0 -1
- package/dist/rules/scope/occurrence.d.ts.map +0 -1
- package/dist/rules/scope/occurrence.js +0 -48
- package/dist/rules/scope/occurrence.js.map +0 -1
- package/dist/rules/scope/pattern.d.ts.map +0 -1
- package/dist/rules/scope/pattern.js +0 -75
- package/dist/rules/scope/pattern.js.map +0 -1
- package/dist/rules/scope/repetition.d.ts.map +0 -1
- package/dist/rules/scope/repetition.js +0 -139
- package/dist/rules/scope/repetition.js.map +0 -1
- package/dist/rules/scope/semantic-line-breaks.d.ts.map +0 -1
- package/dist/rules/scope/semantic-line-breaks.js +0 -236
- package/dist/rules/scope/semantic-line-breaks.js.map +0 -1
- package/dist/rules/scope/spelling.d.ts +0 -27
- package/dist/rules/scope/spelling.d.ts.map +0 -1
- package/dist/rules/scope/spelling.js +0 -227
- package/dist/rules/scope/spelling.js.map +0 -1
- package/dist/rules/scope/swap.d.ts.map +0 -1
- package/dist/rules/scope/swap.js +0 -149
- package/dist/rules/scope/swap.js.map +0 -1
- package/dist/rules/scope/title-case.d.ts +0 -46
- package/dist/rules/scope/title-case.d.ts.map +0 -1
- package/dist/rules/scope/title-case.js +0 -301
- package/dist/rules/scope/title-case.js.map +0 -1
- package/dist/rules/token/blanks-around-fences.d.ts.map +0 -1
- package/dist/rules/token/blanks-around-fences.js.map +0 -1
- package/dist/rules/token/blanks-around-headings.d.ts.map +0 -1
- package/dist/rules/token/blanks-around-headings.js +0 -108
- package/dist/rules/token/blanks-around-headings.js.map +0 -1
- package/dist/rules/token/blanks-around-lists.d.ts.map +0 -1
- package/dist/rules/token/blanks-around-lists.js +0 -56
- package/dist/rules/token/blanks-around-lists.js.map +0 -1
- package/dist/rules/token/blanks-around-tables.d.ts.map +0 -1
- package/dist/rules/token/blanks-around-tables.js +0 -42
- package/dist/rules/token/blanks-around-tables.js.map +0 -1
- package/dist/rules/token/code-block-style.d.ts.map +0 -1
- package/dist/rules/token/code-block-style.js.map +0 -1
- package/dist/rules/token/code-fence-style.d.ts.map +0 -1
- package/dist/rules/token/code-fence-style.js.map +0 -1
- package/dist/rules/token/commands-show-output.d.ts.map +0 -1
- package/dist/rules/token/commands-show-output.js.map +0 -1
- package/dist/rules/token/descriptive-link-text.d.ts.map +0 -1
- package/dist/rules/token/descriptive-link-text.js +0 -53
- package/dist/rules/token/descriptive-link-text.js.map +0 -1
- package/dist/rules/token/fenced-code-language.d.ts.map +0 -1
- package/dist/rules/token/fenced-code-language.js.map +0 -1
- package/dist/rules/token/first-line-h1.d.ts.map +0 -1
- package/dist/rules/token/first-line-h1.js +0 -107
- package/dist/rules/token/first-line-h1.js.map +0 -1
- package/dist/rules/token/front-matter.d.ts.map +0 -1
- package/dist/rules/token/front-matter.js +0 -177
- package/dist/rules/token/front-matter.js.map +0 -1
- package/dist/rules/token/heading-increment.d.ts.map +0 -1
- package/dist/rules/token/heading-increment.js +0 -27
- package/dist/rules/token/heading-increment.js.map +0 -1
- package/dist/rules/token/heading-start-left.d.ts.map +0 -1
- package/dist/rules/token/heading-start-left.js.map +0 -1
- package/dist/rules/token/heading-style.d.ts.map +0 -1
- package/dist/rules/token/heading-style.js.map +0 -1
- package/dist/rules/token/helpers.d.ts +0 -313
- package/dist/rules/token/helpers.d.ts.map +0 -1
- package/dist/rules/token/helpers.js +0 -746
- package/dist/rules/token/helpers.js.map +0 -1
- package/dist/rules/token/hr-style.d.ts.map +0 -1
- package/dist/rules/token/hr-style.js.map +0 -1
- package/dist/rules/token/index.d.ts +0 -76
- package/dist/rules/token/index.d.ts.map +0 -1
- package/dist/rules/token/index.js +0 -229
- package/dist/rules/token/index.js.map +0 -1
- package/dist/rules/token/line-length.d.ts.map +0 -1
- package/dist/rules/token/line-length.js +0 -120
- package/dist/rules/token/line-length.js.map +0 -1
- package/dist/rules/token/link-fragments.d.ts.map +0 -1
- package/dist/rules/token/link-fragments.js +0 -393
- package/dist/rules/token/link-fragments.js.map +0 -1
- package/dist/rules/token/link-image-reference-definitions.d.ts.map +0 -1
- package/dist/rules/token/link-image-reference-definitions.js.map +0 -1
- package/dist/rules/token/link-image-style.d.ts.map +0 -1
- package/dist/rules/token/link-image-style.js +0 -131
- package/dist/rules/token/link-image-style.js.map +0 -1
- package/dist/rules/token/list-indent.d.ts.map +0 -1
- package/dist/rules/token/list-indent.js.map +0 -1
- package/dist/rules/token/list-length.d.ts.map +0 -1
- package/dist/rules/token/list-length.js +0 -55
- package/dist/rules/token/list-length.js.map +0 -1
- package/dist/rules/token/list-marker-space.d.ts.map +0 -1
- package/dist/rules/token/list-marker-space.js.map +0 -1
- package/dist/rules/token/markdoc-attributes.d.ts.map +0 -1
- package/dist/rules/token/markdoc-attributes.js +0 -269
- package/dist/rules/token/markdoc-attributes.js.map +0 -1
- package/dist/rules/token/markdoc-pairing.d.ts.map +0 -1
- package/dist/rules/token/markdoc-pairing.js +0 -73
- package/dist/rules/token/markdoc-pairing.js.map +0 -1
- package/dist/rules/token/markdoc-syntax.d.ts.map +0 -1
- package/dist/rules/token/markdoc-syntax.js +0 -119
- package/dist/rules/token/markdoc-syntax.js.map +0 -1
- package/dist/rules/token/markdoc-unknown-tag.d.ts.map +0 -1
- package/dist/rules/token/markdoc-unknown-tag.js +0 -64
- package/dist/rules/token/markdoc-unknown-tag.js.map +0 -1
- package/dist/rules/token/no-alt-text.d.ts.map +0 -1
- package/dist/rules/token/no-alt-text.js +0 -47
- package/dist/rules/token/no-alt-text.js.map +0 -1
- package/dist/rules/token/no-bare-urls.d.ts.map +0 -1
- package/dist/rules/token/no-bare-urls.js +0 -88
- package/dist/rules/token/no-bare-urls.js.map +0 -1
- package/dist/rules/token/no-blanks-blockquote.d.ts.map +0 -1
- package/dist/rules/token/no-blanks-blockquote.js.map +0 -1
- package/dist/rules/token/no-duplicate-heading.d.ts.map +0 -1
- package/dist/rules/token/no-duplicate-heading.js +0 -101
- package/dist/rules/token/no-duplicate-heading.js.map +0 -1
- package/dist/rules/token/no-duplicate-link-destinations.d.ts.map +0 -1
- package/dist/rules/token/no-duplicate-link-destinations.js +0 -65
- package/dist/rules/token/no-duplicate-link-destinations.js.map +0 -1
- package/dist/rules/token/no-emphasis-as-heading.d.ts.map +0 -1
- package/dist/rules/token/no-emphasis-as-heading.js +0 -44
- package/dist/rules/token/no-emphasis-as-heading.js.map +0 -1
- package/dist/rules/token/no-empty-headings.d.ts.map +0 -1
- package/dist/rules/token/no-empty-headings.js +0 -28
- package/dist/rules/token/no-empty-headings.js.map +0 -1
- package/dist/rules/token/no-empty-links.d.ts.map +0 -1
- package/dist/rules/token/no-empty-links.js.map +0 -1
- package/dist/rules/token/no-hard-tabs.d.ts.map +0 -1
- package/dist/rules/token/no-hard-tabs.js.map +0 -1
- package/dist/rules/token/no-inline-html.d.ts.map +0 -1
- package/dist/rules/token/no-inline-html.js +0 -45
- package/dist/rules/token/no-inline-html.js.map +0 -1
- package/dist/rules/token/no-multiple-blanks.d.ts.map +0 -1
- package/dist/rules/token/no-multiple-blanks.js.map +0 -1
- package/dist/rules/token/no-multiple-space-atx.d.ts +0 -13
- package/dist/rules/token/no-multiple-space-atx.d.ts.map +0 -1
- package/dist/rules/token/no-multiple-space-atx.js +0 -50
- package/dist/rules/token/no-multiple-space-atx.js.map +0 -1
- package/dist/rules/token/no-multiple-space-closed-atx.d.ts.map +0 -1
- package/dist/rules/token/no-multiple-space-closed-atx.js.map +0 -1
- package/dist/rules/token/no-reversed-links.d.ts.map +0 -1
- package/dist/rules/token/no-reversed-links.js.map +0 -1
- package/dist/rules/token/no-space-in-code.d.ts.map +0 -1
- package/dist/rules/token/no-space-in-code.js.map +0 -1
- package/dist/rules/token/no-space-in-emphasis.d.ts.map +0 -1
- package/dist/rules/token/no-space-in-emphasis.js +0 -79
- package/dist/rules/token/no-space-in-emphasis.js.map +0 -1
- package/dist/rules/token/no-space-in-links.d.ts.map +0 -1
- package/dist/rules/token/no-space-in-links.js.map +0 -1
- package/dist/rules/token/no-trailing-punctuation.d.ts.map +0 -1
- package/dist/rules/token/no-trailing-punctuation.js.map +0 -1
- package/dist/rules/token/no-trailing-spaces.d.ts.map +0 -1
- package/dist/rules/token/no-trailing-spaces.js.map +0 -1
- package/dist/rules/token/ol-prefix.d.ts.map +0 -1
- package/dist/rules/token/ol-prefix.js.map +0 -1
- package/dist/rules/token/proper-names.d.ts.map +0 -1
- package/dist/rules/token/proper-names.js +0 -93
- package/dist/rules/token/proper-names.js.map +0 -1
- package/dist/rules/token/reference-links-images.d.ts.map +0 -1
- package/dist/rules/token/reference-links-images.js.map +0 -1
- package/dist/rules/token/required-headings.d.ts.map +0 -1
- package/dist/rules/token/required-headings.js +0 -83
- package/dist/rules/token/required-headings.js.map +0 -1
- package/dist/rules/token/single-h1.d.ts.map +0 -1
- package/dist/rules/token/single-h1.js +0 -56
- package/dist/rules/token/single-h1.js.map +0 -1
- package/dist/rules/token/table-column-count.d.ts.map +0 -1
- package/dist/rules/token/table-column-count.js.map +0 -1
- package/dist/rules/token/table-column-style.d.ts.map +0 -1
- package/dist/rules/token/table-column-style.js +0 -179
- package/dist/rules/token/table-column-style.js.map +0 -1
- package/dist/rules/token/table-pipe-style.d.ts.map +0 -1
- package/dist/rules/token/table-pipe-style.js.map +0 -1
- package/dist/rules/token/ul-indent.d.ts.map +0 -1
- package/dist/rules/token/ul-indent.js.map +0 -1
- package/dist/rules/token/ul-style.d.ts.map +0 -1
- package/dist/rules/token/ul-style.js +0 -80
- package/dist/rules/token/ul-style.js.map +0 -1
- package/dist/rules/types.d.ts +0 -83
- package/dist/rules/types.d.ts.map +0 -1
- package/dist/rules/utils.d.ts +0 -31
- package/dist/rules/utils.d.ts.map +0 -1
- package/dist/rules/utils.js +0 -90
- package/dist/rules/utils.js.map +0 -1
- package/dist/scopes/extractor.d.ts +0 -7
- package/dist/scopes/extractor.d.ts.map +0 -1
- package/dist/scopes/extractor.js +0 -536
- package/dist/scopes/extractor.js.map +0 -1
- package/dist/scopes/selector.d.ts +0 -51
- package/dist/scopes/selector.d.ts.map +0 -1
- package/dist/scopes/selector.js +0 -121
- package/dist/scopes/selector.js.map +0 -1
- package/dist/scopes/sentences.d.ts +0 -15
- package/dist/scopes/sentences.d.ts.map +0 -1
- package/dist/scopes/sentences.js +0 -202
- package/dist/scopes/sentences.js.map +0 -1
- package/dist/scopes/types.d.ts +0 -46
- package/dist/scopes/types.d.ts.map +0 -1
- package/dist/scopes/vocabulary.d.ts +0 -16
- package/dist/scopes/vocabulary.d.ts.map +0 -1
- package/dist/scopes/vocabulary.js +0 -70
- package/dist/scopes/vocabulary.js.map +0 -1
- package/dist/types/assertions.d.ts +0 -121
- package/dist/types/assertions.d.ts.map +0 -1
- package/dist/types/reporting.d.ts +0 -32
- package/dist/types/reporting.d.ts.map +0 -1
- package/dist/types/rules.d.ts +0 -41
- package/dist/types/rules.d.ts.map +0 -1
- package/dist/types/validation.d.ts +0 -6
- package/dist/types/validation.d.ts.map +0 -1
- /package/{dist → lib}/core/auto-fix.d.ts +0 -0
- /package/{dist → lib}/core/directives.d.ts +0 -0
- /package/{dist → lib}/data/markdoc-realm-schema.d.ts +0 -0
- /package/{dist → lib}/data/proper-nouns.d.ts +0 -0
- /package/{dist → lib}/metrics/index.d.ts +0 -0
- /package/{dist → lib}/metrics/index.d.ts.map +0 -0
- /package/{dist → lib}/metrics/index.js +0 -0
- /package/{dist → lib}/metrics/index.js.map +0 -0
- /package/{dist → lib}/parser/types.d.ts +0 -0
- /package/{dist → lib}/parser/types.js +0 -0
- /package/{dist → lib}/parser/types.js.map +0 -0
- /package/{dist → lib}/rules/scope/capitalization.d.ts +0 -0
- /package/{dist → lib}/rules/scope/conditional.d.ts +0 -0
- /package/{dist → lib}/rules/scope/consistency.d.ts +0 -0
- /package/{dist → lib}/rules/scope/length.d.ts +0 -0
- /package/{dist → lib}/rules/scope/max-image-size.d.ts +0 -0
- /package/{dist → lib}/rules/scope/occurrence.d.ts +0 -0
- /package/{dist → lib}/rules/scope/pattern.d.ts +0 -0
- /package/{dist → lib}/rules/scope/repetition.d.ts +0 -0
- /package/{dist → lib}/rules/scope/semantic-line-breaks.d.ts +0 -0
- /package/{dist → lib}/rules/scope/swap.d.ts +0 -0
- /package/{dist → lib}/rules/token/blanks-around-fences.d.ts +0 -0
- /package/{dist → lib}/rules/token/blanks-around-fences.js +0 -0
- /package/{dist → lib}/rules/token/blanks-around-headings.d.ts +0 -0
- /package/{dist → lib}/rules/token/blanks-around-lists.d.ts +0 -0
- /package/{dist → lib}/rules/token/blanks-around-tables.d.ts +0 -0
- /package/{dist → lib}/rules/token/code-block-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/code-block-style.js +0 -0
- /package/{dist → lib}/rules/token/code-fence-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/code-fence-style.js +0 -0
- /package/{dist → lib}/rules/token/commands-show-output.d.ts +0 -0
- /package/{dist → lib}/rules/token/commands-show-output.js +0 -0
- /package/{dist → lib}/rules/token/descriptive-link-text.d.ts +0 -0
- /package/{dist → lib}/rules/token/emphasis-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/emphasis-style.d.ts.map +0 -0
- /package/{dist → lib}/rules/token/emphasis-style.js +0 -0
- /package/{dist → lib}/rules/token/emphasis-style.js.map +0 -0
- /package/{dist → lib}/rules/token/fenced-code-language.d.ts +0 -0
- /package/{dist → lib}/rules/token/fenced-code-language.js +0 -0
- /package/{dist → lib}/rules/token/first-line-h1.d.ts +0 -0
- /package/{dist → lib}/rules/token/front-matter.d.ts +0 -0
- /package/{dist → lib}/rules/token/heading-increment.d.ts +0 -0
- /package/{dist → lib}/rules/token/heading-start-left.d.ts +0 -0
- /package/{dist → lib}/rules/token/heading-start-left.js +0 -0
- /package/{dist → lib}/rules/token/heading-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/heading-style.js +0 -0
- /package/{dist → lib}/rules/token/hr-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/hr-style.js +0 -0
- /package/{dist → lib}/rules/token/line-length.d.ts +0 -0
- /package/{dist → lib}/rules/token/link-fragments.d.ts +0 -0
- /package/{dist → lib}/rules/token/link-image-reference-definitions.d.ts +0 -0
- /package/{dist → lib}/rules/token/link-image-reference-definitions.js +0 -0
- /package/{dist → lib}/rules/token/link-image-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/list-indent.d.ts +0 -0
- /package/{dist → lib}/rules/token/list-indent.js +0 -0
- /package/{dist → lib}/rules/token/list-length.d.ts +0 -0
- /package/{dist → lib}/rules/token/list-marker-space.d.ts +0 -0
- /package/{dist → lib}/rules/token/list-marker-space.js +0 -0
- /package/{dist → lib}/rules/token/markdoc-attributes.d.ts +0 -0
- /package/{dist → lib}/rules/token/markdoc-pairing.d.ts +0 -0
- /package/{dist → lib}/rules/token/markdoc-syntax.d.ts +0 -0
- /package/{dist → lib}/rules/token/markdoc-unknown-tag.d.ts +0 -0
- /package/{dist → lib}/rules/token/messages.d.ts +0 -0
- /package/{dist → lib}/rules/token/messages.d.ts.map +0 -0
- /package/{dist → lib}/rules/token/messages.js +0 -0
- /package/{dist → lib}/rules/token/messages.js.map +0 -0
- /package/{dist → lib}/rules/token/no-alt-text.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-bare-urls.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-blanks-blockquote.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-blanks-blockquote.js +0 -0
- /package/{dist → lib}/rules/token/no-duplicate-heading.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-duplicate-link-destinations.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-emphasis-as-heading.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-empty-headings.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-empty-links.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-empty-links.js +0 -0
- /package/{dist → lib}/rules/token/no-hard-tabs.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-hard-tabs.js +0 -0
- /package/{dist → lib}/rules/token/no-inline-html.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-atx.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-atx.d.ts.map +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-atx.js +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-atx.js.map +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-closed-atx.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-closed-atx.d.ts.map +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-closed-atx.js +0 -0
- /package/{dist → lib}/rules/token/no-missing-space-closed-atx.js.map +0 -0
- /package/{dist → lib}/rules/token/no-multiple-blanks.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-multiple-blanks.js +0 -0
- /package/{dist → lib}/rules/token/no-multiple-space-blockquote.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-multiple-space-blockquote.d.ts.map +0 -0
- /package/{dist → lib}/rules/token/no-multiple-space-blockquote.js +0 -0
- /package/{dist → lib}/rules/token/no-multiple-space-blockquote.js.map +0 -0
- /package/{dist → lib}/rules/token/no-multiple-space-closed-atx.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-multiple-space-closed-atx.js +0 -0
- /package/{dist → lib}/rules/token/no-reversed-links.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-reversed-links.js +0 -0
- /package/{dist → lib}/rules/token/no-space-in-code.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-space-in-code.js +0 -0
- /package/{dist → lib}/rules/token/no-space-in-emphasis.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-space-in-links.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-space-in-links.js +0 -0
- /package/{dist → lib}/rules/token/no-trailing-punctuation.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-trailing-punctuation.js +0 -0
- /package/{dist → lib}/rules/token/no-trailing-spaces.d.ts +0 -0
- /package/{dist → lib}/rules/token/no-trailing-spaces.js +0 -0
- /package/{dist → lib}/rules/token/ol-prefix.d.ts +0 -0
- /package/{dist → lib}/rules/token/ol-prefix.js +0 -0
- /package/{dist → lib}/rules/token/proper-names.d.ts +0 -0
- /package/{dist → lib}/rules/token/reference-links-images.d.ts +0 -0
- /package/{dist → lib}/rules/token/reference-links-images.js +0 -0
- /package/{dist → lib}/rules/token/required-headings.d.ts +0 -0
- /package/{dist → lib}/rules/token/single-h1.d.ts +0 -0
- /package/{dist → lib}/rules/token/single-trailing-newline.d.ts +0 -0
- /package/{dist → lib}/rules/token/single-trailing-newline.d.ts.map +0 -0
- /package/{dist → lib}/rules/token/single-trailing-newline.js +0 -0
- /package/{dist → lib}/rules/token/single-trailing-newline.js.map +0 -0
- /package/{dist → lib}/rules/token/strong-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/strong-style.d.ts.map +0 -0
- /package/{dist → lib}/rules/token/strong-style.js +0 -0
- /package/{dist → lib}/rules/token/strong-style.js.map +0 -0
- /package/{dist → lib}/rules/token/table-column-count.d.ts +0 -0
- /package/{dist → lib}/rules/token/table-column-count.js +0 -0
- /package/{dist → lib}/rules/token/table-column-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/table-pipe-style.d.ts +0 -0
- /package/{dist → lib}/rules/token/table-pipe-style.js +0 -0
- /package/{dist → lib}/rules/token/ul-indent.d.ts +0 -0
- /package/{dist → lib}/rules/token/ul-indent.js +0 -0
- /package/{dist → lib}/rules/token/ul-style.d.ts +0 -0
- /package/{dist → lib}/rules/types.js +0 -0
- /package/{dist → lib}/rules/types.js.map +0 -0
- /package/{dist → lib}/scopes/types.js +0 -0
- /package/{dist → lib}/scopes/types.js.map +0 -0
- /package/{dist → lib}/types/assertions.js +0 -0
- /package/{dist → lib}/types/assertions.js.map +0 -0
- /package/{dist → lib}/types/index.d.ts +0 -0
- /package/{dist → lib}/types/index.d.ts.map +0 -0
- /package/{dist → lib}/types/index.js +0 -0
- /package/{dist → lib}/types/index.js.map +0 -0
- /package/{dist → lib}/types/problems.d.ts +0 -0
- /package/{dist → lib}/types/problems.d.ts.map +0 -0
- /package/{dist → lib}/types/problems.js +0 -0
- /package/{dist → lib}/types/problems.js.map +0 -0
- /package/{dist → lib}/types/reporting.js +0 -0
- /package/{dist → lib}/types/reporting.js.map +0 -0
- /package/{dist → lib}/types/rules.js +0 -0
- /package/{dist → lib}/types/rules.js.map +0 -0
- /package/{dist → lib}/types/validation.js +0 -0
- /package/{dist → lib}/types/validation.js.map +0 -0
|
@@ -0,0 +1,1049 @@
|
|
|
1
|
+
import Ajv from '@redocly/ajv';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
3
|
+
import * as yaml from 'js-yaml';
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import { resolveMarkdocConfig, } from '../parser/markdoc/schema.js';
|
|
7
|
+
import { resolveAssertion } from '../rules/registry.js';
|
|
8
|
+
import { resolveDictionaryPaths } from '../rules/scope/spelling.js';
|
|
9
|
+
import { tokenizeSelector, wholeDocumentKeywordProblems } from '../scopes/selector.js';
|
|
10
|
+
import { validateScopeSelector } from '../scopes/vocabulary.js';
|
|
11
|
+
import { isPlainObject } from '../utils/is-plain-object.js';
|
|
12
|
+
import { RECHECK_CONFIG_SCHEMA, MARKDOC_TAG_SCHEMA } from './schema.js';
|
|
13
|
+
const ajv = new Ajv({
|
|
14
|
+
// mismatching AJV typing due to fork
|
|
15
|
+
useDefaults: true,
|
|
16
|
+
allErrors: true,
|
|
17
|
+
});
|
|
18
|
+
addFormats(ajv); // mismatching AJV typing due to fork
|
|
19
|
+
ajv.addSchema(RECHECK_CONFIG_SCHEMA, 'recheck-config');
|
|
20
|
+
// Compiled once, to check the tags read from `markdoc.extend.tagsFile`.
|
|
21
|
+
const validateMarkdocTagShape = ajv.compile(MARKDOC_TAG_SCHEMA);
|
|
22
|
+
/**
|
|
23
|
+
* Validates configuration structure using JSON Schema
|
|
24
|
+
*/
|
|
25
|
+
function validateStructure(config) {
|
|
26
|
+
const validate = ajv.getSchema('recheck-config');
|
|
27
|
+
if (!validate) {
|
|
28
|
+
throw new Error('Schema not loaded');
|
|
29
|
+
}
|
|
30
|
+
const valid = validate(config);
|
|
31
|
+
if (!valid && validate.errors) {
|
|
32
|
+
return validate.errors.map((error) => {
|
|
33
|
+
// AJV does not name the unknown key in its message, so add it.
|
|
34
|
+
const extra = error.keyword === 'additionalProperties' && error.params?.additionalProperty
|
|
35
|
+
? ` (unknown property "${error.params.additionalProperty}")`
|
|
36
|
+
: '';
|
|
37
|
+
return {
|
|
38
|
+
message: `${error.message}${extra}`,
|
|
39
|
+
path: error.instancePath,
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Validates assertions in a rule
|
|
47
|
+
*/
|
|
48
|
+
function validateAssertions(rule, name, errors) {
|
|
49
|
+
if (!isPlainObject(rule.assertions)) {
|
|
50
|
+
errors.push({
|
|
51
|
+
message: 'Assertions must be an object',
|
|
52
|
+
path: `${name}.assertions`,
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (const assertionType of Object.keys(rule.assertions)) {
|
|
57
|
+
let resolved;
|
|
58
|
+
try {
|
|
59
|
+
// Same lookup the runner uses, so every registered rule is known here.
|
|
60
|
+
resolved = resolveAssertion(assertionType);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
errors.push({
|
|
64
|
+
message: `Unknown assertion type "${assertionType}"`,
|
|
65
|
+
path: `${name}.assertions.${assertionType}`,
|
|
66
|
+
});
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// Scope assertions have their own validators below. Token rules are checked here.
|
|
70
|
+
if (resolved.kind === 'token') {
|
|
71
|
+
validateTokenRuleOptions(rule, name, assertionType, resolved.rule, errors);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// A misspelled option on a token rule would otherwise be silently ignored.
|
|
76
|
+
// The rule's `defaults` list every option it accepts.
|
|
77
|
+
function validateTokenRuleOptions(rule, name, id, tokenRule, errors) {
|
|
78
|
+
const optionsObject = requireOptionsObject(rule, name, id, errors);
|
|
79
|
+
if (!optionsObject)
|
|
80
|
+
return;
|
|
81
|
+
const allowed = new Set(Object.keys(tokenRule.defaults));
|
|
82
|
+
for (const key of Object.keys(optionsObject)) {
|
|
83
|
+
if (!allowed.has(key)) {
|
|
84
|
+
errors.push({
|
|
85
|
+
message: `Unknown option "${key}" for assertion "${id}" (accepted: ${[...allowed].sort().join(', ')})`,
|
|
86
|
+
path: `${name}.assertions.${id}.${key}`,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns the assertion's options if they are a plain object, or `undefined` if it is not set.
|
|
93
|
+
* Reports an error for any other value, which the JSON schema cannot catch.
|
|
94
|
+
*/
|
|
95
|
+
function requireOptionsObject(rule, name, assertionId, errors) {
|
|
96
|
+
const assertions = rule.assertions;
|
|
97
|
+
if (!isPlainObject(assertions) || !(assertionId in assertions)) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
const config = assertions[assertionId];
|
|
101
|
+
if (!isPlainObject(config)) {
|
|
102
|
+
errors.push({
|
|
103
|
+
message: `The ${assertionId} assertion options must be an object`,
|
|
104
|
+
path: `${name}.assertions.${assertionId}`,
|
|
105
|
+
});
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return config;
|
|
109
|
+
}
|
|
110
|
+
// `negate` is listed so it gets its own error message below.
|
|
111
|
+
const PATTERN_OPTION_KEYS = new Set(['tokens', 'ignoreCase', 'nonword', 'includeCode', 'negate']);
|
|
112
|
+
/** Validates the `pattern` options. `negate` is rejected because it never worked. */
|
|
113
|
+
function validatePatternOptions(rule, name, errors) {
|
|
114
|
+
const patternConfig = requireOptionsObject(rule, name, 'pattern', errors);
|
|
115
|
+
if (!patternConfig)
|
|
116
|
+
return;
|
|
117
|
+
for (const key of Object.keys(patternConfig)) {
|
|
118
|
+
if (!PATTERN_OPTION_KEYS.has(key)) {
|
|
119
|
+
errors.push({
|
|
120
|
+
message: `Unknown pattern option "${key}"`,
|
|
121
|
+
path: `${name}.assertions.pattern.${key}`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if ('negate' in patternConfig) {
|
|
126
|
+
errors.push({
|
|
127
|
+
message: `Pattern option "negate" was removed — it never worked ` +
|
|
128
|
+
`(it never reported anything); remove it from the config`,
|
|
129
|
+
path: `${name}.assertions.pattern.negate`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// An empty `tokens` array can never report anything, so it is an error too.
|
|
133
|
+
const { tokens, ignoreCase, nonword } = patternConfig;
|
|
134
|
+
const isValidTokens = Array.isArray(tokens) &&
|
|
135
|
+
tokens.length > 0 &&
|
|
136
|
+
tokens.every((token) => typeof token === 'string');
|
|
137
|
+
if (!isValidTokens) {
|
|
138
|
+
errors.push({
|
|
139
|
+
message: 'Pattern requires "tokens" to be a non-empty array of strings',
|
|
140
|
+
path: `${name}.assertions.pattern.tokens`,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (ignoreCase !== undefined && typeof ignoreCase !== 'boolean') {
|
|
144
|
+
errors.push({
|
|
145
|
+
message: 'Pattern option "ignoreCase" must be a boolean',
|
|
146
|
+
path: `${name}.assertions.pattern.ignoreCase`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (nonword !== undefined && typeof nonword !== 'boolean') {
|
|
150
|
+
errors.push({
|
|
151
|
+
message: 'Pattern option "nonword" must be a boolean',
|
|
152
|
+
path: `${name}.assertions.pattern.nonword`,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const includeCode = patternConfig.includeCode;
|
|
156
|
+
if (includeCode !== undefined && typeof includeCode !== 'boolean') {
|
|
157
|
+
errors.push({
|
|
158
|
+
message: 'Pattern option "includeCode" must be a boolean',
|
|
159
|
+
path: `${name}.assertions.pattern.includeCode`,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/** Validates the `occurrence` options. Needs `min` or `max`, and `min` must not exceed `max`. */
|
|
164
|
+
const OCCURRENCE_OPTION_KEYS = new Set(['pattern', 'min', 'max', 'ignoreCase']);
|
|
165
|
+
function validateOccurrenceOptions(rule, name, errors) {
|
|
166
|
+
const occurrenceConfig = requireOptionsObject(rule, name, 'occurrence', errors);
|
|
167
|
+
if (!occurrenceConfig)
|
|
168
|
+
return;
|
|
169
|
+
for (const key of Object.keys(occurrenceConfig)) {
|
|
170
|
+
if (!OCCURRENCE_OPTION_KEYS.has(key)) {
|
|
171
|
+
errors.push({
|
|
172
|
+
message: `Unknown occurrence option "${key}"`,
|
|
173
|
+
path: `${name}.assertions.occurrence.${key}`,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const { min, max, pattern } = occurrenceConfig;
|
|
178
|
+
if (min === undefined && max === undefined) {
|
|
179
|
+
errors.push({
|
|
180
|
+
message: 'Occurrence requires at least one of "min" or "max"',
|
|
181
|
+
path: `${name}.assertions.occurrence`,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
if (min !== undefined && typeof min !== 'number') {
|
|
185
|
+
errors.push({
|
|
186
|
+
message: 'Occurrence option "min" must be a number',
|
|
187
|
+
path: `${name}.assertions.occurrence.min`,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
if (max !== undefined && typeof max !== 'number') {
|
|
191
|
+
errors.push({
|
|
192
|
+
message: 'Occurrence option "max" must be a number',
|
|
193
|
+
path: `${name}.assertions.occurrence.max`,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (typeof min === 'number' && typeof max === 'number' && min > max) {
|
|
197
|
+
errors.push({
|
|
198
|
+
message: `Occurrence "min" (${min}) must not exceed "max" (${max})`,
|
|
199
|
+
path: `${name}.assertions.occurrence`,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
// An empty pattern would match everywhere.
|
|
203
|
+
if (typeof pattern !== 'string' || pattern.length === 0) {
|
|
204
|
+
errors.push({
|
|
205
|
+
message: 'Occurrence requires a non-empty string "pattern"',
|
|
206
|
+
path: `${name}.assertions.occurrence.pattern`,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/** Validates the `repetition` options. All are optional. */
|
|
211
|
+
const REPETITION_OPTION_KEYS = new Set(['pattern', 'ignoreCase', 'includeCode']);
|
|
212
|
+
function validateRepetitionOptions(rule, name, errors) {
|
|
213
|
+
const repetitionConfig = requireOptionsObject(rule, name, 'repetition', errors);
|
|
214
|
+
if (!repetitionConfig)
|
|
215
|
+
return;
|
|
216
|
+
for (const key of Object.keys(repetitionConfig)) {
|
|
217
|
+
if (!REPETITION_OPTION_KEYS.has(key)) {
|
|
218
|
+
errors.push({
|
|
219
|
+
message: `Unknown repetition option "${key}"`,
|
|
220
|
+
path: `${name}.assertions.repetition.${key}`,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const { pattern, ignoreCase, includeCode } = repetitionConfig;
|
|
225
|
+
if (pattern !== undefined && (typeof pattern !== 'string' || pattern.length === 0)) {
|
|
226
|
+
errors.push({
|
|
227
|
+
message: 'Repetition option "pattern" must be a non-empty string',
|
|
228
|
+
path: `${name}.assertions.repetition.pattern`,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
if (ignoreCase !== undefined && typeof ignoreCase !== 'boolean') {
|
|
232
|
+
errors.push({
|
|
233
|
+
message: 'Repetition option "ignoreCase" must be a boolean',
|
|
234
|
+
path: `${name}.assertions.repetition.ignoreCase`,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
if (includeCode !== undefined && typeof includeCode !== 'boolean') {
|
|
238
|
+
errors.push({
|
|
239
|
+
message: 'Repetition option "includeCode" must be a boolean',
|
|
240
|
+
path: `${name}.assertions.repetition.includeCode`,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/** Validates the `consistency` options. `either` needs at least one pair of variants. */
|
|
245
|
+
const CONSISTENCY_OPTION_KEYS = new Set(['either', 'ignoreCase', 'includeCode']);
|
|
246
|
+
function validateConsistencyOptions(rule, name, errors) {
|
|
247
|
+
const consistencyConfig = requireOptionsObject(rule, name, 'consistency', errors);
|
|
248
|
+
if (!consistencyConfig)
|
|
249
|
+
return;
|
|
250
|
+
for (const key of Object.keys(consistencyConfig)) {
|
|
251
|
+
if (!CONSISTENCY_OPTION_KEYS.has(key)) {
|
|
252
|
+
errors.push({
|
|
253
|
+
message: `Unknown consistency option "${key}"`,
|
|
254
|
+
path: `${name}.assertions.consistency.${key}`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const { either, ignoreCase, includeCode } = consistencyConfig;
|
|
259
|
+
if (!isPlainObject(either)) {
|
|
260
|
+
errors.push({
|
|
261
|
+
message: 'Consistency requires "either" to be an object mapping one variant to another (e.g. behavior: behaviour)',
|
|
262
|
+
path: `${name}.assertions.consistency.either`,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
const entries = Object.entries(either);
|
|
267
|
+
if (entries.length === 0) {
|
|
268
|
+
errors.push({
|
|
269
|
+
message: 'Consistency "either" must declare at least one variant pair',
|
|
270
|
+
path: `${name}.assertions.consistency.either`,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
for (const [variant, alternative] of entries) {
|
|
274
|
+
if (variant.length === 0) {
|
|
275
|
+
errors.push({
|
|
276
|
+
message: 'Consistency "either" entry keys must be non-empty strings',
|
|
277
|
+
path: `${name}.assertions.consistency.either`,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
if (typeof alternative !== 'string' || alternative.length === 0) {
|
|
281
|
+
errors.push({
|
|
282
|
+
message: `Consistency "either" entry "${variant}" must map to a non-empty string variant`,
|
|
283
|
+
path: `${name}.assertions.consistency.either.${variant}`,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (ignoreCase !== undefined && typeof ignoreCase !== 'boolean') {
|
|
289
|
+
errors.push({
|
|
290
|
+
message: 'Consistency option "ignoreCase" must be a boolean',
|
|
291
|
+
path: `${name}.assertions.consistency.ignoreCase`,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
if (includeCode !== undefined && typeof includeCode !== 'boolean') {
|
|
295
|
+
errors.push({
|
|
296
|
+
message: 'Consistency option "includeCode" must be a boolean',
|
|
297
|
+
path: `${name}.assertions.consistency.includeCode`,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/** Validates the `conditional` options. `first` and `second` are required strings. */
|
|
302
|
+
const CONDITIONAL_OPTION_KEYS = new Set(['first', 'second', 'ignoreCase']);
|
|
303
|
+
function validateConditionalOptions(rule, name, errors) {
|
|
304
|
+
const conditionalConfig = requireOptionsObject(rule, name, 'conditional', errors);
|
|
305
|
+
if (!conditionalConfig)
|
|
306
|
+
return;
|
|
307
|
+
for (const key of Object.keys(conditionalConfig)) {
|
|
308
|
+
if (!CONDITIONAL_OPTION_KEYS.has(key)) {
|
|
309
|
+
errors.push({
|
|
310
|
+
message: `Unknown conditional option "${key}"`,
|
|
311
|
+
path: `${name}.assertions.conditional.${key}`,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const { first, second, ignoreCase } = conditionalConfig;
|
|
316
|
+
if (typeof first !== 'string' || first.length === 0) {
|
|
317
|
+
errors.push({
|
|
318
|
+
message: 'Conditional requires a non-empty string "first"',
|
|
319
|
+
path: `${name}.assertions.conditional.first`,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
if (typeof second !== 'string' || second.length === 0) {
|
|
323
|
+
errors.push({
|
|
324
|
+
message: 'Conditional requires a non-empty string "second"',
|
|
325
|
+
path: `${name}.assertions.conditional.second`,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (ignoreCase !== undefined && typeof ignoreCase !== 'boolean') {
|
|
329
|
+
errors.push({
|
|
330
|
+
message: 'Conditional option "ignoreCase" must be a boolean',
|
|
331
|
+
path: `${name}.assertions.conditional.ignoreCase`,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/** Validates the `capitalization` options. `match` is required. */
|
|
336
|
+
const CAPITALIZATION_OPTION_KEYS = new Set(['match', 'exceptions', 'style', 'builtinVocabulary']);
|
|
337
|
+
function validateCapitalizationOptions(rule, name, errors) {
|
|
338
|
+
const capitalizationConfig = requireOptionsObject(rule, name, 'capitalization', errors);
|
|
339
|
+
if (!capitalizationConfig)
|
|
340
|
+
return;
|
|
341
|
+
for (const key of Object.keys(capitalizationConfig)) {
|
|
342
|
+
if (!CAPITALIZATION_OPTION_KEYS.has(key)) {
|
|
343
|
+
errors.push({
|
|
344
|
+
message: `Unknown capitalization option "${key}"`,
|
|
345
|
+
path: `${name}.assertions.capitalization.${key}`,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
const { match, exceptions, style, builtinVocabulary } = capitalizationConfig;
|
|
350
|
+
if (builtinVocabulary !== undefined && typeof builtinVocabulary !== 'boolean') {
|
|
351
|
+
errors.push({
|
|
352
|
+
message: 'Capitalization option "builtinVocabulary" must be a boolean',
|
|
353
|
+
path: `${name}.assertions.capitalization.builtinVocabulary`,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
if (typeof match !== 'string' || match.length === 0) {
|
|
357
|
+
errors.push({
|
|
358
|
+
message: `Capitalization requires a non-empty string "match" ` +
|
|
359
|
+
`($title, $sentence, $lower, $upper, or a regex pattern)`,
|
|
360
|
+
path: `${name}.assertions.capitalization.match`,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
if (style !== undefined && style !== 'ap' && style !== 'chicago') {
|
|
364
|
+
errors.push({
|
|
365
|
+
message: 'Capitalization option "style" must be "ap" or "chicago"',
|
|
366
|
+
path: `${name}.assertions.capitalization.style`,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
if (exceptions !== undefined) {
|
|
370
|
+
const isValidExceptions = Array.isArray(exceptions) &&
|
|
371
|
+
exceptions.every((entry) => typeof entry === 'string' && entry.length > 0);
|
|
372
|
+
if (!isValidExceptions) {
|
|
373
|
+
errors.push({
|
|
374
|
+
message: 'Capitalization option "exceptions" must be an array of non-empty strings',
|
|
375
|
+
path: `${name}.assertions.capitalization.exceptions`,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Validates the `metric` options. `formula` is required, and `min` or `max` is needed.
|
|
382
|
+
* `wordsPerMinute` is only valid with `reading-time`.
|
|
383
|
+
*/
|
|
384
|
+
const METRIC_OPTION_KEYS = new Set(['formula', 'min', 'max', 'wordsPerMinute']);
|
|
385
|
+
const METRIC_FORMULAS = new Set([
|
|
386
|
+
'flesch-reading-ease',
|
|
387
|
+
'flesch-kincaid-grade',
|
|
388
|
+
'gunning-fog',
|
|
389
|
+
'smog',
|
|
390
|
+
'coleman-liau',
|
|
391
|
+
'automated-readability',
|
|
392
|
+
'word-count',
|
|
393
|
+
'sentence-count',
|
|
394
|
+
'reading-time',
|
|
395
|
+
]);
|
|
396
|
+
function validateMetricOptions(rule, name, errors) {
|
|
397
|
+
const metricConfig = requireOptionsObject(rule, name, 'metric', errors);
|
|
398
|
+
if (!metricConfig)
|
|
399
|
+
return;
|
|
400
|
+
for (const key of Object.keys(metricConfig)) {
|
|
401
|
+
if (!METRIC_OPTION_KEYS.has(key)) {
|
|
402
|
+
errors.push({
|
|
403
|
+
message: `Unknown metric option "${key}"`,
|
|
404
|
+
path: `${name}.assertions.metric.${key}`,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const { formula, min, max, wordsPerMinute } = metricConfig;
|
|
409
|
+
if (typeof formula !== 'string' || !METRIC_FORMULAS.has(formula)) {
|
|
410
|
+
errors.push({
|
|
411
|
+
message: `Metric requires "formula" to be one of ${[...METRIC_FORMULAS].join(', ')}`,
|
|
412
|
+
path: `${name}.assertions.metric.formula`,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
if (wordsPerMinute !== undefined) {
|
|
416
|
+
if (typeof wordsPerMinute !== 'number' || !(wordsPerMinute > 0)) {
|
|
417
|
+
errors.push({
|
|
418
|
+
message: 'Metric option "wordsPerMinute" must be a positive number',
|
|
419
|
+
path: `${name}.assertions.metric.wordsPerMinute`,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
else if (formula !== 'reading-time') {
|
|
423
|
+
errors.push({
|
|
424
|
+
message: 'Metric option "wordsPerMinute" only applies to formula "reading-time"',
|
|
425
|
+
path: `${name}.assertions.metric.wordsPerMinute`,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (min === undefined && max === undefined) {
|
|
430
|
+
errors.push({
|
|
431
|
+
message: 'Metric requires at least one of "min" or "max"',
|
|
432
|
+
path: `${name}.assertions.metric`,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
if (min !== undefined && typeof min !== 'number') {
|
|
436
|
+
errors.push({
|
|
437
|
+
message: 'Metric option "min" must be a number',
|
|
438
|
+
path: `${name}.assertions.metric.min`,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
if (max !== undefined && typeof max !== 'number') {
|
|
442
|
+
errors.push({
|
|
443
|
+
message: 'Metric option "max" must be a number',
|
|
444
|
+
path: `${name}.assertions.metric.max`,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
if (typeof min === 'number' && typeof max === 'number' && min > max) {
|
|
448
|
+
errors.push({
|
|
449
|
+
message: `Metric "min" (${min}) must not exceed "max" (${max})`,
|
|
450
|
+
path: `${name}.assertions.metric`,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Checks `min` and `max` for `length` and `list-length`. Counts cannot be negative, so `min` must
|
|
456
|
+
* be a positive integer and `max` a non-negative integer. Wrong types are reported by the caller.
|
|
457
|
+
*/
|
|
458
|
+
function validateCountBounds(name, assertionId, min, max, errors) {
|
|
459
|
+
if (typeof min === 'number' && (!Number.isInteger(min) || min < 1)) {
|
|
460
|
+
errors.push({
|
|
461
|
+
message: `The ${assertionId} option "min" must be a positive integer ` +
|
|
462
|
+
`(${min} could never be violated by a real count)`,
|
|
463
|
+
path: `${name}.assertions.${assertionId}.min`,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
if (typeof max === 'number' && (!Number.isInteger(max) || max < 0)) {
|
|
467
|
+
errors.push({
|
|
468
|
+
message: `The ${assertionId} option "max" must be a non-negative integer ` +
|
|
469
|
+
`(${max} would be violated by every real count)`,
|
|
470
|
+
path: `${name}.assertions.${assertionId}.max`,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Validates the `list-length` options. `min` and `max` are optional, because the rule has a
|
|
476
|
+
* default `min` of 2.
|
|
477
|
+
*/
|
|
478
|
+
function validateListLengthOptions(rule, name, errors) {
|
|
479
|
+
const listLengthConfig = requireOptionsObject(rule, name, 'list-length', errors);
|
|
480
|
+
if (!listLengthConfig)
|
|
481
|
+
return;
|
|
482
|
+
const { min, max } = listLengthConfig;
|
|
483
|
+
if (min !== undefined && typeof min !== 'number') {
|
|
484
|
+
errors.push({
|
|
485
|
+
message: 'List-length option "min" must be a number',
|
|
486
|
+
path: `${name}.assertions.list-length.min`,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
if (max !== undefined && typeof max !== 'number') {
|
|
490
|
+
errors.push({
|
|
491
|
+
message: 'List-length option "max" must be a number',
|
|
492
|
+
path: `${name}.assertions.list-length.max`,
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
if (typeof min === 'number' && typeof max === 'number' && min > max) {
|
|
496
|
+
errors.push({
|
|
497
|
+
message: `List-length "min" (${min}) must not exceed "max" (${max})`,
|
|
498
|
+
path: `${name}.assertions.list-length`,
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
validateCountBounds(name, 'list-length', min, max, errors);
|
|
502
|
+
}
|
|
503
|
+
/** Validates the `spelling` options. All are optional. */
|
|
504
|
+
const SPELLING_OPTION_KEYS = new Set(['dictionary', 'vocab', 'ignore', 'builtinVocabulary']);
|
|
505
|
+
function validateSpellingOptions(rule, name, errors) {
|
|
506
|
+
const spellingConfig = requireOptionsObject(rule, name, 'spelling', errors);
|
|
507
|
+
if (!spellingConfig)
|
|
508
|
+
return;
|
|
509
|
+
for (const key of Object.keys(spellingConfig)) {
|
|
510
|
+
if (!SPELLING_OPTION_KEYS.has(key)) {
|
|
511
|
+
errors.push({
|
|
512
|
+
message: `Unknown spelling option "${key}"`,
|
|
513
|
+
path: `${name}.assertions.spelling.${key}`,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
const { dictionary, vocab, ignore, builtinVocabulary } = spellingConfig;
|
|
518
|
+
if (builtinVocabulary !== undefined && typeof builtinVocabulary !== 'boolean') {
|
|
519
|
+
errors.push({
|
|
520
|
+
message: 'Spelling option "builtinVocabulary" must be a boolean',
|
|
521
|
+
path: `${name}.assertions.spelling.builtinVocabulary`,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
if (dictionary !== undefined && (typeof dictionary !== 'string' || dictionary.length === 0)) {
|
|
525
|
+
errors.push({
|
|
526
|
+
message: 'Spelling option "dictionary" must be a non-empty string',
|
|
527
|
+
path: `${name}.assertions.spelling.dictionary`,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
if (vocab !== undefined) {
|
|
531
|
+
const isValidVocab = Array.isArray(vocab) && vocab.every((word) => typeof word === 'string' && word.length > 0);
|
|
532
|
+
if (!isValidVocab) {
|
|
533
|
+
errors.push({
|
|
534
|
+
message: 'Spelling option "vocab" must be an array of non-empty strings',
|
|
535
|
+
path: `${name}.assertions.spelling.vocab`,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (ignore !== undefined) {
|
|
540
|
+
const isValidIgnore = Array.isArray(ignore) && ignore.every((word) => typeof word === 'string' && word.length > 0);
|
|
541
|
+
if (!isValidIgnore) {
|
|
542
|
+
errors.push({
|
|
543
|
+
message: 'Spelling option "ignore" must be an array of non-empty strings',
|
|
544
|
+
path: `${name}.assertions.spelling.ignore`,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
/** Validates the `length` options. `unit` is required, and `min` or `max` is needed. */
|
|
550
|
+
const LENGTH_OPTION_KEYS = new Set(['unit', 'min', 'max']);
|
|
551
|
+
const LENGTH_UNITS = new Set(['characters', 'words', 'sentences']);
|
|
552
|
+
function validateLengthOptions(rule, name, errors) {
|
|
553
|
+
const lengthConfig = requireOptionsObject(rule, name, 'length', errors);
|
|
554
|
+
if (!lengthConfig)
|
|
555
|
+
return;
|
|
556
|
+
for (const key of Object.keys(lengthConfig)) {
|
|
557
|
+
if (!LENGTH_OPTION_KEYS.has(key)) {
|
|
558
|
+
errors.push({
|
|
559
|
+
message: `Unknown length option "${key}"`,
|
|
560
|
+
path: `${name}.assertions.length.${key}`,
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
const { unit, min, max } = lengthConfig;
|
|
565
|
+
if (typeof unit !== 'string' || !LENGTH_UNITS.has(unit)) {
|
|
566
|
+
errors.push({
|
|
567
|
+
message: `Length requires "unit" to be one of ${[...LENGTH_UNITS].join(', ')}`,
|
|
568
|
+
path: `${name}.assertions.length.unit`,
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
if (min === undefined && max === undefined) {
|
|
572
|
+
errors.push({
|
|
573
|
+
message: 'Length requires at least one of "min" or "max"',
|
|
574
|
+
path: `${name}.assertions.length`,
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
if (min !== undefined && typeof min !== 'number') {
|
|
578
|
+
errors.push({
|
|
579
|
+
message: 'Length option "min" must be a number',
|
|
580
|
+
path: `${name}.assertions.length.min`,
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
if (max !== undefined && typeof max !== 'number') {
|
|
584
|
+
errors.push({
|
|
585
|
+
message: 'Length option "max" must be a number',
|
|
586
|
+
path: `${name}.assertions.length.max`,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
if (typeof min === 'number' && typeof max === 'number' && min > max) {
|
|
590
|
+
errors.push({
|
|
591
|
+
message: `Length "min" (${min}) must not exceed "max" (${max})`,
|
|
592
|
+
path: `${name}.assertions.length`,
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
validateCountBounds(name, 'length', min, max, errors);
|
|
596
|
+
}
|
|
597
|
+
/** Validates the entries of `swap.pairs`. A replacement may be empty, which deletes the match. */
|
|
598
|
+
function validateSwapPairEntries(entries, name, path, errors) {
|
|
599
|
+
for (const [key, value] of entries) {
|
|
600
|
+
const entryPath = `${path}.${key}`;
|
|
601
|
+
if (key.length === 0) {
|
|
602
|
+
errors.push({
|
|
603
|
+
message: 'Swap "pairs" entry keys must be non-empty strings',
|
|
604
|
+
path: entryPath,
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
if (typeof value !== 'string') {
|
|
608
|
+
errors.push({
|
|
609
|
+
message: `Swap "pairs" entry "${key}" must map to a string replacement`,
|
|
610
|
+
path: entryPath,
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Validates the `swap` options. Find and replace entries must be under `pairs`.
|
|
617
|
+
* Entries at the top level are rejected because they would be ignored.
|
|
618
|
+
*/
|
|
619
|
+
const SWAP_RESERVED_KEYS = new Set([
|
|
620
|
+
'ignoreCase',
|
|
621
|
+
'wordBoundary',
|
|
622
|
+
'keysAreRegex',
|
|
623
|
+
'pairs',
|
|
624
|
+
'includeCode',
|
|
625
|
+
]);
|
|
626
|
+
const SWAP_BOOLEAN_OPTION_KEYS = [
|
|
627
|
+
'ignoreCase',
|
|
628
|
+
'wordBoundary',
|
|
629
|
+
'keysAreRegex',
|
|
630
|
+
'includeCode',
|
|
631
|
+
];
|
|
632
|
+
function validateSwapOptions(rule, name, errors) {
|
|
633
|
+
const swapConfig = requireOptionsObject(rule, name, 'swap', errors);
|
|
634
|
+
if (!swapConfig)
|
|
635
|
+
return;
|
|
636
|
+
for (const key of Object.keys(swapConfig)) {
|
|
637
|
+
if (!SWAP_RESERVED_KEYS.has(key)) {
|
|
638
|
+
errors.push({
|
|
639
|
+
message: `Unknown swap option "${key}" -- swap does not accept ` +
|
|
640
|
+
`find -> replace entries at the top level; move find -> replace entries under "pairs:"`,
|
|
641
|
+
path: `${name}.assertions.swap.${key}`,
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
for (const key of SWAP_BOOLEAN_OPTION_KEYS) {
|
|
646
|
+
const value = swapConfig[key];
|
|
647
|
+
if (value !== undefined && typeof value !== 'boolean') {
|
|
648
|
+
errors.push({
|
|
649
|
+
message: `Swap option "${key}" must be a boolean`,
|
|
650
|
+
path: `${name}.assertions.swap.${key}`,
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if (!('pairs' in swapConfig)) {
|
|
655
|
+
errors.push({
|
|
656
|
+
message: 'Swap requires a "pairs" object mapping find -> replace strings',
|
|
657
|
+
path: `${name}.assertions.swap.pairs`,
|
|
658
|
+
});
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
const pairs = swapConfig.pairs;
|
|
662
|
+
if (!isPlainObject(pairs) || Object.keys(pairs).length === 0) {
|
|
663
|
+
errors.push({
|
|
664
|
+
message: 'Swap option "pairs" must be a non-empty object mapping find -> replace strings',
|
|
665
|
+
path: `${name}.assertions.swap.pairs`,
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
validateSwapPairEntries(Object.entries(pairs), name, `${name}.assertions.swap.pairs`, errors);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Checks that the optional `nspell` and `dictionary-en` packages are installed when `spelling`
|
|
674
|
+
* is used, and that a custom `dictionary` points to readable `.aff` and `.dic` files.
|
|
675
|
+
*/
|
|
676
|
+
async function checkSpellingPeerDependencies(rules) {
|
|
677
|
+
const errors = [];
|
|
678
|
+
const reportedMessages = new Set();
|
|
679
|
+
const reportedDictionaryPaths = new Set();
|
|
680
|
+
for (const rule of rules) {
|
|
681
|
+
const spellingConfig = rule.assertions?.['spelling'];
|
|
682
|
+
if (!isPlainObject(spellingConfig))
|
|
683
|
+
continue;
|
|
684
|
+
const dictionaryPath = spellingConfig.dictionary;
|
|
685
|
+
const hasCustomDictionary = typeof dictionaryPath === 'string' && dictionaryPath.length > 0;
|
|
686
|
+
let missingPeer = false;
|
|
687
|
+
try {
|
|
688
|
+
await import('nspell');
|
|
689
|
+
}
|
|
690
|
+
catch {
|
|
691
|
+
missingPeer = true;
|
|
692
|
+
}
|
|
693
|
+
// A custom dictionary does not use `dictionary-en`.
|
|
694
|
+
if (!hasCustomDictionary) {
|
|
695
|
+
try {
|
|
696
|
+
await import('dictionary-en');
|
|
697
|
+
}
|
|
698
|
+
catch {
|
|
699
|
+
missingPeer = true;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (missingPeer) {
|
|
703
|
+
const installCommand = hasCustomDictionary ? 'npm i nspell' : 'npm i nspell dictionary-en';
|
|
704
|
+
const peerNames = hasCustomDictionary ? '"nspell"' : '"nspell" and "dictionary-en"';
|
|
705
|
+
const message = `The spelling assertion requires the optional peer dependenc${hasCustomDictionary ? 'y' : 'ies'} ` +
|
|
706
|
+
`${peerNames} — run \`${installCommand}\` to enable it.`;
|
|
707
|
+
// Report each message once, at the first rule that needs it.
|
|
708
|
+
if (!reportedMessages.has(message)) {
|
|
709
|
+
reportedMessages.add(message);
|
|
710
|
+
errors.push({ message, path: `${rule.name}.assertions.spelling` });
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// Even with `nspell` installed, a custom dictionary may point to missing files.
|
|
714
|
+
// Report each path once.
|
|
715
|
+
if (hasCustomDictionary && !reportedDictionaryPaths.has(dictionaryPath)) {
|
|
716
|
+
reportedDictionaryPaths.add(dictionaryPath);
|
|
717
|
+
const { aff, dic } = resolveDictionaryPaths(dictionaryPath);
|
|
718
|
+
const unreadable = [];
|
|
719
|
+
for (const filePath of [aff, dic]) {
|
|
720
|
+
try {
|
|
721
|
+
await fs.access(filePath, fs.constants.R_OK);
|
|
722
|
+
}
|
|
723
|
+
catch {
|
|
724
|
+
unreadable.push(filePath);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
if (unreadable.length > 0) {
|
|
728
|
+
errors.push({
|
|
729
|
+
message: `Spelling dictionary file${unreadable.length > 1 ? 's' : ''} ` +
|
|
730
|
+
`not found or not readable: ${unreadable.join(', ')}`,
|
|
731
|
+
path: `${rule.name}.assertions.spelling.dictionary`,
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return errors;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Warns when a rule that needs Markdoc parsing is on while `markdoc` is off, because
|
|
740
|
+
* such a rule cannot report then. Goes to `warn`, so `isValid` stays `true`.
|
|
741
|
+
*/
|
|
742
|
+
function warnMarkdocRulesWithoutParsing(config, markdocEnabled, warnOnce) {
|
|
743
|
+
if (markdocEnabled || !isPlainObject(config))
|
|
744
|
+
return;
|
|
745
|
+
const names = Object.entries(config)
|
|
746
|
+
.filter(([, rule]) => isPlainObject(rule) &&
|
|
747
|
+
rule.severity !== 'off' &&
|
|
748
|
+
isPlainObject(rule.assertions) &&
|
|
749
|
+
Object.keys(rule.assertions).some((id) => id.startsWith('markdoc-')))
|
|
750
|
+
.map(([name]) => name);
|
|
751
|
+
if (names.length === 0)
|
|
752
|
+
return;
|
|
753
|
+
warnOnce(`recheck: ${names.join(', ')} need Markdoc parsing, but "markdoc" parsing is off, so they ` +
|
|
754
|
+
'can never fire; set "markdoc: true" (or an object form) to enable them.');
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Reads and checks `markdoc.extend.tagsFile`, relative to `configDir`. Returns the tags and any
|
|
758
|
+
* errors. Does not touch the file system when there is no `tagsFile`.
|
|
759
|
+
*/
|
|
760
|
+
async function loadMarkdocTagsFile(raw, configDir) {
|
|
761
|
+
const tagsFile = isPlainObject(raw) ? raw.extend?.tagsFile : undefined;
|
|
762
|
+
if (!tagsFile)
|
|
763
|
+
return { errors: [] };
|
|
764
|
+
const resolvedPath = path.resolve(configDir, tagsFile);
|
|
765
|
+
const errors = [];
|
|
766
|
+
let content;
|
|
767
|
+
try {
|
|
768
|
+
content = await fs.readFile(resolvedPath, 'utf8');
|
|
769
|
+
}
|
|
770
|
+
catch (error) {
|
|
771
|
+
errors.push({
|
|
772
|
+
path: '/markdoc/extend/tagsFile',
|
|
773
|
+
message: `could not read "${resolvedPath}": ${error instanceof Error ? error.message : String(error)}`,
|
|
774
|
+
});
|
|
775
|
+
return { errors };
|
|
776
|
+
}
|
|
777
|
+
let parsed;
|
|
778
|
+
try {
|
|
779
|
+
parsed = yaml.load(content);
|
|
780
|
+
}
|
|
781
|
+
catch (error) {
|
|
782
|
+
errors.push({
|
|
783
|
+
path: '/markdoc/extend/tagsFile',
|
|
784
|
+
message: `could not parse "${resolvedPath}" as YAML: ${error instanceof Error ? error.message : String(error)}`,
|
|
785
|
+
});
|
|
786
|
+
return { errors };
|
|
787
|
+
}
|
|
788
|
+
if (!isPlainObject(parsed)) {
|
|
789
|
+
errors.push({
|
|
790
|
+
path: '/markdoc/extend/tagsFile',
|
|
791
|
+
message: `"${resolvedPath}" must be a YAML map of tag name to tag schema, got ${parsed === null ? 'null' : Array.isArray(parsed) ? 'an array' : typeof parsed}`,
|
|
792
|
+
});
|
|
793
|
+
return { errors };
|
|
794
|
+
}
|
|
795
|
+
const fileTags = {};
|
|
796
|
+
for (const [tagName, tagValue] of Object.entries(parsed)) {
|
|
797
|
+
if (!validateMarkdocTagShape(tagValue)) {
|
|
798
|
+
const detail = ajv.errorsText(validateMarkdocTagShape.errors, { separator: '; ' });
|
|
799
|
+
errors.push({
|
|
800
|
+
path: `/markdoc/extend/tagsFile/${tagName}`,
|
|
801
|
+
message: `"${resolvedPath}" tag "${tagName}" is invalid: ${detail}`,
|
|
802
|
+
});
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
fileTags[tagName] = tagValue;
|
|
806
|
+
}
|
|
807
|
+
// One bad tag invalidates the whole file.
|
|
808
|
+
if (errors.length > 0)
|
|
809
|
+
return { errors };
|
|
810
|
+
return { fileTags, errors: [] };
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Warns about a `pattern` token that starts with `^#` in a scope other than `raw` or `all`.
|
|
814
|
+
* Those scopes pass only the text without markup, so the token can never match.
|
|
815
|
+
*/
|
|
816
|
+
function warnStalePatternPrefix(rule, name, warnOnce) {
|
|
817
|
+
const patternConfig = rule.assertions?.['pattern'];
|
|
818
|
+
if (!patternConfig || !Array.isArray(patternConfig.tokens))
|
|
819
|
+
return;
|
|
820
|
+
const scopeEntries = rule.scope === undefined ? [] : Array.isArray(rule.scope) ? rule.scope : [rule.scope];
|
|
821
|
+
// A scope entry can join terms with `&`, so check every term.
|
|
822
|
+
const scopeTerms = scopeEntries.flatMap((entry) => typeof entry === 'string' ? tokenizeSelector(entry).map(({ term }) => term) : []);
|
|
823
|
+
const hasRawOrAllScope = scopeEntries.length === 0 || scopeTerms.some((term) => term === 'raw' || term === 'all');
|
|
824
|
+
if (hasRawOrAllScope)
|
|
825
|
+
return;
|
|
826
|
+
for (const token of patternConfig.tokens) {
|
|
827
|
+
if (typeof token === 'string' && token.startsWith('^#')) {
|
|
828
|
+
const scopeDisplay = Array.isArray(rule.scope) ? rule.scope.join(', ') : String(rule.scope);
|
|
829
|
+
warnOnce(`recheck: Rule "${name}": pattern "${token}" starts with '^#' but scope "${scopeDisplay}" matches semantic text without markup — drop the '#' prefix or use scope: raw`);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Forces `scope: summary` on rules with a `metric` assertion, because readability is scored over
|
|
835
|
+
* the whole document's prose. Warns if the user set another scope.
|
|
836
|
+
* `hasExplicitScope` is needed because AJV adds `scope: all` to rules without one.
|
|
837
|
+
*/
|
|
838
|
+
function normalizeMetricScope(rule, name, hasExplicitScope, warnOnce) {
|
|
839
|
+
if (!isPlainObject(rule.assertions) || !('metric' in rule.assertions)) {
|
|
840
|
+
return rule.scope;
|
|
841
|
+
}
|
|
842
|
+
if (hasExplicitScope) {
|
|
843
|
+
const entries = Array.isArray(rule.scope) ? rule.scope : [rule.scope];
|
|
844
|
+
const isSummary = entries.length === 1 && (entries[0] === 'summary' || entries[0] === 'default');
|
|
845
|
+
if (!isSummary) {
|
|
846
|
+
const scopeDisplay = Array.isArray(rule.scope) ? rule.scope.join(', ') : String(rule.scope);
|
|
847
|
+
warnOnce(`recheck: Rule "${name}": metric is always summary-scoped; ignoring configured scope "${scopeDisplay}"`);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
return 'summary';
|
|
851
|
+
}
|
|
852
|
+
/** Checks each term of a rule's `scope` against the scope vocabulary and selector syntax. */
|
|
853
|
+
function validateScope(rule, name, errors) {
|
|
854
|
+
if (rule.scope === undefined)
|
|
855
|
+
return;
|
|
856
|
+
const entries = Array.isArray(rule.scope) ? rule.scope : [rule.scope];
|
|
857
|
+
for (const entry of entries) {
|
|
858
|
+
if (typeof entry !== 'string')
|
|
859
|
+
continue; // caught by schema
|
|
860
|
+
for (const problem of validateScopeSelector(entry)) {
|
|
861
|
+
errors.push({
|
|
862
|
+
message: `Invalid scope — ${problem}`,
|
|
863
|
+
path: `${name}.scope`,
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
// `all` or `raw` inside a compound or negated selector never matches or matches everything.
|
|
867
|
+
for (const problem of wholeDocumentKeywordProblems(entry)) {
|
|
868
|
+
errors.push({
|
|
869
|
+
message: `Invalid scope — ${problem}`,
|
|
870
|
+
path: `${name}.scope`,
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
// `all` and `raw` cover the whole document, so they cannot be mixed with other scopes.
|
|
875
|
+
if (entries.length > 1) {
|
|
876
|
+
for (const entry of entries) {
|
|
877
|
+
if (typeof entry !== 'string')
|
|
878
|
+
continue; // caught by schema
|
|
879
|
+
const term = entry.trim();
|
|
880
|
+
if (term === 'all' || term === 'raw') {
|
|
881
|
+
errors.push({
|
|
882
|
+
message: `Scope "${term}" covers the whole document and cannot be ` +
|
|
883
|
+
`combined with other scopes — use \`scope: ${term}\` alone`,
|
|
884
|
+
path: `${name}.scope`,
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* The most `%s` placeholders a message may have. `metric` fills four and `length` three. Other
|
|
892
|
+
* assertions fill two. A rule gets the highest cap of its assertions.
|
|
893
|
+
*/
|
|
894
|
+
const MESSAGE_PLACEHOLDER_CAPS = {
|
|
895
|
+
metric: 4,
|
|
896
|
+
length: 3,
|
|
897
|
+
};
|
|
898
|
+
const DEFAULT_MESSAGE_PLACEHOLDER_CAP = 2;
|
|
899
|
+
function messagePlaceholderCap(rule) {
|
|
900
|
+
const assertions = rule.assertions;
|
|
901
|
+
const assertionIds = isPlainObject(assertions) ? Object.keys(assertions) : [];
|
|
902
|
+
return assertionIds.reduce((cap, id) => Math.max(cap, MESSAGE_PLACEHOLDER_CAPS[id] ?? DEFAULT_MESSAGE_PLACEHOLDER_CAP), DEFAULT_MESSAGE_PLACEHOLDER_CAP);
|
|
903
|
+
}
|
|
904
|
+
function validateSemantics(config, warn, rulesWithExplicitScope = new Set()) {
|
|
905
|
+
const errors = [];
|
|
906
|
+
const rules = [];
|
|
907
|
+
// Each distinct warning is shown once.
|
|
908
|
+
const warnedMessages = new Set();
|
|
909
|
+
const warnOnce = (message) => {
|
|
910
|
+
if (warnedMessages.has(message))
|
|
911
|
+
return;
|
|
912
|
+
warnedMessages.add(message);
|
|
913
|
+
warn(message);
|
|
914
|
+
};
|
|
915
|
+
for (const [key, rule] of Object.entries(config)) {
|
|
916
|
+
try {
|
|
917
|
+
const name = key;
|
|
918
|
+
const shortName = key.replace(/^recheck\//, '');
|
|
919
|
+
// `message` is required by the schema, so `?? ''` only satisfies the type.
|
|
920
|
+
const placeholderCount = ((rule.message ?? '').match(/%s/g) || []).length;
|
|
921
|
+
const placeholderCap = messagePlaceholderCap(rule);
|
|
922
|
+
if (placeholderCount > placeholderCap) {
|
|
923
|
+
errors.push({
|
|
924
|
+
message: `Message can have at most ${placeholderCap} %s placeholders, found ${placeholderCount}`,
|
|
925
|
+
path: `${name}.message`,
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
validateAssertions(rule, name, errors);
|
|
929
|
+
validatePatternOptions(rule, name, errors);
|
|
930
|
+
validateOccurrenceOptions(rule, name, errors);
|
|
931
|
+
validateRepetitionOptions(rule, name, errors);
|
|
932
|
+
validateConsistencyOptions(rule, name, errors);
|
|
933
|
+
validateConditionalOptions(rule, name, errors);
|
|
934
|
+
validateCapitalizationOptions(rule, name, errors);
|
|
935
|
+
validateMetricOptions(rule, name, errors);
|
|
936
|
+
validateListLengthOptions(rule, name, errors);
|
|
937
|
+
validateSpellingOptions(rule, name, errors);
|
|
938
|
+
validateSwapOptions(rule, name, errors);
|
|
939
|
+
validateLengthOptions(rule, name, errors);
|
|
940
|
+
validateScope(rule, name, errors);
|
|
941
|
+
warnStalePatternPrefix(rule, name, warnOnce);
|
|
942
|
+
const normalizedRule = {
|
|
943
|
+
...rule,
|
|
944
|
+
scope: normalizeMetricScope(rule, name, rulesWithExplicitScope.has(name), warnOnce),
|
|
945
|
+
name,
|
|
946
|
+
shortName,
|
|
947
|
+
};
|
|
948
|
+
rules.push(normalizedRule);
|
|
949
|
+
}
|
|
950
|
+
catch (error) {
|
|
951
|
+
errors.push({
|
|
952
|
+
message: error instanceof Error ? error.message : String(error),
|
|
953
|
+
path: key,
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
return { errors, rules };
|
|
958
|
+
}
|
|
959
|
+
// A token rule's message comes from its defaults; a scope rule must name one.
|
|
960
|
+
function fillDefaultMessages(rules) {
|
|
961
|
+
const filled = { ...rules };
|
|
962
|
+
for (const [key, entry] of Object.entries(rules)) {
|
|
963
|
+
if (!isPlainObject(entry) || entry.message !== undefined)
|
|
964
|
+
continue;
|
|
965
|
+
if (!isPlainObject(entry.assertions))
|
|
966
|
+
continue;
|
|
967
|
+
const message = Object.keys(entry.assertions)
|
|
968
|
+
.map(tokenDefaultMessage)
|
|
969
|
+
.find((candidate) => candidate !== undefined);
|
|
970
|
+
if (message !== undefined)
|
|
971
|
+
filled[key] = { ...entry, message };
|
|
972
|
+
}
|
|
973
|
+
return filled;
|
|
974
|
+
}
|
|
975
|
+
function tokenDefaultMessage(assertionId) {
|
|
976
|
+
try {
|
|
977
|
+
const resolved = resolveAssertion(assertionId);
|
|
978
|
+
const message = resolved.kind === 'token' ? resolved.rule.defaults.message : undefined;
|
|
979
|
+
return typeof message === 'string' ? message : undefined;
|
|
980
|
+
}
|
|
981
|
+
catch {
|
|
982
|
+
return undefined;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Validates a config. `options.configDir` (default `process.cwd()`) is where a relative
|
|
987
|
+
* `markdoc.extend.tagsFile` resolves from.
|
|
988
|
+
*/
|
|
989
|
+
export async function validate(config, options) {
|
|
990
|
+
const warn = options?.warn ?? (() => { });
|
|
991
|
+
// Validation writes defaults into the rules, and core passes preset rules through by
|
|
992
|
+
// reference, so work on a copy.
|
|
993
|
+
const resolvedConfig = isPlainObject(config)
|
|
994
|
+
? fillDefaultMessages(structuredClone(config))
|
|
995
|
+
: config;
|
|
996
|
+
// Remember which rules set `scope` themselves, because AJV fills in `scope: 'all'` on the rest.
|
|
997
|
+
const rulesWithExplicitScope = new Set(isPlainObject(resolvedConfig)
|
|
998
|
+
? Object.entries(resolvedConfig)
|
|
999
|
+
.filter(([key, rule]) => key !== 'markdoc' && key !== 'excludes' && isPlainObject(rule) && 'scope' in rule)
|
|
1000
|
+
.map(([key]) => key)
|
|
1001
|
+
: []);
|
|
1002
|
+
const structureErrors = validateStructure(resolvedConfig);
|
|
1003
|
+
// `markdoc` is a setting, not a rule. Read it here and remove it before the rules are checked.
|
|
1004
|
+
const rawMarkdoc = resolvedConfig?.markdoc;
|
|
1005
|
+
let { enabled: markdocEnabled, schema: markdocSchema } = resolveMarkdocConfig(rawMarkdoc);
|
|
1006
|
+
// Runs before the early return below, so the warning is not skipped.
|
|
1007
|
+
warnMarkdocRulesWithoutParsing(resolvedConfig, markdocEnabled, warn);
|
|
1008
|
+
if (structureErrors.length > 0) {
|
|
1009
|
+
return {
|
|
1010
|
+
isValid: false,
|
|
1011
|
+
errors: structureErrors,
|
|
1012
|
+
rules: [],
|
|
1013
|
+
markdoc: { enabled: markdocEnabled, schema: markdocSchema },
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
// The shape is valid by now, so it is safe to read `tagsFile`.
|
|
1017
|
+
const { fileTags, errors: tagsFileErrors } = await loadMarkdocTagsFile(rawMarkdoc, options?.configDir ?? process.cwd());
|
|
1018
|
+
if (tagsFileErrors.length > 0) {
|
|
1019
|
+
// A broken tags file leaves no schema to check tags against, so turn markdoc off.
|
|
1020
|
+
markdocEnabled = false;
|
|
1021
|
+
markdocSchema = null;
|
|
1022
|
+
}
|
|
1023
|
+
else if (fileTags) {
|
|
1024
|
+
const resolvedExtend = {
|
|
1025
|
+
fileTags,
|
|
1026
|
+
tags: isPlainObject(rawMarkdoc) ? rawMarkdoc.extend?.tags : undefined,
|
|
1027
|
+
};
|
|
1028
|
+
({ enabled: markdocEnabled, schema: markdocSchema } = resolveMarkdocConfig(rawMarkdoc, resolvedExtend));
|
|
1029
|
+
}
|
|
1030
|
+
// Then check the rules. `markdoc` is removed first because it is not a rule.
|
|
1031
|
+
const { markdoc: _markdoc, excludes: globalExcludes, ...rulesOnlyConfig } = resolvedConfig;
|
|
1032
|
+
const { errors: semanticErrors, rules: validatedRules } = validateSemantics(rulesOnlyConfig, warn, rulesWithExplicitScope);
|
|
1033
|
+
// Added before each rule's own list, so a rule keeps the paths it already excludes.
|
|
1034
|
+
const rules = globalExcludes?.length
|
|
1035
|
+
? validatedRules.map((rule) => ({
|
|
1036
|
+
...rule,
|
|
1037
|
+
excludes: [...globalExcludes, ...(rule.excludes ?? [])],
|
|
1038
|
+
}))
|
|
1039
|
+
: validatedRules;
|
|
1040
|
+
const peerErrors = await checkSpellingPeerDependencies(rules);
|
|
1041
|
+
const errors = [...semanticErrors, ...peerErrors, ...tagsFileErrors];
|
|
1042
|
+
return {
|
|
1043
|
+
isValid: errors.length === 0,
|
|
1044
|
+
errors,
|
|
1045
|
+
rules,
|
|
1046
|
+
markdoc: { enabled: markdocEnabled, schema: markdocSchema },
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
//# sourceMappingURL=validate.js.map
|