@stll/oxlint-config 0.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.
- package/dist/index.cjs +119 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +110 -0
- package/dist/index.d.mts +110 -0
- package/dist/index.mjs +110 -0
- package/dist/index.mjs.map +1 -0
- package/dist/plugin.cjs +155 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +36 -0
- package/dist/plugin.d.mts +37 -0
- package/dist/plugin.mjs +151 -0
- package/dist/plugin.mjs.map +1 -0
- package/package.json +62 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
let oxlint = require("oxlint");
|
|
6
|
+
//#region src/index.ts
|
|
7
|
+
const stellaLowercasePluginSpecifier = "@stll/oxlint-config/plugin";
|
|
8
|
+
const libraryIgnorePatterns = [
|
|
9
|
+
"node_modules/",
|
|
10
|
+
"dist/",
|
|
11
|
+
"coverage/"
|
|
12
|
+
];
|
|
13
|
+
const libraryRules = {
|
|
14
|
+
"no-console": "off",
|
|
15
|
+
"no-shadow": "error",
|
|
16
|
+
"require-await": "error",
|
|
17
|
+
"no-useless-catch": "error",
|
|
18
|
+
"no-non-null-assertion": "error",
|
|
19
|
+
"no-useless-assignment": "error",
|
|
20
|
+
"no-loop-func": "error",
|
|
21
|
+
"no-nested-ternary": "error",
|
|
22
|
+
"no-void": ["error", { allowAsStatement: true }],
|
|
23
|
+
"stella-lowercase/stella-lowercase": "error",
|
|
24
|
+
"typescript/no-explicit-any": "error",
|
|
25
|
+
"typescript/no-dynamic-delete": "error",
|
|
26
|
+
"typescript/no-misused-promises": ["error", { checksVoidReturn: { attributes: false } }],
|
|
27
|
+
"typescript/consistent-type-definitions": ["error", "type"],
|
|
28
|
+
"typescript/consistent-return": "error",
|
|
29
|
+
"typescript/dot-notation": "error",
|
|
30
|
+
"typescript/no-inferrable-types": "off",
|
|
31
|
+
"typescript/no-unnecessary-type-conversion": "error",
|
|
32
|
+
"typescript/no-unnecessary-condition": ["error", { allowConstantLoopConditions: "only-allowed-literals" }],
|
|
33
|
+
"typescript/no-unnecessary-type-arguments": "error",
|
|
34
|
+
"typescript/switch-exhaustiveness-check": ["error", { considerDefaultExhaustiveForUnions: true }],
|
|
35
|
+
"typescript/strict-boolean-expressions": ["error", {
|
|
36
|
+
allowNullableString: true,
|
|
37
|
+
allowNullableBoolean: true
|
|
38
|
+
}],
|
|
39
|
+
"typescript/no-confusing-void-expression": ["error", {
|
|
40
|
+
ignoreArrowShorthand: true,
|
|
41
|
+
ignoreVoidReturningFunctions: true
|
|
42
|
+
}],
|
|
43
|
+
"typescript/prefer-nullish-coalescing": ["error", { ignorePrimitives: {
|
|
44
|
+
string: true,
|
|
45
|
+
boolean: true
|
|
46
|
+
} }],
|
|
47
|
+
"typescript/only-throw-error": "error",
|
|
48
|
+
"typescript/return-await": ["error", "error-handling-correctness-only"],
|
|
49
|
+
"unicorn/no-useless-undefined": "off",
|
|
50
|
+
"unicorn/prefer-array-find": "error",
|
|
51
|
+
"unicorn/prefer-at": "error",
|
|
52
|
+
"unicorn/prefer-set-has": "error",
|
|
53
|
+
"unicorn/filename-case": "off",
|
|
54
|
+
"unicorn/consistent-function-scoping": "off",
|
|
55
|
+
"unicorn/prefer-ternary": "off",
|
|
56
|
+
"unicorn/no-array-reduce": "error",
|
|
57
|
+
"unicorn/no-nested-ternary": "off",
|
|
58
|
+
"import/no-cycle": "error",
|
|
59
|
+
"import/consistent-type-specifier-style": "off",
|
|
60
|
+
"promise/always-return": "error",
|
|
61
|
+
"promise/no-return-in-finally": "error",
|
|
62
|
+
"promise/prefer-await-to-then": "off",
|
|
63
|
+
"promise/prefer-await-to-callbacks": "off",
|
|
64
|
+
"promise/avoid-new": "off",
|
|
65
|
+
"sort-keys": "off",
|
|
66
|
+
"no-plusplus": "off",
|
|
67
|
+
"no-inline-comments": "off",
|
|
68
|
+
"max-statements": "off",
|
|
69
|
+
"prefer-destructuring": "off",
|
|
70
|
+
"no-negated-condition": "off",
|
|
71
|
+
"no-use-before-define": "off",
|
|
72
|
+
"no-useless-return": "off",
|
|
73
|
+
"no-warning-comments": "off",
|
|
74
|
+
"no-unexpected-multiline": "off",
|
|
75
|
+
"max-classes-per-file": "off",
|
|
76
|
+
"class-methods-use-this": "off",
|
|
77
|
+
"no-unmodified-loop-condition": "off",
|
|
78
|
+
complexity: "off",
|
|
79
|
+
"func-style": "off",
|
|
80
|
+
"func-names": "off",
|
|
81
|
+
"default-case": "off"
|
|
82
|
+
};
|
|
83
|
+
const libraryOverrides = [{
|
|
84
|
+
files: [
|
|
85
|
+
"**/*.{test,spec}.{ts,tsx,js,jsx}",
|
|
86
|
+
"__test__/**",
|
|
87
|
+
"__tests__/**"
|
|
88
|
+
],
|
|
89
|
+
rules: {
|
|
90
|
+
"no-console": "off",
|
|
91
|
+
"require-await": "off",
|
|
92
|
+
"no-non-null-assertion": "off"
|
|
93
|
+
}
|
|
94
|
+
}];
|
|
95
|
+
const library = (options = {}) => (0, oxlint.defineConfig)({
|
|
96
|
+
options: {
|
|
97
|
+
denyWarnings: true,
|
|
98
|
+
reportUnusedDisableDirectives: "error",
|
|
99
|
+
typeAware: true,
|
|
100
|
+
...options.options
|
|
101
|
+
},
|
|
102
|
+
jsPlugins: [stellaLowercasePluginSpecifier, ...options.jsPlugins ?? []],
|
|
103
|
+
ignorePatterns: [...libraryIgnorePatterns, ...options.ignorePatterns ?? []],
|
|
104
|
+
rules: {
|
|
105
|
+
...libraryRules,
|
|
106
|
+
...options.rules
|
|
107
|
+
},
|
|
108
|
+
overrides: [...libraryOverrides, ...options.overrides ?? []]
|
|
109
|
+
});
|
|
110
|
+
var src_default = library();
|
|
111
|
+
//#endregion
|
|
112
|
+
exports.default = src_default;
|
|
113
|
+
exports.library = library;
|
|
114
|
+
exports.libraryIgnorePatterns = libraryIgnorePatterns;
|
|
115
|
+
exports.libraryOverrides = libraryOverrides;
|
|
116
|
+
exports.libraryRules = libraryRules;
|
|
117
|
+
exports.stellaLowercasePluginSpecifier = stellaLowercasePluginSpecifier;
|
|
118
|
+
|
|
119
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { defineConfig, type OxlintConfig, type OxlintOverride } from \"oxlint\";\n\ntype Rules = NonNullable<OxlintConfig[\"rules\"]>;\ntype JsPlugins = NonNullable<OxlintConfig[\"jsPlugins\"]>;\ntype Options = NonNullable<OxlintConfig[\"options\"]>;\n\nexport type LibraryOptions = {\n jsPlugins?: JsPlugins;\n ignorePatterns?: string[];\n options?: Options;\n overrides?: OxlintOverride[];\n rules?: Rules;\n};\n\nexport const stellaLowercasePluginSpecifier = \"@stll/oxlint-config/plugin\";\n\nexport const libraryIgnorePatterns = [\"node_modules/\", \"dist/\", \"coverage/\"];\n\nexport const libraryRules = {\n \"no-console\": \"off\",\n \"no-shadow\": \"error\",\n \"require-await\": \"error\",\n \"no-useless-catch\": \"error\",\n \"no-non-null-assertion\": \"error\",\n \"no-useless-assignment\": \"error\",\n \"no-loop-func\": \"error\",\n \"no-nested-ternary\": \"error\",\n \"no-void\": [\"error\", { allowAsStatement: true }],\n \"stella-lowercase/stella-lowercase\": \"error\",\n\n \"typescript/no-explicit-any\": \"error\",\n \"typescript/no-dynamic-delete\": \"error\",\n \"typescript/no-misused-promises\": [\n \"error\",\n { checksVoidReturn: { attributes: false } },\n ],\n \"typescript/consistent-type-definitions\": [\"error\", \"type\"],\n \"typescript/consistent-return\": \"error\",\n \"typescript/dot-notation\": \"error\",\n \"typescript/no-inferrable-types\": \"off\",\n \"typescript/no-unnecessary-type-conversion\": \"error\",\n \"typescript/no-unnecessary-condition\": [\n \"error\",\n { allowConstantLoopConditions: \"only-allowed-literals\" },\n ],\n \"typescript/no-unnecessary-type-arguments\": \"error\",\n \"typescript/switch-exhaustiveness-check\": [\n \"error\",\n { considerDefaultExhaustiveForUnions: true },\n ],\n \"typescript/strict-boolean-expressions\": [\n \"error\",\n { allowNullableString: true, allowNullableBoolean: true },\n ],\n \"typescript/no-confusing-void-expression\": [\n \"error\",\n { ignoreArrowShorthand: true, ignoreVoidReturningFunctions: true },\n ],\n \"typescript/prefer-nullish-coalescing\": [\n \"error\",\n { ignorePrimitives: { string: true, boolean: true } },\n ],\n \"typescript/only-throw-error\": \"error\",\n \"typescript/return-await\": [\"error\", \"error-handling-correctness-only\"],\n\n \"unicorn/no-useless-undefined\": \"off\",\n \"unicorn/prefer-array-find\": \"error\",\n \"unicorn/prefer-at\": \"error\",\n \"unicorn/prefer-set-has\": \"error\",\n \"unicorn/filename-case\": \"off\",\n \"unicorn/consistent-function-scoping\": \"off\",\n \"unicorn/prefer-ternary\": \"off\",\n \"unicorn/no-array-reduce\": \"error\",\n \"unicorn/no-nested-ternary\": \"off\",\n\n \"import/no-cycle\": \"error\",\n \"import/consistent-type-specifier-style\": \"off\",\n\n \"promise/always-return\": \"error\",\n \"promise/no-return-in-finally\": \"error\",\n \"promise/prefer-await-to-then\": \"off\",\n \"promise/prefer-await-to-callbacks\": \"off\",\n \"promise/avoid-new\": \"off\",\n\n \"sort-keys\": \"off\",\n \"no-plusplus\": \"off\",\n \"no-inline-comments\": \"off\",\n \"max-statements\": \"off\",\n \"prefer-destructuring\": \"off\",\n \"no-negated-condition\": \"off\",\n \"no-use-before-define\": \"off\",\n \"no-useless-return\": \"off\",\n \"no-warning-comments\": \"off\",\n \"no-unexpected-multiline\": \"off\",\n \"max-classes-per-file\": \"off\",\n \"class-methods-use-this\": \"off\",\n \"no-unmodified-loop-condition\": \"off\",\n complexity: \"off\",\n \"func-style\": \"off\",\n \"func-names\": \"off\",\n \"default-case\": \"off\",\n} satisfies Rules;\n\nexport const libraryOverrides = [\n {\n files: [\"**/*.{test,spec}.{ts,tsx,js,jsx}\", \"__test__/**\", \"__tests__/**\"],\n rules: {\n \"no-console\": \"off\",\n \"require-await\": \"off\",\n \"no-non-null-assertion\": \"off\",\n },\n },\n] satisfies OxlintOverride[];\n\nexport const library = (options: LibraryOptions = {}): OxlintConfig =>\n defineConfig({\n options: {\n denyWarnings: true,\n reportUnusedDisableDirectives: \"error\",\n typeAware: true,\n ...options.options,\n },\n jsPlugins: [stellaLowercasePluginSpecifier, ...(options.jsPlugins ?? [])],\n ignorePatterns: [\n ...libraryIgnorePatterns,\n ...(options.ignorePatterns ?? []),\n ],\n rules: {\n ...libraryRules,\n ...options.rules,\n },\n overrides: [...libraryOverrides, ...(options.overrides ?? [])],\n });\n\nexport default library();\n"],"mappings":";;;;;;AAcA,MAAa,iCAAiC;AAE9C,MAAa,wBAAwB;CAAC;CAAiB;CAAS;AAAW;AAE3E,MAAa,eAAe;CAC1B,cAAc;CACd,aAAa;CACb,iBAAiB;CACjB,oBAAoB;CACpB,yBAAyB;CACzB,yBAAyB;CACzB,gBAAgB;CAChB,qBAAqB;CACrB,WAAW,CAAC,SAAS,EAAE,kBAAkB,KAAK,CAAC;CAC/C,qCAAqC;CAErC,8BAA8B;CAC9B,gCAAgC;CAChC,kCAAkC,CAChC,SACA,EAAE,kBAAkB,EAAE,YAAY,MAAM,EAAE,CAC5C;CACA,0CAA0C,CAAC,SAAS,MAAM;CAC1D,gCAAgC;CAChC,2BAA2B;CAC3B,kCAAkC;CAClC,6CAA6C;CAC7C,uCAAuC,CACrC,SACA,EAAE,6BAA6B,wBAAwB,CACzD;CACA,4CAA4C;CAC5C,0CAA0C,CACxC,SACA,EAAE,oCAAoC,KAAK,CAC7C;CACA,yCAAyC,CACvC,SACA;EAAE,qBAAqB;EAAM,sBAAsB;CAAK,CAC1D;CACA,2CAA2C,CACzC,SACA;EAAE,sBAAsB;EAAM,8BAA8B;CAAK,CACnE;CACA,wCAAwC,CACtC,SACA,EAAE,kBAAkB;EAAE,QAAQ;EAAM,SAAS;CAAK,EAAE,CACtD;CACA,+BAA+B;CAC/B,2BAA2B,CAAC,SAAS,iCAAiC;CAEtE,gCAAgC;CAChC,6BAA6B;CAC7B,qBAAqB;CACrB,0BAA0B;CAC1B,yBAAyB;CACzB,uCAAuC;CACvC,0BAA0B;CAC1B,2BAA2B;CAC3B,6BAA6B;CAE7B,mBAAmB;CACnB,0CAA0C;CAE1C,yBAAyB;CACzB,gCAAgC;CAChC,gCAAgC;CAChC,qCAAqC;CACrC,qBAAqB;CAErB,aAAa;CACb,eAAe;CACf,sBAAsB;CACtB,kBAAkB;CAClB,wBAAwB;CACxB,wBAAwB;CACxB,wBAAwB;CACxB,qBAAqB;CACrB,uBAAuB;CACvB,2BAA2B;CAC3B,wBAAwB;CACxB,0BAA0B;CAC1B,gCAAgC;CAChC,YAAY;CACZ,cAAc;CACd,cAAc;CACd,gBAAgB;AAClB;AAEA,MAAa,mBAAmB,CAC9B;CACE,OAAO;EAAC;EAAoC;EAAe;CAAc;CACzE,OAAO;EACL,cAAc;EACd,iBAAiB;EACjB,yBAAyB;CAC3B;AACF,CACF;AAEA,MAAa,WAAW,UAA0B,CAAC,OAAA,GAAA,OAAA,cACpC;CACX,SAAS;EACP,cAAc;EACd,+BAA+B;EAC/B,WAAW;EACX,GAAG,QAAQ;CACb;CACA,WAAW,CAAC,gCAAgC,GAAI,QAAQ,aAAa,CAAC,CAAE;CACxE,gBAAgB,CACd,GAAG,uBACH,GAAI,QAAQ,kBAAkB,CAAC,CACjC;CACA,OAAO;EACL,GAAG;EACH,GAAG,QAAQ;CACb;CACA,WAAW,CAAC,GAAG,kBAAkB,GAAI,QAAQ,aAAa,CAAC,CAAE;AAC/D,CAAC;AAEH,IAAA,cAAe,QAAQ"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { OxlintConfig, OxlintOverride } from "oxlint";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
type Rules = NonNullable<OxlintConfig["rules"]>;
|
|
5
|
+
type JsPlugins = NonNullable<OxlintConfig["jsPlugins"]>;
|
|
6
|
+
type Options = NonNullable<OxlintConfig["options"]>;
|
|
7
|
+
type LibraryOptions = {
|
|
8
|
+
jsPlugins?: JsPlugins;
|
|
9
|
+
ignorePatterns?: string[];
|
|
10
|
+
options?: Options;
|
|
11
|
+
overrides?: OxlintOverride[];
|
|
12
|
+
rules?: Rules;
|
|
13
|
+
};
|
|
14
|
+
declare const stellaLowercasePluginSpecifier = "@stll/oxlint-config/plugin";
|
|
15
|
+
declare const libraryIgnorePatterns: string[];
|
|
16
|
+
declare const libraryRules: {
|
|
17
|
+
"no-console": "off";
|
|
18
|
+
"no-shadow": "error";
|
|
19
|
+
"require-await": "error";
|
|
20
|
+
"no-useless-catch": "error";
|
|
21
|
+
"no-non-null-assertion": "error";
|
|
22
|
+
"no-useless-assignment": "error";
|
|
23
|
+
"no-loop-func": "error";
|
|
24
|
+
"no-nested-ternary": "error";
|
|
25
|
+
"no-void": ["error", {
|
|
26
|
+
allowAsStatement: boolean;
|
|
27
|
+
}];
|
|
28
|
+
"stella-lowercase/stella-lowercase": "error";
|
|
29
|
+
"typescript/no-explicit-any": "error";
|
|
30
|
+
"typescript/no-dynamic-delete": "error";
|
|
31
|
+
"typescript/no-misused-promises": ["error", {
|
|
32
|
+
checksVoidReturn: {
|
|
33
|
+
attributes: boolean;
|
|
34
|
+
};
|
|
35
|
+
}];
|
|
36
|
+
"typescript/consistent-type-definitions": ["error", string];
|
|
37
|
+
"typescript/consistent-return": "error";
|
|
38
|
+
"typescript/dot-notation": "error";
|
|
39
|
+
"typescript/no-inferrable-types": "off";
|
|
40
|
+
"typescript/no-unnecessary-type-conversion": "error";
|
|
41
|
+
"typescript/no-unnecessary-condition": ["error", {
|
|
42
|
+
allowConstantLoopConditions: string;
|
|
43
|
+
}];
|
|
44
|
+
"typescript/no-unnecessary-type-arguments": "error";
|
|
45
|
+
"typescript/switch-exhaustiveness-check": ["error", {
|
|
46
|
+
considerDefaultExhaustiveForUnions: boolean;
|
|
47
|
+
}];
|
|
48
|
+
"typescript/strict-boolean-expressions": ["error", {
|
|
49
|
+
allowNullableString: boolean;
|
|
50
|
+
allowNullableBoolean: boolean;
|
|
51
|
+
}];
|
|
52
|
+
"typescript/no-confusing-void-expression": ["error", {
|
|
53
|
+
ignoreArrowShorthand: boolean;
|
|
54
|
+
ignoreVoidReturningFunctions: boolean;
|
|
55
|
+
}];
|
|
56
|
+
"typescript/prefer-nullish-coalescing": ["error", {
|
|
57
|
+
ignorePrimitives: {
|
|
58
|
+
string: boolean;
|
|
59
|
+
boolean: boolean;
|
|
60
|
+
};
|
|
61
|
+
}];
|
|
62
|
+
"typescript/only-throw-error": "error";
|
|
63
|
+
"typescript/return-await": ["error", string];
|
|
64
|
+
"unicorn/no-useless-undefined": "off";
|
|
65
|
+
"unicorn/prefer-array-find": "error";
|
|
66
|
+
"unicorn/prefer-at": "error";
|
|
67
|
+
"unicorn/prefer-set-has": "error";
|
|
68
|
+
"unicorn/filename-case": "off";
|
|
69
|
+
"unicorn/consistent-function-scoping": "off";
|
|
70
|
+
"unicorn/prefer-ternary": "off";
|
|
71
|
+
"unicorn/no-array-reduce": "error";
|
|
72
|
+
"unicorn/no-nested-ternary": "off";
|
|
73
|
+
"import/no-cycle": "error";
|
|
74
|
+
"import/consistent-type-specifier-style": "off";
|
|
75
|
+
"promise/always-return": "error";
|
|
76
|
+
"promise/no-return-in-finally": "error";
|
|
77
|
+
"promise/prefer-await-to-then": "off";
|
|
78
|
+
"promise/prefer-await-to-callbacks": "off";
|
|
79
|
+
"promise/avoid-new": "off";
|
|
80
|
+
"sort-keys": "off";
|
|
81
|
+
"no-plusplus": "off";
|
|
82
|
+
"no-inline-comments": "off";
|
|
83
|
+
"max-statements": "off";
|
|
84
|
+
"prefer-destructuring": "off";
|
|
85
|
+
"no-negated-condition": "off";
|
|
86
|
+
"no-use-before-define": "off";
|
|
87
|
+
"no-useless-return": "off";
|
|
88
|
+
"no-warning-comments": "off";
|
|
89
|
+
"no-unexpected-multiline": "off";
|
|
90
|
+
"max-classes-per-file": "off";
|
|
91
|
+
"class-methods-use-this": "off";
|
|
92
|
+
"no-unmodified-loop-condition": "off";
|
|
93
|
+
complexity: "off";
|
|
94
|
+
"func-style": "off";
|
|
95
|
+
"func-names": "off";
|
|
96
|
+
"default-case": "off";
|
|
97
|
+
};
|
|
98
|
+
declare const libraryOverrides: {
|
|
99
|
+
files: string[];
|
|
100
|
+
rules: {
|
|
101
|
+
"no-console": "off";
|
|
102
|
+
"require-await": "off";
|
|
103
|
+
"no-non-null-assertion": "off";
|
|
104
|
+
};
|
|
105
|
+
}[];
|
|
106
|
+
declare const library: (options?: LibraryOptions) => OxlintConfig;
|
|
107
|
+
declare const _default: OxlintConfig;
|
|
108
|
+
//#endregion
|
|
109
|
+
export { LibraryOptions, _default as default, library, libraryIgnorePatterns, libraryOverrides, libraryRules, stellaLowercasePluginSpecifier };
|
|
110
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { OxlintConfig, OxlintOverride } from "oxlint";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
type Rules = NonNullable<OxlintConfig["rules"]>;
|
|
5
|
+
type JsPlugins = NonNullable<OxlintConfig["jsPlugins"]>;
|
|
6
|
+
type Options = NonNullable<OxlintConfig["options"]>;
|
|
7
|
+
type LibraryOptions = {
|
|
8
|
+
jsPlugins?: JsPlugins;
|
|
9
|
+
ignorePatterns?: string[];
|
|
10
|
+
options?: Options;
|
|
11
|
+
overrides?: OxlintOverride[];
|
|
12
|
+
rules?: Rules;
|
|
13
|
+
};
|
|
14
|
+
declare const stellaLowercasePluginSpecifier = "@stll/oxlint-config/plugin";
|
|
15
|
+
declare const libraryIgnorePatterns: string[];
|
|
16
|
+
declare const libraryRules: {
|
|
17
|
+
"no-console": "off";
|
|
18
|
+
"no-shadow": "error";
|
|
19
|
+
"require-await": "error";
|
|
20
|
+
"no-useless-catch": "error";
|
|
21
|
+
"no-non-null-assertion": "error";
|
|
22
|
+
"no-useless-assignment": "error";
|
|
23
|
+
"no-loop-func": "error";
|
|
24
|
+
"no-nested-ternary": "error";
|
|
25
|
+
"no-void": ["error", {
|
|
26
|
+
allowAsStatement: boolean;
|
|
27
|
+
}];
|
|
28
|
+
"stella-lowercase/stella-lowercase": "error";
|
|
29
|
+
"typescript/no-explicit-any": "error";
|
|
30
|
+
"typescript/no-dynamic-delete": "error";
|
|
31
|
+
"typescript/no-misused-promises": ["error", {
|
|
32
|
+
checksVoidReturn: {
|
|
33
|
+
attributes: boolean;
|
|
34
|
+
};
|
|
35
|
+
}];
|
|
36
|
+
"typescript/consistent-type-definitions": ["error", string];
|
|
37
|
+
"typescript/consistent-return": "error";
|
|
38
|
+
"typescript/dot-notation": "error";
|
|
39
|
+
"typescript/no-inferrable-types": "off";
|
|
40
|
+
"typescript/no-unnecessary-type-conversion": "error";
|
|
41
|
+
"typescript/no-unnecessary-condition": ["error", {
|
|
42
|
+
allowConstantLoopConditions: string;
|
|
43
|
+
}];
|
|
44
|
+
"typescript/no-unnecessary-type-arguments": "error";
|
|
45
|
+
"typescript/switch-exhaustiveness-check": ["error", {
|
|
46
|
+
considerDefaultExhaustiveForUnions: boolean;
|
|
47
|
+
}];
|
|
48
|
+
"typescript/strict-boolean-expressions": ["error", {
|
|
49
|
+
allowNullableString: boolean;
|
|
50
|
+
allowNullableBoolean: boolean;
|
|
51
|
+
}];
|
|
52
|
+
"typescript/no-confusing-void-expression": ["error", {
|
|
53
|
+
ignoreArrowShorthand: boolean;
|
|
54
|
+
ignoreVoidReturningFunctions: boolean;
|
|
55
|
+
}];
|
|
56
|
+
"typescript/prefer-nullish-coalescing": ["error", {
|
|
57
|
+
ignorePrimitives: {
|
|
58
|
+
string: boolean;
|
|
59
|
+
boolean: boolean;
|
|
60
|
+
};
|
|
61
|
+
}];
|
|
62
|
+
"typescript/only-throw-error": "error";
|
|
63
|
+
"typescript/return-await": ["error", string];
|
|
64
|
+
"unicorn/no-useless-undefined": "off";
|
|
65
|
+
"unicorn/prefer-array-find": "error";
|
|
66
|
+
"unicorn/prefer-at": "error";
|
|
67
|
+
"unicorn/prefer-set-has": "error";
|
|
68
|
+
"unicorn/filename-case": "off";
|
|
69
|
+
"unicorn/consistent-function-scoping": "off";
|
|
70
|
+
"unicorn/prefer-ternary": "off";
|
|
71
|
+
"unicorn/no-array-reduce": "error";
|
|
72
|
+
"unicorn/no-nested-ternary": "off";
|
|
73
|
+
"import/no-cycle": "error";
|
|
74
|
+
"import/consistent-type-specifier-style": "off";
|
|
75
|
+
"promise/always-return": "error";
|
|
76
|
+
"promise/no-return-in-finally": "error";
|
|
77
|
+
"promise/prefer-await-to-then": "off";
|
|
78
|
+
"promise/prefer-await-to-callbacks": "off";
|
|
79
|
+
"promise/avoid-new": "off";
|
|
80
|
+
"sort-keys": "off";
|
|
81
|
+
"no-plusplus": "off";
|
|
82
|
+
"no-inline-comments": "off";
|
|
83
|
+
"max-statements": "off";
|
|
84
|
+
"prefer-destructuring": "off";
|
|
85
|
+
"no-negated-condition": "off";
|
|
86
|
+
"no-use-before-define": "off";
|
|
87
|
+
"no-useless-return": "off";
|
|
88
|
+
"no-warning-comments": "off";
|
|
89
|
+
"no-unexpected-multiline": "off";
|
|
90
|
+
"max-classes-per-file": "off";
|
|
91
|
+
"class-methods-use-this": "off";
|
|
92
|
+
"no-unmodified-loop-condition": "off";
|
|
93
|
+
complexity: "off";
|
|
94
|
+
"func-style": "off";
|
|
95
|
+
"func-names": "off";
|
|
96
|
+
"default-case": "off";
|
|
97
|
+
};
|
|
98
|
+
declare const libraryOverrides: {
|
|
99
|
+
files: string[];
|
|
100
|
+
rules: {
|
|
101
|
+
"no-console": "off";
|
|
102
|
+
"require-await": "off";
|
|
103
|
+
"no-non-null-assertion": "off";
|
|
104
|
+
};
|
|
105
|
+
}[];
|
|
106
|
+
declare const library: (options?: LibraryOptions) => OxlintConfig;
|
|
107
|
+
declare const _default: OxlintConfig;
|
|
108
|
+
//#endregion
|
|
109
|
+
export { LibraryOptions, _default as default, library, libraryIgnorePatterns, libraryOverrides, libraryRules, stellaLowercasePluginSpecifier };
|
|
110
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { defineConfig } from "oxlint";
|
|
2
|
+
//#region src/index.ts
|
|
3
|
+
const stellaLowercasePluginSpecifier = "@stll/oxlint-config/plugin";
|
|
4
|
+
const libraryIgnorePatterns = [
|
|
5
|
+
"node_modules/",
|
|
6
|
+
"dist/",
|
|
7
|
+
"coverage/"
|
|
8
|
+
];
|
|
9
|
+
const libraryRules = {
|
|
10
|
+
"no-console": "off",
|
|
11
|
+
"no-shadow": "error",
|
|
12
|
+
"require-await": "error",
|
|
13
|
+
"no-useless-catch": "error",
|
|
14
|
+
"no-non-null-assertion": "error",
|
|
15
|
+
"no-useless-assignment": "error",
|
|
16
|
+
"no-loop-func": "error",
|
|
17
|
+
"no-nested-ternary": "error",
|
|
18
|
+
"no-void": ["error", { allowAsStatement: true }],
|
|
19
|
+
"stella-lowercase/stella-lowercase": "error",
|
|
20
|
+
"typescript/no-explicit-any": "error",
|
|
21
|
+
"typescript/no-dynamic-delete": "error",
|
|
22
|
+
"typescript/no-misused-promises": ["error", { checksVoidReturn: { attributes: false } }],
|
|
23
|
+
"typescript/consistent-type-definitions": ["error", "type"],
|
|
24
|
+
"typescript/consistent-return": "error",
|
|
25
|
+
"typescript/dot-notation": "error",
|
|
26
|
+
"typescript/no-inferrable-types": "off",
|
|
27
|
+
"typescript/no-unnecessary-type-conversion": "error",
|
|
28
|
+
"typescript/no-unnecessary-condition": ["error", { allowConstantLoopConditions: "only-allowed-literals" }],
|
|
29
|
+
"typescript/no-unnecessary-type-arguments": "error",
|
|
30
|
+
"typescript/switch-exhaustiveness-check": ["error", { considerDefaultExhaustiveForUnions: true }],
|
|
31
|
+
"typescript/strict-boolean-expressions": ["error", {
|
|
32
|
+
allowNullableString: true,
|
|
33
|
+
allowNullableBoolean: true
|
|
34
|
+
}],
|
|
35
|
+
"typescript/no-confusing-void-expression": ["error", {
|
|
36
|
+
ignoreArrowShorthand: true,
|
|
37
|
+
ignoreVoidReturningFunctions: true
|
|
38
|
+
}],
|
|
39
|
+
"typescript/prefer-nullish-coalescing": ["error", { ignorePrimitives: {
|
|
40
|
+
string: true,
|
|
41
|
+
boolean: true
|
|
42
|
+
} }],
|
|
43
|
+
"typescript/only-throw-error": "error",
|
|
44
|
+
"typescript/return-await": ["error", "error-handling-correctness-only"],
|
|
45
|
+
"unicorn/no-useless-undefined": "off",
|
|
46
|
+
"unicorn/prefer-array-find": "error",
|
|
47
|
+
"unicorn/prefer-at": "error",
|
|
48
|
+
"unicorn/prefer-set-has": "error",
|
|
49
|
+
"unicorn/filename-case": "off",
|
|
50
|
+
"unicorn/consistent-function-scoping": "off",
|
|
51
|
+
"unicorn/prefer-ternary": "off",
|
|
52
|
+
"unicorn/no-array-reduce": "error",
|
|
53
|
+
"unicorn/no-nested-ternary": "off",
|
|
54
|
+
"import/no-cycle": "error",
|
|
55
|
+
"import/consistent-type-specifier-style": "off",
|
|
56
|
+
"promise/always-return": "error",
|
|
57
|
+
"promise/no-return-in-finally": "error",
|
|
58
|
+
"promise/prefer-await-to-then": "off",
|
|
59
|
+
"promise/prefer-await-to-callbacks": "off",
|
|
60
|
+
"promise/avoid-new": "off",
|
|
61
|
+
"sort-keys": "off",
|
|
62
|
+
"no-plusplus": "off",
|
|
63
|
+
"no-inline-comments": "off",
|
|
64
|
+
"max-statements": "off",
|
|
65
|
+
"prefer-destructuring": "off",
|
|
66
|
+
"no-negated-condition": "off",
|
|
67
|
+
"no-use-before-define": "off",
|
|
68
|
+
"no-useless-return": "off",
|
|
69
|
+
"no-warning-comments": "off",
|
|
70
|
+
"no-unexpected-multiline": "off",
|
|
71
|
+
"max-classes-per-file": "off",
|
|
72
|
+
"class-methods-use-this": "off",
|
|
73
|
+
"no-unmodified-loop-condition": "off",
|
|
74
|
+
complexity: "off",
|
|
75
|
+
"func-style": "off",
|
|
76
|
+
"func-names": "off",
|
|
77
|
+
"default-case": "off"
|
|
78
|
+
};
|
|
79
|
+
const libraryOverrides = [{
|
|
80
|
+
files: [
|
|
81
|
+
"**/*.{test,spec}.{ts,tsx,js,jsx}",
|
|
82
|
+
"__test__/**",
|
|
83
|
+
"__tests__/**"
|
|
84
|
+
],
|
|
85
|
+
rules: {
|
|
86
|
+
"no-console": "off",
|
|
87
|
+
"require-await": "off",
|
|
88
|
+
"no-non-null-assertion": "off"
|
|
89
|
+
}
|
|
90
|
+
}];
|
|
91
|
+
const library = (options = {}) => defineConfig({
|
|
92
|
+
options: {
|
|
93
|
+
denyWarnings: true,
|
|
94
|
+
reportUnusedDisableDirectives: "error",
|
|
95
|
+
typeAware: true,
|
|
96
|
+
...options.options
|
|
97
|
+
},
|
|
98
|
+
jsPlugins: [stellaLowercasePluginSpecifier, ...options.jsPlugins ?? []],
|
|
99
|
+
ignorePatterns: [...libraryIgnorePatterns, ...options.ignorePatterns ?? []],
|
|
100
|
+
rules: {
|
|
101
|
+
...libraryRules,
|
|
102
|
+
...options.rules
|
|
103
|
+
},
|
|
104
|
+
overrides: [...libraryOverrides, ...options.overrides ?? []]
|
|
105
|
+
});
|
|
106
|
+
var src_default = library();
|
|
107
|
+
//#endregion
|
|
108
|
+
export { src_default as default, library, libraryIgnorePatterns, libraryOverrides, libraryRules, stellaLowercasePluginSpecifier };
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { defineConfig, type OxlintConfig, type OxlintOverride } from \"oxlint\";\n\ntype Rules = NonNullable<OxlintConfig[\"rules\"]>;\ntype JsPlugins = NonNullable<OxlintConfig[\"jsPlugins\"]>;\ntype Options = NonNullable<OxlintConfig[\"options\"]>;\n\nexport type LibraryOptions = {\n jsPlugins?: JsPlugins;\n ignorePatterns?: string[];\n options?: Options;\n overrides?: OxlintOverride[];\n rules?: Rules;\n};\n\nexport const stellaLowercasePluginSpecifier = \"@stll/oxlint-config/plugin\";\n\nexport const libraryIgnorePatterns = [\"node_modules/\", \"dist/\", \"coverage/\"];\n\nexport const libraryRules = {\n \"no-console\": \"off\",\n \"no-shadow\": \"error\",\n \"require-await\": \"error\",\n \"no-useless-catch\": \"error\",\n \"no-non-null-assertion\": \"error\",\n \"no-useless-assignment\": \"error\",\n \"no-loop-func\": \"error\",\n \"no-nested-ternary\": \"error\",\n \"no-void\": [\"error\", { allowAsStatement: true }],\n \"stella-lowercase/stella-lowercase\": \"error\",\n\n \"typescript/no-explicit-any\": \"error\",\n \"typescript/no-dynamic-delete\": \"error\",\n \"typescript/no-misused-promises\": [\n \"error\",\n { checksVoidReturn: { attributes: false } },\n ],\n \"typescript/consistent-type-definitions\": [\"error\", \"type\"],\n \"typescript/consistent-return\": \"error\",\n \"typescript/dot-notation\": \"error\",\n \"typescript/no-inferrable-types\": \"off\",\n \"typescript/no-unnecessary-type-conversion\": \"error\",\n \"typescript/no-unnecessary-condition\": [\n \"error\",\n { allowConstantLoopConditions: \"only-allowed-literals\" },\n ],\n \"typescript/no-unnecessary-type-arguments\": \"error\",\n \"typescript/switch-exhaustiveness-check\": [\n \"error\",\n { considerDefaultExhaustiveForUnions: true },\n ],\n \"typescript/strict-boolean-expressions\": [\n \"error\",\n { allowNullableString: true, allowNullableBoolean: true },\n ],\n \"typescript/no-confusing-void-expression\": [\n \"error\",\n { ignoreArrowShorthand: true, ignoreVoidReturningFunctions: true },\n ],\n \"typescript/prefer-nullish-coalescing\": [\n \"error\",\n { ignorePrimitives: { string: true, boolean: true } },\n ],\n \"typescript/only-throw-error\": \"error\",\n \"typescript/return-await\": [\"error\", \"error-handling-correctness-only\"],\n\n \"unicorn/no-useless-undefined\": \"off\",\n \"unicorn/prefer-array-find\": \"error\",\n \"unicorn/prefer-at\": \"error\",\n \"unicorn/prefer-set-has\": \"error\",\n \"unicorn/filename-case\": \"off\",\n \"unicorn/consistent-function-scoping\": \"off\",\n \"unicorn/prefer-ternary\": \"off\",\n \"unicorn/no-array-reduce\": \"error\",\n \"unicorn/no-nested-ternary\": \"off\",\n\n \"import/no-cycle\": \"error\",\n \"import/consistent-type-specifier-style\": \"off\",\n\n \"promise/always-return\": \"error\",\n \"promise/no-return-in-finally\": \"error\",\n \"promise/prefer-await-to-then\": \"off\",\n \"promise/prefer-await-to-callbacks\": \"off\",\n \"promise/avoid-new\": \"off\",\n\n \"sort-keys\": \"off\",\n \"no-plusplus\": \"off\",\n \"no-inline-comments\": \"off\",\n \"max-statements\": \"off\",\n \"prefer-destructuring\": \"off\",\n \"no-negated-condition\": \"off\",\n \"no-use-before-define\": \"off\",\n \"no-useless-return\": \"off\",\n \"no-warning-comments\": \"off\",\n \"no-unexpected-multiline\": \"off\",\n \"max-classes-per-file\": \"off\",\n \"class-methods-use-this\": \"off\",\n \"no-unmodified-loop-condition\": \"off\",\n complexity: \"off\",\n \"func-style\": \"off\",\n \"func-names\": \"off\",\n \"default-case\": \"off\",\n} satisfies Rules;\n\nexport const libraryOverrides = [\n {\n files: [\"**/*.{test,spec}.{ts,tsx,js,jsx}\", \"__test__/**\", \"__tests__/**\"],\n rules: {\n \"no-console\": \"off\",\n \"require-await\": \"off\",\n \"no-non-null-assertion\": \"off\",\n },\n },\n] satisfies OxlintOverride[];\n\nexport const library = (options: LibraryOptions = {}): OxlintConfig =>\n defineConfig({\n options: {\n denyWarnings: true,\n reportUnusedDisableDirectives: \"error\",\n typeAware: true,\n ...options.options,\n },\n jsPlugins: [stellaLowercasePluginSpecifier, ...(options.jsPlugins ?? [])],\n ignorePatterns: [\n ...libraryIgnorePatterns,\n ...(options.ignorePatterns ?? []),\n ],\n rules: {\n ...libraryRules,\n ...options.rules,\n },\n overrides: [...libraryOverrides, ...(options.overrides ?? [])],\n });\n\nexport default library();\n"],"mappings":";;AAcA,MAAa,iCAAiC;AAE9C,MAAa,wBAAwB;CAAC;CAAiB;CAAS;AAAW;AAE3E,MAAa,eAAe;CAC1B,cAAc;CACd,aAAa;CACb,iBAAiB;CACjB,oBAAoB;CACpB,yBAAyB;CACzB,yBAAyB;CACzB,gBAAgB;CAChB,qBAAqB;CACrB,WAAW,CAAC,SAAS,EAAE,kBAAkB,KAAK,CAAC;CAC/C,qCAAqC;CAErC,8BAA8B;CAC9B,gCAAgC;CAChC,kCAAkC,CAChC,SACA,EAAE,kBAAkB,EAAE,YAAY,MAAM,EAAE,CAC5C;CACA,0CAA0C,CAAC,SAAS,MAAM;CAC1D,gCAAgC;CAChC,2BAA2B;CAC3B,kCAAkC;CAClC,6CAA6C;CAC7C,uCAAuC,CACrC,SACA,EAAE,6BAA6B,wBAAwB,CACzD;CACA,4CAA4C;CAC5C,0CAA0C,CACxC,SACA,EAAE,oCAAoC,KAAK,CAC7C;CACA,yCAAyC,CACvC,SACA;EAAE,qBAAqB;EAAM,sBAAsB;CAAK,CAC1D;CACA,2CAA2C,CACzC,SACA;EAAE,sBAAsB;EAAM,8BAA8B;CAAK,CACnE;CACA,wCAAwC,CACtC,SACA,EAAE,kBAAkB;EAAE,QAAQ;EAAM,SAAS;CAAK,EAAE,CACtD;CACA,+BAA+B;CAC/B,2BAA2B,CAAC,SAAS,iCAAiC;CAEtE,gCAAgC;CAChC,6BAA6B;CAC7B,qBAAqB;CACrB,0BAA0B;CAC1B,yBAAyB;CACzB,uCAAuC;CACvC,0BAA0B;CAC1B,2BAA2B;CAC3B,6BAA6B;CAE7B,mBAAmB;CACnB,0CAA0C;CAE1C,yBAAyB;CACzB,gCAAgC;CAChC,gCAAgC;CAChC,qCAAqC;CACrC,qBAAqB;CAErB,aAAa;CACb,eAAe;CACf,sBAAsB;CACtB,kBAAkB;CAClB,wBAAwB;CACxB,wBAAwB;CACxB,wBAAwB;CACxB,qBAAqB;CACrB,uBAAuB;CACvB,2BAA2B;CAC3B,wBAAwB;CACxB,0BAA0B;CAC1B,gCAAgC;CAChC,YAAY;CACZ,cAAc;CACd,cAAc;CACd,gBAAgB;AAClB;AAEA,MAAa,mBAAmB,CAC9B;CACE,OAAO;EAAC;EAAoC;EAAe;CAAc;CACzE,OAAO;EACL,cAAc;EACd,iBAAiB;EACjB,yBAAyB;CAC3B;AACF,CACF;AAEA,MAAa,WAAW,UAA0B,CAAC,MACjD,aAAa;CACX,SAAS;EACP,cAAc;EACd,+BAA+B;EAC/B,WAAW;EACX,GAAG,QAAQ;CACb;CACA,WAAW,CAAC,gCAAgC,GAAI,QAAQ,aAAa,CAAC,CAAE;CACxE,gBAAgB,CACd,GAAG,uBACH,GAAI,QAAQ,kBAAkB,CAAC,CACjC;CACA,OAAO;EACL,GAAG;EACH,GAAG,QAAQ;CACb;CACA,WAAW,CAAC,GAAG,kBAAkB,GAAI,QAAQ,aAAa,CAAC,CAAE;AAC/D,CAAC;AAEH,IAAA,cAAe,QAAQ"}
|
package/dist/plugin.cjs
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
//#region src/plugin.ts
|
|
6
|
+
const isAstNode = (node) => typeof node === "object" && node !== null && "type" in node && typeof node.type === "string";
|
|
7
|
+
const isStringLiteral = (node) => isAstNode(node) && node.type === "Literal" && typeof node["value"] === "string";
|
|
8
|
+
const CAPITALIZED_WORDMARK_PATTERN = /\bStella\b/gu;
|
|
9
|
+
const WHOLE_PATH = /^(?=.*[/\\.:~@])[\w./\\:~@-]+$/u;
|
|
10
|
+
const SKIP_WHITESPACE = new Set([
|
|
11
|
+
" ",
|
|
12
|
+
" ",
|
|
13
|
+
"\xA0"
|
|
14
|
+
]);
|
|
15
|
+
const SKIP_OPENERS = new Set([
|
|
16
|
+
"\"",
|
|
17
|
+
"'",
|
|
18
|
+
"`",
|
|
19
|
+
"(",
|
|
20
|
+
"[",
|
|
21
|
+
"{",
|
|
22
|
+
"“",
|
|
23
|
+
"”",
|
|
24
|
+
"‘",
|
|
25
|
+
"’",
|
|
26
|
+
"„",
|
|
27
|
+
"«",
|
|
28
|
+
"»",
|
|
29
|
+
"‹",
|
|
30
|
+
"›",
|
|
31
|
+
"¿",
|
|
32
|
+
"¡"
|
|
33
|
+
]);
|
|
34
|
+
const SENTENCE_TERMINATORS = new Set([
|
|
35
|
+
".",
|
|
36
|
+
"!",
|
|
37
|
+
"?",
|
|
38
|
+
"…",
|
|
39
|
+
"\n",
|
|
40
|
+
"\r"
|
|
41
|
+
]);
|
|
42
|
+
const isSentenceStart = (text, idx, isContinuation) => {
|
|
43
|
+
let i = idx - 1;
|
|
44
|
+
while (i >= 0) {
|
|
45
|
+
const ch = text[i];
|
|
46
|
+
if (ch === void 0) return !isContinuation;
|
|
47
|
+
if (SKIP_WHITESPACE.has(ch) || SKIP_OPENERS.has(ch)) {
|
|
48
|
+
i--;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (isContinuation && (ch === "\n" || ch === "\r")) {
|
|
52
|
+
i--;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
if (i < 0) return !isContinuation;
|
|
58
|
+
const previous = text[i];
|
|
59
|
+
return previous !== void 0 && SENTENCE_TERMINATORS.has(previous);
|
|
60
|
+
};
|
|
61
|
+
const isCodeLikeSuffix = (text, endIdx) => {
|
|
62
|
+
const next = text[endIdx];
|
|
63
|
+
if (next === "-" || next === "_") return true;
|
|
64
|
+
if (next === ".") return /[a-z]/u.test(text[endIdx + 1] ?? "");
|
|
65
|
+
return false;
|
|
66
|
+
};
|
|
67
|
+
const checkText = (context, node, value, isContinuation) => {
|
|
68
|
+
if (!value.includes("Stella")) return;
|
|
69
|
+
if (WHOLE_PATH.test(value)) return;
|
|
70
|
+
CAPITALIZED_WORDMARK_PATTERN.lastIndex = 0;
|
|
71
|
+
let match = CAPITALIZED_WORDMARK_PATTERN.exec(value);
|
|
72
|
+
while (match !== null) {
|
|
73
|
+
const start = match.index;
|
|
74
|
+
const end = start + match[0].length;
|
|
75
|
+
if (!isSentenceStart(value, start, isContinuation) && !isCodeLikeSuffix(value, end)) {
|
|
76
|
+
context.report({
|
|
77
|
+
node,
|
|
78
|
+
messageId: "lowercaseStella",
|
|
79
|
+
data: { match: match[0] }
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
match = CAPITALIZED_WORDMARK_PATTERN.exec(value);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const isImportOrExportSource = (literalNode) => {
|
|
87
|
+
const parent = literalNode.parent;
|
|
88
|
+
if (!isAstNode(parent)) return false;
|
|
89
|
+
return parent.type === "ImportDeclaration" || parent.type === "ExportNamedDeclaration" || parent.type === "ExportAllDeclaration";
|
|
90
|
+
};
|
|
91
|
+
const isJsxContinuation = (node) => {
|
|
92
|
+
const parent = node.parent;
|
|
93
|
+
if (!isAstNode(parent)) return false;
|
|
94
|
+
if (parent.type !== "JSXElement" && parent.type !== "JSXFragment") return false;
|
|
95
|
+
const children = parent["children"];
|
|
96
|
+
if (!Array.isArray(children)) return false;
|
|
97
|
+
return children.indexOf(node) > 0;
|
|
98
|
+
};
|
|
99
|
+
const isJsxExpressionContinuation = (node) => {
|
|
100
|
+
const parent = node.parent;
|
|
101
|
+
if (!isAstNode(parent) || parent.type !== "JSXExpressionContainer") return false;
|
|
102
|
+
const grandparent = parent.parent;
|
|
103
|
+
if (!isAstNode(grandparent)) return false;
|
|
104
|
+
if (grandparent.type !== "JSXElement" && grandparent.type !== "JSXFragment") return false;
|
|
105
|
+
const children = grandparent["children"];
|
|
106
|
+
if (!Array.isArray(children)) return false;
|
|
107
|
+
return children.indexOf(parent) > 0;
|
|
108
|
+
};
|
|
109
|
+
const quasiText = (quasi) => {
|
|
110
|
+
if (!isAstNode(quasi)) return null;
|
|
111
|
+
const raw = quasi["value"];
|
|
112
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
113
|
+
const cooked = raw.cooked;
|
|
114
|
+
if (typeof cooked === "string") return cooked;
|
|
115
|
+
const rawValue = raw.raw;
|
|
116
|
+
return typeof rawValue === "string" ? rawValue : null;
|
|
117
|
+
};
|
|
118
|
+
var plugin_default = {
|
|
119
|
+
meta: { name: "stella-lowercase" },
|
|
120
|
+
rules: { "stella-lowercase": {
|
|
121
|
+
meta: {
|
|
122
|
+
type: "problem",
|
|
123
|
+
messages: { lowercaseStella: "Use lowercase `stella` for the product wordmark. The capitalized form is only valid at a sentence start." }
|
|
124
|
+
},
|
|
125
|
+
create(context) {
|
|
126
|
+
return {
|
|
127
|
+
Literal(node) {
|
|
128
|
+
if (!isStringLiteral(node)) return;
|
|
129
|
+
if (isImportOrExportSource(node)) return;
|
|
130
|
+
checkText(context, node, node.value, isJsxExpressionContinuation(node));
|
|
131
|
+
},
|
|
132
|
+
TemplateLiteral(node) {
|
|
133
|
+
const quasis = node["quasis"];
|
|
134
|
+
if (!Array.isArray(quasis)) return;
|
|
135
|
+
const headIsContinuation = isJsxExpressionContinuation(node);
|
|
136
|
+
for (let i = 0; i < quasis.length; i++) {
|
|
137
|
+
const quasi = quasis[i];
|
|
138
|
+
const value = quasiText(quasi);
|
|
139
|
+
if (value === null) continue;
|
|
140
|
+
checkText(context, quasi, value, headIsContinuation || i > 0);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
JSXText(node) {
|
|
144
|
+
const value = node["value"];
|
|
145
|
+
if (typeof value !== "string") return;
|
|
146
|
+
checkText(context, node, value, isJsxContinuation(node));
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
} }
|
|
151
|
+
};
|
|
152
|
+
//#endregion
|
|
153
|
+
exports.default = plugin_default;
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=plugin.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["// Enforce the lowercase \"stella\" wordmark in source text.\n//\n// The stella brand identity is a lowercase wordmark. Generated copy and\n// hand-written prose can introduce a capitalized form mid-sentence, which\n// contradicts the wordmark. This rule scans string literals, template\n// literals, and JSX text for capitalized wordmark tokens that are not at a\n// sentence boundary and do not look like code identifiers or asset filenames.\n\ntype AstNode = { type: string; parent?: unknown } & Record<string, unknown>;\n\ntype RuleContext = {\n report: (diagnostic: {\n node: unknown;\n messageId: \"lowercaseStella\";\n data?: { match: string };\n }) => void;\n};\n\nconst isAstNode = (node: unknown): node is AstNode =>\n typeof node === \"object\" &&\n node !== null &&\n \"type\" in node &&\n typeof (node as { type: unknown }).type === \"string\";\n\nconst isStringLiteral = (node: unknown): node is AstNode & { value: string } =>\n isAstNode(node) &&\n node.type === \"Literal\" &&\n typeof node[\"value\"] === \"string\";\n\nconst CAPITALIZED_WORDMARK_PATTERN = /\\bStella\\b/gu;\nconst WHOLE_PATH = /^(?=.*[/\\\\.:~@])[\\w./\\\\:~@-]+$/u;\nconst SKIP_WHITESPACE = new Set([\" \", \"\\t\", \" \"]);\nconst SKIP_OPENERS = new Set([\n '\"',\n \"'\",\n \"`\",\n \"(\",\n \"[\",\n \"{\",\n \"“\",\n \"”\",\n \"‘\",\n \"’\",\n \"„\",\n \"«\",\n \"»\",\n \"‹\",\n \"›\",\n \"¿\",\n \"¡\",\n]);\nconst SENTENCE_TERMINATORS = new Set([\".\", \"!\", \"?\", \"…\", \"\\n\", \"\\r\"]);\n\nconst isSentenceStart = (\n text: string,\n idx: number,\n isContinuation: boolean,\n): boolean => {\n let i = idx - 1;\n while (i >= 0) {\n const ch = text[i];\n if (ch === undefined) {\n return !isContinuation;\n }\n if (SKIP_WHITESPACE.has(ch) || SKIP_OPENERS.has(ch)) {\n i--;\n continue;\n }\n if (isContinuation && (ch === \"\\n\" || ch === \"\\r\")) {\n i--;\n continue;\n }\n break;\n }\n if (i < 0) {\n return !isContinuation;\n }\n const previous = text[i];\n return previous !== undefined && SENTENCE_TERMINATORS.has(previous);\n};\n\nconst isCodeLikeSuffix = (text: string, endIdx: number): boolean => {\n const next = text[endIdx];\n if (next === \"-\" || next === \"_\") {\n return true;\n }\n if (next === \".\") {\n return /[a-z]/u.test(text[endIdx + 1] ?? \"\");\n }\n return false;\n};\n\nconst checkText = (\n context: RuleContext,\n node: unknown,\n value: string,\n isContinuation: boolean,\n): void => {\n if (!value.includes(\"Stella\")) {\n return;\n }\n if (WHOLE_PATH.test(value)) {\n return;\n }\n CAPITALIZED_WORDMARK_PATTERN.lastIndex = 0;\n let match = CAPITALIZED_WORDMARK_PATTERN.exec(value);\n while (match !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (\n !isSentenceStart(value, start, isContinuation) &&\n !isCodeLikeSuffix(value, end)\n ) {\n context.report({\n node,\n messageId: \"lowercaseStella\",\n data: { match: match[0] },\n });\n return;\n }\n match = CAPITALIZED_WORDMARK_PATTERN.exec(value);\n }\n};\n\nconst isImportOrExportSource = (literalNode: AstNode): boolean => {\n const parent = literalNode.parent;\n if (!isAstNode(parent)) {\n return false;\n }\n return (\n parent.type === \"ImportDeclaration\" ||\n parent.type === \"ExportNamedDeclaration\" ||\n parent.type === \"ExportAllDeclaration\"\n );\n};\n\nconst isJsxContinuation = (node: AstNode): boolean => {\n const parent = node.parent;\n if (!isAstNode(parent)) {\n return false;\n }\n if (parent.type !== \"JSXElement\" && parent.type !== \"JSXFragment\") {\n return false;\n }\n const children = parent[\"children\"];\n if (!Array.isArray(children)) {\n return false;\n }\n return children.indexOf(node) > 0;\n};\n\nconst isJsxExpressionContinuation = (node: AstNode): boolean => {\n const parent = node.parent;\n if (!isAstNode(parent) || parent.type !== \"JSXExpressionContainer\") {\n return false;\n }\n const grandparent = parent.parent;\n if (!isAstNode(grandparent)) {\n return false;\n }\n if (grandparent.type !== \"JSXElement\" && grandparent.type !== \"JSXFragment\") {\n return false;\n }\n const children = grandparent[\"children\"];\n if (!Array.isArray(children)) {\n return false;\n }\n return children.indexOf(parent) > 0;\n};\n\nconst quasiText = (quasi: unknown): string | null => {\n if (!isAstNode(quasi)) {\n return null;\n }\n const raw = quasi[\"value\"];\n if (typeof raw !== \"object\" || raw === null) {\n return null;\n }\n const cooked = (raw as { cooked?: unknown }).cooked;\n if (typeof cooked === \"string\") {\n return cooked;\n }\n const rawValue = (raw as { raw?: unknown }).raw;\n return typeof rawValue === \"string\" ? rawValue : null;\n};\n\nexport default {\n meta: { name: \"stella-lowercase\" },\n rules: {\n \"stella-lowercase\": {\n meta: {\n type: \"problem\",\n messages: {\n lowercaseStella:\n \"Use lowercase `stella` for the product wordmark. The capitalized form is only valid at a sentence start.\",\n },\n },\n create(context: RuleContext) {\n return {\n Literal(node: AstNode) {\n if (!isStringLiteral(node)) {\n return;\n }\n if (isImportOrExportSource(node)) {\n return;\n }\n checkText(\n context,\n node,\n node.value,\n isJsxExpressionContinuation(node),\n );\n },\n TemplateLiteral(node: AstNode) {\n const quasis = node[\"quasis\"];\n if (!Array.isArray(quasis)) {\n return;\n }\n const headIsContinuation = isJsxExpressionContinuation(node);\n for (let i = 0; i < quasis.length; i++) {\n const quasi = quasis[i];\n const value = quasiText(quasi);\n if (value === null) {\n continue;\n }\n checkText(context, quasi, value, headIsContinuation || i > 0);\n }\n },\n JSXText(node: AstNode) {\n const value = node[\"value\"];\n if (typeof value !== \"string\") {\n return;\n }\n checkText(context, node, value, isJsxContinuation(node));\n },\n };\n },\n },\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/plugin.d.ts
|
|
2
|
+
type AstNode = {
|
|
3
|
+
type: string;
|
|
4
|
+
parent?: unknown;
|
|
5
|
+
} & Record<string, unknown>;
|
|
6
|
+
type RuleContext = {
|
|
7
|
+
report: (diagnostic: {
|
|
8
|
+
node: unknown;
|
|
9
|
+
messageId: "lowercaseStella";
|
|
10
|
+
data?: {
|
|
11
|
+
match: string;
|
|
12
|
+
};
|
|
13
|
+
}) => void;
|
|
14
|
+
};
|
|
15
|
+
declare const _default: {
|
|
16
|
+
meta: {
|
|
17
|
+
name: string;
|
|
18
|
+
};
|
|
19
|
+
rules: {
|
|
20
|
+
"stella-lowercase": {
|
|
21
|
+
meta: {
|
|
22
|
+
type: string;
|
|
23
|
+
messages: {
|
|
24
|
+
lowercaseStella: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
create(context: RuleContext): {
|
|
28
|
+
Literal(node: AstNode): void;
|
|
29
|
+
TemplateLiteral(node: AstNode): void;
|
|
30
|
+
JSXText(node: AstNode): void;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export = _default;
|
|
36
|
+
//# sourceMappingURL=plugin.d.cts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/plugin.d.ts
|
|
2
|
+
type AstNode = {
|
|
3
|
+
type: string;
|
|
4
|
+
parent?: unknown;
|
|
5
|
+
} & Record<string, unknown>;
|
|
6
|
+
type RuleContext = {
|
|
7
|
+
report: (diagnostic: {
|
|
8
|
+
node: unknown;
|
|
9
|
+
messageId: "lowercaseStella";
|
|
10
|
+
data?: {
|
|
11
|
+
match: string;
|
|
12
|
+
};
|
|
13
|
+
}) => void;
|
|
14
|
+
};
|
|
15
|
+
declare const _default: {
|
|
16
|
+
meta: {
|
|
17
|
+
name: string;
|
|
18
|
+
};
|
|
19
|
+
rules: {
|
|
20
|
+
"stella-lowercase": {
|
|
21
|
+
meta: {
|
|
22
|
+
type: string;
|
|
23
|
+
messages: {
|
|
24
|
+
lowercaseStella: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
create(context: RuleContext): {
|
|
28
|
+
Literal(node: AstNode): void;
|
|
29
|
+
TemplateLiteral(node: AstNode): void;
|
|
30
|
+
JSXText(node: AstNode): void;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
export { _default as default };
|
|
37
|
+
//# sourceMappingURL=plugin.d.mts.map
|
package/dist/plugin.mjs
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
//#region src/plugin.ts
|
|
2
|
+
const isAstNode = (node) => typeof node === "object" && node !== null && "type" in node && typeof node.type === "string";
|
|
3
|
+
const isStringLiteral = (node) => isAstNode(node) && node.type === "Literal" && typeof node["value"] === "string";
|
|
4
|
+
const CAPITALIZED_WORDMARK_PATTERN = /\bStella\b/gu;
|
|
5
|
+
const WHOLE_PATH = /^(?=.*[/\\.:~@])[\w./\\:~@-]+$/u;
|
|
6
|
+
const SKIP_WHITESPACE = new Set([
|
|
7
|
+
" ",
|
|
8
|
+
" ",
|
|
9
|
+
"\xA0"
|
|
10
|
+
]);
|
|
11
|
+
const SKIP_OPENERS = new Set([
|
|
12
|
+
"\"",
|
|
13
|
+
"'",
|
|
14
|
+
"`",
|
|
15
|
+
"(",
|
|
16
|
+
"[",
|
|
17
|
+
"{",
|
|
18
|
+
"“",
|
|
19
|
+
"”",
|
|
20
|
+
"‘",
|
|
21
|
+
"’",
|
|
22
|
+
"„",
|
|
23
|
+
"«",
|
|
24
|
+
"»",
|
|
25
|
+
"‹",
|
|
26
|
+
"›",
|
|
27
|
+
"¿",
|
|
28
|
+
"¡"
|
|
29
|
+
]);
|
|
30
|
+
const SENTENCE_TERMINATORS = new Set([
|
|
31
|
+
".",
|
|
32
|
+
"!",
|
|
33
|
+
"?",
|
|
34
|
+
"…",
|
|
35
|
+
"\n",
|
|
36
|
+
"\r"
|
|
37
|
+
]);
|
|
38
|
+
const isSentenceStart = (text, idx, isContinuation) => {
|
|
39
|
+
let i = idx - 1;
|
|
40
|
+
while (i >= 0) {
|
|
41
|
+
const ch = text[i];
|
|
42
|
+
if (ch === void 0) return !isContinuation;
|
|
43
|
+
if (SKIP_WHITESPACE.has(ch) || SKIP_OPENERS.has(ch)) {
|
|
44
|
+
i--;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (isContinuation && (ch === "\n" || ch === "\r")) {
|
|
48
|
+
i--;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
if (i < 0) return !isContinuation;
|
|
54
|
+
const previous = text[i];
|
|
55
|
+
return previous !== void 0 && SENTENCE_TERMINATORS.has(previous);
|
|
56
|
+
};
|
|
57
|
+
const isCodeLikeSuffix = (text, endIdx) => {
|
|
58
|
+
const next = text[endIdx];
|
|
59
|
+
if (next === "-" || next === "_") return true;
|
|
60
|
+
if (next === ".") return /[a-z]/u.test(text[endIdx + 1] ?? "");
|
|
61
|
+
return false;
|
|
62
|
+
};
|
|
63
|
+
const checkText = (context, node, value, isContinuation) => {
|
|
64
|
+
if (!value.includes("Stella")) return;
|
|
65
|
+
if (WHOLE_PATH.test(value)) return;
|
|
66
|
+
CAPITALIZED_WORDMARK_PATTERN.lastIndex = 0;
|
|
67
|
+
let match = CAPITALIZED_WORDMARK_PATTERN.exec(value);
|
|
68
|
+
while (match !== null) {
|
|
69
|
+
const start = match.index;
|
|
70
|
+
const end = start + match[0].length;
|
|
71
|
+
if (!isSentenceStart(value, start, isContinuation) && !isCodeLikeSuffix(value, end)) {
|
|
72
|
+
context.report({
|
|
73
|
+
node,
|
|
74
|
+
messageId: "lowercaseStella",
|
|
75
|
+
data: { match: match[0] }
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
match = CAPITALIZED_WORDMARK_PATTERN.exec(value);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const isImportOrExportSource = (literalNode) => {
|
|
83
|
+
const parent = literalNode.parent;
|
|
84
|
+
if (!isAstNode(parent)) return false;
|
|
85
|
+
return parent.type === "ImportDeclaration" || parent.type === "ExportNamedDeclaration" || parent.type === "ExportAllDeclaration";
|
|
86
|
+
};
|
|
87
|
+
const isJsxContinuation = (node) => {
|
|
88
|
+
const parent = node.parent;
|
|
89
|
+
if (!isAstNode(parent)) return false;
|
|
90
|
+
if (parent.type !== "JSXElement" && parent.type !== "JSXFragment") return false;
|
|
91
|
+
const children = parent["children"];
|
|
92
|
+
if (!Array.isArray(children)) return false;
|
|
93
|
+
return children.indexOf(node) > 0;
|
|
94
|
+
};
|
|
95
|
+
const isJsxExpressionContinuation = (node) => {
|
|
96
|
+
const parent = node.parent;
|
|
97
|
+
if (!isAstNode(parent) || parent.type !== "JSXExpressionContainer") return false;
|
|
98
|
+
const grandparent = parent.parent;
|
|
99
|
+
if (!isAstNode(grandparent)) return false;
|
|
100
|
+
if (grandparent.type !== "JSXElement" && grandparent.type !== "JSXFragment") return false;
|
|
101
|
+
const children = grandparent["children"];
|
|
102
|
+
if (!Array.isArray(children)) return false;
|
|
103
|
+
return children.indexOf(parent) > 0;
|
|
104
|
+
};
|
|
105
|
+
const quasiText = (quasi) => {
|
|
106
|
+
if (!isAstNode(quasi)) return null;
|
|
107
|
+
const raw = quasi["value"];
|
|
108
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
109
|
+
const cooked = raw.cooked;
|
|
110
|
+
if (typeof cooked === "string") return cooked;
|
|
111
|
+
const rawValue = raw.raw;
|
|
112
|
+
return typeof rawValue === "string" ? rawValue : null;
|
|
113
|
+
};
|
|
114
|
+
var plugin_default = {
|
|
115
|
+
meta: { name: "stella-lowercase" },
|
|
116
|
+
rules: { "stella-lowercase": {
|
|
117
|
+
meta: {
|
|
118
|
+
type: "problem",
|
|
119
|
+
messages: { lowercaseStella: "Use lowercase `stella` for the product wordmark. The capitalized form is only valid at a sentence start." }
|
|
120
|
+
},
|
|
121
|
+
create(context) {
|
|
122
|
+
return {
|
|
123
|
+
Literal(node) {
|
|
124
|
+
if (!isStringLiteral(node)) return;
|
|
125
|
+
if (isImportOrExportSource(node)) return;
|
|
126
|
+
checkText(context, node, node.value, isJsxExpressionContinuation(node));
|
|
127
|
+
},
|
|
128
|
+
TemplateLiteral(node) {
|
|
129
|
+
const quasis = node["quasis"];
|
|
130
|
+
if (!Array.isArray(quasis)) return;
|
|
131
|
+
const headIsContinuation = isJsxExpressionContinuation(node);
|
|
132
|
+
for (let i = 0; i < quasis.length; i++) {
|
|
133
|
+
const quasi = quasis[i];
|
|
134
|
+
const value = quasiText(quasi);
|
|
135
|
+
if (value === null) continue;
|
|
136
|
+
checkText(context, quasi, value, headIsContinuation || i > 0);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
JSXText(node) {
|
|
140
|
+
const value = node["value"];
|
|
141
|
+
if (typeof value !== "string") return;
|
|
142
|
+
checkText(context, node, value, isJsxContinuation(node));
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
} }
|
|
147
|
+
};
|
|
148
|
+
//#endregion
|
|
149
|
+
export { plugin_default as default };
|
|
150
|
+
|
|
151
|
+
//# sourceMappingURL=plugin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["// Enforce the lowercase \"stella\" wordmark in source text.\n//\n// The stella brand identity is a lowercase wordmark. Generated copy and\n// hand-written prose can introduce a capitalized form mid-sentence, which\n// contradicts the wordmark. This rule scans string literals, template\n// literals, and JSX text for capitalized wordmark tokens that are not at a\n// sentence boundary and do not look like code identifiers or asset filenames.\n\ntype AstNode = { type: string; parent?: unknown } & Record<string, unknown>;\n\ntype RuleContext = {\n report: (diagnostic: {\n node: unknown;\n messageId: \"lowercaseStella\";\n data?: { match: string };\n }) => void;\n};\n\nconst isAstNode = (node: unknown): node is AstNode =>\n typeof node === \"object\" &&\n node !== null &&\n \"type\" in node &&\n typeof (node as { type: unknown }).type === \"string\";\n\nconst isStringLiteral = (node: unknown): node is AstNode & { value: string } =>\n isAstNode(node) &&\n node.type === \"Literal\" &&\n typeof node[\"value\"] === \"string\";\n\nconst CAPITALIZED_WORDMARK_PATTERN = /\\bStella\\b/gu;\nconst WHOLE_PATH = /^(?=.*[/\\\\.:~@])[\\w./\\\\:~@-]+$/u;\nconst SKIP_WHITESPACE = new Set([\" \", \"\\t\", \" \"]);\nconst SKIP_OPENERS = new Set([\n '\"',\n \"'\",\n \"`\",\n \"(\",\n \"[\",\n \"{\",\n \"“\",\n \"”\",\n \"‘\",\n \"’\",\n \"„\",\n \"«\",\n \"»\",\n \"‹\",\n \"›\",\n \"¿\",\n \"¡\",\n]);\nconst SENTENCE_TERMINATORS = new Set([\".\", \"!\", \"?\", \"…\", \"\\n\", \"\\r\"]);\n\nconst isSentenceStart = (\n text: string,\n idx: number,\n isContinuation: boolean,\n): boolean => {\n let i = idx - 1;\n while (i >= 0) {\n const ch = text[i];\n if (ch === undefined) {\n return !isContinuation;\n }\n if (SKIP_WHITESPACE.has(ch) || SKIP_OPENERS.has(ch)) {\n i--;\n continue;\n }\n if (isContinuation && (ch === \"\\n\" || ch === \"\\r\")) {\n i--;\n continue;\n }\n break;\n }\n if (i < 0) {\n return !isContinuation;\n }\n const previous = text[i];\n return previous !== undefined && SENTENCE_TERMINATORS.has(previous);\n};\n\nconst isCodeLikeSuffix = (text: string, endIdx: number): boolean => {\n const next = text[endIdx];\n if (next === \"-\" || next === \"_\") {\n return true;\n }\n if (next === \".\") {\n return /[a-z]/u.test(text[endIdx + 1] ?? \"\");\n }\n return false;\n};\n\nconst checkText = (\n context: RuleContext,\n node: unknown,\n value: string,\n isContinuation: boolean,\n): void => {\n if (!value.includes(\"Stella\")) {\n return;\n }\n if (WHOLE_PATH.test(value)) {\n return;\n }\n CAPITALIZED_WORDMARK_PATTERN.lastIndex = 0;\n let match = CAPITALIZED_WORDMARK_PATTERN.exec(value);\n while (match !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (\n !isSentenceStart(value, start, isContinuation) &&\n !isCodeLikeSuffix(value, end)\n ) {\n context.report({\n node,\n messageId: \"lowercaseStella\",\n data: { match: match[0] },\n });\n return;\n }\n match = CAPITALIZED_WORDMARK_PATTERN.exec(value);\n }\n};\n\nconst isImportOrExportSource = (literalNode: AstNode): boolean => {\n const parent = literalNode.parent;\n if (!isAstNode(parent)) {\n return false;\n }\n return (\n parent.type === \"ImportDeclaration\" ||\n parent.type === \"ExportNamedDeclaration\" ||\n parent.type === \"ExportAllDeclaration\"\n );\n};\n\nconst isJsxContinuation = (node: AstNode): boolean => {\n const parent = node.parent;\n if (!isAstNode(parent)) {\n return false;\n }\n if (parent.type !== \"JSXElement\" && parent.type !== \"JSXFragment\") {\n return false;\n }\n const children = parent[\"children\"];\n if (!Array.isArray(children)) {\n return false;\n }\n return children.indexOf(node) > 0;\n};\n\nconst isJsxExpressionContinuation = (node: AstNode): boolean => {\n const parent = node.parent;\n if (!isAstNode(parent) || parent.type !== \"JSXExpressionContainer\") {\n return false;\n }\n const grandparent = parent.parent;\n if (!isAstNode(grandparent)) {\n return false;\n }\n if (grandparent.type !== \"JSXElement\" && grandparent.type !== \"JSXFragment\") {\n return false;\n }\n const children = grandparent[\"children\"];\n if (!Array.isArray(children)) {\n return false;\n }\n return children.indexOf(parent) > 0;\n};\n\nconst quasiText = (quasi: unknown): string | null => {\n if (!isAstNode(quasi)) {\n return null;\n }\n const raw = quasi[\"value\"];\n if (typeof raw !== \"object\" || raw === null) {\n return null;\n }\n const cooked = (raw as { cooked?: unknown }).cooked;\n if (typeof cooked === \"string\") {\n return cooked;\n }\n const rawValue = (raw as { raw?: unknown }).raw;\n return typeof rawValue === \"string\" ? rawValue : null;\n};\n\nexport default {\n meta: { name: \"stella-lowercase\" },\n rules: {\n \"stella-lowercase\": {\n meta: {\n type: \"problem\",\n messages: {\n lowercaseStella:\n \"Use lowercase `stella` for the product wordmark. The capitalized form is only valid at a sentence start.\",\n },\n },\n create(context: RuleContext) {\n return {\n Literal(node: AstNode) {\n if (!isStringLiteral(node)) {\n return;\n }\n if (isImportOrExportSource(node)) {\n return;\n }\n checkText(\n context,\n node,\n node.value,\n isJsxExpressionContinuation(node),\n );\n },\n TemplateLiteral(node: AstNode) {\n const quasis = node[\"quasis\"];\n if (!Array.isArray(quasis)) {\n return;\n }\n const headIsContinuation = isJsxExpressionContinuation(node);\n for (let i = 0; i < quasis.length; i++) {\n const quasi = quasis[i];\n const value = quasiText(quasi);\n if (value === null) {\n continue;\n }\n checkText(context, quasi, value, headIsContinuation || i > 0);\n }\n },\n JSXText(node: AstNode) {\n const value = node[\"value\"];\n if (typeof value !== \"string\") {\n return;\n }\n checkText(context, node, value, isJsxContinuation(node));\n },\n };\n },\n },\n },\n};\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stll/oxlint-config",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared general oxlint configuration for stella packages.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/stella/tooling.git",
|
|
9
|
+
"directory": "packages/oxlint-config"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "dist/index.mjs",
|
|
16
|
+
"types": "dist/index.d.mts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": {
|
|
20
|
+
"types": "./dist/index.d.mts",
|
|
21
|
+
"default": "./dist/index.mjs"
|
|
22
|
+
},
|
|
23
|
+
"require": {
|
|
24
|
+
"types": "./dist/index.d.cts",
|
|
25
|
+
"default": "./dist/index.cjs"
|
|
26
|
+
},
|
|
27
|
+
"default": "./dist/index.mjs"
|
|
28
|
+
},
|
|
29
|
+
"./plugin": {
|
|
30
|
+
"import": {
|
|
31
|
+
"types": "./dist/plugin.d.mts",
|
|
32
|
+
"default": "./dist/plugin.mjs"
|
|
33
|
+
},
|
|
34
|
+
"require": {
|
|
35
|
+
"types": "./dist/plugin.d.cts",
|
|
36
|
+
"default": "./dist/plugin.cjs"
|
|
37
|
+
},
|
|
38
|
+
"default": "./dist/plugin.mjs"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsdown",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"format": "oxfmt ."
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@stll/typescript-config": "workspace:*",
|
|
51
|
+
"oxfmt": "0.48.0",
|
|
52
|
+
"oxlint": "1.67.0",
|
|
53
|
+
"typescript": "6.0.3"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"oxlint": ">=1.66.0",
|
|
57
|
+
"oxlint-tsgolint": ">=0.23.0"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
61
|
+
}
|
|
62
|
+
}
|