@nkzw/eslint-plugin-fbtee 0.1.4 → 0.2.1

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 CHANGED
@@ -18,7 +18,13 @@ This is a fork of Facebook's original `fbt` library, which has been archived. Th
18
18
  **fbtee** requires at least Node 22, and React 19 if you are using React.
19
19
 
20
20
  ```bash
21
- npm install fbtee @nkzw/babel-preset-fbtee
21
+ npm install fbtee
22
+ ```
23
+
24
+ In addition to `fbtee`, you need to install the Babel preset and React plugin for Vite:
25
+
26
+ ```bash
27
+ npm install -D @nkzw/babel-preset-fbtee @vitejs/plugin-react
22
28
  ```
23
29
 
24
30
  In your `vite.config.ts`:
@@ -43,20 +49,26 @@ export default {
43
49
  ```json
44
50
  {
45
51
  "scripts": {
46
- "fbtee:collect": "fbtee collect --manifest < .src_manifest.json > .source_strings.json",
47
52
  "fbtee:manifest": "fbtee manifest --src src",
53
+ "fbtee:collect": "fbtee collect --manifest < .src_manifest.json > .source_strings.json",
48
54
  "fbtee:translate": "fbtee translate --translations translations/*.json --jenkins > src/translations.json"
49
55
  }
50
56
  }
51
57
  ```
52
58
 
53
- Run these commands to set up the initial translation files:
59
+ Here is what each command does:
60
+
61
+ - `fbtee manifest --src src` searches through files in the `src` directory and generates a manifest file (`.src_manifest.json`) that lists all the files translatable strings marked with `<fbt>`. In addition it creates `.enum_manifest.json` which lists all the files containing `<fbt:enum>` tags. Since these files are auto-generated, we recommend adding them to your `.gitignore`.
62
+ - `fbtee collect --manifest < .src_manifest.json > .source_strings.json` reads the manifest file and extracts all the strings marked for translation into a `.source_strings.json` file. This file should be uploaded to your translation provider as the source for your translations.
63
+ - `fbtee translate --translations translations/*.json --jenkins > src/translations.json` reads all the translations in the `translations/` directory and compiles them into a single `src/translations.json` file. This file is used by **fbtee** to display translated content in your app. The `--translations` parameter specifies the path to the translation files. The `--jenkins` flag is used to define the utilized [hash function](https://en.wikipedia.org/wiki/Jenkins_hash_function). You can adjust the `--translations` parameter to point to your translation directory. If your translations are within your app directory in a folder called `i18n`, for example, you'd use `--translations app/i18n/*.json`. The output is the translation file used by **fbtee**. This file is going to be referred to in your applications entry point, therefor it needs to be generated as part of the build, but should not be part of version control. This command requires the translations to be present in the `translations/` directory, created based on real translations of what was previously collected using the `collect` command.
64
+
65
+ Now, the first step is to run these commands to set up the initial strings for translation:
54
66
 
55
67
  ```bash
56
- npm run fbtee:manifest && npm run fbtee:collect && npm run fbtee:translate
68
+ npm run fbtee:manifest && npm run fbtee:collect
57
69
  ```
58
70
 
59
- The files generated by these commands are auto-generated and should not be checked into version control. Add the following entries to your `.gitignore`:
71
+ The files generated by these commands should be added to `.gitignore`:
60
72
 
61
73
  ```
62
74
  .src_manifest.json
@@ -82,13 +94,13 @@ setupFbtee({
82
94
  });
83
95
  ```
84
96
 
85
- Finally, if you are using React and TypeScript in your project, you need to add TypeScript types for **fbtee** to enable proper type checking in JSX. You can do this by referencing the `ReactTypes.d.ts` file in your main `index.tsx` file or a global type declaration file (e.g., `types.d.ts`):
97
+ Next up, if you are using React and TypeScript in your project, you need to add TypeScript types for **fbtee** to enable proper type checking in JSX. You can do this by referencing the `ReactTypes.d.ts` file in your main `index.tsx` file or a global type declaration file (e.g., `types.d.ts`):
86
98
 
87
99
  ```tsx
88
100
  /// <reference types="fbtee/ReactTypes.d.ts" />
89
101
  ```
90
102
 
91
- _You’re now ready to go!_
103
+ _You’re now ready to define your first translatable element!_
92
104
 
93
105
  ## Usage
94
106
 
@@ -141,16 +153,102 @@ _Note: `<fbt>` is auto-imported for you by the `@nkzw/babel-preset-fbtee` plugin
141
153
  After marking your strings for translation with `<fbt>`, run the following commands to extract, and compile translations:
142
154
 
143
155
  ```bash
144
- npm run fbtee:collect
156
+ npm run fbtee:manifest && npm run fbtee:collect
157
+ ```
158
+
159
+ You can now upload the `.source_strings.json` file to your translation provider. One sample for such a translation provider is [Crowdin](https://crowdin.com/).
160
+
161
+ ### Generated File Structure
162
+
163
+ Your `.source_strings.json` might look like this:
164
+
165
+ ```json
166
+ {
167
+ "childParentMappings": {},
168
+ "phrases": [
169
+ {
170
+ "hashToLeaf": {
171
+ "MB6OYuvCF1VzjOmqinI42g==": {
172
+ "desc": "What's next question",
173
+ "text": "What's next?"
174
+ }
175
+ },
176
+ "col_beg": 12,
177
+ "col_end": 68,
178
+ "filepath": "app/welcome/welcome.tsx",
179
+ "line_beg": 43,
180
+ "line_end": 43,
181
+ "project": "",
182
+ "jsfbt": {
183
+ "m": [],
184
+ "t": {
185
+ "desc": "What's next question",
186
+ "text": "What's next?"
187
+ }
188
+ }
189
+ }
190
+ ]
191
+ }
192
+ ```
193
+
194
+ Based on the above source string, the US English translation (ie. `translations/en_US.json`) might look like this:
195
+
196
+ ```json
197
+ {
198
+ "fb-locale": "en_US",
199
+ "translations": {
200
+ "MB6OYuvCF1VzjOmqinI42g==": {
201
+ "tokens": [],
202
+ "types": [],
203
+ "translations": [
204
+ {
205
+ "translation": "What's next?",
206
+ "variations": []
207
+ }
208
+ ]
209
+ }
210
+ }
211
+ }
145
212
  ```
146
213
 
147
- You can now upload the `.source_strings.json` file to your translation provider. Once you have the translated strings stored in a `translations/` folder as JSON files, you can run the following command to generate the translations file:
214
+ And German (`translations/de_DE.json`) might look like this:
215
+
216
+ ```json
217
+ {
218
+ "fb-locale": "de_DE",
219
+ "translations": {
220
+ "MB6OYuvCF1VzjOmqinI42g==": {
221
+ "tokens": [],
222
+ "types": [],
223
+ "translations": [
224
+ {
225
+ "translation": "Was kommt jetzt?",
226
+ "variations": []
227
+ }
228
+ ]
229
+ }
230
+ }
231
+ }
232
+ ```
233
+
234
+ Once you have the translated strings stored in a `translations/` folder as JSON files, you can run the following command to generate the translations file:
148
235
 
149
236
  ```bash
150
237
  npm run fbtee:translate
151
238
  ```
152
239
 
153
- After generating the translations file, your app is ready to display translated content in other languages.
240
+ This will generate the `translation.json` file referred to in the setup done before. This file might look like this:
241
+
242
+ ```json
243
+ {
244
+ "de_DE": { "2HVYhv": "Was kommt jetzt?" },
245
+ "en_US": { "2HVYhv": "What's next?" }
246
+ }
247
+ ```
248
+
249
+ After generating the translations file, your app is ready to display translated content in other languages. The error you had until now in the `setupFbtee` with regards to the imported translations file should be resolved now.
250
+
251
+ Since the `translations.json` is an auto-generated file part of your build process, the `fbtee:translate` command should be added to your build step.
154
252
 
155
253
  ## ESLint Plugin
156
254
 
@@ -200,7 +298,7 @@ The open-source version of `fbt`, however, became unmaintained, difficult to set
200
298
  - **Easier Setup:** fbtee works with modern tools like Vite.
201
299
  - **Statically Typed:** The fbtee compiler ensures correct usage of fbtee, libary TypeScript types are provided, and an eslint plugin helps fix common mistakes.
202
300
  - **Improved React Compatibility:** Removed React-specific hacks and added support for implicit React fragments (`<>`).
203
- - **Enhanced Features:** Fixed and exported `intlList`, which was not functional in the original `fbt`.
301
+ - **Enhanced Features:** Fixed and exported `inltList` as a new `<fbt:list>` construt, which was not functional in the original `fbt`.
204
302
  - **Modernized Codebase:** Rewritten using TypeScript, ES modules (ESM), eslint, and modern JavaScript standards. Removed cruft and legacy code.
205
303
  - **Updated Tooling:** Uses modern tools like pnpm, Vite, and esbuild for faster and more efficient development of **fbtee**.
206
304
 
package/lib/index.cjs CHANGED
@@ -18,18 +18,16 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
20
  // src/index.tsx
21
- var src_exports = {};
22
- __export(src_exports, {
23
- configs: () => configs,
24
- meta: () => meta,
25
- rules: () => rules
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ default: () => index_default
26
24
  });
27
- module.exports = __toCommonJS(src_exports);
25
+ module.exports = __toCommonJS(index_exports);
28
26
 
29
27
  // package.json
30
28
  var package_default = {
31
29
  name: "@nkzw/eslint-plugin-fbtee",
32
- version: "0.1.4",
30
+ version: "0.2.1",
33
31
  description: "",
34
32
  keywords: [],
35
33
  repository: {
@@ -43,14 +41,15 @@ var package_default = {
43
41
  import: "./lib/index.js",
44
42
  require: "./lib/index.cjs"
45
43
  },
44
+ main: "lib/index.cjs",
46
45
  scripts: {
47
46
  build: "tsup src/index.tsx -d lib --target=node22 --format=esm,cjs --clean --no-splitting --dts"
48
47
  },
49
48
  dependencies: {
50
- "@typescript-eslint/utils": "^8.18.0"
49
+ "@typescript-eslint/utils": "^8.19.1"
51
50
  },
52
51
  devDependencies: {
53
- "@typescript-eslint/rule-tester": "^8.18.0"
52
+ "@typescript-eslint/rule-tester": "^8.19.1"
54
53
  }
55
54
  };
56
55
 
@@ -121,6 +120,16 @@ function resolveNodeValue(node) {
121
120
  if (node.type === "JSXExpressionContainer") {
122
121
  return resolveNodeValue(node.expression);
123
122
  }
123
+ if (node.type === "ConditionalExpression") {
124
+ const consequent = resolveNodeValue(node.consequent);
125
+ const alternate = resolveNodeValue(node.alternate);
126
+ return consequent || alternate || null;
127
+ }
128
+ if (node.type === "LogicalExpression") {
129
+ const left = resolveNodeValue(node.left);
130
+ const right = resolveNodeValue(node.right);
131
+ return left || right || null;
132
+ }
124
133
  return null;
125
134
  }
126
135
  function getPropName(prop) {
@@ -433,33 +442,29 @@ var no_untranslated_strings_default = createRule({
433
442
  });
434
443
 
435
444
  // src/index.tsx
436
- var meta = {
437
- name: package_default.name,
438
- version: package_default.version
439
- };
440
- var rules = {
441
- "no-empty-strings": no_empty_strings_default,
442
- "no-unhelpful-desc": no_unhelpful_desc_default,
443
- "no-untranslated-strings": no_untranslated_strings_default
444
- };
445
- var configs = {
446
- recommended: {
447
- rules: {
448
- "@nkzw/fbtee/no-empty-strings": 2,
449
- "@nkzw/fbtee/no-unhelpful-desc": 2
445
+ var index_default = {
446
+ configs: {
447
+ recommended: {
448
+ rules: {
449
+ "@nkzw/fbtee/no-empty-strings": 2,
450
+ "@nkzw/fbtee/no-unhelpful-desc": 2
451
+ }
452
+ },
453
+ strict: {
454
+ rules: {
455
+ "@nkzw/fbtee/no-empty-strings": 2,
456
+ "@nkzw/fbtee/no-unhelpful-desc": 2,
457
+ "@nkzw/fbtee/no-untranslated-strings": 2
458
+ }
450
459
  }
451
460
  },
452
- strict: {
453
- rules: {
454
- "@nkzw/fbtee/no-empty-strings": 2,
455
- "@nkzw/fbtee/no-unhelpful-desc": 2,
456
- "@nkzw/fbtee/no-untranslated-strings": 2
457
- }
461
+ meta: {
462
+ name: package_default.name,
463
+ version: package_default.version
464
+ },
465
+ rules: {
466
+ "no-empty-strings": no_empty_strings_default,
467
+ "no-unhelpful-desc": no_unhelpful_desc_default,
468
+ "no-untranslated-strings": no_untranslated_strings_default
458
469
  }
459
470
  };
460
- // Annotate the CommonJS export names for ESM import in node:
461
- 0 && (module.exports = {
462
- configs,
463
- meta,
464
- rules
465
- });
package/lib/index.d.cts CHANGED
@@ -1,30 +1,32 @@
1
1
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
2
2
 
3
- declare const meta: {
4
- name: string;
5
- version: string;
6
- };
7
- declare const rules: {
8
- 'no-empty-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyString" | "jsxEmptyString", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
9
- 'no-unhelpful-desc': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyDesc" | "jsxEmptyDesc" | "duplicateDesc" | "shortDesc", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
10
- 'no-untranslated-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"unwrappedString", [{
11
- ignoredWords: Array<string>;
12
- }], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
13
- };
14
- declare const configs: {
15
- recommended: {
16
- rules: {
17
- '@nkzw/fbtee/no-empty-strings': number;
18
- '@nkzw/fbtee/no-unhelpful-desc': number;
3
+ declare const _default: {
4
+ configs: {
5
+ recommended: {
6
+ rules: {
7
+ '@nkzw/fbtee/no-empty-strings': number;
8
+ '@nkzw/fbtee/no-unhelpful-desc': number;
9
+ };
19
10
  };
20
- };
21
- strict: {
22
- rules: {
23
- '@nkzw/fbtee/no-empty-strings': number;
24
- '@nkzw/fbtee/no-unhelpful-desc': number;
25
- '@nkzw/fbtee/no-untranslated-strings': number;
11
+ strict: {
12
+ rules: {
13
+ '@nkzw/fbtee/no-empty-strings': number;
14
+ '@nkzw/fbtee/no-unhelpful-desc': number;
15
+ '@nkzw/fbtee/no-untranslated-strings': number;
16
+ };
26
17
  };
27
18
  };
19
+ meta: {
20
+ name: string;
21
+ version: string;
22
+ };
23
+ rules: {
24
+ 'no-empty-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyString" | "jsxEmptyString", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
25
+ 'no-unhelpful-desc': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyDesc" | "jsxEmptyDesc" | "duplicateDesc" | "shortDesc", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
26
+ 'no-untranslated-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"unwrappedString", [{
27
+ ignoredWords: Array<string>;
28
+ }], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
29
+ };
28
30
  };
29
31
 
30
- export { configs, meta, rules };
32
+ export { _default as default };
package/lib/index.d.ts CHANGED
@@ -1,30 +1,32 @@
1
1
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
2
2
 
3
- declare const meta: {
4
- name: string;
5
- version: string;
6
- };
7
- declare const rules: {
8
- 'no-empty-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyString" | "jsxEmptyString", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
9
- 'no-unhelpful-desc': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyDesc" | "jsxEmptyDesc" | "duplicateDesc" | "shortDesc", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
10
- 'no-untranslated-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"unwrappedString", [{
11
- ignoredWords: Array<string>;
12
- }], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
13
- };
14
- declare const configs: {
15
- recommended: {
16
- rules: {
17
- '@nkzw/fbtee/no-empty-strings': number;
18
- '@nkzw/fbtee/no-unhelpful-desc': number;
3
+ declare const _default: {
4
+ configs: {
5
+ recommended: {
6
+ rules: {
7
+ '@nkzw/fbtee/no-empty-strings': number;
8
+ '@nkzw/fbtee/no-unhelpful-desc': number;
9
+ };
19
10
  };
20
- };
21
- strict: {
22
- rules: {
23
- '@nkzw/fbtee/no-empty-strings': number;
24
- '@nkzw/fbtee/no-unhelpful-desc': number;
25
- '@nkzw/fbtee/no-untranslated-strings': number;
11
+ strict: {
12
+ rules: {
13
+ '@nkzw/fbtee/no-empty-strings': number;
14
+ '@nkzw/fbtee/no-unhelpful-desc': number;
15
+ '@nkzw/fbtee/no-untranslated-strings': number;
16
+ };
26
17
  };
27
18
  };
19
+ meta: {
20
+ name: string;
21
+ version: string;
22
+ };
23
+ rules: {
24
+ 'no-empty-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyString" | "jsxEmptyString", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
25
+ 'no-unhelpful-desc': _typescript_eslint_utils_ts_eslint.RuleModule<"emptyDesc" | "jsxEmptyDesc" | "duplicateDesc" | "shortDesc", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
26
+ 'no-untranslated-strings': _typescript_eslint_utils_ts_eslint.RuleModule<"unwrappedString", [{
27
+ ignoredWords: Array<string>;
28
+ }], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
29
+ };
28
30
  };
29
31
 
30
- export { configs, meta, rules };
32
+ export { _default as default };
package/lib/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@nkzw/eslint-plugin-fbtee",
4
- version: "0.1.4",
4
+ version: "0.2.1",
5
5
  description: "",
6
6
  keywords: [],
7
7
  repository: {
@@ -15,14 +15,15 @@ var package_default = {
15
15
  import: "./lib/index.js",
16
16
  require: "./lib/index.cjs"
17
17
  },
18
+ main: "lib/index.cjs",
18
19
  scripts: {
19
20
  build: "tsup src/index.tsx -d lib --target=node22 --format=esm,cjs --clean --no-splitting --dts"
20
21
  },
21
22
  dependencies: {
22
- "@typescript-eslint/utils": "^8.18.0"
23
+ "@typescript-eslint/utils": "^8.19.1"
23
24
  },
24
25
  devDependencies: {
25
- "@typescript-eslint/rule-tester": "^8.18.0"
26
+ "@typescript-eslint/rule-tester": "^8.19.1"
26
27
  }
27
28
  };
28
29
 
@@ -93,6 +94,16 @@ function resolveNodeValue(node) {
93
94
  if (node.type === "JSXExpressionContainer") {
94
95
  return resolveNodeValue(node.expression);
95
96
  }
97
+ if (node.type === "ConditionalExpression") {
98
+ const consequent = resolveNodeValue(node.consequent);
99
+ const alternate = resolveNodeValue(node.alternate);
100
+ return consequent || alternate || null;
101
+ }
102
+ if (node.type === "LogicalExpression") {
103
+ const left = resolveNodeValue(node.left);
104
+ const right = resolveNodeValue(node.right);
105
+ return left || right || null;
106
+ }
96
107
  return null;
97
108
  }
98
109
  function getPropName(prop) {
@@ -405,32 +416,32 @@ var no_untranslated_strings_default = createRule({
405
416
  });
406
417
 
407
418
  // src/index.tsx
408
- var meta = {
409
- name: package_default.name,
410
- version: package_default.version
411
- };
412
- var rules = {
413
- "no-empty-strings": no_empty_strings_default,
414
- "no-unhelpful-desc": no_unhelpful_desc_default,
415
- "no-untranslated-strings": no_untranslated_strings_default
416
- };
417
- var configs = {
418
- recommended: {
419
- rules: {
420
- "@nkzw/fbtee/no-empty-strings": 2,
421
- "@nkzw/fbtee/no-unhelpful-desc": 2
419
+ var index_default = {
420
+ configs: {
421
+ recommended: {
422
+ rules: {
423
+ "@nkzw/fbtee/no-empty-strings": 2,
424
+ "@nkzw/fbtee/no-unhelpful-desc": 2
425
+ }
426
+ },
427
+ strict: {
428
+ rules: {
429
+ "@nkzw/fbtee/no-empty-strings": 2,
430
+ "@nkzw/fbtee/no-unhelpful-desc": 2,
431
+ "@nkzw/fbtee/no-untranslated-strings": 2
432
+ }
422
433
  }
423
434
  },
424
- strict: {
425
- rules: {
426
- "@nkzw/fbtee/no-empty-strings": 2,
427
- "@nkzw/fbtee/no-unhelpful-desc": 2,
428
- "@nkzw/fbtee/no-untranslated-strings": 2
429
- }
435
+ meta: {
436
+ name: package_default.name,
437
+ version: package_default.version
438
+ },
439
+ rules: {
440
+ "no-empty-strings": no_empty_strings_default,
441
+ "no-unhelpful-desc": no_unhelpful_desc_default,
442
+ "no-untranslated-strings": no_untranslated_strings_default
430
443
  }
431
444
  };
432
445
  export {
433
- configs,
434
- meta,
435
- rules
446
+ index_default as default
436
447
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nkzw/eslint-plugin-fbtee",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "repository": {
@@ -14,11 +14,12 @@
14
14
  "import": "./lib/index.js",
15
15
  "require": "./lib/index.cjs"
16
16
  },
17
+ "main": "lib/index.cjs",
17
18
  "dependencies": {
18
- "@typescript-eslint/utils": "^8.18.0"
19
+ "@typescript-eslint/utils": "^8.19.1"
19
20
  },
20
21
  "devDependencies": {
21
- "@typescript-eslint/rule-tester": "^8.18.0"
22
+ "@typescript-eslint/rule-tester": "^8.19.1"
22
23
  },
23
24
  "scripts": {
24
25
  "build": "tsup src/index.tsx -d lib --target=node22 --format=esm,cjs --clean --no-splitting --dts"
@@ -72,7 +72,48 @@ ruleTester.run('no-untranslated-strings', rule, {
72
72
  },
73
73
  {
74
74
  code: `
75
- <>Hello world</>
75
+ <>Hello world</>;
76
+ `,
77
+ errors: [
78
+ {
79
+ messageId: 'unwrappedString',
80
+ },
81
+ ],
82
+ },
83
+ {
84
+ code: `
85
+ <span>{foo ? 'bar' : 'baz'}</span>;
86
+ `,
87
+ errors: [
88
+ {
89
+ messageId: 'unwrappedString',
90
+ },
91
+ ],
92
+ },
93
+ {
94
+ code: `
95
+ <span>{foo ?? 'bar'}</span>;
96
+ `,
97
+ errors: [
98
+ {
99
+ messageId: 'unwrappedString',
100
+ },
101
+ ],
102
+ },
103
+ {
104
+ code: `
105
+ <span>{foo || 'bar'}</span>;
106
+ `,
107
+ errors: [
108
+ {
109
+ messageId: 'unwrappedString',
110
+ },
111
+ ],
112
+ },
113
+ {
114
+ code: `
115
+ const foo = true;
116
+ <span>{foo && 'bar'}</span>;
76
117
  `,
77
118
  errors: [
78
119
  {
@@ -219,5 +260,20 @@ ruleTester.run('no-untranslated-strings', rule, {
219
260
  foo.bar('Baz')
220
261
  `,
221
262
  },
263
+ {
264
+ code: `
265
+ const foo = isGreeting ? 'Hello' : 'Goodbye'
266
+ `,
267
+ },
268
+ {
269
+ code: `
270
+ const foo = helloGreeting ?? 'goodbye'
271
+ `,
272
+ },
273
+ {
274
+ code: `
275
+ const foo = helloGreeting || 'goodbye'
276
+ `,
277
+ },
222
278
  ],
223
279
  });
package/src/index.tsx CHANGED
@@ -3,29 +3,29 @@ import noEmptyStringsRule from './rules/no-empty-strings.tsx';
3
3
  import noUnhelpfulDesc from './rules/no-unhelpful-desc.tsx';
4
4
  import noUntranslatedStrings from './rules/no-untranslated-strings.tsx';
5
5
 
6
- export const meta = {
7
- name: packageJson.name,
8
- version: packageJson.version,
9
- };
10
-
11
- export const rules = {
12
- 'no-empty-strings': noEmptyStringsRule,
13
- 'no-unhelpful-desc': noUnhelpfulDesc,
14
- 'no-untranslated-strings': noUntranslatedStrings,
15
- };
16
-
17
- export const configs = {
18
- recommended: {
19
- rules: {
20
- '@nkzw/fbtee/no-empty-strings': 2,
21
- '@nkzw/fbtee/no-unhelpful-desc': 2,
6
+ export default {
7
+ configs: {
8
+ recommended: {
9
+ rules: {
10
+ '@nkzw/fbtee/no-empty-strings': 2,
11
+ '@nkzw/fbtee/no-unhelpful-desc': 2,
12
+ },
22
13
  },
23
- },
24
- strict: {
25
- rules: {
26
- '@nkzw/fbtee/no-empty-strings': 2,
27
- '@nkzw/fbtee/no-unhelpful-desc': 2,
28
- '@nkzw/fbtee/no-untranslated-strings': 2,
14
+ strict: {
15
+ rules: {
16
+ '@nkzw/fbtee/no-empty-strings': 2,
17
+ '@nkzw/fbtee/no-unhelpful-desc': 2,
18
+ '@nkzw/fbtee/no-untranslated-strings': 2,
19
+ },
29
20
  },
30
21
  },
22
+ meta: {
23
+ name: packageJson.name,
24
+ version: packageJson.version,
25
+ },
26
+ rules: {
27
+ 'no-empty-strings': noEmptyStringsRule,
28
+ 'no-unhelpful-desc': noUnhelpfulDesc,
29
+ 'no-untranslated-strings': noUntranslatedStrings,
30
+ },
31
31
  };
package/src/utils.tsx CHANGED
@@ -105,6 +105,20 @@ export function resolveNodeValue(
105
105
  return resolveNodeValue(node.expression);
106
106
  }
107
107
 
108
+ if (node.type === 'ConditionalExpression') {
109
+ const consequent = resolveNodeValue(node.consequent);
110
+ const alternate = resolveNodeValue(node.alternate);
111
+
112
+ return consequent || alternate || null;
113
+ }
114
+
115
+ if (node.type === 'LogicalExpression') {
116
+ const left = resolveNodeValue(node.left);
117
+ const right = resolveNodeValue(node.right);
118
+
119
+ return left || right || null;
120
+ }
121
+
108
122
  return null;
109
123
  }
110
124