Create strict JSON Schema for configuration (standalone for ease of use) and corresponding strict TypeScript type (via extends for conciseness) (fixes #1248).

This commit is contained in:
David Anson 2024-08-27 20:47:33 -07:00
parent bbca3ad209
commit 9c8e7156e1
10 changed files with 3070 additions and 1207 deletions

View file

@ -1,7 +1,7 @@
# Validating Configuration
A [JSON Schema][json-schema] is provided to enable validating configuration
objects: [`markdownlint-config-schema.json`][markdownlint-config-schema]
objects: [`markdownlint-config-schema.json`][markdownlint-config-schema].
Some editors automatically use a JSON Schema with files that reference it. For
example, a `.markdownlint.json` file with:
@ -16,13 +16,11 @@ A JSON Schema validator can be used to check configuration files like so:
npx ajv-cli validate -s ./markdownlint/schema/markdownlint-config-schema.json -d "**/.markdownlint.{json,yaml}" --strict=false
```
By default, any rule name is valid in order to allow for custom rules. To ensure
that only built-in rules are used, change the value of `#/additionalProperties`
(at the bottom of the schema file) to `false` before validating:
```json
"additionalProperties": false
```
By default, any rule name is valid because of custom rules. To allow only
built-in rules, use the
[`markdownlint-config-schema-strict.json`][markdownlint-config-schema-strict]
JSON Schema instead.
[json-schema]: https://json-schema.org
[markdownlint-config-schema]: markdownlint-config-schema.json
[markdownlint-config-schema-strict]: markdownlint-config-schema-strict.json

View file

@ -9,7 +9,10 @@ const rules = require("../lib/rules");
const jsonSchemaToTypeScript = require("json-schema-to-typescript");
const { version } = require("../lib/constants");
const schemaUri = `https://raw.githubusercontent.com/DavidAnson/markdownlint/v${version}/schema/markdownlint-config-schema.json`;
const schemaName = "markdownlint-config-schema.json";
const schemaUri = `https://raw.githubusercontent.com/DavidAnson/markdownlint/v${version}/schema/${schemaName}`;
const schemaStrictName = "markdownlint-config-schema-strict.json";
const schemaStrictUri = `https://raw.githubusercontent.com/DavidAnson/markdownlint/v${version}/schema/${schemaStrictName}`;
// Schema scaffolding
const schema = {
@ -574,20 +577,24 @@ for (const [ tag, tagTags ] of Object.entries(tags)) {
}
// Write schema
const schemaFile = path.join(__dirname, "markdownlint-config-schema.json");
const schemaFile = path.join(__dirname, schemaName);
fs.writeFileSync(schemaFile, JSON.stringify(schema, null, " "));
// Write TypeScript declaration
// See https://github.com/bcherny/json-schema-to-typescript/issues/356 for why
// additionalProperties is deleted
const schemaDeclaration =
path.join(__dirname, "..", "lib", "configuration.d.ts");
// @ts-ignore
delete schema.additionalProperties;
schema.title = "Configuration";
// Create and write strict schema
const schemaStrict = {
...schema,
"$id": schemaStrictUri,
"additionalProperties": false
};
const schemaFileStrict = path.join(__dirname, schemaStrictName);
fs.writeFileSync(schemaFileStrict, JSON.stringify(schemaStrict, null, " "));
// Write TypeScript declaration file
const declarationStrictName = path.join(__dirname, "..", "lib", "configuration-strict.d.ts");
schemaStrict.title = "ConfigurationStrict";
jsonSchemaToTypeScript.compile(
// @ts-ignore
schema,
schemaStrict,
"UNUSED"
// eslint-disable-next-line unicorn/prefer-top-level-await
).then((declaration) => fs.writeFileSync(schemaDeclaration, declaration));
).then((declaration) => fs.writeFileSync(declarationStrictName, declaration));

File diff suppressed because it is too large Load diff