eslint-plugin-lingui-typescript 1.0.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/README.md +111 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/rules/consistent-plural-format.d.ts +5 -0
- package/dist/rules/consistent-plural-format.d.ts.map +1 -0
- package/dist/rules/consistent-plural-format.js +67 -0
- package/dist/rules/consistent-plural-format.js.map +1 -0
- package/dist/rules/consistent-plural-format.test.d.ts +2 -0
- package/dist/rules/consistent-plural-format.test.d.ts.map +1 -0
- package/dist/rules/consistent-plural-format.test.js +74 -0
- package/dist/rules/consistent-plural-format.test.js.map +1 -0
- package/dist/rules/no-complex-expressions-in-message.d.ts +7 -0
- package/dist/rules/no-complex-expressions-in-message.d.ts.map +1 -0
- package/dist/rules/no-complex-expressions-in-message.js +184 -0
- package/dist/rules/no-complex-expressions-in-message.js.map +1 -0
- package/dist/rules/no-complex-expressions-in-message.test.d.ts +2 -0
- package/dist/rules/no-complex-expressions-in-message.test.d.ts.map +1 -0
- package/dist/rules/no-complex-expressions-in-message.test.js +122 -0
- package/dist/rules/no-complex-expressions-in-message.test.js.map +1 -0
- package/dist/rules/no-nested-macros.d.ts +6 -0
- package/dist/rules/no-nested-macros.d.ts.map +1 -0
- package/dist/rules/no-nested-macros.js +109 -0
- package/dist/rules/no-nested-macros.js.map +1 -0
- package/dist/rules/no-nested-macros.test.d.ts +2 -0
- package/dist/rules/no-nested-macros.test.d.ts.map +1 -0
- package/dist/rules/no-nested-macros.test.js +93 -0
- package/dist/rules/no-nested-macros.test.js.map +1 -0
- package/dist/rules/no-single-tag-message.d.ts +2 -0
- package/dist/rules/no-single-tag-message.d.ts.map +1 -0
- package/dist/rules/no-single-tag-message.js +49 -0
- package/dist/rules/no-single-tag-message.js.map +1 -0
- package/dist/rules/no-single-tag-message.test.d.ts +2 -0
- package/dist/rules/no-single-tag-message.test.d.ts.map +1 -0
- package/dist/rules/no-single-tag-message.test.js +72 -0
- package/dist/rules/no-single-tag-message.test.js.map +1 -0
- package/dist/rules/no-single-variable-message.d.ts +2 -0
- package/dist/rules/no-single-variable-message.d.ts.map +1 -0
- package/dist/rules/no-single-variable-message.js +74 -0
- package/dist/rules/no-single-variable-message.js.map +1 -0
- package/dist/rules/no-single-variable-message.test.d.ts +2 -0
- package/dist/rules/no-single-variable-message.test.d.ts.map +1 -0
- package/dist/rules/no-single-variable-message.test.js +74 -0
- package/dist/rules/no-single-variable-message.test.js.map +1 -0
- package/dist/rules/no-unlocalized-strings.d.ts +9 -0
- package/dist/rules/no-unlocalized-strings.d.ts.map +1 -0
- package/dist/rules/no-unlocalized-strings.js +374 -0
- package/dist/rules/no-unlocalized-strings.js.map +1 -0
- package/dist/rules/no-unlocalized-strings.test.d.ts +2 -0
- package/dist/rules/no-unlocalized-strings.test.d.ts.map +1 -0
- package/dist/rules/no-unlocalized-strings.test.js +200 -0
- package/dist/rules/no-unlocalized-strings.test.js.map +1 -0
- package/dist/rules/text-restrictions.d.ts +8 -0
- package/dist/rules/text-restrictions.d.ts.map +1 -0
- package/dist/rules/text-restrictions.js +103 -0
- package/dist/rules/text-restrictions.js.map +1 -0
- package/dist/rules/text-restrictions.test.d.ts +2 -0
- package/dist/rules/text-restrictions.test.d.ts.map +1 -0
- package/dist/rules/text-restrictions.test.js +107 -0
- package/dist/rules/text-restrictions.test.js.map +1 -0
- package/dist/rules/valid-t-call-location.d.ts +5 -0
- package/dist/rules/valid-t-call-location.d.ts.map +1 -0
- package/dist/rules/valid-t-call-location.js +69 -0
- package/dist/rules/valid-t-call-location.js.map +1 -0
- package/dist/rules/valid-t-call-location.test.d.ts +2 -0
- package/dist/rules/valid-t-call-location.test.d.ts.map +1 -0
- package/dist/rules/valid-t-call-location.test.js +104 -0
- package/dist/rules/valid-t-call-location.test.js.map +1 -0
- package/dist/utils/create-rule.d.ts +6 -0
- package/dist/utils/create-rule.d.ts.map +1 -0
- package/dist/utils/create-rule.js +6 -0
- package/dist/utils/create-rule.js.map +1 -0
- package/package.json +89 -0
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# eslint-plugin-lingui-typescript
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/eslint-plugin-lingui-typescript)
|
|
4
|
+
[](https://github.com/sebastian-software/eslint-plugin-lingui-typescript/actions/workflows/ci.yml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
ESLint plugin for [Lingui](https://lingui.dev/) with TypeScript type-aware rules.
|
|
8
|
+
|
|
9
|
+
## Why TypeScript?
|
|
10
|
+
|
|
11
|
+
Traditional i18n linters rely on heuristics and manual whitelists to distinguish user-visible text from technical strings. This leads to false positives and constant configuration tweaking.
|
|
12
|
+
|
|
13
|
+
This plugin leverages TypeScript's type system to **automatically** recognize technical strings:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// ✅ Automatically ignored - TypeScript knows these are technical
|
|
17
|
+
document.createElement("div") // keyof HTMLElementTagNameMap
|
|
18
|
+
element.addEventListener("click", handler) // keyof GlobalEventHandlersEventMap
|
|
19
|
+
fetch(url, { mode: "cors" }) // RequestMode
|
|
20
|
+
date.toLocaleDateString("de-DE", { weekday: "long" }) // Intl.DateTimeFormatOptions
|
|
21
|
+
|
|
22
|
+
type Status = "idle" | "loading" | "error"
|
|
23
|
+
const status: Status = "loading" // String literal union
|
|
24
|
+
|
|
25
|
+
// ❌ Reported - actual user-visible text
|
|
26
|
+
const message = "Welcome to our app"
|
|
27
|
+
<button>Save changes</button>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**No configuration needed** for DOM APIs, Intl methods, or your own string literal union types. TypeScript already knows!
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- 🔍 Detects incorrect usage of Lingui translation macros
|
|
35
|
+
- 📝 Enforces simple, safe expressions inside translated messages
|
|
36
|
+
- 🎯 Detects missing localization of user-visible text
|
|
37
|
+
- 🧠 Zero-config recognition of technical strings via TypeScript types
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- Node.js ≥ 24
|
|
42
|
+
- ESLint ≥ 9
|
|
43
|
+
- TypeScript ≥ 5
|
|
44
|
+
- `typescript-eslint` with type-aware linting enabled
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install --save-dev eslint-plugin-lingui-typescript
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
This plugin requires TypeScript and type-aware linting. Configure your `eslint.config.ts`:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import eslint from "@eslint/js"
|
|
58
|
+
import tseslint from "typescript-eslint"
|
|
59
|
+
import linguiPlugin from "eslint-plugin-lingui-typescript"
|
|
60
|
+
|
|
61
|
+
export default [
|
|
62
|
+
eslint.configs.recommended,
|
|
63
|
+
...tseslint.configs.strictTypeChecked,
|
|
64
|
+
linguiPlugin.configs["flat/recommended"],
|
|
65
|
+
{
|
|
66
|
+
languageOptions: {
|
|
67
|
+
parserOptions: {
|
|
68
|
+
projectService: true,
|
|
69
|
+
tsconfigRootDir: import.meta.dirname
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or configure rules manually:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
{
|
|
80
|
+
plugins: {
|
|
81
|
+
"lingui-ts": linguiPlugin
|
|
82
|
+
},
|
|
83
|
+
rules: {
|
|
84
|
+
"lingui-ts/no-unlocalized-strings": "error",
|
|
85
|
+
"lingui-ts/no-single-variable-message": "error"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Rules
|
|
91
|
+
|
|
92
|
+
| Rule | Description | Recommended |
|
|
93
|
+
|------|-------------|:-----------:|
|
|
94
|
+
| [no-unlocalized-strings](docs/rules/no-unlocalized-strings.md) | Detects user-visible strings not wrapped in Lingui macros. Uses TypeScript types to automatically ignore technical strings like string literal unions, DOM APIs, Intl methods, and discriminated union fields. | ✅ |
|
|
95
|
+
| [no-single-variable-message](docs/rules/no-single-variable-message.md) | Disallows messages that consist only of a single variable without surrounding text. Such messages provide no context for translators. | ✅ |
|
|
96
|
+
| [no-single-tag-message](docs/rules/no-single-tag-message.md) | Disallows `<Trans>` components that contain only a single JSX element without text. The wrapped element should be translated directly instead. | ✅ |
|
|
97
|
+
| [no-nested-macros](docs/rules/no-nested-macros.md) | Prevents nesting Lingui macros inside each other (e.g., `t` inside `<Trans>`). Nested macros create invalid message catalogs and confuse translators. | ✅ |
|
|
98
|
+
| [no-complex-expressions-in-message](docs/rules/no-complex-expressions-in-message.md) | Restricts embedded expressions in messages to simple identifiers and member access. Complex expressions like function calls or ternaries should be extracted to variables. | ✅ |
|
|
99
|
+
| [valid-t-call-location](docs/rules/valid-t-call-location.md) | Ensures `t` macro calls are inside functions, not at module scope. Module-level calls execute before i18n is initialized and won't update on locale change. | ✅ |
|
|
100
|
+
| [consistent-plural-format](docs/rules/consistent-plural-format.md) | Validates `<Plural>` component usage by ensuring required plural keys (`one`, `other`) are present. Helps maintain consistent pluralization across the codebase. | ✅ |
|
|
101
|
+
| [text-restrictions](docs/rules/text-restrictions.md) | Enforces project-specific text restrictions like disallowed patterns or minimum length. Requires configuration to be useful. | — |
|
|
102
|
+
|
|
103
|
+
## Related Projects
|
|
104
|
+
|
|
105
|
+
- [Lingui](https://lingui.dev/) – The excellent i18n library this plugin is built for. Provides powerful macros like `t`, `<Trans>`, and `plural` for seamless internationalization.
|
|
106
|
+
- [eslint-plugin-lingui](https://github.com/lingui/eslint-plugin-lingui) – The official Lingui ESLint plugin. Great for JavaScript projects; this plugin extends the concept with TypeScript type-awareness.
|
|
107
|
+
- [typescript-eslint](https://typescript-eslint.io/) – The foundation that makes type-aware linting possible. This plugin builds on their excellent tooling.
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
[MIT](LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint Plugin for Lingui with TypeScript type-aware rules
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
declare const plugin: {
|
|
7
|
+
meta: {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
};
|
|
11
|
+
rules: {
|
|
12
|
+
"consistent-plural-format": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPluralKey", [import("./rules/consistent-plural-format.js").Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
13
|
+
"no-complex-expressions-in-message": import("@typescript-eslint/utils/ts-eslint").RuleModule<"complexExpression", [import("./rules/no-complex-expressions-in-message.js").Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
14
|
+
"no-nested-macros": import("@typescript-eslint/utils/ts-eslint").RuleModule<"nestedMacro", [import("./rules/no-nested-macros.js").Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
15
|
+
"no-single-tag-message": import("@typescript-eslint/utils/ts-eslint").RuleModule<"singleTag", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
16
|
+
"no-single-variable-message": import("@typescript-eslint/utils/ts-eslint").RuleModule<"singleVariable", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
17
|
+
"no-unlocalized-strings": import("@typescript-eslint/utils/ts-eslint").RuleModule<"unlocalizedString", [import("./rules/no-unlocalized-strings.js").Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
18
|
+
"text-restrictions": import("@typescript-eslint/utils/ts-eslint").RuleModule<"forbiddenPattern" | "tooShort", [import("./rules/text-restrictions.js").Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
19
|
+
"valid-t-call-location": import("@typescript-eslint/utils/ts-eslint").RuleModule<"topLevelNotAllowed", [import("./rules/valid-t-call-location.js").Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
20
|
+
};
|
|
21
|
+
configs: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
export default plugin;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;aAeK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACvC,CAAA;AAqBD,eAAe,MAAM,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint Plugin for Lingui with TypeScript type-aware rules
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import { consistentPluralFormat } from "./rules/consistent-plural-format.js";
|
|
7
|
+
import { noComplexExpressionsInMessage } from "./rules/no-complex-expressions-in-message.js";
|
|
8
|
+
import { noNestedMacros } from "./rules/no-nested-macros.js";
|
|
9
|
+
import { noSingleTagMessage } from "./rules/no-single-tag-message.js";
|
|
10
|
+
import { noSingleVariableMessage } from "./rules/no-single-variable-message.js";
|
|
11
|
+
import { noUnlocalizedStrings } from "./rules/no-unlocalized-strings.js";
|
|
12
|
+
import { textRestrictions } from "./rules/text-restrictions.js";
|
|
13
|
+
import { validTCallLocation } from "./rules/valid-t-call-location.js";
|
|
14
|
+
const plugin = {
|
|
15
|
+
meta: {
|
|
16
|
+
name: "eslint-plugin-lingui-typescript",
|
|
17
|
+
version: "1.0.0"
|
|
18
|
+
},
|
|
19
|
+
rules: {
|
|
20
|
+
"consistent-plural-format": consistentPluralFormat,
|
|
21
|
+
"no-complex-expressions-in-message": noComplexExpressionsInMessage,
|
|
22
|
+
"no-nested-macros": noNestedMacros,
|
|
23
|
+
"no-single-tag-message": noSingleTagMessage,
|
|
24
|
+
"no-single-variable-message": noSingleVariableMessage,
|
|
25
|
+
"no-unlocalized-strings": noUnlocalizedStrings,
|
|
26
|
+
"text-restrictions": textRestrictions,
|
|
27
|
+
"valid-t-call-location": validTCallLocation
|
|
28
|
+
},
|
|
29
|
+
configs: {}
|
|
30
|
+
};
|
|
31
|
+
// Add flat config with self-reference
|
|
32
|
+
plugin.configs = {
|
|
33
|
+
"flat/recommended": {
|
|
34
|
+
plugins: {
|
|
35
|
+
"lingui-ts": plugin
|
|
36
|
+
},
|
|
37
|
+
rules: {
|
|
38
|
+
"lingui-ts/consistent-plural-format": "error",
|
|
39
|
+
"lingui-ts/no-complex-expressions-in-message": "error",
|
|
40
|
+
"lingui-ts/no-nested-macros": "error",
|
|
41
|
+
"lingui-ts/no-single-tag-message": "error",
|
|
42
|
+
"lingui-ts/no-single-variable-message": "error",
|
|
43
|
+
"lingui-ts/no-unlocalized-strings": "error",
|
|
44
|
+
"lingui-ts/valid-t-call-location": "error"
|
|
45
|
+
// text-restrictions not in recommended (requires configuration)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
export default plugin;
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AAC5E,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAA;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAErE,MAAM,MAAM,GAAG;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,iCAAiC;QACvC,OAAO,EAAE,OAAO;KACjB;IACD,KAAK,EAAE;QACL,0BAA0B,EAAE,sBAAsB;QAClD,mCAAmC,EAAE,6BAA6B;QAClE,kBAAkB,EAAE,cAAc;QAClC,uBAAuB,EAAE,kBAAkB;QAC3C,4BAA4B,EAAE,uBAAuB;QACrD,wBAAwB,EAAE,oBAAoB;QAC9C,mBAAmB,EAAE,gBAAgB;QACrC,uBAAuB,EAAE,kBAAkB;KAC5C;IACD,OAAO,EAAE,EAA6B;CACvC,CAAA;AAED,sCAAsC;AACtC,MAAM,CAAC,OAAO,GAAG;IACf,kBAAkB,EAAE;QAClB,OAAO,EAAE;YACP,WAAW,EAAE,MAAM;SACpB;QACD,KAAK,EAAE;YACL,oCAAoC,EAAE,OAAO;YAC7C,6CAA6C,EAAE,OAAO;YACtD,4BAA4B,EAAE,OAAO;YACrC,iCAAiC,EAAE,OAAO;YAC1C,sCAAsC,EAAE,OAAO;YAC/C,kCAAkC,EAAE,OAAO;YAC3C,iCAAiC,EAAE,OAAO;YAC1C,gEAAgE;SACjE;KACF;CACF,CAAA;AAED,eAAe,MAAM,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export interface Options {
|
|
2
|
+
requiredKeys: string[];
|
|
3
|
+
}
|
|
4
|
+
export declare const consistentPluralFormat: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPluralKey", [Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
5
|
+
//# sourceMappingURL=consistent-plural-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-plural-format.d.ts","sourceRoot":"","sources":["../../src/rules/consistent-plural-format.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,OAAO;IACtB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAmBD,eAAO,MAAM,sBAAsB,4JAqDjC,CAAA"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
import { createRule } from "../utils/create-rule.js";
|
|
3
|
+
const DEFAULT_REQUIRED_KEYS = ["one", "other"];
|
|
4
|
+
/**
|
|
5
|
+
* Extracts attribute names from a JSX opening element.
|
|
6
|
+
*/
|
|
7
|
+
function getJSXAttributeNames(node) {
|
|
8
|
+
const names = [];
|
|
9
|
+
for (const attr of node.attributes) {
|
|
10
|
+
if (attr.type === AST_NODE_TYPES.JSXAttribute && attr.name.type === AST_NODE_TYPES.JSXIdentifier) {
|
|
11
|
+
names.push(attr.name.name);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return names;
|
|
15
|
+
}
|
|
16
|
+
export const consistentPluralFormat = createRule({
|
|
17
|
+
name: "consistent-plural-format",
|
|
18
|
+
meta: {
|
|
19
|
+
type: "problem",
|
|
20
|
+
docs: {
|
|
21
|
+
description: "Ensure <Plural> component has required plural category props"
|
|
22
|
+
},
|
|
23
|
+
messages: {
|
|
24
|
+
missingPluralKey: "<Plural> is missing required prop '{{key}}'"
|
|
25
|
+
},
|
|
26
|
+
schema: [
|
|
27
|
+
{
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
requiredKeys: {
|
|
31
|
+
type: "array",
|
|
32
|
+
items: { type: "string" },
|
|
33
|
+
default: DEFAULT_REQUIRED_KEYS
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
additionalProperties: false
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
defaultOptions: [
|
|
41
|
+
{
|
|
42
|
+
requiredKeys: DEFAULT_REQUIRED_KEYS
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
create(context, [options]) {
|
|
46
|
+
return {
|
|
47
|
+
JSXElement(node) {
|
|
48
|
+
const openingElement = node.openingElement;
|
|
49
|
+
// Check for <Plural> component
|
|
50
|
+
if (openingElement.name.type !== AST_NODE_TYPES.JSXIdentifier || openingElement.name.name !== "Plural") {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const providedProps = getJSXAttributeNames(openingElement);
|
|
54
|
+
for (const requiredKey of options.requiredKeys) {
|
|
55
|
+
if (!providedProps.includes(requiredKey)) {
|
|
56
|
+
context.report({
|
|
57
|
+
node,
|
|
58
|
+
messageId: "missingPluralKey",
|
|
59
|
+
data: { key: requiredKey }
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=consistent-plural-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-plural-format.js","sourceRoot":"","sources":["../../src/rules/consistent-plural-format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,MAAM,0BAA0B,CAAA;AAExE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAQpD,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AAE9C;;GAEG;AACH,SAAS,oBAAoB,CAAC,IAAgC;IAC5D,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,aAAa,EAAE,CAAC;YACjG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,UAAU,CAAuB;IACrE,IAAI,EAAE,0BAA0B;IAChC,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,8DAA8D;SAC5E;QACD,QAAQ,EAAE;YACR,gBAAgB,EAAE,6CAA6C;SAChE;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,YAAY,EAAE;wBACZ,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,OAAO,EAAE,qBAAqB;qBAC/B;iBACF;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;KACF;IACD,cAAc,EAAE;QACd;YACE,YAAY,EAAE,qBAAqB;SACpC;KACF;IACD,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC;QACvB,OAAO;YACL,UAAU,CAAC,IAAI;gBACb,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAA;gBAE1C,+BAA+B;gBAC/B,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,aAAa,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACvG,OAAM;gBACR,CAAC;gBAED,MAAM,aAAa,GAAG,oBAAoB,CAAC,cAAc,CAAC,CAAA;gBAE1D,KAAK,MAAM,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;oBAC/C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;wBACzC,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI;4BACJ,SAAS,EAAE,kBAAkB;4BAC7B,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE;yBAC3B,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-plural-format.test.d.ts","sourceRoot":"","sources":["../../src/rules/consistent-plural-format.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { RuleTester } from "@typescript-eslint/rule-tester";
|
|
2
|
+
import { afterAll, describe, it } from "vitest";
|
|
3
|
+
import { consistentPluralFormat } from "./consistent-plural-format.js";
|
|
4
|
+
RuleTester.afterAll = afterAll;
|
|
5
|
+
RuleTester.describe = describe;
|
|
6
|
+
RuleTester.it = it;
|
|
7
|
+
const ruleTester = new RuleTester({
|
|
8
|
+
languageOptions: {
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 2022,
|
|
11
|
+
sourceType: "module",
|
|
12
|
+
ecmaFeatures: {
|
|
13
|
+
jsx: true
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
ruleTester.run("consistent-plural-format", consistentPluralFormat, {
|
|
19
|
+
valid: [
|
|
20
|
+
// All required props present (default: one, other)
|
|
21
|
+
'<Plural value={count} one="# item" other="# items" />',
|
|
22
|
+
'<Plural value={count} one="One" other="Many" zero="None" />',
|
|
23
|
+
// With expressions
|
|
24
|
+
"<Plural value={count} one={oneMsg} other={otherMsg} />",
|
|
25
|
+
// Custom required keys
|
|
26
|
+
{
|
|
27
|
+
code: '<Plural value={count} other="items" />',
|
|
28
|
+
options: [{ requiredKeys: ["other"] }]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: '<Plural value={count} one="#" other="#" zero="none" />',
|
|
32
|
+
options: [{ requiredKeys: ["one", "other", "zero"] }]
|
|
33
|
+
},
|
|
34
|
+
// Non-Plural components should be ignored
|
|
35
|
+
'<Select value={gender} male="He" female="She" other="They" />',
|
|
36
|
+
'<div one="x" />',
|
|
37
|
+
"<Trans>Hello</Trans>"
|
|
38
|
+
],
|
|
39
|
+
invalid: [
|
|
40
|
+
// Missing 'other' (default required)
|
|
41
|
+
{
|
|
42
|
+
code: '<Plural value={count} one="# item" />',
|
|
43
|
+
errors: [{ messageId: "missingPluralKey", data: { key: "other" } }]
|
|
44
|
+
},
|
|
45
|
+
// Missing 'one' (default required)
|
|
46
|
+
{
|
|
47
|
+
code: '<Plural value={count} other="# items" />',
|
|
48
|
+
errors: [{ messageId: "missingPluralKey", data: { key: "one" } }]
|
|
49
|
+
},
|
|
50
|
+
// Missing both default required keys
|
|
51
|
+
{
|
|
52
|
+
code: '<Plural value={count} zero="None" />',
|
|
53
|
+
errors: [
|
|
54
|
+
{ messageId: "missingPluralKey", data: { key: "one" } },
|
|
55
|
+
{ messageId: "missingPluralKey", data: { key: "other" } }
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
// Custom required keys missing
|
|
59
|
+
{
|
|
60
|
+
code: '<Plural value={count} one="#" other="#" />',
|
|
61
|
+
options: [{ requiredKeys: ["one", "other", "zero"] }],
|
|
62
|
+
errors: [{ messageId: "missingPluralKey", data: { key: "zero" } }]
|
|
63
|
+
},
|
|
64
|
+
// Only value prop
|
|
65
|
+
{
|
|
66
|
+
code: "<Plural value={count} />",
|
|
67
|
+
errors: [
|
|
68
|
+
{ messageId: "missingPluralKey", data: { key: "one" } },
|
|
69
|
+
{ messageId: "missingPluralKey", data: { key: "other" } }
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=consistent-plural-format.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-plural-format.test.js","sourceRoot":"","sources":["../../src/rules/consistent-plural-format.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAEtE,UAAU,CAAC,QAAQ,GAAG,QAAQ,CAAA;AAC9B,UAAU,CAAC,QAAQ,GAAG,QAAQ,CAAA;AAC9B,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;AAElB,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC;IAChC,eAAe,EAAE;QACf,aAAa,EAAE;YACb,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,QAAQ;YACpB,YAAY,EAAE;gBACZ,GAAG,EAAE,IAAI;aACV;SACF;KACF;CACF,CAAC,CAAA;AAEF,UAAU,CAAC,GAAG,CAAC,0BAA0B,EAAE,sBAAsB,EAAE;IACjE,KAAK,EAAE;QACL,mDAAmD;QACnD,uDAAuD;QACvD,6DAA6D;QAE7D,mBAAmB;QACnB,wDAAwD;QAExD,uBAAuB;QACvB;YACE,IAAI,EAAE,wCAAwC;YAC9C,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;SACvC;QACD;YACE,IAAI,EAAE,wDAAwD;YAC9D,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;SACtD;QAED,0CAA0C;QAC1C,+DAA+D;QAC/D,iBAAiB;QACjB,sBAAsB;KACvB;IACD,OAAO,EAAE;QACP,qCAAqC;QACrC;YACE,IAAI,EAAE,uCAAuC;YAC7C,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;SACpE;QAED,mCAAmC;QACnC;YACE,IAAI,EAAE,0CAA0C;YAChD,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC;SAClE;QAED,qCAAqC;QACrC;YACE,IAAI,EAAE,sCAAsC;YAC5C,MAAM,EAAE;gBACN,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACvD,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;aAC1D;SACF;QAED,+BAA+B;QAC/B;YACE,IAAI,EAAE,4CAA4C;YAClD,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;YACrD,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;SACnE;QAED,kBAAkB;QAClB;YACE,IAAI,EAAE,0BAA0B;YAChC,MAAM,EAAE;gBACN,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACvD,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;aAC1D;SACF;KACF;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface Options {
|
|
2
|
+
allowedCallees: string[];
|
|
3
|
+
allowMemberExpressions: boolean;
|
|
4
|
+
maxExpressionDepth: number | null;
|
|
5
|
+
}
|
|
6
|
+
export declare const noComplexExpressionsInMessage: import("@typescript-eslint/utils/ts-eslint").RuleModule<"complexExpression", [Options], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
7
|
+
//# sourceMappingURL=no-complex-expressions-in-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-complex-expressions-in-message.d.ts","sourceRoot":"","sources":["../../src/rules/no-complex-expressions-in-message.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,OAAO;IACtB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC;AA+GD,eAAO,MAAM,6BAA6B,6JA+FxC,CAAA"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
import { createRule } from "../utils/create-rule.js";
|
|
3
|
+
const DEFAULT_ALLOWED_CALLEES = ["i18n.number", "i18n.date"];
|
|
4
|
+
/**
|
|
5
|
+
* Gets the string representation of a callee (e.g., "i18n.number", "Math.random").
|
|
6
|
+
*/
|
|
7
|
+
function getCalleeName(node) {
|
|
8
|
+
if (node.type === AST_NODE_TYPES.Identifier) {
|
|
9
|
+
return node.name;
|
|
10
|
+
}
|
|
11
|
+
if (node.type === AST_NODE_TYPES.MemberExpression && !node.computed) {
|
|
12
|
+
const object = getCalleeName(node.object);
|
|
13
|
+
const property = node.property.type === AST_NODE_TYPES.Identifier ? node.property.name : null;
|
|
14
|
+
if (object !== null && property !== null) {
|
|
15
|
+
return `${object}.${property}`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Gets the depth of a member expression chain.
|
|
22
|
+
*/
|
|
23
|
+
function getMemberExpressionDepth(node) {
|
|
24
|
+
let depth = 1;
|
|
25
|
+
let current = node.object;
|
|
26
|
+
while (current.type === AST_NODE_TYPES.MemberExpression) {
|
|
27
|
+
depth++;
|
|
28
|
+
current = current.object;
|
|
29
|
+
}
|
|
30
|
+
return depth;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Checks if an expression is allowed within a Lingui message.
|
|
34
|
+
*/
|
|
35
|
+
function isAllowedExpression(node, options) {
|
|
36
|
+
// Simple identifiers are always allowed: name, count
|
|
37
|
+
if (node.type === AST_NODE_TYPES.Identifier) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// Member expressions: props.name, user.id
|
|
41
|
+
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
42
|
+
if (!options.allowMemberExpressions) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
// Check depth limit
|
|
46
|
+
const depth = getMemberExpressionDepth(node);
|
|
47
|
+
if (options.maxExpressionDepth !== null && depth > options.maxExpressionDepth) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
// Optional chaining is not allowed
|
|
51
|
+
if (node.optional) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
// Call expressions: check if callee is whitelisted
|
|
57
|
+
if (node.type === AST_NODE_TYPES.CallExpression) {
|
|
58
|
+
const calleeName = getCalleeName(node.callee);
|
|
59
|
+
if (calleeName !== null && options.allowedCallees.includes(calleeName)) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
// All other expression types are not allowed
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Gets a readable representation of an expression for error messages.
|
|
69
|
+
*/
|
|
70
|
+
function getExpressionText(node) {
|
|
71
|
+
switch (node.type) {
|
|
72
|
+
case AST_NODE_TYPES.BinaryExpression:
|
|
73
|
+
return `binary expression (${node.operator})`;
|
|
74
|
+
case AST_NODE_TYPES.CallExpression: {
|
|
75
|
+
const name = getCalleeName(node.callee);
|
|
76
|
+
return name !== null ? `function call (${name})` : "function call";
|
|
77
|
+
}
|
|
78
|
+
case AST_NODE_TYPES.MemberExpression:
|
|
79
|
+
return "member expression";
|
|
80
|
+
case AST_NODE_TYPES.ConditionalExpression:
|
|
81
|
+
return "conditional expression";
|
|
82
|
+
case AST_NODE_TYPES.LogicalExpression:
|
|
83
|
+
return `logical expression (${node.operator})`;
|
|
84
|
+
case AST_NODE_TYPES.UnaryExpression:
|
|
85
|
+
return `unary expression (${node.operator})`;
|
|
86
|
+
case AST_NODE_TYPES.TemplateLiteral:
|
|
87
|
+
return "template literal";
|
|
88
|
+
case AST_NODE_TYPES.ArrayExpression:
|
|
89
|
+
return "array expression";
|
|
90
|
+
case AST_NODE_TYPES.ObjectExpression:
|
|
91
|
+
return "object expression";
|
|
92
|
+
default:
|
|
93
|
+
return node.type;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export const noComplexExpressionsInMessage = createRule({
|
|
97
|
+
name: "no-complex-expressions-in-message",
|
|
98
|
+
meta: {
|
|
99
|
+
type: "problem",
|
|
100
|
+
docs: {
|
|
101
|
+
description: "Disallow complex expressions in Lingui messages"
|
|
102
|
+
},
|
|
103
|
+
messages: {
|
|
104
|
+
complexExpression: "Complex expression '{{expression}}' in Lingui message. Use simple identifiers or extract to a variable."
|
|
105
|
+
},
|
|
106
|
+
schema: [
|
|
107
|
+
{
|
|
108
|
+
type: "object",
|
|
109
|
+
properties: {
|
|
110
|
+
allowedCallees: {
|
|
111
|
+
type: "array",
|
|
112
|
+
items: { type: "string" },
|
|
113
|
+
default: DEFAULT_ALLOWED_CALLEES
|
|
114
|
+
},
|
|
115
|
+
allowMemberExpressions: {
|
|
116
|
+
type: "boolean",
|
|
117
|
+
default: false
|
|
118
|
+
},
|
|
119
|
+
maxExpressionDepth: {
|
|
120
|
+
type: ["number", "null"],
|
|
121
|
+
default: 1
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
additionalProperties: false
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
defaultOptions: [
|
|
129
|
+
{
|
|
130
|
+
allowedCallees: DEFAULT_ALLOWED_CALLEES,
|
|
131
|
+
allowMemberExpressions: false,
|
|
132
|
+
maxExpressionDepth: 1
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
create(context, [options]) {
|
|
136
|
+
function checkExpressions(expressions) {
|
|
137
|
+
for (const expr of expressions) {
|
|
138
|
+
if (!isAllowedExpression(expr, options)) {
|
|
139
|
+
context.report({
|
|
140
|
+
node: expr,
|
|
141
|
+
messageId: "complexExpression",
|
|
142
|
+
data: {
|
|
143
|
+
expression: getExpressionText(expr)
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function checkJSXChildren(children) {
|
|
150
|
+
for (const child of children) {
|
|
151
|
+
if (child.type === AST_NODE_TYPES.JSXExpressionContainer &&
|
|
152
|
+
child.expression.type !== AST_NODE_TYPES.JSXEmptyExpression) {
|
|
153
|
+
if (!isAllowedExpression(child.expression, options)) {
|
|
154
|
+
context.report({
|
|
155
|
+
node: child.expression,
|
|
156
|
+
messageId: "complexExpression",
|
|
157
|
+
data: {
|
|
158
|
+
expression: getExpressionText(child.expression)
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
// Check t`Hello ${expr}` pattern
|
|
167
|
+
TaggedTemplateExpression(node) {
|
|
168
|
+
if (node.tag.type !== AST_NODE_TYPES.Identifier || node.tag.name !== "t") {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
checkExpressions(node.quasi.expressions);
|
|
172
|
+
},
|
|
173
|
+
// Check <Trans>Hello {expr}</Trans> pattern
|
|
174
|
+
JSXElement(node) {
|
|
175
|
+
const openingElement = node.openingElement;
|
|
176
|
+
if (openingElement.name.type !== AST_NODE_TYPES.JSXIdentifier || openingElement.name.name !== "Trans") {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
checkJSXChildren(node.children);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
//# sourceMappingURL=no-complex-expressions-in-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-complex-expressions-in-message.js","sourceRoot":"","sources":["../../src/rules/no-complex-expressions-in-message.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-complex-expressions-in-message.test.d.ts","sourceRoot":"","sources":["../../src/rules/no-complex-expressions-in-message.test.ts"],"names":[],"mappings":""}
|