@exbotanical/eslint-config 1.0.1 → 1.1.0

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +27 -11
  2. package/dist/index.js +128 -93
  3. package/package.json +12 -3
package/dist/index.d.ts CHANGED
@@ -1979,6 +1979,11 @@ interface OptionsTypescript extends AllOptions, OptionsTypeScriptParser {
1979
1979
  typeAwareOverrides?: FlatConfigRecord['rules'];
1980
1980
  }
1981
1981
 
1982
+ interface OptionsVue extends AllOptions, OptionsHasTypeScript {
1983
+ vueVersion?: 2 | 3;
1984
+ graphql?: boolean;
1985
+ }
1986
+
1982
1987
  interface OptionsOverrides {
1983
1988
  overrides?: FlatConfigRecord['rules'];
1984
1989
  }
@@ -2023,7 +2028,7 @@ interface OptionsConfig extends OptionsProjectType {
2023
2028
  /**
2024
2029
  * Core ruleset. Cannot be disabled.
2025
2030
  */
2026
- javascript?: OptionsOverrides;
2031
+ javascript?: OptionsOverrides & OptionsFiles;
2027
2032
  /**
2028
2033
  * Enables TypeScript support.
2029
2034
  *
@@ -2040,23 +2045,24 @@ interface OptionsConfig extends OptionsProjectType {
2040
2045
  * Enables Vue rules.
2041
2046
  *
2042
2047
  * Requires installing:
2043
- * - `eslint-plugin-vue`
2044
- * - `vue-eslint-parser`
2048
+ * - eslint-plugin-vue
2049
+ * - vue-eslint-parser
2050
+ * - eslint-processor-vue-blocks (only if embedded graphql is enabled)
2045
2051
  *
2046
2052
  * @default false
2047
2053
  */
2048
- vue?: boolean | OptionsOverrides;
2054
+ vue?: boolean | OptionsVue;
2049
2055
  /**
2050
2056
  * Enables React rules.
2051
2057
  *
2052
2058
  * Requires installing:
2053
- * - `@eslint-react/eslint-plugin`
2054
- * - `eslint-plugin-react-hooks`
2055
- * - `eslint-plugin-react-refresh`
2059
+ * - @eslint-react/eslint-plugin
2060
+ * - eslint-plugin-react-hooks
2061
+ * - eslint-plugin-react-refresh
2056
2062
  *
2057
2063
  * @default false
2058
2064
  */
2059
- react?: boolean | OptionsOverrides;
2065
+ react?: boolean | (OptionsOverrides & OptionsFiles);
2060
2066
  /**
2061
2067
  * Enables JSONC support.
2062
2068
  */
@@ -2066,7 +2072,7 @@ interface OptionsConfig extends OptionsProjectType {
2066
2072
  *
2067
2073
  * @default true
2068
2074
  */
2069
- yaml?: boolean | OptionsOverrides;
2075
+ yaml?: boolean | (OptionsOverrides & OptionsFiles);
2070
2076
  /**
2071
2077
  * Enables TOML support.
2072
2078
  *
@@ -2078,7 +2084,7 @@ interface OptionsConfig extends OptionsProjectType {
2078
2084
  * TODO: update rules
2079
2085
  * @default true
2080
2086
  */
2081
- markdown?: boolean | OptionsOverrides;
2087
+ markdown?: boolean | (OptionsOverrides & OptionsFiles);
2082
2088
  /**
2083
2089
  * Configurable global ignores.
2084
2090
  */
@@ -2093,6 +2099,16 @@ interface OptionsConfig extends OptionsProjectType {
2093
2099
  * @default true
2094
2100
  */
2095
2101
  formatter?: boolean;
2102
+ /**
2103
+ * Enables graphql linting.
2104
+ *
2105
+ * Requires installing:
2106
+ * - @graphql-eslint/eslint-plugin
2107
+ * - eslint-processor-vue-blocks (only if graphql embedded in vue is enabled)
2108
+
2109
+ * @default false
2110
+ */
2111
+ graphql?: boolean | (OptionsOverrides & OptionsFiles);
2096
2112
  }
2097
2113
  interface OptionsStyle {
2098
2114
  indent?: number | 'tab';
@@ -2102,6 +2118,6 @@ interface OptionsStyle {
2102
2118
  }
2103
2119
 
2104
2120
  type LinterOptions = OptionsConfig;
2105
- declare function exbotanical({ javascript: optionsJavascript, ignores: optionsIgnore, jsonc: optionsJsonc, markdown: optionsMarkdown, toml: optionsToml, yaml: optionsYaml, test: optionsTest, formatter, typescript: optionsTypescript, style: optionsStyle, react: optionsReact, vue: optionsVue, type, }: LinterOptions, ...userConfigs: Awaitable<FlatConfigRecord | FlatConfigRecord[] | Linter.Config[]>[]): Promise<FlatConfigRecord[]>;
2121
+ declare function exbotanical({ javascript: optionsJavascript, ignores: optionsIgnore, jsonc: optionsJsonc, markdown: optionsMarkdown, toml: optionsToml, yaml: optionsYaml, test: optionsTest, formatter, typescript: optionsTypescript, style: optionsStyle, react: optionsReact, vue: optionsVue, graphql: optionsGraphql, type, }: LinterOptions, ...userConfigs: Awaitable<FlatConfigRecord | FlatConfigRecord[] | Linter.Config[]>[]): Promise<FlatConfigRecord[]>;
2106
2122
 
2107
2123
  export { type AllOptions, type Awaitable, type FlatConfigRecord, type OptionsConfig, type OptionsFiles, type OptionsHasTypeScript, type OptionsOverrides, type OptionsProjectType, type OptionsStyle, type OptionsTypeScriptParser, type Rules, exbotanical as default };
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ async function comments() {
24
24
  }
25
25
 
26
26
  // src/filepaths.ts
27
+ var GLOB_JS = "**/*.?([cm])js";
27
28
  var GLOB_JSX = "**/*.?([cm])jsx";
28
29
  var GLOB_TS = "**/*.?([cm])ts";
29
30
  var GLOB_TSX = "**/*.?([cm])tsx";
@@ -36,6 +37,7 @@ var GLOB_MARKDOWN = "**/*.md";
36
37
  var GLOB_VUE = "**/*.vue";
37
38
  var GLOB_YAML = "**/*.y?(a)ml";
38
39
  var GLOB_TOML = "**/*.toml";
40
+ var GLOB_GRAPHQL = "**/*.{g,graph}ql";
39
41
  var GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
40
42
  var GLOB_TESTS = [
41
43
  `**/__tests__/**/*.${GLOB_SRC_EXT}`,
@@ -116,6 +118,110 @@ async function disables() {
116
118
  ];
117
119
  }
118
120
 
121
+ // src/utils.ts
122
+ import { fileURLToPath } from "node:url";
123
+ import { isPackageExists } from "local-pkg";
124
+ var parserPlain = {
125
+ meta: {
126
+ name: "parser-plain"
127
+ },
128
+ parseForESLint: (code) => ({
129
+ ast: {
130
+ body: [],
131
+ comments: [],
132
+ loc: { end: code.length, start: 0 },
133
+ range: [0, code.length],
134
+ tokens: [],
135
+ type: "Program"
136
+ },
137
+ scopeManager: null,
138
+ services: { isPlain: true },
139
+ visitorKeys: {
140
+ Program: []
141
+ }
142
+ })
143
+ };
144
+ async function interopDefault(module) {
145
+ const resolved = await module;
146
+ return resolved.default || resolved;
147
+ }
148
+ function renameRules(rules, map) {
149
+ return Object.fromEntries(
150
+ Object.entries(rules).map(([key, value]) => {
151
+ for (const [from, to] of Object.entries(map)) {
152
+ if (key.startsWith(`${from}/`))
153
+ return [to + key.slice(from.length), value];
154
+ }
155
+ return [key, value];
156
+ })
157
+ );
158
+ }
159
+ function mergeProcessors(processors) {
160
+ const cache = /* @__PURE__ */ new Map();
161
+ return {
162
+ meta: {
163
+ name: `merged-processor:${processors.map((processor) => processor.meta?.name || "unknown").join("+")}`
164
+ },
165
+ supportsAutofix: true,
166
+ preprocess(text, filename) {
167
+ const counts = [];
168
+ cache.set(filename, counts);
169
+ return processors.flatMap((processor) => {
170
+ const result = processor.preprocess?.(text, filename) || [];
171
+ counts.push(result.length);
172
+ return result;
173
+ });
174
+ },
175
+ postprocess(messages, filename) {
176
+ const counts = cache.get(filename);
177
+ cache.delete(filename);
178
+ let index = 0;
179
+ return processors.flatMap((processor, index_) => {
180
+ const msgs = messages.slice(index, index + counts[index_]);
181
+ index += counts[index_];
182
+ return processor.postprocess?.(msgs, filename) || [];
183
+ });
184
+ }
185
+ };
186
+ }
187
+ var processorPassThrough = {
188
+ meta: {
189
+ name: "pass-through"
190
+ },
191
+ preprocess(text) {
192
+ return [text];
193
+ },
194
+ postprocess(messages) {
195
+ return messages[0];
196
+ }
197
+ };
198
+ var scopeUrl = fileURLToPath(new URL(".", import.meta.url));
199
+
200
+ // src/configs/graphql.ts
201
+ async function graphql() {
202
+ const graphqlPlugin = await interopDefault(import("@graphql-eslint/eslint-plugin"));
203
+ const rules = {
204
+ ...graphqlPlugin.configs["flat/operations-recommended"].rules,
205
+ ...graphqlPlugin.configs["flat/schema-recommended"].rules
206
+ };
207
+ return [
208
+ {
209
+ files: [GLOB_JS, GLOB_JSX, GLOB_TS, GLOB_TSX],
210
+ processor: graphqlPlugin.processor
211
+ },
212
+ {
213
+ files: [GLOB_GRAPHQL],
214
+ languageOptions: {
215
+ parser: graphqlPlugin.parser
216
+ },
217
+ plugins: {
218
+ "@graphql-eslint": graphqlPlugin
219
+ },
220
+ rules
221
+ }
222
+ ];
223
+ }
224
+
119
225
  // src/configs/ignores.ts
120
226
  var NAMESPACE3 = "exbotanical/ignores";
121
227
  async function ignores({ files = [] } = {}) {
@@ -469,85 +575,6 @@ async function javascript({ overrides = {} } = {}) {
469
575
  ];
470
576
  }
471
577
 
472
- // src/utils.ts
473
- import { fileURLToPath } from "node:url";
474
- import { isPackageExists } from "local-pkg";
475
- var parserPlain = {
476
- meta: {
477
- name: "parser-plain"
478
- },
479
- parseForESLint: (code) => ({
480
- ast: {
481
- body: [],
482
- comments: [],
483
- loc: { end: code.length, start: 0 },
484
- range: [0, code.length],
485
- tokens: [],
486
- type: "Program"
487
- },
488
- scopeManager: null,
489
- services: { isPlain: true },
490
- visitorKeys: {
491
- Program: []
492
- }
493
- })
494
- };
495
- async function interopDefault(module) {
496
- const resolved = await module;
497
- return resolved.default || resolved;
498
- }
499
- function renameRules(rules, map) {
500
- return Object.fromEntries(
501
- Object.entries(rules).map(([key, value]) => {
502
- for (const [from, to] of Object.entries(map)) {
503
- if (key.startsWith(`${from}/`))
504
- return [to + key.slice(from.length), value];
505
- }
506
- return [key, value];
507
- })
508
- );
509
- }
510
- function mergeProcessors(processors) {
511
- const cache = /* @__PURE__ */ new Map();
512
- return {
513
- meta: {
514
- name: `merged-processor:${processors.map((processor) => processor.meta?.name || "unknown").join("+")}`
515
- },
516
- supportsAutofix: true,
517
- preprocess(text, filename) {
518
- const counts = [];
519
- cache.set(filename, counts);
520
- return processors.flatMap((processor) => {
521
- const result = processor.preprocess?.(text, filename) || [];
522
- counts.push(result.length);
523
- return result;
524
- });
525
- },
526
- postprocess(messages, filename) {
527
- const counts = cache.get(filename);
528
- cache.delete(filename);
529
- let index = 0;
530
- return processors.flatMap((processor, index_) => {
531
- const msgs = messages.slice(index, index + counts[index_]);
532
- index += counts[index_];
533
- return processor.postprocess?.(msgs, filename) || [];
534
- });
535
- }
536
- };
537
- }
538
- var processorPassThrough = {
539
- meta: {
540
- name: "pass-through"
541
- },
542
- preprocess(text) {
543
- return [text];
544
- },
545
- postprocess(messages) {
546
- return messages[0];
547
- }
548
- };
549
- var scopeUrl = fileURLToPath(new URL(".", import.meta.url));
550
-
551
578
  // src/configs/jsdoc.ts
552
579
  var NAMESPACE6 = "exbotanical/jsdoc";
553
580
  async function jsdoc() {
@@ -1822,11 +1849,13 @@ async function vue({
1822
1849
  files = [GLOB_VUE],
1823
1850
  overrides = {},
1824
1851
  typescript: typescript2 = true,
1825
- vueVersion = 3
1852
+ vueVersion = 3,
1853
+ graphql: graphql2 = false
1826
1854
  }, { indent } = STYLE_DEFAULTS) {
1827
- const [pluginVue, parserVue] = await Promise.all([
1855
+ const [pluginVue, parserVue, processorVueBlocks] = await Promise.all([
1828
1856
  interopDefault(import("eslint-plugin-vue")),
1829
- interopDefault(import("vue-eslint-parser"))
1857
+ interopDefault(import("vue-eslint-parser")),
1858
+ interopDefault(import("eslint-processor-vue-blocks"))
1830
1859
  ]);
1831
1860
  return [
1832
1861
  {
@@ -1867,7 +1896,16 @@ async function vue({
1867
1896
  sourceType: "module"
1868
1897
  }
1869
1898
  },
1870
- processor: pluginVue.processors[".vue"],
1899
+ processor: graphql2 === false ? pluginVue.processors[".vue"] : mergeProcessors([
1900
+ pluginVue.processors[".vue"],
1901
+ processorVueBlocks({
1902
+ blocks: {
1903
+ script: true,
1904
+ scriptSetup: true,
1905
+ customBlocks: true
1906
+ }
1907
+ })
1908
+ ]),
1871
1909
  rules: {
1872
1910
  ...pluginVue.configs.base.rules,
1873
1911
  ...vueVersion === 2 ? {
@@ -1894,12 +1932,7 @@ async function vue({
1894
1932
  "vue/define-macros-order": [
1895
1933
  "error",
1896
1934
  {
1897
- order: [
1898
- "defineOptions",
1899
- "defineProps",
1900
- "defineEmits",
1901
- "defineSlots"
1902
- ]
1935
+ order: ["defineOptions", "defineProps", "defineEmits", "defineSlots"]
1903
1936
  }
1904
1937
  ],
1905
1938
  "vue/dot-location": ["error", "property"],
@@ -2051,6 +2084,7 @@ async function exbotanical({
2051
2084
  style: optionsStyle = STYLE_DEFAULTS,
2052
2085
  react: optionsReact,
2053
2086
  vue: optionsVue,
2087
+ graphql: optionsGraphql,
2054
2088
  type
2055
2089
  }, ...userConfigs) {
2056
2090
  const configs2 = [
@@ -2078,6 +2112,9 @@ async function exbotanical({
2078
2112
  if (optionsMarkdown) {
2079
2113
  configs2.push(markdown({ ...factoryConfig(optionsMarkdown) }));
2080
2114
  }
2115
+ if (optionsGraphql) {
2116
+ configs2.push(graphql());
2117
+ }
2081
2118
  if (optionsReact) {
2082
2119
  configs2.push(react({ ...factoryConfig(optionsReact) }));
2083
2120
  }
@@ -2088,7 +2125,7 @@ async function exbotanical({
2088
2125
  configs2.push(typescript({ ...factoryConfig(optionsTypescript), type }));
2089
2126
  }
2090
2127
  if (optionsVue) {
2091
- configs2.push(vue({ ...factoryConfig(optionsVue) }));
2128
+ configs2.push(vue({ ...factoryConfig(optionsVue), graphql: !!optionsGraphql }));
2092
2129
  }
2093
2130
  if (optionsYaml) {
2094
2131
  configs2.push(yaml({ ...factoryConfig(optionsYaml), ...optionsStyle }));
@@ -2099,9 +2136,7 @@ async function exbotanical({
2099
2136
  configs2.push(disables(), ignores({ ...optionsIgnore }));
2100
2137
  if (userConfigs.length > 0) {
2101
2138
  const resolved2 = await Promise.all(userConfigs);
2102
- configs2.push(
2103
- ...resolved2.map((r) => Promise.resolve(Array.isArray(r) ? r : [r]))
2104
- );
2139
+ configs2.push(...resolved2.map((r) => Promise.resolve(Array.isArray(r) ? r : [r])));
2105
2140
  }
2106
2141
  const resolved = await Promise.all(configs2);
2107
2142
  return resolved.flat();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exbotanical/eslint-config",
3
3
  "type": "module",
4
- "version": "1.0.1",
4
+ "version": "1.1.0",
5
5
  "private": false,
6
6
  "description": "Zito's eslint config",
7
7
  "author": "Matthew Zito <exbotanical@protonmail.com> (https://github.com/exbotanical/)",
@@ -38,18 +38,23 @@
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@eslint-react/eslint-plugin": "^1.30.1",
41
+ "@graphql-eslint/eslint-plugin": "^4.3.0",
41
42
  "@prettier/plugin-xml": "^3.4.1",
42
43
  "eslint": "^9.10.0",
43
44
  "eslint-plugin-react-hooks": "^5.0.0",
44
45
  "eslint-plugin-react-refresh": "^0.4.4",
45
46
  "eslint-plugin-tap": "^1.2.1",
46
47
  "eslint-plugin-vue": "^9.32.0",
48
+ "eslint-processor-vue-blocks": "^2.0.0",
47
49
  "vue-eslint-parser": "^9.4.3"
48
50
  },
49
51
  "peerDependenciesMeta": {
50
52
  "@eslint-react/eslint-plugin": {
51
53
  "optional": true
52
54
  },
55
+ "@graphql-eslint/eslint-plugin": {
56
+ "optional": true
57
+ },
53
58
  "@prettier/plugin-xml": {
54
59
  "optional": true
55
60
  },
@@ -65,6 +70,9 @@
65
70
  "eslint-plugin-vue": {
66
71
  "optional": true
67
72
  },
73
+ "eslint-processor-vue-blocks": {
74
+ "optional": true
75
+ },
68
76
  "vue-eslint-parser": {
69
77
  "optional": true
70
78
  }
@@ -97,7 +105,8 @@
97
105
  },
98
106
  "devDependencies": {
99
107
  "@eslint-react/eslint-plugin": "^1.31.0",
100
- "@magister_zito/prettier-config": "^0.0.5",
108
+ "@exbotanical/prettier-config": "^1.0.1",
109
+ "@graphql-eslint/eslint-plugin": "^4.3.0",
101
110
  "@prettier/plugin-xml": "^3.4.1",
102
111
  "@stylistic/eslint-plugin": "^4.2.0",
103
112
  "@types/eslint-config-prettier": "^6.11.3",
@@ -107,6 +116,7 @@
107
116
  "eslint-plugin-react-hooks": "^5.2.0",
108
117
  "eslint-plugin-react-refresh": "^0.4.19",
109
118
  "eslint-plugin-vue": "^9.32.0",
119
+ "eslint-processor-vue-blocks": "^2.0.0",
110
120
  "jiti": "^2.4.2",
111
121
  "lint-staged": "^15.4.3",
112
122
  "simple-git-hooks": "^2.11.1",
@@ -116,7 +126,6 @@
116
126
  "vitest": "^3.0.7",
117
127
  "vue-eslint-parser": "^10.1.1"
118
128
  },
119
- "prettier": "@magister_zito/prettier-config",
120
129
  "simple-git-hooks": {
121
130
  "pre-commit": "npx lint-staged"
122
131
  },