@zimbra/eslint-config 0.0.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.
@@ -0,0 +1,47 @@
1
+ export default {
2
+ meta: {
3
+ type: 'problem',
4
+ docs: {
5
+ description:
6
+ 'Disallow direct import of es-toolkit/compat/memoize or es-toolkit/memoize; use createLRUMemoize',
7
+ recommended: true
8
+ },
9
+ fixable: null,
10
+ messages: {
11
+ useCreateLRU:
12
+ "Do not import es-toolkit/compat/memoize or es-toolkit/memoize; directly. Use 'createLRUMemoize' instead."
13
+ },
14
+ schema: []
15
+ },
16
+
17
+ create(context) {
18
+ // List of disallowed modules
19
+ const disallowedModules = ['es-toolkit/compat/memoize', 'es-toolkit/memoize'];
20
+
21
+ return {
22
+ ImportDeclaration(node) {
23
+ if (disallowedModules.includes(node.source.value)) {
24
+ context.report({
25
+ node,
26
+ messageId: 'useCreateLRU',
27
+ data: { module: node.source.value }
28
+ });
29
+ }
30
+ },
31
+
32
+ CallExpression(node) {
33
+ if (
34
+ node.callee.name === 'require' &&
35
+ node.arguments[0] &&
36
+ disallowedModules.includes(node.arguments[0].value)
37
+ ) {
38
+ context.report({
39
+ node,
40
+ messageId: 'useCreateLRU',
41
+ data: { module: node.arguments[0].value }
42
+ });
43
+ }
44
+ }
45
+ };
46
+ }
47
+ };
@@ -0,0 +1,200 @@
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
3
+
4
+ const configUrl = import.meta.url;
5
+ const intlPath = process.env.ESLINT_INTL_PATH ?? 'src/intl';
6
+ const PRIMARY_LANGUAGE = 'en_US.json';
7
+ const __filename = fileURLToPath(configUrl);
8
+ const __dirname = path.dirname(__filename);
9
+ const CUSTOM_SORT_PATH = path.join(__dirname, '../../scripts/intl/lint-custom-sort.cjs');
10
+
11
+ // i18n-json rules
12
+ export const i18nJsonRules = {
13
+ 'i18n-json/sorted-keys': [
14
+ 'error',
15
+ {
16
+ sortFunctionPath: CUSTOM_SORT_PATH
17
+ }
18
+ ],
19
+ 'i18n-json/identical-keys': [
20
+ 'error',
21
+ {
22
+ filePath: path.resolve(path.join(intlPath, PRIMARY_LANGUAGE))
23
+ }
24
+ ]
25
+ };
26
+
27
+ // Preact i18n rules
28
+ export const i18nRules = {
29
+ 'preact-i18n/no-missing-template-field': 'error',
30
+ 'preact-i18n/no-text-as-attribute': 'error',
31
+ 'preact-i18n/no-text-as-children': [
32
+ 'error',
33
+ { ignoreTextRegex: '^(?:\\s*[()🚩.":<>\\-/]\\s*)*$' }
34
+ ],
35
+ 'preact-i18n/no-unknown-key': 'error'
36
+ };
37
+
38
+ export const LANGUAGE_FILES_RELATIVE = [
39
+ {
40
+ name: 'ar',
41
+ filename: 'ar.json'
42
+ },
43
+ {
44
+ name: 'bg',
45
+ filename: 'bg.json'
46
+ },
47
+ {
48
+ name: 'ca',
49
+ filename: 'ca.json'
50
+ },
51
+ {
52
+ name: 'cs',
53
+ filename: 'cs.json'
54
+ },
55
+ {
56
+ name: 'da',
57
+ filename: 'da.json'
58
+ },
59
+ {
60
+ name: 'de',
61
+ filename: 'de.json'
62
+ },
63
+ {
64
+ name: 'en_US',
65
+ filename: 'en_US.json'
66
+ },
67
+ {
68
+ name: 'es',
69
+ filename: 'es.json'
70
+ },
71
+ {
72
+ name: 'eu',
73
+ filename: 'eu.json'
74
+ },
75
+ {
76
+ name: 'fr_FR',
77
+ filename: 'fr_FR.json'
78
+ },
79
+ {
80
+ name: 'fr_CA',
81
+ filename: 'fr_CA.json'
82
+ },
83
+ {
84
+ name: 'hi',
85
+ filename: 'hi.json'
86
+ },
87
+ {
88
+ name: 'hr',
89
+ filename: 'hr.json'
90
+ },
91
+ {
92
+ name: 'hu',
93
+ filename: 'hu.json'
94
+ },
95
+ {
96
+ name: 'id',
97
+ filename: 'id.json'
98
+ },
99
+ {
100
+ name: 'it',
101
+ filename: 'it.json'
102
+ },
103
+ {
104
+ name: 'ja',
105
+ filename: 'ja.json'
106
+ },
107
+ {
108
+ name: 'ko',
109
+ filename: 'ko.json'
110
+ },
111
+ {
112
+ name: 'lo',
113
+ filename: 'lo.json'
114
+ },
115
+ {
116
+ name: 'ms',
117
+ filename: 'ms.json'
118
+ },
119
+ {
120
+ name: 'nl',
121
+ filename: 'nl.json'
122
+ },
123
+ {
124
+ name: 'nn_NO',
125
+ filename: 'nn_NO.json'
126
+ },
127
+ {
128
+ name: 'pl',
129
+ filename: 'pl.json'
130
+ },
131
+ {
132
+ name: 'pt_BR',
133
+ filename: 'pt_BR.json'
134
+ },
135
+ {
136
+ name: 'pt',
137
+ filename: 'pt.json'
138
+ },
139
+ {
140
+ name: 'ro',
141
+ filename: 'ro.json'
142
+ },
143
+ {
144
+ name: 'ru',
145
+ filename: 'ru.json'
146
+ },
147
+ {
148
+ name: 'sk',
149
+ filename: 'sk.json'
150
+ },
151
+ {
152
+ name: 'sl',
153
+ filename: 'sl.json'
154
+ },
155
+ {
156
+ name: 'sv',
157
+ filename: 'sv.json'
158
+ },
159
+ {
160
+ name: 'ta',
161
+ filename: 'ta.json'
162
+ },
163
+ {
164
+ name: 'th',
165
+ filename: 'th.json'
166
+ },
167
+ {
168
+ name: 'tr',
169
+ filename: 'tr.json'
170
+ },
171
+ {
172
+ name: 'uk',
173
+ filename: 'uk.json'
174
+ },
175
+ {
176
+ name: 'vi',
177
+ filename: 'vi.json'
178
+ },
179
+ {
180
+ name: 'zh_CN',
181
+ filename: 'zh_CN.json'
182
+ },
183
+ {
184
+ name: 'zh_HK',
185
+ filename: 'zh_HK.json'
186
+ },
187
+ {
188
+ name: 'zh_TW',
189
+ filename: 'zh_TW.json'
190
+ }
191
+ ];
192
+
193
+ // Global settings for text component recognition
194
+ export const i18nTextComponents = [
195
+ { nameRegex: '^Text$' },
196
+ { nameRegex: '^TextInput$', id: 'placeholderId' },
197
+ { nameRegex: '^AlignedLabel$', id: 'textId' },
198
+ { nameRegex: '^(?:Inline)?Modal(?:Dialog|Drawer)', id: 'title' },
199
+ { nameRegex: '^ContactSuggestion$', id: 'previouslySelectedLabel' }
200
+ ];
@@ -0,0 +1,8 @@
1
+ export const importRules = {
2
+ 'import/no-unresolved': 'off',
3
+
4
+ // TODO: Enable these rules once the codebase is updated to follow best practices
5
+ 'import/no-named-as-default': 'off'
6
+ };
7
+
8
+ export default importRules;
@@ -0,0 +1,11 @@
1
+ import tsParser from '@typescript-eslint/parser';
2
+
3
+ export default {
4
+ parser: tsParser,
5
+ sourceType: 'module',
6
+ ecmaVersion: 'latest',
7
+ parserOptions: {
8
+ requireConfigFile: false,
9
+ ecmaFeatures: { jsx: true }
10
+ }
11
+ };
@@ -0,0 +1,11 @@
1
+ export default {
2
+ 'prettier/prettier': [
3
+ 'error',
4
+ {
5
+ singleQuote: true,
6
+ printWidth: 100,
7
+ trailingComma: 'none',
8
+ arrowParens: 'avoid'
9
+ }
10
+ ]
11
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ // TODO: Enable these rules once the codebase is updated to follow best practices
3
+ 'react-hooks/refs': 'off',
4
+ 'react-hooks/immutability': 'off'
5
+ };
@@ -0,0 +1,24 @@
1
+ export const reactRules = {
2
+ 'react/prop-types': 'off',
3
+ 'react/no-did-mount-set-state': 'error',
4
+ 'react/no-did-update-set-state': 'error',
5
+ 'react/prefer-stateless-function': 'error',
6
+ 'react/jsx-fragments': ['error', 'element'],
7
+ 'react/jsx-no-useless-fragment': 'error',
8
+ 'react/display-name': ['error', { ignoreTranspilerName: false }],
9
+ 'react/no-find-dom-node': 'error',
10
+ 'react/no-is-mounted': 'error',
11
+ 'react/require-render-return': 'error',
12
+ 'react/jsx-no-bind': ['error', { ignoreRefs: true }],
13
+ 'react/jsx-no-comment-textnodes': 'error',
14
+ 'react/jsx-no-duplicate-props': 'error',
15
+ 'react/jsx-pascal-case': 'error',
16
+
17
+ // TODO: Enable these rules once the codebase is updated to follow best practices
18
+ 'react/react-in-jsx-scope': 'off',
19
+ 'react/jsx-key': 'off',
20
+ 'react/no-string-refs': 'off',
21
+ 'react/no-unknown-property': 'off'
22
+ };
23
+
24
+ export default reactRules;
@@ -0,0 +1,12 @@
1
+ export const styleRules = {
2
+ // TODO: Fully enable this rule once the codebase is updated to follow best practices
3
+ 'no-unused-vars': [
4
+ 'error',
5
+ { vars: 'all', args: 'after-used', ignoreRestSiblings: true, caughtErrors: 'none' }
6
+ ],
7
+ 'no-empty': 'off',
8
+ 'no-empty-pattern': 'off',
9
+ 'no-unsafe-optional-chaining': 'off'
10
+ };
11
+
12
+ export default styleRules;
@@ -0,0 +1,7 @@
1
+ export default {
2
+ '@typescript-eslint/no-explicit-any': 'off',
3
+ '@typescript-eslint/no-empty-object-type': 'off',
4
+ '@typescript-eslint/no-unused-expressions': 'off',
5
+ '@typescript-eslint/no-unsafe-function-type': 'off',
6
+ '@typescript-eslint/no-unused-vars': 'off'
7
+ };
@@ -0,0 +1,3 @@
1
+ import tsEslintConfig from './configs/ts-eslint-config.js';
2
+
3
+ export { tsEslintConfig };