From 058f1cd415f190c8c1fcda4d47d9a8a9a17b9b80 Mon Sep 17 00:00:00 2001 From: Michael Naumov Date: Tue, 18 Nov 2025 22:39:11 -0600 Subject: [PATCH 1/3] fix: proper use of extends --- lib/index.ts | 141 +++++++++++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 4f4ff57..154b6b2 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -29,13 +29,9 @@ import sdl from "@microsoft/eslint-plugin-sdl"; import importPlugin from "eslint-plugin-import"; import depend from 'eslint-plugin-depend'; import globals from "globals"; - +import { Config, defineConfig, globalIgnores } from "eslint/config"; import type { RuleDefinition, RuleDefinitionTypeOptions, RulesConfig } from "@eslint/core"; -interface ConfigWithIterator extends Linter.Config { - [Symbol.iterator]: () => Generator; -} - const plugin = { meta: { name: "eslint-plugin-obsidianmd", @@ -74,8 +70,8 @@ const plugin = { "ui/sentence-case-locale-module": ui.sentenceCaseLocaleModule, } as unknown as Record>, configs: { - recommended: >{}, - recommendedWithLocalesEn: >{} + recommended: [] as Config[], + recommendedWithLocalesEn: [] as Config[] } } satisfies ESLint.Plugin; @@ -104,7 +100,7 @@ const recommendedPluginRulesConfig: RulesConfig = { "obsidianmd/sample-names": "error", "obsidianmd/validate-manifest": "error", "obsidianmd/validate-license": ["error"], - "obsidianmd/ui/sentence-case": ["error", { enforceCamelCaseLower: true }], + "obsidianmd/ui/sentence-case": ["error", { enforceCamelCaseLower: true }], } const flatRecommendedGeneralRules: RulesConfig = { @@ -189,31 +185,34 @@ const flatRecommendedGeneralRules: RulesConfig = { "import/no-extraneous-dependencies": "error", } -const flatRecommendedConfig: Linter.Config[] = [ +const flatRecommendedConfig: Config[] = defineConfig([ js.configs.recommended, { - ...tseslint.configs.recommended, + plugins: { + obsidianmd: plugin + } + }, + { plugins: { import: importPlugin, "@microsoft/sdl": sdl, - obsidianmd: plugin, depend }, files: ['**/*.js', "**/*.jsx"], + extends: tseslint.configs.recommended as Config[], rules: { ...flatRecommendedGeneralRules, ...recommendedPluginRulesConfig } }, { - ...tseslint.configs.recommendedTypeChecked, plugins: { import: importPlugin, "@microsoft/sdl": sdl, - obsidianmd: plugin, depend }, files: ['**/*.ts', "**/*.tsx"], + extends: tseslint.configs.recommendedTypeChecked as Config[], rules: { ...flatRecommendedGeneralRules, ...recommendedPluginRulesConfig @@ -222,6 +221,7 @@ const flatRecommendedConfig: Linter.Config[] = [ { files: ['package.json'], language: 'json/json', + extends: [tseslint.configs.disableTypeChecked as Config], plugins: { depend, json @@ -232,9 +232,10 @@ const flatRecommendedConfig: Linter.Config[] = [ "error", { "presets": ["native", "microutilities", "preferred"] } - ] + ] } - }, { + }, + { languageOptions: { globals: { ...globals.browser, @@ -261,68 +262,66 @@ const flatRecommendedConfig: Linter.Config[] = [ } }, } -]; +]); -const hybridRecommendedConfig: ConfigWithIterator = { - // Properties for eslint-doc-generator to read - ...recommendedPluginRulesConfig, +const hybridRecommendedConfig: Config[] = defineConfig({ + rules: recommendedPluginRulesConfig, + extends: flatRecommendedConfig +}); - // Make the object iterable for the ESLint 9 runtime - [Symbol.iterator]: function* () { - yield* flatRecommendedConfig +const recommendedWithLocalesEnBase: Config[] = defineConfig([ + ...flatRecommendedConfig, + { + plugins: { obsidianmd: plugin }, + files: [ + "**/en.json", + "**/en*.json", + "**/en/*.json", + "**/en/**/*.json", + ], + rules: { + "obsidianmd/ui/sentence-case-json": "warn", + }, }, -}; + // TS/JS English locale modules + { + plugins: { obsidianmd: plugin }, + files: [ + "**/en.ts", + "**/en.js", + "**/en.cjs", + "**/en.mjs", + "**/en-*.ts", + "**/en-*.js", + "**/en-*.cjs", + "**/en-*.mjs", + "**/en_*.ts", + "**/en_*.js", + "**/en_*.cjs", + "**/en_*.mjs", + "**/en/*.ts", + "**/en/*.js", + "**/en/*.cjs", + "**/en/*.mjs", + "**/en/**/*.ts", + "**/en/**/*.js", + "**/en/**/*.cjs", + "**/en/**/*.mjs", + ], + rules: { + "obsidianmd/ui/sentence-case-locale-module": "warn", + }, + } +]); + +const recommendedWithLocalesEn: Config[] = defineConfig({ + rules: recommendedPluginRulesConfig, + extends: recommendedWithLocalesEnBase +}); plugin.configs = { recommended: hybridRecommendedConfig, - recommendedWithLocalesEn: { - ...recommendedPluginRulesConfig, - [Symbol.iterator]: function* () { - yield* flatRecommendedConfig; - // JSON English locales - yield { - plugins: { obsidianmd: plugin }, - files: [ - "**/en.json", - "**/en*.json", - "**/en/*.json", - "**/en/**/*.json", - ], - rules: { - "obsidianmd/ui/sentence-case-json": "warn", - }, - }; - // TS/JS English locale modules - yield { - plugins: { obsidianmd: plugin }, - files: [ - "**/en.ts", - "**/en.js", - "**/en.cjs", - "**/en.mjs", - "**/en-*.ts", - "**/en-*.js", - "**/en-*.cjs", - "**/en-*.mjs", - "**/en_*.ts", - "**/en_*.js", - "**/en_*.cjs", - "**/en_*.mjs", - "**/en/*.ts", - "**/en/*.js", - "**/en/*.cjs", - "**/en/*.mjs", - "**/en/**/*.ts", - "**/en/**/*.js", - "**/en/**/*.cjs", - "**/en/**/*.mjs", - ], - rules: { - "obsidianmd/ui/sentence-case-locale-module": "warn", - }, - }; - }, - }, + recommendedWithLocalesEn }; export default plugin; From bec313e95d9379faabc33f10860a63f2d4db011f Mon Sep 17 00:00:00 2001 From: Michael Naumov Date: Tue, 18 Nov 2025 23:31:09 -0600 Subject: [PATCH 2/3] fix: extract package.json rules into separate config --- lib/index.ts | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 154b6b2..4f8c65a 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -71,7 +71,8 @@ const plugin = { } as unknown as Record>, configs: { recommended: [] as Config[], - recommendedWithLocalesEn: [] as Config[] + recommendedWithLocalesEn: [] as Config[], + packageJson: [] as Config[] } } satisfies ESLint.Plugin; @@ -218,23 +219,6 @@ const flatRecommendedConfig: Config[] = defineConfig([ ...recommendedPluginRulesConfig }, }, - { - files: ['package.json'], - language: 'json/json', - extends: [tseslint.configs.disableTypeChecked as Config], - plugins: { - depend, - json - }, - rules: { - "no-irregular-whitespace": "off", - "depend/ban-dependencies": [ - "error", { - "presets": ["native", "microutilities", "preferred"] - } - ] - } - }, { languageOptions: { globals: { @@ -319,9 +303,28 @@ const recommendedWithLocalesEn: Config[] = defineConfig({ extends: recommendedWithLocalesEnBase }); +const packageJsonConfig: Config[] = defineConfig( { + files: ['package.json'], + language: 'json/json', + extends: [tseslint.configs.disableTypeChecked as Config], + plugins: { + depend, + json + }, + rules: { + "no-irregular-whitespace": "off", + "depend/ban-dependencies": [ + "error", { + "presets": ["native", "microutilities", "preferred"] + } + ] + } +}); + plugin.configs = { recommended: hybridRecommendedConfig, - recommendedWithLocalesEn + recommendedWithLocalesEn, + packageJson: packageJsonConfig }; export default plugin; From a91e78c072e36b1073e844a28942511d522b5960 Mon Sep 17 00:00:00 2001 From: Michael Naumov Date: Tue, 18 Nov 2025 23:54:00 -0600 Subject: [PATCH 3/3] docs: add usage readme --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index 1fc9b77..21ca718 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,33 @@ export default defineConfig([ ``` +### `package.json` lint rules + +The package exposes special configuration `packageJson` to lint `package.json` file. + +Due to `ESLint` configuration limitation, it's hard to make it working together with other TypeScript rules. + +So it's recommended to extract it into a separate config file, e.g. `eslint.config.package.json.mjs` + +```javascript +// eslint.config.package.json.mjs +import { defineConfig, globalIgnores } from "eslint/config"; + +export default defineConfig([ + globalIgnores([ + '**/*.*', + '!package.json' + ]), + obsidianmd.configs.packageJson +]); +``` + +And then you can run it via + +```bash +npx eslint --config eslint.config.package.json.mjs +``` + ### Legacy Config (`.eslintrc`)