tldr-lint 0.0.14 → 0.0.16
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 +23 -0
- package/lib/tldr-lint-cli.js +3 -3
- package/lib/tldr-lint.js +8 -0
- package/lib/tldr-parser.js +13 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -33,6 +33,26 @@ Options:
|
|
|
33
33
|
-h, --help display help for command
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
### Usage via Docker
|
|
37
|
+
|
|
38
|
+
We provide a Dockerfile for reproducibly building and testing `tldr-lint` even without having NodeJS installed.
|
|
39
|
+
|
|
40
|
+
For building the Docker image, run this command inside the cloned `tldr-lint` repository:
|
|
41
|
+
|
|
42
|
+
`docker build -t tldr-lint .`
|
|
43
|
+
|
|
44
|
+
For running a `tldr-lint` container, you need to mount a volume containing the page(s) you want to lint to the container.
|
|
45
|
+
For checking a single page, run (replacing `{{/path/to/page.md}}` with the path to the page you want to check):
|
|
46
|
+
|
|
47
|
+
`docker run --rm -v {{/path/to/page.md}}:/app/page.md tldr-lint page.md`
|
|
48
|
+
|
|
49
|
+
In order to run the container on a directory, mount this directory as follows:
|
|
50
|
+
|
|
51
|
+
`docker run --rm -v {{/path/to/directory}}:/app/pages tldr-lint pages/`
|
|
52
|
+
|
|
53
|
+
> [!NOTE]
|
|
54
|
+
> For Windows users, specify the full path to the directory or page you want to check along with the `docker run` command above.
|
|
55
|
+
|
|
36
56
|
## Linter errors
|
|
37
57
|
|
|
38
58
|
All of the errors can be found in [`lib/tldr-lint.js`](./lib/tldr-lint.js).
|
|
@@ -58,6 +78,8 @@ TLDR016 | Label for information link should be spelled exactly `More informa
|
|
|
58
78
|
TLDR017 | Information link should be surrounded with angle brackets
|
|
59
79
|
TLDR018 | Page should only include a single information link
|
|
60
80
|
TLDR019 | Page should only include a maximum of 8 examples
|
|
81
|
+
TLDR020 | Label for additional notes should be spelled exactly `Note:` (with a succeeding whitespace)
|
|
82
|
+
TLDR021 | Command example should not begin or end in whitespace
|
|
61
83
|
TLDR101 | Command description probably not properly annotated
|
|
62
84
|
TLDR102 | Example description probably not properly annotated
|
|
63
85
|
TLDR103 | Command example is missing its closing backtick
|
|
@@ -68,6 +90,7 @@ TLDR107 | File name should end with `.md` extension
|
|
|
68
90
|
TLDR108 | File name should not contain whitespace
|
|
69
91
|
TLDR109 | File name should be lowercase
|
|
70
92
|
TLDR110 | Command example should not be empty
|
|
93
|
+
TLDR111 | File name should not contain any Windows-forbidden character
|
|
71
94
|
|
|
72
95
|
[npm-url]: https://www.npmjs.com/package/tldr-lint
|
|
73
96
|
[npm-image]: https://img.shields.io/npm/v/tldr-lint.svg
|
package/lib/tldr-lint-cli.js
CHANGED
|
@@ -90,10 +90,10 @@ cli.process = function(file, args) {
|
|
|
90
90
|
|
|
91
91
|
if (require.main === module) {
|
|
92
92
|
const { program } = require('commander');
|
|
93
|
-
const
|
|
93
|
+
const pkg = require('../package.json');
|
|
94
94
|
program
|
|
95
|
-
.version(
|
|
96
|
-
.description(
|
|
95
|
+
.version(pkg.version)
|
|
96
|
+
.description(pkg.description)
|
|
97
97
|
.arguments('<file|dir>')
|
|
98
98
|
.option('-f, --format', 'also attempt formatting (to stdout, or as specified by -o)')
|
|
99
99
|
.option('-o, --output <file>', 'output to formatted file')
|
package/lib/tldr-lint.js
CHANGED
|
@@ -25,6 +25,9 @@ module.exports.ERRORS = parser.ERRORS = {
|
|
|
25
25
|
'TLDR017': 'Information link should be surrounded with angle brackets',
|
|
26
26
|
'TLDR018': 'Page should only include a single information link',
|
|
27
27
|
'TLDR019': 'Page should only include a maximum of 8 examples',
|
|
28
|
+
'TLDR020': 'Label for additional notes should be spelled exactly `Note: `',
|
|
29
|
+
'TLDR021': 'Command example should not begin or end in whitespace',
|
|
30
|
+
|
|
28
31
|
|
|
29
32
|
'TLDR101': 'Command description probably not properly annotated',
|
|
30
33
|
'TLDR102': 'Example description probably not properly annotated',
|
|
@@ -36,6 +39,7 @@ module.exports.ERRORS = parser.ERRORS = {
|
|
|
36
39
|
'TLDR108': 'File name should not contain whitespace',
|
|
37
40
|
'TLDR109': 'File name should be lowercase',
|
|
38
41
|
'TLDR110': 'Command example should not be empty',
|
|
42
|
+
'TLDR111': 'File name should not contain any Windows-forbidden character'
|
|
39
43
|
};
|
|
40
44
|
|
|
41
45
|
(function(parser) {
|
|
@@ -209,6 +213,10 @@ linter.processFile = function(file, verbose, alsoFormat, ignoreErrors) {
|
|
|
209
213
|
result.errors.push({ locinfo: { first_line: '0' }, code: 'TLDR109', description: this.ERRORS.TLDR109 });
|
|
210
214
|
}
|
|
211
215
|
|
|
216
|
+
if (/[<>:"/\\|?*]/.test(path.basename(file))) {
|
|
217
|
+
result.errors.push({ locinfo: { first_line: '0' }, code: 'TLDR111', description: this.ERRORS.TLDR111 });
|
|
218
|
+
}
|
|
219
|
+
|
|
212
220
|
if (ignoreErrors) {
|
|
213
221
|
ignoreErrors = ignoreErrors.split(',').map(function(val) {
|
|
214
222
|
return val.trim();
|
package/lib/tldr-parser.js
CHANGED
|
@@ -729,6 +729,9 @@ case 8:
|
|
|
729
729
|
if (!exceptions.includes(yy_.yytext.replace(/ .*/,'')) && yy_.yytext.match(/^[a-z]/)) {
|
|
730
730
|
yy.error(yy_.yylloc, 'TLDR003');
|
|
731
731
|
}
|
|
732
|
+
if (yy_.yytext.match(/(note|NOTE): /)) {
|
|
733
|
+
yy.error(yy_.yylloc, 'TLDR020');
|
|
734
|
+
}
|
|
732
735
|
var punctuation = this.matches[2];
|
|
733
736
|
if (punctuation !== '.') {
|
|
734
737
|
yy.error(yy_.yylloc, 'TLDR004');
|
|
@@ -750,6 +753,9 @@ case 9:
|
|
|
750
753
|
yy_.yytext = this.matches[1];
|
|
751
754
|
if (!yy_.yytext.match(/^[\p{Lu}\[]/u)) yy.error(yy_.yylloc, 'TLDR015');
|
|
752
755
|
if (this.matches[2] !== ':') yy.error(yy_.yylloc, 'TLDR005');
|
|
756
|
+
if (yy_.yytext.match(/(note|NOTE): /)) {
|
|
757
|
+
yy.error(yy_.yylloc, 'TLDR020');
|
|
758
|
+
}
|
|
753
759
|
// Try to ensure that verbs at the beginning of the description are in the infinitive tense
|
|
754
760
|
// 1. Any word at the start of a sentence that ends with "ing" and is 6 or more characters long (e.g. executing, writing) is likely a verb in the gerund
|
|
755
761
|
// 2. Any word at the start of a sentence that doesn't end with "us", "ss", or "ys" (e.g. superfluous, success, always) is likely a verb in the present tense
|
|
@@ -777,6 +783,9 @@ case 10:
|
|
|
777
783
|
break;
|
|
778
784
|
case 11:
|
|
779
785
|
this.pushState('example_command');
|
|
786
|
+
if (this.matches[1].match(/ /)) {
|
|
787
|
+
yy.error(yy_.yylloc, 'TLDR021')
|
|
788
|
+
}
|
|
780
789
|
return 26;
|
|
781
790
|
|
|
782
791
|
break;
|
|
@@ -807,6 +816,9 @@ case 14:
|
|
|
807
816
|
if (this.matches[2].match(/ /)) {
|
|
808
817
|
yy.error(yy_.yylloc, 'TLDR014');
|
|
809
818
|
}
|
|
819
|
+
if (this.matches[1].endsWith(' ') && !this.matches[1].endsWith('\\ ')) {
|
|
820
|
+
yy.error(yy_.yylloc, 'TLDR021');
|
|
821
|
+
}
|
|
810
822
|
// Don't swallow the trailing backtick just yet
|
|
811
823
|
if (this.matches[2].match(/\`/)) this.unput('`');
|
|
812
824
|
else {
|
|
@@ -841,7 +853,7 @@ case 17:
|
|
|
841
853
|
break;
|
|
842
854
|
}
|
|
843
855
|
},
|
|
844
|
-
rules: [/^(?:\s+$)/,/^(?:.*?\t+.*)/,/^(?:[^\n]$)/,/^(?:(\s*)#(\s*))/,/^(?:([\>-])(\s*))/,/^(?:([Mm]ore\s+[Ii]nfo(?:rmation)?:?\s*))/,/^(?:(<https?:\/\/[^\s\>]*>))/,/^(?:(.+?)([ ]*)((?:\r\n)|\n|\r))/,/^(?:(.+?)([\.,;!\?]?)([ ]*)((?:\r\n)|\n|\r))/,/^(?:(.+?)([\.:,;]?)([ ]*)((?:\r\n)|\n|\r))/,/^(?:`((?:\r\n)|\n|\r))/,/^(?:`)/,/^(?:\{\{([^\n\`\{\}]*)\}\}(((?:\r\n)|\n|\r)?))/,/^(?:([^\`\n]+?)\{\{)/,/^(?:([^\`\n]+?)(`[ ]*|[ ]*((?:\r\n)|\n|\r)))/,/^(?:[ ]+)/,/^(?:((?:\r\n)|\n|\r)+)/,/^(?:(.+?)[\.:]?((?:\r\n)|\n|\r))/],
|
|
856
|
+
rules: [/^(?:\s+$)/,/^(?:.*?\t+.*)/,/^(?:[^\n]$)/,/^(?:(\s*)#(\s*))/,/^(?:([\>-])(\s*))/,/^(?:([Mm]ore\s+[Ii]nfo(?:rmation)?:?\s*))/,/^(?:(<https?:\/\/[^\s\>]*>))/,/^(?:(.+?)([ ]*)((?:\r\n)|\n|\r))/,/^(?:(.+?)([\.,;!\?]?)([ ]*)((?:\r\n)|\n|\r))/,/^(?:(.+?)([\.:,;]?)([ ]*)((?:\r\n)|\n|\r))/,/^(?:`((?:\r\n)|\n|\r))/,/^(?:`([ ]*))/,/^(?:\{\{([^\n\`\{\}]*)\}\}(((?:\r\n)|\n|\r)?))/,/^(?:([^\`\n]+?)\{\{)/,/^(?:([^\`\n]+?)(`[ ]*|[ ]*((?:\r\n)|\n|\r)))/,/^(?:[ ]+)/,/^(?:((?:\r\n)|\n|\r)+)/,/^(?:(.+?)[\.:]?((?:\r\n)|\n|\r))/],
|
|
845
857
|
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"inclusive":true}}
|
|
846
858
|
});
|
|
847
859
|
return lexer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tldr-lint",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "A linting tool to validate tldr pages",
|
|
5
5
|
"repository": "tldr-pages/tldr-lint",
|
|
6
6
|
"scripts": {
|
|
@@ -40,9 +40,10 @@
|
|
|
40
40
|
"commander": "^12.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"concurrently": "^
|
|
44
|
-
"eslint": "^
|
|
45
|
-
"eslint-
|
|
43
|
+
"concurrently": "^9.0.0",
|
|
44
|
+
"eslint": "^9.4.0",
|
|
45
|
+
"eslint-config-eslint": "^11.0.0",
|
|
46
|
+
"eslint-plugin-jest": "^28.5.0",
|
|
46
47
|
"husky": "^9.0.6",
|
|
47
48
|
"jest": "^29.1.2",
|
|
48
49
|
"jison": "^0.4.18",
|