From 5b7e9b87be062d9e6224ccfcbc54182ff1120ce9 Mon Sep 17 00:00:00 2001 From: David Anson Date: Tue, 19 Jan 2021 20:41:04 -0800 Subject: [PATCH] Generate example JSONC configuration with all properties set to their default value. --- README.md | 3 + demo/markdownlint-browser.js | 2 +- package.json | 4 +- schema/.markdownlint.jsonc | 250 +++++++++++++++++++++++++ schema/build-config-example.js | 37 ++++ schema/build-config-schema.js | 11 +- schema/markdownlint-config-schema.json | 21 ++- test/markdownlint-test.js | 13 ++ 8 files changed, 326 insertions(+), 15 deletions(-) create mode 100644 schema/.markdownlint.jsonc create mode 100644 schema/build-config-example.js diff --git a/README.md b/README.md index ae046505..08505193 100644 --- a/README.md +++ b/README.md @@ -380,6 +380,9 @@ Example: } ``` +See [.markdownlint.jsonc](schema/.markdownlint.jsonc) for an example +configuration object with all properties set to their default value. + Sets of rules (known as a "style") can be stored separately and loaded as [JSON](https://en.wikipedia.org/wiki/JSON). diff --git a/demo/markdownlint-browser.js b/demo/markdownlint-browser.js index 24fe7934..0fe2b1cb 100644 --- a/demo/markdownlint-browser.js +++ b/demo/markdownlint-browser.js @@ -3945,7 +3945,7 @@ module.exports = rules; /***/ ((module) => { "use strict"; -module.exports = JSON.parse("{\"name\":\"markdownlint\",\"version\":\"0.22.0\",\"description\":\"A Node.js style checker and lint tool for Markdown/CommonMark files.\",\"main\":\"lib/markdownlint.js\",\"types\":\"lib/markdownlint.d.ts\",\"author\":\"David Anson (https://dlaa.me/)\",\"license\":\"MIT\",\"homepage\":\"https://github.com/DavidAnson/markdownlint\",\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/DavidAnson/markdownlint.git\"},\"bugs\":\"https://github.com/DavidAnson/markdownlint/issues\",\"scripts\":{\"build-config-schema\":\"node schema/build-config-schema.js\",\"build-declaration\":\"tsc --allowJs --declaration --emitDeclarationOnly --resolveJsonModule lib/markdownlint.js && rimraf 'lib/{c,md,r}*.d.ts' 'helpers/*.d.ts'\",\"build-demo\":\"cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && webpack --no-stats\",\"build-example\":\"npm install --no-save --ignore-scripts grunt grunt-cli gulp through2\",\"ci\":\"npm-run-all --continue-on-error --parallel test-cover lint declaration build-config-schema build-demo && git diff --exit-code\",\"clean-test-repos\":\"rimraf test-repos\",\"clone-test-repos\":\"mkdir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet\",\"clone-test-repos-large\":\"npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet\",\"declaration\":\"npm run build-declaration && npm run test-declaration\",\"example\":\"cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint\",\"lint\":\"eslint --max-warnings 0 .\",\"lint-test-repos\":\"ava --timeout=5m test/markdownlint-test-repos.js\",\"test\":\"ava test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js\",\"test-cover\":\"c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test\",\"test-declaration\":\"cd example/typescript && tsc && node type-check.js\",\"test-extra\":\"ava --timeout=5m test/markdownlint-test-extra.js\"},\"engines\":{\"node\":\">=10\"},\"dependencies\":{\"markdown-it\":\"12.0.2\"},\"devDependencies\":{\"@types/node\":\"~14.14.9\",\"ava\":\"~3.15.0\",\"c8\":\"~7.3.5\",\"cpy-cli\":\"~3.1.1\",\"eslint\":\"~7.14.0\",\"eslint-plugin-jsdoc\":\"~30.7.8\",\"eslint-plugin-node\":\"~11.1.0\",\"eslint-plugin-unicorn\":\"~23.0.0\",\"globby\":\"~11.0.1\",\"js-yaml\":\"~3.14.0\",\"markdown-it-for-inline\":\"~0.1.1\",\"markdown-it-sub\":\"~1.0.0\",\"markdown-it-sup\":\"~1.0.0\",\"markdown-it-texmath\":\"~0.8.0\",\"markdownlint-rule-helpers\":\"~0.12.0\",\"npm-run-all\":\"~4.1.5\",\"rimraf\":\"~3.0.2\",\"strip-json-comments\":\"~3.1.1\",\"toml\":\"~3.0.0\",\"ts-loader\":\"~8.0.14\",\"tv4\":\"~1.3.0\",\"typescript\":\"~4.1.2\",\"webpack\":\"~5.11.1\",\"webpack-cli\":\"~4.3.1\"},\"keywords\":[\"markdown\",\"lint\",\"md\",\"CommonMark\",\"markdownlint\"]}"); +module.exports = JSON.parse("{\"name\":\"markdownlint\",\"version\":\"0.22.0\",\"description\":\"A Node.js style checker and lint tool for Markdown/CommonMark files.\",\"main\":\"lib/markdownlint.js\",\"types\":\"lib/markdownlint.d.ts\",\"author\":\"David Anson (https://dlaa.me/)\",\"license\":\"MIT\",\"homepage\":\"https://github.com/DavidAnson/markdownlint\",\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/DavidAnson/markdownlint.git\"},\"bugs\":\"https://github.com/DavidAnson/markdownlint/issues\",\"scripts\":{\"build-config\":\"npm run build-config-schema && npm run build-config-example\",\"build-config-example\":\"node schema/build-config-example.js\",\"build-config-schema\":\"node schema/build-config-schema.js\",\"build-declaration\":\"tsc --allowJs --declaration --emitDeclarationOnly --resolveJsonModule lib/markdownlint.js && rimraf 'lib/{c,md,r}*.d.ts' 'helpers/*.d.ts'\",\"build-demo\":\"cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && webpack --no-stats\",\"build-example\":\"npm install --no-save --ignore-scripts grunt grunt-cli gulp through2\",\"ci\":\"npm-run-all --continue-on-error --parallel test-cover lint declaration build-config build-demo && git diff --exit-code\",\"clean-test-repos\":\"rimraf test-repos\",\"clone-test-repos\":\"mkdir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet\",\"clone-test-repos-large\":\"npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet\",\"declaration\":\"npm run build-declaration && npm run test-declaration\",\"example\":\"cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint\",\"lint\":\"eslint --max-warnings 0 .\",\"lint-test-repos\":\"ava --timeout=5m test/markdownlint-test-repos.js\",\"test\":\"ava test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js\",\"test-cover\":\"c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test\",\"test-declaration\":\"cd example/typescript && tsc && node type-check.js\",\"test-extra\":\"ava --timeout=5m test/markdownlint-test-extra.js\"},\"engines\":{\"node\":\">=10\"},\"dependencies\":{\"markdown-it\":\"12.0.2\"},\"devDependencies\":{\"@types/node\":\"~14.14.9\",\"ava\":\"~3.15.0\",\"c8\":\"~7.3.5\",\"cpy-cli\":\"~3.1.1\",\"eslint\":\"~7.14.0\",\"eslint-plugin-jsdoc\":\"~30.7.8\",\"eslint-plugin-node\":\"~11.1.0\",\"eslint-plugin-unicorn\":\"~23.0.0\",\"globby\":\"~11.0.1\",\"js-yaml\":\"~3.14.0\",\"markdown-it-for-inline\":\"~0.1.1\",\"markdown-it-sub\":\"~1.0.0\",\"markdown-it-sup\":\"~1.0.0\",\"markdown-it-texmath\":\"~0.8.0\",\"markdownlint-rule-helpers\":\"~0.12.0\",\"npm-run-all\":\"~4.1.5\",\"rimraf\":\"~3.0.2\",\"strip-json-comments\":\"~3.1.1\",\"toml\":\"~3.0.0\",\"ts-loader\":\"~8.0.14\",\"tv4\":\"~1.3.0\",\"typescript\":\"~4.1.2\",\"webpack\":\"~5.11.1\",\"webpack-cli\":\"~4.3.1\"},\"keywords\":[\"markdown\",\"lint\",\"md\",\"CommonMark\",\"markdownlint\"]}"); /***/ }), diff --git a/package.json b/package.json index dce97c75..16adfecf 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,13 @@ }, "bugs": "https://github.com/DavidAnson/markdownlint/issues", "scripts": { + "build-config": "npm run build-config-schema && npm run build-config-example", + "build-config-example": "node schema/build-config-example.js", "build-config-schema": "node schema/build-config-schema.js", "build-declaration": "tsc --allowJs --declaration --emitDeclarationOnly --resolveJsonModule lib/markdownlint.js && rimraf 'lib/{c,md,r}*.d.ts' 'helpers/*.d.ts'", "build-demo": "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && webpack --no-stats", "build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2", - "ci": "npm-run-all --continue-on-error --parallel test-cover lint declaration build-config-schema build-demo && git diff --exit-code", + "ci": "npm-run-all --continue-on-error --parallel test-cover lint declaration build-config build-demo && git diff --exit-code", "clean-test-repos": "rimraf test-repos", "clone-test-repos": "mkdir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet", "clone-test-repos-large": "npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet", diff --git a/schema/.markdownlint.jsonc b/schema/.markdownlint.jsonc new file mode 100644 index 00000000..412af350 --- /dev/null +++ b/schema/.markdownlint.jsonc @@ -0,0 +1,250 @@ +{ + // Example markdownlint JSON(C) configuration with all properties set to their default value + + // Default state for all rules + "default": true, + + // Path to configuration file to extend + "extends": null, + + // MD001/heading-increment/header-increment - Heading levels should only increment by one level at a time + "MD001": true, + + // MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading + "MD002": { + // Heading level + "level": 1 + }, + + // MD003/heading-style/header-style - Heading style + "MD003": { + // Heading style + "style": "consistent" + }, + + // MD004/ul-style - Unordered list style + "MD004": { + // List style + "style": "consistent" + }, + + // MD005/list-indent - Inconsistent indentation for list items at the same level + "MD005": true, + + // MD006/ul-start-left - Consider starting bulleted lists at the beginning of the line + "MD006": true, + + // MD007/ul-indent - Unordered list indentation + "MD007": { + // Spaces for indent + "indent": 2, + // Whether to indent the first level of the list + "start_indented": false + }, + + // MD009/no-trailing-spaces - Trailing spaces + "MD009": { + // Spaces for line break + "br_spaces": 2, + // Allow spaces for empty lines in list items + "list_item_empty_lines": false, + // Include unnecessary breaks + "strict": false + }, + + // MD010/no-hard-tabs - Hard tabs + "MD010": { + // Include code blocks + "code_blocks": true + }, + + // MD011/no-reversed-links - Reversed link syntax + "MD011": true, + + // MD012/no-multiple-blanks - Multiple consecutive blank lines + "MD012": { + // Consecutive blank lines + "maximum": 1 + }, + + // MD013/line-length - Line length + "MD013": { + // Number of characters + "line_length": 80, + // Number of characters for headings + "heading_line_length": 80, + // Number of characters for code blocks + "code_block_line_length": 80, + // Include code blocks + "code_blocks": true, + // Include tables + "tables": true, + // Include headings + "headings": true, + // Include headings + "headers": true, + // Strict length checking + "strict": false, + // Stern length checking + "stern": false + }, + + // MD014/commands-show-output - Dollar signs used before commands without showing output + "MD014": true, + + // MD018/no-missing-space-atx - No space after hash on atx style heading + "MD018": true, + + // MD019/no-multiple-space-atx - Multiple spaces after hash on atx style heading + "MD019": true, + + // MD020/no-missing-space-closed-atx - No space inside hashes on closed atx style heading + "MD020": true, + + // MD021/no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading + "MD021": true, + + // MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines + "MD022": { + // Blank lines above heading + "lines_above": 1, + // Blank lines below heading + "lines_below": 1 + }, + + // MD023/heading-start-left/header-start-left - Headings must start at the beginning of the line + "MD023": true, + + // MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content + "MD024": { + // Only check sibling headings + "allow_different_nesting": false, + // Only check sibling headings + "siblings_only": false + }, + + // MD025/single-title/single-h1 - Multiple top-level headings in the same document + "MD025": { + // Heading level + "level": 1, + // RegExp for matching title in front matter + "front_matter_title": "^\\s*title\\s*[:=]" + }, + + // MD026/no-trailing-punctuation - Trailing punctuation in heading + "MD026": { + // Punctuation characters + "punctuation": ".,;:!。,;:!" + }, + + // MD027/no-multiple-space-blockquote - Multiple spaces after blockquote symbol + "MD027": true, + + // MD028/no-blanks-blockquote - Blank line inside blockquote + "MD028": true, + + // MD029/ol-prefix - Ordered list item prefix + "MD029": { + // List style + "style": "one_or_ordered" + }, + + // MD030/list-marker-space - Spaces after list markers + "MD030": { + // Spaces for single-line unordered list items + "ul_single": 1, + // Spaces for single-line ordered list items + "ol_single": 1, + // Spaces for multi-line unordered list items + "ul_multi": 1, + // Spaces for multi-line ordered list items + "ol_multi": 1 + }, + + // MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines + "MD031": { + // Include list items + "list_items": true + }, + + // MD032/blanks-around-lists - Lists should be surrounded by blank lines + "MD032": true, + + // MD033/no-inline-html - Inline HTML + "MD033": { + // Allowed elements + "allowed_elements": [] + }, + + // MD034/no-bare-urls - Bare URL used + "MD034": true, + + // MD035/hr-style - Horizontal rule style + "MD035": { + // Horizontal rule style + "style": "consistent" + }, + + // MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading + "MD036": { + // Punctuation characters + "punctuation": ".,;:!?。,;:!?" + }, + + // MD037/no-space-in-emphasis - Spaces inside emphasis markers + "MD037": true, + + // MD038/no-space-in-code - Spaces inside code span elements + "MD038": true, + + // MD039/no-space-in-links - Spaces inside link text + "MD039": true, + + // MD040/fenced-code-language - Fenced code blocks should have a language specified + "MD040": true, + + // MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading + "MD041": { + // Heading level + "level": 1, + // RegExp for matching title in front matter + "front_matter_title": "^\\s*title\\s*[:=]" + }, + + // MD042/no-empty-links - No empty links + "MD042": true, + + // MD043/required-headings/required-headers - Required heading structure + "MD043": { + // List of headings + "headings": [], + // List of headings + "headers": [] + }, + + // MD044/proper-names - Proper names should have the correct capitalization + "MD044": { + // List of proper names + "names": [], + // Include code blocks + "code_blocks": true + }, + + // MD045/no-alt-text - Images should have alternate text (alt text) + "MD045": true, + + // MD046/code-block-style - Code block style + "MD046": { + // Block style + "style": "consistent" + }, + + // MD047/single-trailing-newline - Files should end with a single newline character + "MD047": true, + + // MD048/code-fence-style - Code fence style + "MD048": { + // Code fence syle + "style": "consistent" + } +} \ No newline at end of file diff --git a/schema/build-config-example.js b/schema/build-config-example.js new file mode 100644 index 00000000..58ac5bed --- /dev/null +++ b/schema/build-config-example.js @@ -0,0 +1,37 @@ +// @ts-check + +"use strict"; + +const fs = require("fs"); +const path = require("path"); +const configSchema = require("./markdownlint-config-schema.json"); + +const configExample = {}; +for (const rule in configSchema.properties) { + if (/^(MD\d{3}|default|extends)$/.test(rule)) { + const properties = configSchema.properties[rule]; + configExample[rule + "-description"] = properties.description; + configExample[rule] = properties.default; + if (properties.properties) { + const ruleExample = {}; + // eslint-disable-next-line guard-for-in + for (const property in properties.properties) { + const ruleProperties = properties.properties[property]; + ruleExample[property + "-sub-description"] = ruleProperties.description; + ruleExample[property] = ruleProperties.default; + } + configExample[rule] = ruleExample; + } + } +} + +const configString = JSON.stringify(configExample, null, 2) + // eslint-disable-next-line max-len + .replace(/^\{/, "{\n // Example markdownlint JSON(C) configuration with all properties set to their default value") + .replace(/(\s+)"[^-"]+-description": "(.+)",/g, "\n$1// $2") + .replace(/"[^-"]+-sub-description": "(.+)",/g, "// $1"); +fs.writeFileSync( + path.join(__dirname, ".markdownlint.jsonc"), + configString, + "utf8" +); diff --git a/schema/build-config-schema.js b/schema/build-config-schema.js index 62da961d..6e8ff95b 100644 --- a/schema/build-config-schema.js +++ b/schema/build-config-schema.js @@ -18,7 +18,10 @@ const schema = { }, "extends": { "description": "Path to configuration file to extend", - "type": "string", + "type": [ + "string", + "null" + ], "default": null }, "$schema": { @@ -331,7 +334,7 @@ rules.forEach(function forRule(rule) { "items": { "type": "string" }, - "default": null + "default": [] }, "headers": { "description": "List of headings", @@ -339,7 +342,7 @@ rules.forEach(function forRule(rule) { "items": { "type": "string" }, - "default": null + "default": [] } }; break; @@ -351,7 +354,7 @@ rules.forEach(function forRule(rule) { "items": { "type": "string" }, - "default": null + "default": [] }, "code_blocks": { "description": "Include code blocks", diff --git a/schema/markdownlint-config-schema.json b/schema/markdownlint-config-schema.json index 25e1056f..20a4d094 100644 --- a/schema/markdownlint-config-schema.json +++ b/schema/markdownlint-config-schema.json @@ -9,7 +9,10 @@ }, "extends": { "description": "Path to configuration file to extend", - "type": "string", + "type": [ + "string", + "null" + ], "default": null }, "$schema": { @@ -1207,7 +1210,7 @@ "items": { "type": "string" }, - "default": null + "default": [] }, "headers": { "description": "List of headings", @@ -1215,7 +1218,7 @@ "items": { "type": "string" }, - "default": null + "default": [] } }, "additionalProperties": false @@ -1234,7 +1237,7 @@ "items": { "type": "string" }, - "default": null + "default": [] }, "headers": { "description": "List of headings", @@ -1242,7 +1245,7 @@ "items": { "type": "string" }, - "default": null + "default": [] } }, "additionalProperties": false @@ -1261,7 +1264,7 @@ "items": { "type": "string" }, - "default": null + "default": [] }, "headers": { "description": "List of headings", @@ -1269,7 +1272,7 @@ "items": { "type": "string" }, - "default": null + "default": [] } }, "additionalProperties": false @@ -1288,7 +1291,7 @@ "items": { "type": "string" }, - "default": null + "default": [] }, "code_blocks": { "description": "Include code blocks", @@ -1312,7 +1315,7 @@ "items": { "type": "string" }, - "default": null + "default": [] }, "code_blocks": { "description": "Include code blocks", diff --git a/test/markdownlint-test.js b/test/markdownlint-test.js index 9fbf9734..e5fee10e 100644 --- a/test/markdownlint-test.js +++ b/test/markdownlint-test.js @@ -9,6 +9,7 @@ const pluginInline = require("markdown-it-for-inline"); const pluginSub = require("markdown-it-sub"); const pluginSup = require("markdown-it-sup"); const pluginTexMath = require("markdown-it-texmath"); +const stripJsonComments = require("strip-json-comments"); const test = require("ava").default; const tv4 = require("tv4"); const { homepage, version } = require("../package.json"); @@ -1006,6 +1007,18 @@ test("validateConfigSchemaAllowsUnknownProperties", (t) => { }); }); +test("validateConfigExampleJson", (t) => { + const file = ".markdownlint.jsonc"; + const data = fs.readFileSync( + path.join(__dirname, "../schema", file), + "utf8" + ); + t.true( + // @ts-ignore + tv4.validate(JSON.parse(stripJsonComments(data)), configSchemaStrict), + file + "\n" + JSON.stringify(tv4.error, null, 2)); +}); + test.cb("configSingle", (t) => { t.plan(2); markdownlint.readConfig("./test/config/config-child.json",