ilib-lint 1.2.0 → 1.3.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 +14 -0
- package/README.md.orig +627 -0
- package/docs/AnsiConsoleFormatter.html +2 -2
- package/docs/ConfigBasedFormatter.html +2 -2
- package/docs/DirItem.html +2 -2
- package/docs/DirItem.js.html +2 -2
- package/docs/FileType.html +2 -2
- package/docs/FileType.js.html +2 -2
- package/docs/FormatterManager.html +2 -2
- package/docs/FormatterManager.js.html +2 -2
- package/docs/ParserManager.html +2 -2
- package/docs/ParserManager.js.html +2 -2
- package/docs/PluginManager.html +2 -2
- package/docs/PluginManager.js.html +2 -2
- package/docs/Project.html +2 -2
- package/docs/Project.js.html +2 -2
- package/docs/ResourceICUPlurals.html +2 -2
- package/docs/ResourceMatcher.html +2 -2
- package/docs/ResourceQuoteStyle.html +2 -2
- package/docs/ResourceStateChecker.html +348 -0
- package/docs/ResourceUniqueKeys.html +2 -2
- package/docs/RuleManager.html +2 -2
- package/docs/RuleManager.js.html +2 -2
- package/docs/RuleSet.html +2 -2
- package/docs/RuleSet.js.html +2 -2
- package/docs/SourceFile.html +2 -2
- package/docs/SourceFile.js.html +2 -2
- package/docs/XliffParser.html +2 -2
- package/docs/XliffPlugin.html +2 -2
- package/docs/formatters_AnsiConsoleFormatter.js.html +2 -2
- package/docs/formatters_ConfigBasedFormatter.js.html +2 -2
- package/docs/global.html +2 -2
- package/docs/ilibLint.md +51 -0
- package/docs/index.html +2 -2
- package/docs/plugins_XliffParser.js.html +2 -2
- package/docs/plugins_XliffPlugin.js.html +2 -2
- package/docs/resource-state-checker.md +26 -0
- package/docs/rules_ResourceICUPlurals.js.html +2 -2
- package/docs/rules_ResourceMatcher.js.html +2 -2
- package/docs/rules_ResourceQuoteStyle.js.html +2 -2
- package/docs/rules_ResourceSourceChecker.js.html +2 -2
- package/docs/rules_ResourceStateChecker.js.html +175 -0
- package/docs/rules_ResourceTargetChecker.js.html +2 -2
- package/docs/rules_ResourceUniqueKeys.js.html +2 -2
- package/docs/rules_SourceFileChecker.js.html +2 -2
- package/docs/walk.js.html +2 -2
- package/package.json +2 -3
- package/src/rules/ResourceStateChecker.js +103 -0
package/README.md
CHANGED
|
@@ -333,6 +333,10 @@ The built-in rules are:
|
|
|
333
333
|
string are also used in the translated string
|
|
334
334
|
- resource-unique-key - Ensure that the keys are unique within a locale across
|
|
335
335
|
all resource files
|
|
336
|
+
- resource-state-checker - Ensure that all resources have a particular state
|
|
337
|
+
field value, or one of an array of state field values. The parameter for this
|
|
338
|
+
rule should either be a string or an array of strings that name the allowed
|
|
339
|
+
values.
|
|
336
340
|
|
|
337
341
|
## Writing Plugins
|
|
338
342
|
|
|
@@ -587,6 +591,16 @@ limitations under the License.
|
|
|
587
591
|
|
|
588
592
|
## Release Notes
|
|
589
593
|
|
|
594
|
+
### v1.3.0
|
|
595
|
+
|
|
596
|
+
- added resource-state-checker Rule so that you can ensure that all
|
|
597
|
+
resources have a particular state field value
|
|
598
|
+
|
|
599
|
+
### v1.2.1
|
|
600
|
+
|
|
601
|
+
- fixed packaging problem where the test plugin was listed in the
|
|
602
|
+
dependencies instead of the devDependencies
|
|
603
|
+
|
|
590
604
|
### v1.2.0
|
|
591
605
|
|
|
592
606
|
- added Rule links to give rule writers a way of giving a more complete explanation
|
package/README.md.orig
ADDED
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
# ilib-lint
|
|
2
|
+
|
|
3
|
+
A static analysis linter for many types of source files that looks for i18n problems.
|
|
4
|
+
|
|
5
|
+
This i18n linter differs from other static linters in the following ways:
|
|
6
|
+
|
|
7
|
+
* It can apply different rulesets to different sets of files. This is useful for
|
|
8
|
+
a number of reasons:
|
|
9
|
+
* when linting a mono-repo that has different subprojects inside of it
|
|
10
|
+
and each subproject needs different rules applied to its files
|
|
11
|
+
* when different sets of files need different rulesets, even within the same file type
|
|
12
|
+
* It can handle any file type
|
|
13
|
+
* most linters are specific to a programming language and its related files. This linter
|
|
14
|
+
can read any type of file and apply the appropriate set of rules.
|
|
15
|
+
* Rules can be locale-sensitive
|
|
16
|
+
* most linters apply the same rules blindly to all files, regardless of the locale
|
|
17
|
+
* for resource files, it can apply the appropriate locale for each resource individually
|
|
18
|
+
* It can recognize the locale of files from the path name of files
|
|
19
|
+
* this allows it to apply the locale-sensitive rules automatically. For example, you can apply
|
|
20
|
+
a rule that checks that the translations in a resource file of a plural resource
|
|
21
|
+
contain the correct set of plural categories for the target language.
|
|
22
|
+
* It can load plugins
|
|
23
|
+
* Parsers - you can add parsers for new programming languages or resource file types
|
|
24
|
+
* Formatters - you can make the output look exactly the way you want
|
|
25
|
+
* Rules - you can add new rules declaratively or programmatically
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
npm install ilib-lint
|
|
31
|
+
|
|
32
|
+
or
|
|
33
|
+
|
|
34
|
+
yarn add ilib-lint
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then, in your package.json, add a script:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
"scripts": {
|
|
41
|
+
"lint": "ilib-lint"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Please note: nodejs version 14 or above is required to run this tool, as it
|
|
46
|
+
is written with ESM modules.
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
Running ilib-lint is easy. Just change your directory to the top level directory
|
|
51
|
+
of your project and run it with no parameters and no configuration file. It will
|
|
52
|
+
do all default behaviours and apply the default rules, which for some projects
|
|
53
|
+
is sufficient:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
$ cd myproject
|
|
57
|
+
$ ilib-lint
|
|
58
|
+
ilib-lint - Copyright (c) 2022-2023 JEDLsoft, All rights reserved.
|
|
59
|
+
WARN: i18n/ru_RU.properties(45): translation should use the appropriate
|
|
60
|
+
quote style
|
|
61
|
+
myproject.dialog1.body.text = Нажмите кнопку "Справка", чтобы получить
|
|
62
|
+
дополнительную информацию.
|
|
63
|
+
Rule (locale-quote-style): quote style for the the locale "ru-RU" should
|
|
64
|
+
be «text»
|
|
65
|
+
$
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Default Behaviours
|
|
69
|
+
|
|
70
|
+
The default behaviour is to recursively search the current directory for all
|
|
71
|
+
xliff files, and then apply all of the built-in resource rules to those files
|
|
72
|
+
and report human-readable results to the standard output.
|
|
73
|
+
|
|
74
|
+
The default behaviours are:
|
|
75
|
+
|
|
76
|
+
* Start in the current directory and recursively find all xliff files
|
|
77
|
+
underneath there. The xliff file type is built-in to the linter.
|
|
78
|
+
* All built-in rules will be added to the current rule set, and it will
|
|
79
|
+
instantiate each rule with its default settings.
|
|
80
|
+
* It will use the default set of locales (the top 20 locales on the internet
|
|
81
|
+
by traffic) with "en-US" being the source locale
|
|
82
|
+
* For each file found, it applies each rule in the ruleset.
|
|
83
|
+
If a file type does not have any rulesets that apply to it,
|
|
84
|
+
it will be skipped.
|
|
85
|
+
* the locale of a file can sometimes be gleaned from its path name
|
|
86
|
+
* for some types of resource files, the locale is documented in
|
|
87
|
+
the file itself. (eg. xliff or other resource files)
|
|
88
|
+
* Output will be printed on the standard output in human readable form
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
## Command-line Parameters
|
|
92
|
+
|
|
93
|
+
ilib-lint accepts the following command-line parameters:
|
|
94
|
+
|
|
95
|
+
* help - Print out a help message detailing these command-line parameters
|
|
96
|
+
* config - Give an explicit path to a configuration file instead of trying to
|
|
97
|
+
find it in the current directory.
|
|
98
|
+
* errorsOnly - Only give information on errors, not warnings. Also, only exit
|
|
99
|
+
with status 2 if there are errors, and status 0 if there are warnings. This
|
|
100
|
+
flag allows you to squelch the warnings and only fail a script if there are
|
|
101
|
+
actual errors.
|
|
102
|
+
* locales - Locales you want your app to support globally. Value is a comma-separated
|
|
103
|
+
list of BCP-47 style locale tags. File types can override this list.
|
|
104
|
+
Default: the top 20 locales on the internet by traffic.
|
|
105
|
+
* sourceLocale - locale of the source files or the source locale for resource
|
|
106
|
+
files. Default: "en-US"
|
|
107
|
+
* quiet - Produce no progress output during the run, except for errors running
|
|
108
|
+
the tool such as the inability to load a plugin. Instead exit with a return
|
|
109
|
+
value. Zero indicates no errors, and a positive exit value indicates errors.
|
|
110
|
+
|
|
111
|
+
## Exit Status
|
|
112
|
+
|
|
113
|
+
If you want to use this linter in a script, you can check for the following
|
|
114
|
+
exit status:
|
|
115
|
+
|
|
116
|
+
* 0 - no problems found
|
|
117
|
+
* 1 - warnings found
|
|
118
|
+
* 2 - errors found
|
|
119
|
+
|
|
120
|
+
When the `--errorsOnly` flag is given, the program will return 0 unless at least
|
|
121
|
+
one error was found.
|
|
122
|
+
|
|
123
|
+
## Configuration
|
|
124
|
+
|
|
125
|
+
The paths to process are given on the command-line. If no path is specified
|
|
126
|
+
on the command-line, the tool will default to the current directory.
|
|
127
|
+
If any named path contains a file called `ilib-lint-config.json`, that
|
|
128
|
+
file will be read and processed to configure a project within the ilib-lint tool
|
|
129
|
+
with that path as the root directory for the project.
|
|
130
|
+
|
|
131
|
+
This json config file will be parsed as [JSON5](https://json5.org), which means
|
|
132
|
+
it can contain comments and other nice features that make it easier for humans
|
|
133
|
+
to read and write.
|
|
134
|
+
|
|
135
|
+
The `ilib-lint-config.json` file can have any of the following properties:
|
|
136
|
+
|
|
137
|
+
* name (String, required) - name of this project
|
|
138
|
+
* locales (Array of strings) - that name the default set of locales for the
|
|
139
|
+
whole project if they are not configured by each path
|
|
140
|
+
* sourceLocale (String) - name the locale for source strings in this app.
|
|
141
|
+
Default if not specified is "en-US".
|
|
142
|
+
* excludes (Array of String) - an array of micromatch expressions for files
|
|
143
|
+
or folders in the project to exclude from the recursive search.
|
|
144
|
+
* rules (Array of Object) - an array of declarative regular-expression-based rules to use
|
|
145
|
+
with this project. Resource rules are applied to resources loaded from a
|
|
146
|
+
resource file. Source file rules are applied to regular programming source
|
|
147
|
+
files. Each item in the rules array should be an
|
|
148
|
+
object that contains the following properties, all of which are required:
|
|
149
|
+
* type (String) - the type of this rule. This may be any of the
|
|
150
|
+
following:
|
|
151
|
+
* resource-matcher - check resources in a resource file. The
|
|
152
|
+
regular expressions that match in the
|
|
153
|
+
source strings must also match in the target string
|
|
154
|
+
* resource-source - check resources in a resource file. If
|
|
155
|
+
the regular expressions match in the source string of a
|
|
156
|
+
resource, a result will be generated
|
|
157
|
+
* resource-target - check resources in a resource file. If
|
|
158
|
+
the regular expressions match in the target string of a
|
|
159
|
+
resource, a result will be generated
|
|
160
|
+
* sourcefile - Check the text in a source file, such as a
|
|
161
|
+
java file or a python file. Regular expressions that match
|
|
162
|
+
in the source file will generate results
|
|
163
|
+
* name (String) - a unique dash-separated name of this rule.
|
|
164
|
+
eg. "resource-url-match",
|
|
165
|
+
* description (String) - a description of what this rule is trying
|
|
166
|
+
to do. eg. "Ensure that URLs that appear in the source string are
|
|
167
|
+
also used in the translated string"
|
|
168
|
+
* note (String) - string to use when the regular expression check fails.
|
|
169
|
+
eg. "URL '{matchString}' from the source string does not appear in
|
|
170
|
+
the target string"
|
|
171
|
+
Note that you can use `{matchString}` to show the user the string
|
|
172
|
+
that the regular expression matched in the source but not in the target.
|
|
173
|
+
* regexps (Array.<String>) - an array of regular expressions to match
|
|
174
|
+
in the source and target strings. If any one of those expressions
|
|
175
|
+
matches in the source, but not the target, the rule will create
|
|
176
|
+
a Result that will be formatted for the user.
|
|
177
|
+
* formatters (Array of Object) - a set of declarative formatters. Each array element is
|
|
178
|
+
an object that contains the following properties:
|
|
179
|
+
* name - a unique name for this formatter
|
|
180
|
+
* description - a description of this formatter to show to users
|
|
181
|
+
* template - a template string that shows how the various fields of a Result instance should be
|
|
182
|
+
formatted, plus two extras that come from the rule: ruleName and ruleDescription
|
|
183
|
+
* highlightStart - string to use as the highlight starting marker in the highlight string
|
|
184
|
+
* highlightEnd - string to use as the highlight ending marker in the highlight string
|
|
185
|
+
* rulesets (Object) - configure named sets of rules. Some rules can be shared between
|
|
186
|
+
file types and others are more specific to the file type. As such, it is sometimes
|
|
187
|
+
convenient to to name a set of rules and refer to the whole set by its name instead
|
|
188
|
+
of listing them all out. The properties of the rulesets object are the names of the
|
|
189
|
+
sets, and the values is also a Object that configures each rule that should be
|
|
190
|
+
included in that set. The rules are turned on with a value "true" or with a
|
|
191
|
+
rule-specific option. They are turned off with a falsy value.
|
|
192
|
+
* filetypes (Object) - a set of configurations for various file types. The file types
|
|
193
|
+
are given dash-separated names such as "python-source-files" so that they can be referred
|
|
194
|
+
to in the
|
|
195
|
+
paths object below. Properties in the filetypes object are the name of the file type,
|
|
196
|
+
and the values are an object that gives the settings for that file type. The value
|
|
197
|
+
object can contain any of the following properties:
|
|
198
|
+
* template (String, required) - a template that can be used to parse the
|
|
199
|
+
file name for the locale of that file.
|
|
200
|
+
* locales (Array of String) - a set of locales that override
|
|
201
|
+
the global locales list. If not specified, the file type uses the
|
|
202
|
+
global set of locales.
|
|
203
|
+
* ruleset (String, Array of String, or Object) - name the rule set or
|
|
204
|
+
list of rule sets to use with files of this type if the value is
|
|
205
|
+
a string or an array of strings. When the value is a list of strings,
|
|
206
|
+
the rules are a superset of all of the rules in the named rule sets.
|
|
207
|
+
If the value is an object, then it is considered to be an on-the-fly
|
|
208
|
+
unnamed rule set defined directly.
|
|
209
|
+
* paths (Object) - this maps sets of files to file types. The properties in this
|
|
210
|
+
object are [micromatch](https://github.com/micromatch/micromatch) glob expressions
|
|
211
|
+
that select a subset of files within the current project. The glob expressions
|
|
212
|
+
can only be relative to the root of the project.
|
|
213
|
+
The value of each glob expression property should be either a string that names
|
|
214
|
+
a file type for files that match the glob expression, or an on-the-fly unnamed
|
|
215
|
+
definition of the file type. If you specify the file type directly, it cannot be
|
|
216
|
+
shared with other mappings, so it is usually a good idea to define a named file type
|
|
217
|
+
in the "filetypes" property first.
|
|
218
|
+
|
|
219
|
+
The `ilib-lint-config.json` file can be written in [JSON5](https://github.com/json5/json5)
|
|
220
|
+
syntax, which means it can contain comments and other enhancements.
|
|
221
|
+
|
|
222
|
+
### Example Config File
|
|
223
|
+
|
|
224
|
+
Here is an example of a configuration file:
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
// the name is required and should be unique amongst all your projects
|
|
229
|
+
"name": "tester",
|
|
230
|
+
// this is the global set of locales that applies unless something else overrides it
|
|
231
|
+
"locales": [
|
|
232
|
+
"en-US",
|
|
233
|
+
"de-DE",
|
|
234
|
+
"ja-JP",
|
|
235
|
+
"ko-KR"
|
|
236
|
+
],
|
|
237
|
+
// list of plugins to load
|
|
238
|
+
"plugins": [
|
|
239
|
+
"react"
|
|
240
|
+
],
|
|
241
|
+
// default micromatch expressions to exclude from recursive dir searches
|
|
242
|
+
"excludes": [
|
|
243
|
+
"node_modules/**",
|
|
244
|
+
".git/**",
|
|
245
|
+
"test/**"
|
|
246
|
+
],
|
|
247
|
+
// declarative definitions of new rules
|
|
248
|
+
"rules": [
|
|
249
|
+
// test that named parameters like {param} appear in both the source and target
|
|
250
|
+
{
|
|
251
|
+
"name": "resource-named-params",
|
|
252
|
+
"type": "resource-matcher",
|
|
253
|
+
"description": "Ensure that named parameters that appear in the source string are also used in the translated string",
|
|
254
|
+
"note": "The named parameter '{matchString}' from the source string does not appear in the target string",
|
|
255
|
+
"regexps": [ "\\{\\w+\\}" ],
|
|
256
|
+
"link": "https://github.com/ilib-js/i18nlint/blob/main/README.md"
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
"formatters": [
|
|
260
|
+
{
|
|
261
|
+
"name": "minimal",
|
|
262
|
+
"description": "A minimalistic formatter that only outputs the path and the highlight",
|
|
263
|
+
"template": "{pathName}\n{highlight}\n",
|
|
264
|
+
"highlightStart": ">>",
|
|
265
|
+
"highlightEnd": "<<"
|
|
266
|
+
}
|
|
267
|
+
],
|
|
268
|
+
// named rule sets to be used with the file types
|
|
269
|
+
"rulesets": {
|
|
270
|
+
"react-rules": {
|
|
271
|
+
// this is the declarative rule defined above
|
|
272
|
+
"resource-named-params": true,
|
|
273
|
+
// the "localeOnly" is an option that the quote matcher supports
|
|
274
|
+
// so this both includes the rule in the rule set and instantiates
|
|
275
|
+
// it with the "localeOnly" option
|
|
276
|
+
"resource-quote-matcher": "localeOnly"
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
// defines common settings for a particular types of file
|
|
280
|
+
"filetypes": {
|
|
281
|
+
"json": {
|
|
282
|
+
// override the general locales
|
|
283
|
+
"locales": [
|
|
284
|
+
"en-US",
|
|
285
|
+
"de-DE",
|
|
286
|
+
"ja-JP"
|
|
287
|
+
]
|
|
288
|
+
},
|
|
289
|
+
"javascript": {
|
|
290
|
+
"rulesets": [
|
|
291
|
+
"react-rules"
|
|
292
|
+
]
|
|
293
|
+
},
|
|
294
|
+
"jsx": {
|
|
295
|
+
"rulesets": [
|
|
296
|
+
"react-rules"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
// this maps micromatch path expressions to a file type definition
|
|
301
|
+
"paths": {
|
|
302
|
+
// use the file type defined above
|
|
303
|
+
"src/**/*.json": "json",
|
|
304
|
+
"src/**/*.js": "javascript",
|
|
305
|
+
"src/**/*.jsx": "jsx",
|
|
306
|
+
// define a file type on the fly
|
|
307
|
+
"**/*.xliff": {
|
|
308
|
+
"ruleset": {
|
|
309
|
+
"formatjs-plural-syntax": true,
|
|
310
|
+
"formatjs-plural-categories": true,
|
|
311
|
+
"formatjs-match-substitution-params": true,
|
|
312
|
+
"match-quote-style": "localeOnly"
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Built-in Rules
|
|
320
|
+
|
|
321
|
+
Some generic rules that apply to many types of files are built-in to ilib-lint.
|
|
322
|
+
This apply mostly to resource files, such as XLIFF files.
|
|
323
|
+
|
|
324
|
+
The built-in rules are:
|
|
325
|
+
|
|
326
|
+
- resource-icu-plurals - check for ICU-style plurals. Also works with formatjs
|
|
327
|
+
plurals, as it has the same syntax.
|
|
328
|
+
- resource-quote-style - if the source string has quotes, check that the target
|
|
329
|
+
string also has quotes and that those quotes are appropriate for the locale
|
|
330
|
+
- resource-url-match - if the source string contains references to URLs, check
|
|
331
|
+
that the target string also contains references to the same URLs
|
|
332
|
+
- resource-named-params - Ensure that named parameters that appear in the source
|
|
333
|
+
string are also used in the translated string
|
|
334
|
+
- resource-unique-key - Ensure that the keys are unique within a locale across
|
|
335
|
+
all resource files
|
|
336
|
+
- resource-state-checker - Ensure that all resources have a particular state
|
|
337
|
+
field value, or one of an array of state field values. The parameter for this
|
|
338
|
+
rule should either be a string or an array of strings that name the allowed
|
|
339
|
+
values.
|
|
340
|
+
|
|
341
|
+
## Writing Plugins
|
|
342
|
+
|
|
343
|
+
The linter tool can support plugins that provide parsers, formatters, or rules,
|
|
344
|
+
or any of them at the same time.
|
|
345
|
+
|
|
346
|
+
## Common Code
|
|
347
|
+
|
|
348
|
+
All plugins should import and use the classes in the
|
|
349
|
+
[i18nlint-common](https://github.com/ilib-js/i18nlint-common) package.
|
|
350
|
+
This defines the super classes for each plugin type, as well as a number
|
|
351
|
+
of utility classes and functions.
|
|
352
|
+
|
|
353
|
+
### Linter Plugins
|
|
354
|
+
|
|
355
|
+
Linter plugins are simple wrappers around the parser, formatter, and rule
|
|
356
|
+
plugins, which allow the plugin to define multiple plugins. For example, many
|
|
357
|
+
plugins define multiple related rules at the same time which check for
|
|
358
|
+
different aspects of a string.
|
|
359
|
+
|
|
360
|
+
The linter plugin should override and implement these three methods:
|
|
361
|
+
|
|
362
|
+
- getParsers - return an array of classes that inherit from the Parser class
|
|
363
|
+
- getRules - return an array of classes that inherit from the Rule class
|
|
364
|
+
- getFormatters - return an array of classes that inherit from the Formatter class
|
|
365
|
+
|
|
366
|
+
For rules and formatters, each array entry can be either declarative or
|
|
367
|
+
programmatic. See the descriptions below about declarative and programmatic
|
|
368
|
+
plugins.
|
|
369
|
+
|
|
370
|
+
When returning programmatic plugins, make sure to return the actual class
|
|
371
|
+
itself instead of instances of the class. The linter will need to create
|
|
372
|
+
multiple instances of each class during the run of the program.
|
|
373
|
+
|
|
374
|
+
### Parsers
|
|
375
|
+
|
|
376
|
+
The job of the parser is to convert a source file into an intermediate representation
|
|
377
|
+
that rules can easily digest. There are two standard representations that many
|
|
378
|
+
rules use, but your parser and rules can use their own representation, as
|
|
379
|
+
long as the parser and the rules agree on what that format is. Typically, the
|
|
380
|
+
parser will produce something like an abstract syntax tree (AST) that the rules
|
|
381
|
+
know how to traverse and interpret.
|
|
382
|
+
|
|
383
|
+
The two standard representations are:
|
|
384
|
+
|
|
385
|
+
- resources - the file is converted into a set of Resource instances
|
|
386
|
+
- lines - the file in converted into a simple array of lines
|
|
387
|
+
|
|
388
|
+
The resources representation is intended to represent entries in resource files
|
|
389
|
+
such as xliff files, gnu po files, or java properties files. Each entry in the
|
|
390
|
+
resource file is represented as an instance of one of the standard resource
|
|
391
|
+
classes all defined in the
|
|
392
|
+
[ilib-tools-common](https://github.com/ilib-js/ilib-tools-common)
|
|
393
|
+
project:
|
|
394
|
+
|
|
395
|
+
- ResourceString - the resource is a single string
|
|
396
|
+
- ResourceArray - the resource is an array of strings
|
|
397
|
+
- ResourcePlural - the resource is a plural string
|
|
398
|
+
|
|
399
|
+
The power of a resource file is that resources can contain both a source and a
|
|
400
|
+
target string, so the rules are able to check the source strings against the target
|
|
401
|
+
strings. Regularly, source files only have source strings in them (if any) so
|
|
402
|
+
the target translations cannot be checked.
|
|
403
|
+
|
|
404
|
+
Parsers should extend the `Parser` class from the `i18nlint-common` package. The constructor
|
|
405
|
+
for your class should define the following properties:
|
|
406
|
+
|
|
407
|
+
- `this.name` - a unique name for this parser
|
|
408
|
+
- `this.description` - a description of this type of parser to display to users
|
|
409
|
+
|
|
410
|
+
It should also override the
|
|
411
|
+
[parseData()](https://github.com/iLib-js/i18nlint-common/blob/main/src/Parser.js)
|
|
412
|
+
method which parses a string, and the
|
|
413
|
+
[parse()](https://github.com/iLib-js/i18nlint-common/blob/main/src/Parser.js)
|
|
414
|
+
method, which loads data from the file and then parses it.
|
|
415
|
+
|
|
416
|
+
You can see an example of a parser plugin by looking at the gnu PO file parser at
|
|
417
|
+
[ilib-lint-python-gnu](https://github.com/ilib-js/ilib-lint-python-gnu/blob/main/src/POParser.js).
|
|
418
|
+
That parser interprets a .po file as a resource file and returns a set of
|
|
419
|
+
Resource instances.
|
|
420
|
+
|
|
421
|
+
### Rules
|
|
422
|
+
|
|
423
|
+
Rules interpret the intermediate representation of a file produced by a Parser
|
|
424
|
+
and produce a single
|
|
425
|
+
[Result](https://github.com/iLib-js/i18nlint-common/blob/main/src/Result.js)
|
|
426
|
+
instance, an array of Result instances, one for each problem found, or undefined
|
|
427
|
+
if there are no problems found.
|
|
428
|
+
|
|
429
|
+
There are two types of rules, declarative and programmatic.
|
|
430
|
+
|
|
431
|
+
Declarative rules are simply a list of regular expressions with metadata. The
|
|
432
|
+
linter searches for matches to those regular expressions and produces Result
|
|
433
|
+
instances when found. (Or when they are not found in some cases!)
|
|
434
|
+
|
|
435
|
+
These can be declared in the config file. (See the example config file above.)
|
|
436
|
+
|
|
437
|
+
Each declarative rule should have the following properties:
|
|
438
|
+
|
|
439
|
+
* type (String) - the type of this rule. This may be any of the
|
|
440
|
+
following:
|
|
441
|
+
* resource-matcher - check resources in a resource file. The
|
|
442
|
+
regular expressions that match in the
|
|
443
|
+
source strings must also match in the target string
|
|
444
|
+
* resource-source - check resources in a resource file. If
|
|
445
|
+
the regular expressions match in the source string of a
|
|
446
|
+
resource, a result will be generated
|
|
447
|
+
* resource-target - check resources in a resource file. If
|
|
448
|
+
the regular expressions match in the target string of a
|
|
449
|
+
resource, a result will be generated
|
|
450
|
+
* sourcefile - Check the text in a source file, such as a
|
|
451
|
+
java file or a python file. Regular expressions that match
|
|
452
|
+
in the source file will generate results
|
|
453
|
+
* name (String) - a unique dash-separated name of this rule.
|
|
454
|
+
eg. "resource-url-match",
|
|
455
|
+
* description (String) - a description of what this rule is trying
|
|
456
|
+
to do. eg. "Ensure that URLs that appear in the source string are
|
|
457
|
+
also used in the translated string"
|
|
458
|
+
* note (String) - string to use when the regular expression check fails.
|
|
459
|
+
eg. "URL '{matchString}' from the source string does not appear in
|
|
460
|
+
the target string"
|
|
461
|
+
Note that you can use `{matchString}` to show the user the string
|
|
462
|
+
that the regular expression matched in the source but not in the target.
|
|
463
|
+
* regexps (Array.<String>) - an array of regular expressions to match
|
|
464
|
+
in the source and target strings. If any one of those expressions
|
|
465
|
+
matches in the source, but not the target, the rule will create
|
|
466
|
+
a Result that will be formatted for the user.
|
|
467
|
+
* link (String) - an URL to a website with a more complete explanation
|
|
468
|
+
of the problem that was found and how the problem can be resolved
|
|
469
|
+
and avoided in the future. Often, this is a link to a markdown file
|
|
470
|
+
in the docs folder on the github repo for the plugin, but it can be
|
|
471
|
+
any link you like.
|
|
472
|
+
|
|
473
|
+
Programmatic rules are used when the requirements for the rules are more complicated
|
|
474
|
+
than a simple regular expression string can handle. For example, a rule that checks
|
|
475
|
+
if the target string of a resource has the correct quote style for the target
|
|
476
|
+
locale first needs to look up what the correct quote style even is in
|
|
477
|
+
order to apply the rule.
|
|
478
|
+
|
|
479
|
+
In order to create a rule instance, create a class that extends the
|
|
480
|
+
[Rule](https://github.com/ilib-js/i18nlint-common/blob/main/src/Rule.js)
|
|
481
|
+
class in the [i18nlint-common](https://github.com/ilib-js/i18nlint-common/] project.
|
|
482
|
+
The constructor of this class should define the following properties:
|
|
483
|
+
|
|
484
|
+
- `this.name` - a unique name for this rule
|
|
485
|
+
- `this.description` - a description of this type of rule to display to users
|
|
486
|
+
|
|
487
|
+
There are no rules for what to name your Rule, but the Rules written by the ilib-js
|
|
488
|
+
organization generally follow some conventions. Resource checkers start with
|
|
489
|
+
"resource-" and source file checkers start with "source-". For resource checkers,
|
|
490
|
+
the word "match" is used at the end when checking both the source and target,
|
|
491
|
+
"source" is used at the end when checking only the source string, and "target"
|
|
492
|
+
when checking only the target string. So, "resource-urls-match" is a Rule that
|
|
493
|
+
checks resource files for URLs in both the source and target. You are free to name
|
|
494
|
+
your rules anything you like or to follow the conventions above. The important
|
|
495
|
+
part is that the name should uniquely identify your Rule so that you can use it
|
|
496
|
+
in config files.
|
|
497
|
+
|
|
498
|
+
The rule should also override and implement the getRuleType() method and the
|
|
499
|
+
[match()](https://github.com/iLib-js/i18nlint-common/blob/main/src/Rule.js) method,
|
|
500
|
+
which takes an intermediate representation as a parameter and returns either
|
|
501
|
+
a single Result, an array of Result, or undefined.
|
|
502
|
+
|
|
503
|
+
If you would like to see an example rule plugin, see the definition of
|
|
504
|
+
the built-in ICU plural matcher rule:
|
|
505
|
+
[resource-icu-plurals](https://github.com/ilib-js/i18nlint/blob/main/src/rules/ResourceICUPlurals.js)
|
|
506
|
+
which checks resources to make sure that plurals in source and target strings
|
|
507
|
+
have the correct syntax for ICU and formatjs.
|
|
508
|
+
|
|
509
|
+
### Formatters
|
|
510
|
+
|
|
511
|
+
Formatters transform a [Result object](https://github.com/iLib-js/i18nlint-common/blob/main/src/Result.js) into a format that the consumer can use. For the most part, the consumer
|
|
512
|
+
is a human, so the result should be formatted in text so that the user can read
|
|
513
|
+
it easily. Other times, the consumer is another program, so the result should be
|
|
514
|
+
formatted for easy parsing. Formatters can formats the results in any way necessary.
|
|
515
|
+
|
|
516
|
+
There are two types of formatters, declarative and programmatic.
|
|
517
|
+
|
|
518
|
+
Declarative formatters are simply a template string where properties of the Result
|
|
519
|
+
instances are formatted into it. These can be declared in the config file. (See the
|
|
520
|
+
example config file above.)
|
|
521
|
+
|
|
522
|
+
The template strings may have any of the following fields from the Result instance
|
|
523
|
+
in them:
|
|
524
|
+
|
|
525
|
+
- severity
|
|
526
|
+
- pathName
|
|
527
|
+
- lineNumber
|
|
528
|
+
- source
|
|
529
|
+
- highlight
|
|
530
|
+
- id
|
|
531
|
+
|
|
532
|
+
Additionally, they may have the following fields from the Rule instance in them:
|
|
533
|
+
|
|
534
|
+
- ruleDescription
|
|
535
|
+
- ruleName
|
|
536
|
+
- ruleLink
|
|
537
|
+
|
|
538
|
+
Programmatic formatters are used when the requirements for formatting are more complicated
|
|
539
|
+
than a simple template string can handle. For example, a CSV formatter would have to make
|
|
540
|
+
sure that fields in a CSV file are escaped properly to conform to CSV syntax, and would
|
|
541
|
+
include escaping code in it.
|
|
542
|
+
|
|
543
|
+
In order to create a formatter instance, create a class that extends the
|
|
544
|
+
[Formatter](https://github.com/ilib-js/i18nlint-common/blob/main/src/Formatter.js)
|
|
545
|
+
class in the [i18nlint-common](https://github.com/ilib-js/i18nlint-common/] project.
|
|
546
|
+
The constructor of this class should define the following properties:
|
|
547
|
+
|
|
548
|
+
- `this.name` - a unique name for this formatter
|
|
549
|
+
- `this.description` - a description of this type of formatter to display to users
|
|
550
|
+
- `this.link` - (optional) a link to a web page that gives a more complete explanation
|
|
551
|
+
the the rule and how to resolve the problem it found
|
|
552
|
+
|
|
553
|
+
The formatter should also override and implement the
|
|
554
|
+
[format()](https://github.com/iLib-js/i18nlint-common/blob/main/src/Formatter.js) method,
|
|
555
|
+
which takes a Result instance as a parameter and returns a formatted string.
|
|
556
|
+
|
|
557
|
+
If you would like to look at an example formatter plugin, see the definition of
|
|
558
|
+
the built-in default formatter
|
|
559
|
+
[ansi-console-formatter](https://github.com/ilib-js/i18nlint/blob/main/src/formatters/AnsiConsoleFormatter.js)
|
|
560
|
+
which formats a Result for colorful output on an ANSI console.
|
|
561
|
+
|
|
562
|
+
## Example Plugin
|
|
563
|
+
|
|
564
|
+
You can take a look at the [ilib-lint-python](https://github.com/ilib-js/ilib-lint-python)
|
|
565
|
+
plugin as a working example of ilib-lint plugin. It implements some rules that
|
|
566
|
+
check the various types of substitution parameters that python/django and
|
|
567
|
+
gnu gettext support.
|
|
568
|
+
|
|
569
|
+
Additionally, there is a [sample python project](https://github.com/ilib-js/ilib-samples/lint)
|
|
570
|
+
that uses the ilib-lint-python plugin. It has purposeful errors built into it which
|
|
571
|
+
violate the rules implemented in the plugin so that the linter will produce some output.
|
|
572
|
+
Clone the project, cd to the lint directory, run `npm install`, and then `npm run lint`
|
|
573
|
+
to see the results.
|
|
574
|
+
|
|
575
|
+
## License
|
|
576
|
+
|
|
577
|
+
Copyright © 2022-2023, JEDLSoft
|
|
578
|
+
|
|
579
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
580
|
+
you may not use this file except in compliance with the License.
|
|
581
|
+
You may obtain a copy of the License at
|
|
582
|
+
|
|
583
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
584
|
+
|
|
585
|
+
Unless required by applicable law or agreed to in writing, software
|
|
586
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
587
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
588
|
+
|
|
589
|
+
See the License for the specific language governing permissions and
|
|
590
|
+
limitations under the License.
|
|
591
|
+
|
|
592
|
+
## Release Notes
|
|
593
|
+
|
|
594
|
+
### v1.3.0
|
|
595
|
+
|
|
596
|
+
<<<<<<< HEAD
|
|
597
|
+
- added resource-state-checker Rule so that you can ensure that all
|
|
598
|
+
resources have a particular state field value
|
|
599
|
+
=======
|
|
600
|
+
- moved functionality into Project class
|
|
601
|
+
- main loop moved from index.js into the run() method
|
|
602
|
+
- directory walk function moved to a method of Project
|
|
603
|
+
>>>>>>> 94ea98a (Changes to support source rules)
|
|
604
|
+
|
|
605
|
+
### v1.2.1
|
|
606
|
+
|
|
607
|
+
- fixed packaging problem where the test plugin was listed in the
|
|
608
|
+
dependencies instead of the devDependencies
|
|
609
|
+
|
|
610
|
+
### v1.2.0
|
|
611
|
+
|
|
612
|
+
- added Rule links to give rule writers a way of giving a more complete explanation
|
|
613
|
+
of the rule and how to resolve the problem.
|
|
614
|
+
|
|
615
|
+
### v1.1.0
|
|
616
|
+
|
|
617
|
+
- added support for plugins
|
|
618
|
+
- added count at the end of the output
|
|
619
|
+
- added the --list option to show what things are available to
|
|
620
|
+
put in the config file
|
|
621
|
+
|
|
622
|
+
### v1.0.0
|
|
623
|
+
|
|
624
|
+
- initial version
|
|
625
|
+
- define initial code and default built-in rules
|
|
626
|
+
- this is an ESM-only project, which is why it can only be run with
|
|
627
|
+
nodejs v14+
|