@saasmakers/eslint 1.0.21 → 1.0.23
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/dist/eslint.config.cjs +2 -1
- package/dist/eslint.config.d.cts +2 -1
- package/dist/eslint.config.d.mts +2 -1
- package/dist/eslint.config.d.ts +2 -1
- package/dist/eslint.config.mjs +2 -1
- package/dist/index.cjs +37 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +37 -1
- package/package.json +3 -2
package/dist/eslint.config.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const antfu = require('@antfu/eslint-config');
|
|
4
4
|
const saasmakers = require('@saasmakers/eslint');
|
|
5
|
+
const shared = require('@saasmakers/shared');
|
|
5
6
|
const vitest = require('@vitest/eslint-plugin');
|
|
6
7
|
const packageJson = require('eslint-plugin-package-json');
|
|
7
8
|
const index$1 = require('./shared/eslint.BqRQ4tAN.cjs');
|
|
@@ -10869,7 +10870,7 @@ const eslint_config = antfu__default(
|
|
|
10869
10870
|
rules: {
|
|
10870
10871
|
"saasmakers/ts-format-layout": "error",
|
|
10871
10872
|
"saasmakers/ts-format-tests": "error",
|
|
10872
|
-
"saasmakers/vue-format-i18n": "error",
|
|
10873
|
+
"saasmakers/vue-format-i18n": ["error", { locales: shared.localeCodes }],
|
|
10873
10874
|
"saasmakers/vue-format-script": "error",
|
|
10874
10875
|
"saasmakers/vue-format-template": "error"
|
|
10875
10876
|
}
|
package/dist/eslint.config.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import antfu from '@antfu/eslint-config';
|
|
2
2
|
import saasmakers from '@saasmakers/eslint';
|
|
3
|
+
import { localeCodes } from '@saasmakers/shared';
|
|
3
4
|
import vitest from '@vitest/eslint-plugin';
|
|
4
5
|
import packageJson from 'eslint-plugin-package-json';
|
|
5
6
|
import { Linter, ESLint } from 'eslint';
|
|
@@ -149,7 +150,7 @@ var eslint_config = antfu(
|
|
|
149
150
|
rules: {
|
|
150
151
|
"saasmakers/ts-format-layout": "error",
|
|
151
152
|
"saasmakers/ts-format-tests": "error",
|
|
152
|
-
"saasmakers/vue-format-i18n": "error",
|
|
153
|
+
"saasmakers/vue-format-i18n": ["error", { locales: localeCodes }],
|
|
153
154
|
"saasmakers/vue-format-script": "error",
|
|
154
155
|
"saasmakers/vue-format-template": "error"
|
|
155
156
|
}
|
package/dist/eslint.config.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import antfu from '@antfu/eslint-config';
|
|
2
2
|
import saasmakers from '@saasmakers/eslint';
|
|
3
|
+
import { localeCodes } from '@saasmakers/shared';
|
|
3
4
|
import vitest from '@vitest/eslint-plugin';
|
|
4
5
|
import packageJson from 'eslint-plugin-package-json';
|
|
5
6
|
import { Linter, ESLint } from 'eslint';
|
|
@@ -149,7 +150,7 @@ var eslint_config = antfu(
|
|
|
149
150
|
rules: {
|
|
150
151
|
"saasmakers/ts-format-layout": "error",
|
|
151
152
|
"saasmakers/ts-format-tests": "error",
|
|
152
|
-
"saasmakers/vue-format-i18n": "error",
|
|
153
|
+
"saasmakers/vue-format-i18n": ["error", { locales: localeCodes }],
|
|
153
154
|
"saasmakers/vue-format-script": "error",
|
|
154
155
|
"saasmakers/vue-format-template": "error"
|
|
155
156
|
}
|
package/dist/eslint.config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import antfu from '@antfu/eslint-config';
|
|
2
2
|
import saasmakers from '@saasmakers/eslint';
|
|
3
|
+
import { localeCodes } from '@saasmakers/shared';
|
|
3
4
|
import vitest from '@vitest/eslint-plugin';
|
|
4
5
|
import packageJson from 'eslint-plugin-package-json';
|
|
5
6
|
import { Linter, ESLint } from 'eslint';
|
|
@@ -149,7 +150,7 @@ var eslint_config = antfu(
|
|
|
149
150
|
rules: {
|
|
150
151
|
"saasmakers/ts-format-layout": "error",
|
|
151
152
|
"saasmakers/ts-format-tests": "error",
|
|
152
|
-
"saasmakers/vue-format-i18n": "error",
|
|
153
|
+
"saasmakers/vue-format-i18n": ["error", { locales: localeCodes }],
|
|
153
154
|
"saasmakers/vue-format-script": "error",
|
|
154
155
|
"saasmakers/vue-format-template": "error"
|
|
155
156
|
}
|
package/dist/eslint.config.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import antfu from '@antfu/eslint-config';
|
|
2
2
|
import saasmakers from '@saasmakers/eslint';
|
|
3
|
+
import { localeCodes } from '@saasmakers/shared';
|
|
3
4
|
import vitest from '@vitest/eslint-plugin';
|
|
4
5
|
import packageJson from 'eslint-plugin-package-json';
|
|
5
6
|
import { d as distExports } from './shared/eslint.DOaqyhfZ.mjs';
|
|
@@ -10843,7 +10844,7 @@ const eslint_config = antfu(
|
|
|
10843
10844
|
rules: {
|
|
10844
10845
|
"saasmakers/ts-format-layout": "error",
|
|
10845
10846
|
"saasmakers/ts-format-tests": "error",
|
|
10846
|
-
"saasmakers/vue-format-i18n": "error",
|
|
10847
|
+
"saasmakers/vue-format-i18n": ["error", { locales: localeCodes }],
|
|
10847
10848
|
"saasmakers/vue-format-script": "error",
|
|
10848
10849
|
"saasmakers/vue-format-template": "error"
|
|
10849
10850
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -281,6 +281,9 @@ const rule$4 = {
|
|
|
281
281
|
type: "layout"
|
|
282
282
|
},
|
|
283
283
|
create(context) {
|
|
284
|
+
if (context.filename.endsWith(".d.ts")) {
|
|
285
|
+
return {};
|
|
286
|
+
}
|
|
284
287
|
const sourceCode = context.sourceCode;
|
|
285
288
|
const maxCharacters = context.options[0]?.maxCharacters ?? defaultMaxCharacters;
|
|
286
289
|
const maxLineLength = context.options[0]?.maxLineLength ?? defaultMaxLineLength;
|
|
@@ -805,6 +808,11 @@ const templateRegex = /<template>([\s\S]*)<\/template>/i;
|
|
|
805
808
|
const templateTagLength = "<template>".length;
|
|
806
809
|
const propsPrefixRegex = /\$?props\.(\w+)/g;
|
|
807
810
|
const trueAttributeRegex = /(?<![\w-]):?(?!aria-)([a-z0-9-]+)="true"/gi;
|
|
811
|
+
const eventHandlerRegex = /(?:@|v-on:)[^\s="'<>/]+\s*=\s*"([^"]*)"/g;
|
|
812
|
+
const bareIdentifierRegex = /^[A-Za-z_$][\w$]*$/;
|
|
813
|
+
const singleCallRegex = /^([A-Za-z_$][\w$]*)\s*\(.*\)$/s;
|
|
814
|
+
const onPrefixRegex = /^on[A-Z]/;
|
|
815
|
+
const exemptCallees = /* @__PURE__ */ new Set(["$emit", "emit"]);
|
|
808
816
|
const dollarTPatterns = [
|
|
809
817
|
{
|
|
810
818
|
pattern: / \$t\(/g,
|
|
@@ -830,10 +838,11 @@ const dollarTPatterns = [
|
|
|
830
838
|
const rule = {
|
|
831
839
|
defaultOptions: [],
|
|
832
840
|
meta: {
|
|
833
|
-
docs: { description: 'Format Vue templates: strip unnecessary props/$props prefixes, redundant ="true" attributes (except aria- attributes),
|
|
841
|
+
docs: { description: 'Format Vue templates: strip unnecessary props/$props prefixes, redundant ="true" attributes (except aria- attributes), enforce t() over $t(), and require "on" prefix on named event listener handlers' },
|
|
834
842
|
fixable: "code",
|
|
835
843
|
messages: {
|
|
836
844
|
noPropsPrefix: "Unnecessary props/$props prefix in template. Props are automatically available in template scope.",
|
|
845
|
+
prefixEventHandlerWithOn: 'Event listener handler "{{name}}" must be prefixed with "on" (e.g. @click="onClick").',
|
|
837
846
|
removeTrueAttribute: 'Unnecessary ="true" attribute. Use the attribute name directly instead.',
|
|
838
847
|
useT: "Use t() instead of $t() in Vue templates as it does not work with <i18n> tags."
|
|
839
848
|
},
|
|
@@ -908,6 +917,33 @@ const rule = {
|
|
|
908
917
|
dollarTMatch = pattern.exec(templateContent);
|
|
909
918
|
}
|
|
910
919
|
}
|
|
920
|
+
eventHandlerRegex.lastIndex = 0;
|
|
921
|
+
let eventHandlerMatch = eventHandlerRegex.exec(templateContent);
|
|
922
|
+
while (eventHandlerMatch !== null) {
|
|
923
|
+
const handlerValue = eventHandlerMatch[1].trim();
|
|
924
|
+
let handlerName;
|
|
925
|
+
if (bareIdentifierRegex.test(handlerValue)) {
|
|
926
|
+
handlerName = handlerValue;
|
|
927
|
+
} else {
|
|
928
|
+
const singleCallMatch = singleCallRegex.exec(handlerValue);
|
|
929
|
+
if (singleCallMatch) {
|
|
930
|
+
handlerName = singleCallMatch[1];
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
if (handlerName && !exemptCallees.has(handlerName) && !onPrefixRegex.test(handlerName)) {
|
|
934
|
+
const valueStart = templateStartIndex + eventHandlerMatch.index + eventHandlerMatch[0].length - 1 - eventHandlerMatch[1].length;
|
|
935
|
+
const valueEnd = valueStart + eventHandlerMatch[1].length;
|
|
936
|
+
context.report({
|
|
937
|
+
data: { name: handlerName },
|
|
938
|
+
loc: {
|
|
939
|
+
end: sourceCode.getLocFromIndex(valueEnd),
|
|
940
|
+
start: sourceCode.getLocFromIndex(valueStart)
|
|
941
|
+
},
|
|
942
|
+
messageId: "prefixEventHandlerWithOn"
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
eventHandlerMatch = eventHandlerRegex.exec(templateContent);
|
|
946
|
+
}
|
|
911
947
|
}
|
|
912
948
|
};
|
|
913
949
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -5203,7 +5203,7 @@ declare const _default: {
|
|
|
5203
5203
|
locales?: string[];
|
|
5204
5204
|
} | undefined)?], unknown, RuleListener>;
|
|
5205
5205
|
'vue-format-script': RuleModule<"multilineComputed" | "untypedEmits", [], unknown, RuleListener>;
|
|
5206
|
-
'vue-format-template': RuleModule<"noPropsPrefix" | "removeTrueAttribute" | "useT", [], unknown, RuleListener>;
|
|
5206
|
+
'vue-format-template': RuleModule<"noPropsPrefix" | "prefixEventHandlerWithOn" | "removeTrueAttribute" | "useT", [], unknown, RuleListener>;
|
|
5207
5207
|
};
|
|
5208
5208
|
};
|
|
5209
5209
|
|
package/dist/index.d.mts
CHANGED
|
@@ -5203,7 +5203,7 @@ declare const _default: {
|
|
|
5203
5203
|
locales?: string[];
|
|
5204
5204
|
} | undefined)?], unknown, RuleListener>;
|
|
5205
5205
|
'vue-format-script': RuleModule<"multilineComputed" | "untypedEmits", [], unknown, RuleListener>;
|
|
5206
|
-
'vue-format-template': RuleModule<"noPropsPrefix" | "removeTrueAttribute" | "useT", [], unknown, RuleListener>;
|
|
5206
|
+
'vue-format-template': RuleModule<"noPropsPrefix" | "prefixEventHandlerWithOn" | "removeTrueAttribute" | "useT", [], unknown, RuleListener>;
|
|
5207
5207
|
};
|
|
5208
5208
|
};
|
|
5209
5209
|
|
package/dist/index.d.ts
CHANGED
|
@@ -5203,7 +5203,7 @@ declare const _default: {
|
|
|
5203
5203
|
locales?: string[];
|
|
5204
5204
|
} | undefined)?], unknown, RuleListener>;
|
|
5205
5205
|
'vue-format-script': RuleModule<"multilineComputed" | "untypedEmits", [], unknown, RuleListener>;
|
|
5206
|
-
'vue-format-template': RuleModule<"noPropsPrefix" | "removeTrueAttribute" | "useT", [], unknown, RuleListener>;
|
|
5206
|
+
'vue-format-template': RuleModule<"noPropsPrefix" | "prefixEventHandlerWithOn" | "removeTrueAttribute" | "useT", [], unknown, RuleListener>;
|
|
5207
5207
|
};
|
|
5208
5208
|
};
|
|
5209
5209
|
|
package/dist/index.mjs
CHANGED
|
@@ -279,6 +279,9 @@ const rule$4 = {
|
|
|
279
279
|
type: "layout"
|
|
280
280
|
},
|
|
281
281
|
create(context) {
|
|
282
|
+
if (context.filename.endsWith(".d.ts")) {
|
|
283
|
+
return {};
|
|
284
|
+
}
|
|
282
285
|
const sourceCode = context.sourceCode;
|
|
283
286
|
const maxCharacters = context.options[0]?.maxCharacters ?? defaultMaxCharacters;
|
|
284
287
|
const maxLineLength = context.options[0]?.maxLineLength ?? defaultMaxLineLength;
|
|
@@ -803,6 +806,11 @@ const templateRegex = /<template>([\s\S]*)<\/template>/i;
|
|
|
803
806
|
const templateTagLength = "<template>".length;
|
|
804
807
|
const propsPrefixRegex = /\$?props\.(\w+)/g;
|
|
805
808
|
const trueAttributeRegex = /(?<![\w-]):?(?!aria-)([a-z0-9-]+)="true"/gi;
|
|
809
|
+
const eventHandlerRegex = /(?:@|v-on:)[^\s="'<>/]+\s*=\s*"([^"]*)"/g;
|
|
810
|
+
const bareIdentifierRegex = /^[A-Za-z_$][\w$]*$/;
|
|
811
|
+
const singleCallRegex = /^([A-Za-z_$][\w$]*)\s*\(.*\)$/s;
|
|
812
|
+
const onPrefixRegex = /^on[A-Z]/;
|
|
813
|
+
const exemptCallees = /* @__PURE__ */ new Set(["$emit", "emit"]);
|
|
806
814
|
const dollarTPatterns = [
|
|
807
815
|
{
|
|
808
816
|
pattern: / \$t\(/g,
|
|
@@ -828,10 +836,11 @@ const dollarTPatterns = [
|
|
|
828
836
|
const rule = {
|
|
829
837
|
defaultOptions: [],
|
|
830
838
|
meta: {
|
|
831
|
-
docs: { description: 'Format Vue templates: strip unnecessary props/$props prefixes, redundant ="true" attributes (except aria- attributes),
|
|
839
|
+
docs: { description: 'Format Vue templates: strip unnecessary props/$props prefixes, redundant ="true" attributes (except aria- attributes), enforce t() over $t(), and require "on" prefix on named event listener handlers' },
|
|
832
840
|
fixable: "code",
|
|
833
841
|
messages: {
|
|
834
842
|
noPropsPrefix: "Unnecessary props/$props prefix in template. Props are automatically available in template scope.",
|
|
843
|
+
prefixEventHandlerWithOn: 'Event listener handler "{{name}}" must be prefixed with "on" (e.g. @click="onClick").',
|
|
835
844
|
removeTrueAttribute: 'Unnecessary ="true" attribute. Use the attribute name directly instead.',
|
|
836
845
|
useT: "Use t() instead of $t() in Vue templates as it does not work with <i18n> tags."
|
|
837
846
|
},
|
|
@@ -906,6 +915,33 @@ const rule = {
|
|
|
906
915
|
dollarTMatch = pattern.exec(templateContent);
|
|
907
916
|
}
|
|
908
917
|
}
|
|
918
|
+
eventHandlerRegex.lastIndex = 0;
|
|
919
|
+
let eventHandlerMatch = eventHandlerRegex.exec(templateContent);
|
|
920
|
+
while (eventHandlerMatch !== null) {
|
|
921
|
+
const handlerValue = eventHandlerMatch[1].trim();
|
|
922
|
+
let handlerName;
|
|
923
|
+
if (bareIdentifierRegex.test(handlerValue)) {
|
|
924
|
+
handlerName = handlerValue;
|
|
925
|
+
} else {
|
|
926
|
+
const singleCallMatch = singleCallRegex.exec(handlerValue);
|
|
927
|
+
if (singleCallMatch) {
|
|
928
|
+
handlerName = singleCallMatch[1];
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
if (handlerName && !exemptCallees.has(handlerName) && !onPrefixRegex.test(handlerName)) {
|
|
932
|
+
const valueStart = templateStartIndex + eventHandlerMatch.index + eventHandlerMatch[0].length - 1 - eventHandlerMatch[1].length;
|
|
933
|
+
const valueEnd = valueStart + eventHandlerMatch[1].length;
|
|
934
|
+
context.report({
|
|
935
|
+
data: { name: handlerName },
|
|
936
|
+
loc: {
|
|
937
|
+
end: sourceCode.getLocFromIndex(valueEnd),
|
|
938
|
+
start: sourceCode.getLocFromIndex(valueStart)
|
|
939
|
+
},
|
|
940
|
+
messageId: "prefixEventHandlerWithOn"
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
eventHandlerMatch = eventHandlerRegex.exec(templateContent);
|
|
944
|
+
}
|
|
909
945
|
}
|
|
910
946
|
};
|
|
911
947
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saasmakers/eslint",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared ESLint config and rules for SaaS Makers projects",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"eslint-plugin-package-json": "0.31.0",
|
|
33
33
|
"eslint-plugin-turbo": "2.9.18",
|
|
34
34
|
"eslint-plugin-zod": "3.4.0",
|
|
35
|
-
"typescript-eslint": "8.61.0"
|
|
35
|
+
"typescript-eslint": "8.61.0",
|
|
36
|
+
"@saasmakers/shared": "0.2.8"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@eslint/config-inspector": "1.4.2",
|