ilib-lint 2.9.2 → 2.10.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/package.json +3 -3
- package/src/LintableFile.js +1 -1
- package/src/Project.js +3 -2
- package/src/formatters/JsonFormatter.js +3 -1
- package/src/plugins/ErrorFilterTransformer.js +10 -3
- package/src/plugins/XliffParser.js +37 -5
- package/src/rules/ResourceCompleteness.js +4 -2
- package/src/rules/ResourceRule.js +1 -1
- package/src/rules/ResourceSourceICUPluralCategories.js +2 -1
- package/src/rules/ResourceSourceICUPluralParams.js +2 -1
- package/src/rules/ResourceSourceICUPluralSyntax.js +2 -1
- package/src/rules/ResourceSourceICUUnexplainedParams.js +3 -2
- package/src/rules/ResourceUniqueKeys.js +2 -2
- package/src/rules/SourceRegexpChecker.js +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilib-lint",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"module": "./src/index.js",
|
|
@@ -72,9 +72,9 @@
|
|
|
72
72
|
"options-parser": "^0.4.0",
|
|
73
73
|
"xml-js": "^1.6.11",
|
|
74
74
|
"ilib-common": "^1.1.6",
|
|
75
|
-
"ilib-lint-common": "^3.
|
|
75
|
+
"ilib-lint-common": "^3.4.0",
|
|
76
76
|
"ilib-locale": "^1.2.4",
|
|
77
|
-
"ilib-tools-common": "^1.
|
|
77
|
+
"ilib-tools-common": "^1.16.0"
|
|
78
78
|
},
|
|
79
79
|
"scripts": {
|
|
80
80
|
"coverage": "pnpm test -- --coverage",
|
package/src/LintableFile.js
CHANGED
package/src/Project.js
CHANGED
|
@@ -668,7 +668,7 @@ class Project extends DirItem {
|
|
|
668
668
|
errorsOnly : this.options.opt.errorsOnly || false
|
|
669
669
|
});
|
|
670
670
|
} else {
|
|
671
|
-
results.
|
|
671
|
+
resultAll = results.map(result => {
|
|
672
672
|
const str = this.formatter.format(result);
|
|
673
673
|
if (str) {
|
|
674
674
|
if (result.severity === "error") {
|
|
@@ -683,7 +683,8 @@ class Project extends DirItem {
|
|
|
683
683
|
}
|
|
684
684
|
}
|
|
685
685
|
}
|
|
686
|
-
|
|
686
|
+
return str;
|
|
687
|
+
}).join("\n");
|
|
687
688
|
|
|
688
689
|
logger.info(`Total Elapse Time: ${String(totalTime)} seconds`);
|
|
689
690
|
logger.info(` ${`Average over`.padEnd(15, ' ')}${`Average over`.padEnd(15, ' ')}${`Average over`.padEnd(15, ' ')}`);
|
|
@@ -70,7 +70,8 @@ class JsonFormatter extends Formatter {
|
|
|
70
70
|
return {
|
|
71
71
|
pathName: result.pathName,
|
|
72
72
|
rule: result.rule.getName(),
|
|
73
|
-
severity: result.severity
|
|
73
|
+
severity: result.severity,
|
|
74
|
+
locale: result.locale
|
|
74
75
|
};
|
|
75
76
|
})
|
|
76
77
|
};
|
|
@@ -86,6 +87,7 @@ class JsonFormatter extends Formatter {
|
|
|
86
87
|
obj[name].stats.lines = fileStats.lines;
|
|
87
88
|
obj[name].stats.bytes = fileStats.bytes;
|
|
88
89
|
obj[name].stats.modules = fileStats.modules;
|
|
90
|
+
obj[name].stats.words = fileStats.words;
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
// write as compressed JSON to save space;
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { IntermediateRepresentation, Transformer, Result } from 'ilib-lint-common';
|
|
22
|
+
import { Resource } from 'ilib-tools-common';
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* Filter out errors from the intermediate representation.
|
|
@@ -46,12 +47,18 @@ class ErrorFilterTransformer extends Transformer {
|
|
|
46
47
|
return ir;
|
|
47
48
|
}
|
|
48
49
|
const resources = ir.getRepresentation();
|
|
49
|
-
const
|
|
50
|
-
|
|
50
|
+
const hashesToExclude = results.filter(result => result.id && result.severity === 'error').
|
|
51
|
+
map(result => [result.id, result.locale, result.pathName].join('_'));
|
|
52
|
+
const filteredResources = resources.filter(/** @type Resource */ resource => {
|
|
53
|
+
const filePath = resource.getResFile() ?? resource.getPath();
|
|
54
|
+
const hash = [resource.getKey(), resource.getTargetLocale(), filePath].join('_');
|
|
55
|
+
return !hashesToExclude.includes(hash);
|
|
56
|
+
});
|
|
51
57
|
return new IntermediateRepresentation({
|
|
52
58
|
type: ir.getType(),
|
|
53
59
|
ir: filteredResources,
|
|
54
|
-
sourceFile: ir.getSourceFile()
|
|
60
|
+
sourceFile: ir.getSourceFile(),
|
|
61
|
+
dirty: (filteredResources.length !== resources.length)
|
|
55
62
|
});
|
|
56
63
|
}
|
|
57
64
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* XliffParser.js - Parser for XLIFF files
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2022-
|
|
4
|
+
* Copyright © 2022-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -17,9 +17,39 @@
|
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { ResourceXliff } from 'ilib-tools-common';
|
|
20
|
+
import { ResourceXliff, Resource } from 'ilib-tools-common';
|
|
21
21
|
import { FileStats, Parser, IntermediateRepresentation, SourceFile } from 'ilib-lint-common';
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Count the number of words in the source strings of the resources.
|
|
25
|
+
* This is a very simple word count that splits the source string
|
|
26
|
+
* on whitespace and counts the number of resulting pieces. We can replace it
|
|
27
|
+
* later with a more sophisticated word count if needed.
|
|
28
|
+
*
|
|
29
|
+
* @param {Array.<Resource>} resources the resources to count words in
|
|
30
|
+
* @returns {Number} the total number of words in the source strings
|
|
31
|
+
*/
|
|
32
|
+
function countSourceWords(resources) {
|
|
33
|
+
return resources.reduce((sum, res) =>
|
|
34
|
+
sum + (res.getSource() ? res.getSource().split(/\s+/).length : 0), 0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Count the number of bytes in the source strings of the resources.
|
|
39
|
+
* This is a simple byte count that counts the number of characters in the
|
|
40
|
+
* source string, assuming that each character is one byte. This is not
|
|
41
|
+
* necessarily accurate for all languages, but it is a good enough approximation
|
|
42
|
+
* for most cases. We can replace it later with a more sophisticated byte count
|
|
43
|
+
* if needed.
|
|
44
|
+
*
|
|
45
|
+
* @param {Array.<Resource>} resources the resources to count bytes in
|
|
46
|
+
* @returns {Number} the total number of bytes in the source strings
|
|
47
|
+
*/
|
|
48
|
+
function countSourceBytes(resources) {
|
|
49
|
+
return resources.reduce((sum, res) =>
|
|
50
|
+
sum + (res.getSource() ? res.getSource().length : 0), 0);
|
|
51
|
+
}
|
|
52
|
+
|
|
23
53
|
/**
|
|
24
54
|
* @class Parser for XLIFF files based on the ilib-xliff library.
|
|
25
55
|
*/
|
|
@@ -49,15 +79,17 @@ class XliffParser extends Parser {
|
|
|
49
79
|
});
|
|
50
80
|
|
|
51
81
|
xliff.parse(data);
|
|
52
|
-
const resources = xliff.getResources();
|
|
82
|
+
const resources = xliff.getResources() ?? [];
|
|
53
83
|
return [new IntermediateRepresentation({
|
|
54
84
|
type: "resource",
|
|
55
85
|
ir: resources,
|
|
56
86
|
sourceFile,
|
|
57
87
|
stats: new FileStats({
|
|
58
88
|
lines: xliff.getLines(),
|
|
59
|
-
|
|
60
|
-
|
|
89
|
+
files: 1,
|
|
90
|
+
bytes: countSourceBytes(resources),
|
|
91
|
+
modules: resources.length,
|
|
92
|
+
words: countSourceWords(resources)
|
|
61
93
|
})
|
|
62
94
|
})];
|
|
63
95
|
}
|
|
@@ -66,7 +66,8 @@ class ResourceCompleteness extends ResourceRule {
|
|
|
66
66
|
return new Result({
|
|
67
67
|
...resultMetaProps,
|
|
68
68
|
severity: "error",
|
|
69
|
-
description: "Missing target string in resource"
|
|
69
|
+
description: "Missing target string in resource",
|
|
70
|
+
locale: resource.getTargetLocale()
|
|
70
71
|
});
|
|
71
72
|
}
|
|
72
73
|
// if there's an extra translation string for which there is no source, just warn
|
|
@@ -75,7 +76,8 @@ class ResourceCompleteness extends ResourceRule {
|
|
|
75
76
|
...resultMetaProps,
|
|
76
77
|
severity: "warning",
|
|
77
78
|
description: "Extra target string in resource",
|
|
78
|
-
highlight: `<e0>${target}</e0
|
|
79
|
+
highlight: `<e0>${target}</e0>`,
|
|
80
|
+
locale: resource.getTargetLocale()
|
|
79
81
|
});
|
|
80
82
|
}
|
|
81
83
|
else return /* no error */;
|
|
@@ -25,7 +25,7 @@ import { Rule } from 'ilib-lint-common';
|
|
|
25
25
|
class ResourceRule extends Rule {
|
|
26
26
|
/**
|
|
27
27
|
* Construct a new resource checker rule.
|
|
28
|
-
*
|
|
28
|
+
*
|
|
29
29
|
* If a subclass defines a property "locales" with the
|
|
30
30
|
* value being a Set of locale lang-specs, then this
|
|
31
31
|
* class will ensure that the rule is only applied to
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* ResourceSourceICUPluralCategories.js
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2023-
|
|
4
|
+
* Copyright © 2023-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -116,6 +116,7 @@ export class ResourceSourceICUPluralCategories extends ResourceRule {
|
|
|
116
116
|
highlight: `<e0>${this.substringForLocation(source, partialResult.location)}</e0>`,
|
|
117
117
|
severity: partialResult.severity,
|
|
118
118
|
description: partialResult.description,
|
|
119
|
+
locale: resource.getTargetLocale(),
|
|
119
120
|
})
|
|
120
121
|
)
|
|
121
122
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* ResourceSourceICUPluralParams.js
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2023-
|
|
4
|
+
* Copyright © 2023-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -117,6 +117,7 @@ export class ResourceSourceICUPluralParams extends ResourceRule {
|
|
|
117
117
|
highlight: `<e0>${this.substringForLocation(source, partialResult.location)}</e0>`,
|
|
118
118
|
severity: partialResult.severity,
|
|
119
119
|
description: partialResult.description,
|
|
120
|
+
locale: resource.getTargetLocale(),
|
|
120
121
|
});
|
|
121
122
|
}
|
|
122
123
|
return undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* ResourceSourceICUPluralSyntax.js
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2023-
|
|
4
|
+
* Copyright © 2023-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -74,6 +74,7 @@ export class ResourceSourceICUPluralSyntax extends ResourceRule {
|
|
|
74
74
|
id: resource.getKey(),
|
|
75
75
|
pathName: file,
|
|
76
76
|
lineNumber,
|
|
77
|
+
locale: resource.getSourceLocale(),
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
return undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* ResourceSourceICUUnexplainedParams.js
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2023-
|
|
4
|
+
* Copyright © 2023-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -136,7 +136,8 @@ export class ResourceSourceICUUnexplainedParams extends ResourceRule {
|
|
|
136
136
|
source: source,
|
|
137
137
|
severity: "warning",
|
|
138
138
|
description: `Replacement parameter "${name}" is not mentioned in the string's comment for translators.`,
|
|
139
|
-
highlight: this.highlightLocation(source, location)
|
|
139
|
+
highlight: this.highlightLocation(source, location),
|
|
140
|
+
locale: resource.getTargetLocale()
|
|
140
141
|
})
|
|
141
142
|
);
|
|
142
143
|
}
|
|
@@ -64,12 +64,13 @@ class ResourceUniqueKeys extends Rule {
|
|
|
64
64
|
|
|
65
65
|
if (other) {
|
|
66
66
|
logger.trace(`hash '${hash}' already found in the translation set!`);
|
|
67
|
+
const otherFile = other.getResFile() ?? other.getPath();
|
|
67
68
|
let value = {
|
|
68
69
|
severity: "error",
|
|
69
70
|
id: resource.getKey(),
|
|
70
71
|
rule: this,
|
|
71
72
|
pathName: file,
|
|
72
|
-
highlight: `Key is also defined in this file: ${
|
|
73
|
+
highlight: `Key is also defined in this file: ${otherFile}`,
|
|
73
74
|
description: `Key is not unique within locale ${locale}.`,
|
|
74
75
|
locale
|
|
75
76
|
};
|
|
@@ -79,7 +80,6 @@ class ResourceUniqueKeys extends Rule {
|
|
|
79
80
|
return new Result(value);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
resource.resfile = file;
|
|
83
83
|
this.ts.add(resource);
|
|
84
84
|
|
|
85
85
|
// no result
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* SourceRegexpChecker.js - rule to check if regexps match in the source
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2023-
|
|
4
|
+
* Copyright © 2023-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -126,7 +126,8 @@ class SourceRegexpChecker extends Rule {
|
|
|
126
126
|
pathName: ir.getSourceFile().getPath(),
|
|
127
127
|
highlight: snippet,
|
|
128
128
|
description: this.note.replace(/\{matchString\}/g, match[0]),
|
|
129
|
-
lineNumber
|
|
129
|
+
lineNumber,
|
|
130
|
+
locale: ir.getSourceFile().sourceLocale || this.sourceLocale
|
|
130
131
|
}));
|
|
131
132
|
match = re.exec(src);
|
|
132
133
|
}
|