@mark1russell7/ste-lint 0.0.0-stage → 0.1.2
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 +246 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-core.d.ts +92 -0
- package/dist/config-core.d.ts.map +1 -0
- package/dist/config-core.js +198 -0
- package/dist/config-core.js.map +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +68 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +16 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +16 -0
- package/dist/core.js.map +1 -0
- package/dist/dictionary-core.d.ts +72 -0
- package/dist/dictionary-core.d.ts.map +1 -0
- package/dist/dictionary-core.js +150 -0
- package/dist/dictionary-core.js.map +1 -0
- package/dist/dictionary.d.ts +9 -0
- package/dist/dictionary.d.ts.map +1 -0
- package/dist/dictionary.js +26 -0
- package/dist/dictionary.js.map +1 -0
- package/dist/engine.d.ts +44 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +122 -0
- package/dist/engine.js.map +1 -0
- package/dist/files.d.ts +35 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +181 -0
- package/dist/files.js.map +1 -0
- package/dist/format.d.ts +21 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +61 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lexicon.d.ts +33 -0
- package/dist/lexicon.d.ts.map +1 -0
- package/dist/lexicon.js +71 -0
- package/dist/lexicon.js.map +1 -0
- package/dist/lint.d.ts +18 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +23 -0
- package/dist/lint.js.map +1 -0
- package/dist/rules/about-quantity.d.ts +3 -0
- package/dist/rules/about-quantity.d.ts.map +1 -0
- package/dist/rules/about-quantity.js +34 -0
- package/dist/rules/about-quantity.js.map +1 -0
- package/dist/rules/index.d.ts +8 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +35 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/ing-verb.d.ts +9 -0
- package/dist/rules/ing-verb.d.ts.map +1 -0
- package/dist/rules/ing-verb.js +60 -0
- package/dist/rules/ing-verb.js.map +1 -0
- package/dist/rules/latin-abbreviation.d.ts +3 -0
- package/dist/rules/latin-abbreviation.d.ts.map +1 -0
- package/dist/rules/latin-abbreviation.js +48 -0
- package/dist/rules/latin-abbreviation.js.map +1 -0
- package/dist/rules/missing-subject.d.ts +16 -0
- package/dist/rules/missing-subject.d.ts.map +1 -0
- package/dist/rules/missing-subject.js +138 -0
- package/dist/rules/missing-subject.js.map +1 -0
- package/dist/rules/modal-verb.d.ts +3 -0
- package/dist/rules/modal-verb.d.ts.map +1 -0
- package/dist/rules/modal-verb.js +72 -0
- package/dist/rules/modal-verb.js.map +1 -0
- package/dist/rules/noun-cluster.d.ts +17 -0
- package/dist/rules/noun-cluster.d.ts.map +1 -0
- package/dist/rules/noun-cluster.js +83 -0
- package/dist/rules/noun-cluster.js.map +1 -0
- package/dist/rules/paragraph-length.d.ts +3 -0
- package/dist/rules/paragraph-length.d.ts.map +1 -0
- package/dist/rules/paragraph-length.js +19 -0
- package/dist/rules/paragraph-length.js.map +1 -0
- package/dist/rules/passive-instruction.d.ts +15 -0
- package/dist/rules/passive-instruction.d.ts.map +1 -0
- package/dist/rules/passive-instruction.js +38 -0
- package/dist/rules/passive-instruction.js.map +1 -0
- package/dist/rules/pronouns.d.ts +4 -0
- package/dist/rules/pronouns.d.ts.map +1 -0
- package/dist/rules/pronouns.js +57 -0
- package/dist/rules/pronouns.js.map +1 -0
- package/dist/rules/rule.d.ts +46 -0
- package/dist/rules/rule.d.ts.map +1 -0
- package/dist/rules/rule.js +31 -0
- package/dist/rules/rule.js.map +1 -0
- package/dist/rules/semicolon.d.ts +3 -0
- package/dist/rules/semicolon.d.ts.map +1 -0
- package/dist/rules/semicolon.js +20 -0
- package/dist/rules/semicolon.js.map +1 -0
- package/dist/rules/sentence-length.d.ts +3 -0
- package/dist/rules/sentence-length.d.ts.map +1 -0
- package/dist/rules/sentence-length.js +31 -0
- package/dist/rules/sentence-length.js.map +1 -0
- package/dist/rules/unknown-word.d.ts +9 -0
- package/dist/rules/unknown-word.d.ts.map +1 -0
- package/dist/rules/unknown-word.js +49 -0
- package/dist/rules/unknown-word.js.map +1 -0
- package/dist/rules/word-list-matcher.d.ts +25 -0
- package/dist/rules/word-list-matcher.d.ts.map +1 -0
- package/dist/rules/word-list-matcher.js +60 -0
- package/dist/rules/word-list-matcher.js.map +1 -0
- package/dist/rules/word-list.d.ts +3 -0
- package/dist/rules/word-list.d.ts.map +1 -0
- package/dist/rules/word-list.js +26 -0
- package/dist/rules/word-list.js.map +1 -0
- package/dist/run-cli.d.ts +27 -0
- package/dist/run-cli.d.ts.map +1 -0
- package/dist/run-cli.js +176 -0
- package/dist/run-cli.js.map +1 -0
- package/dist/source/blocks.d.ts +55 -0
- package/dist/source/blocks.d.ts.map +1 -0
- package/dist/source/blocks.js +464 -0
- package/dist/source/blocks.js.map +1 -0
- package/dist/source/code.d.ts +9 -0
- package/dist/source/code.d.ts.map +1 -0
- package/dist/source/code.js +16 -0
- package/dist/source/code.js.map +1 -0
- package/dist/source/inline.d.ts +42 -0
- package/dist/source/inline.d.ts.map +1 -0
- package/dist/source/inline.js +396 -0
- package/dist/source/inline.js.map +1 -0
- package/dist/source/jsx.d.ts +18 -0
- package/dist/source/jsx.d.ts.map +1 -0
- package/dist/source/jsx.js +137 -0
- package/dist/source/jsx.js.map +1 -0
- package/dist/source/lines.d.ts +34 -0
- package/dist/source/lines.d.ts.map +1 -0
- package/dist/source/lines.js +83 -0
- package/dist/source/lines.js.map +1 -0
- package/dist/source/markdown.d.ts +23 -0
- package/dist/source/markdown.d.ts.map +1 -0
- package/dist/source/markdown.js +42 -0
- package/dist/source/markdown.js.map +1 -0
- package/dist/source/suppressions.d.ts +38 -0
- package/dist/source/suppressions.d.ts.map +1 -0
- package/dist/source/suppressions.js +69 -0
- package/dist/source/suppressions.js.map +1 -0
- package/dist/source/tsdoc.d.ts +40 -0
- package/dist/source/tsdoc.d.ts.map +1 -0
- package/dist/source/tsdoc.js +176 -0
- package/dist/source/tsdoc.js.map +1 -0
- package/dist/text/grammar.d.ts +91 -0
- package/dist/text/grammar.d.ts.map +1 -0
- package/dist/text/grammar.js +289 -0
- package/dist/text/grammar.js.map +1 -0
- package/dist/text/phrases.d.ts +30 -0
- package/dist/text/phrases.d.ts.map +1 -0
- package/dist/text/phrases.js +65 -0
- package/dist/text/phrases.js.map +1 -0
- package/dist/text/sentences.d.ts +45 -0
- package/dist/text/sentences.d.ts.map +1 -0
- package/dist/text/sentences.js +141 -0
- package/dist/text/sentences.js.map +1 -0
- package/dist/text/tokens.d.ts +35 -0
- package/dist/text/tokens.d.ts.map +1 -0
- package/dist/text/tokens.js +113 -0
- package/dist/text/tokens.js.map +1 -0
- package/dist/text/words.d.ts +58 -0
- package/dist/text/words.d.ts.map +1 -0
- package/dist/text/words.js +159 -0
- package/dist/text/words.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/dist/units.d.ts +47 -0
- package/dist/units.d.ts.map +1 -0
- package/dist/units.js +42 -0
- package/dist/units.js.map +1 -0
- package/dist/word-list.d.ts +34 -0
- package/dist/word-list.d.ts.map +1 -0
- package/dist/word-list.js +90 -0
- package/dist/word-list.js.map +1 -0
- package/package.json +54 -3
- package/src/cli.ts +9 -0
- package/src/config-core.ts +258 -0
- package/src/config.test.ts +188 -0
- package/src/config.ts +83 -0
- package/src/core.test.ts +87 -0
- package/src/core.ts +32 -0
- package/src/dictionary-core.ts +158 -0
- package/src/dictionary.test.ts +82 -0
- package/src/dictionary.ts +26 -0
- package/src/engine.ts +138 -0
- package/src/files.test.ts +107 -0
- package/src/files.ts +191 -0
- package/src/format.ts +78 -0
- package/src/index.test.ts +28 -0
- package/src/index.ts +38 -0
- package/src/lexicon.ts +92 -0
- package/src/lint.test.ts +182 -0
- package/src/lint.ts +30 -0
- package/src/rules/about-quantity.ts +33 -0
- package/src/rules/index.ts +40 -0
- package/src/rules/ing-verb.test.ts +48 -0
- package/src/rules/ing-verb.ts +54 -0
- package/src/rules/latin-abbreviation.ts +46 -0
- package/src/rules/missing-subject.test.ts +53 -0
- package/src/rules/missing-subject.ts +129 -0
- package/src/rules/modal-verb.test.ts +45 -0
- package/src/rules/modal-verb.ts +72 -0
- package/src/rules/noun-cluster.test.ts +49 -0
- package/src/rules/noun-cluster.ts +82 -0
- package/src/rules/paragraph-length.test.ts +30 -0
- package/src/rules/paragraph-length.ts +19 -0
- package/src/rules/passive-instruction.test.ts +38 -0
- package/src/rules/passive-instruction.ts +37 -0
- package/src/rules/pronouns.test.ts +38 -0
- package/src/rules/pronouns.ts +54 -0
- package/src/rules/punctuation.test.ts +59 -0
- package/src/rules/rule.ts +73 -0
- package/src/rules/semicolon.ts +19 -0
- package/src/rules/sentence-length.test.ts +52 -0
- package/src/rules/sentence-length.ts +32 -0
- package/src/rules/unknown-word.test.ts +81 -0
- package/src/rules/unknown-word.ts +43 -0
- package/src/rules/word-list-matcher.ts +68 -0
- package/src/rules/word-list.test.ts +110 -0
- package/src/rules/word-list.ts +25 -0
- package/src/run-cli.test.ts +189 -0
- package/src/run-cli.ts +193 -0
- package/src/source/blocks.ts +534 -0
- package/src/source/code.ts +17 -0
- package/src/source/inline.test.ts +92 -0
- package/src/source/inline.ts +416 -0
- package/src/source/jsx.test.ts +46 -0
- package/src/source/jsx.ts +147 -0
- package/src/source/lines.test.ts +51 -0
- package/src/source/lines.ts +91 -0
- package/src/source/markdown.test.ts +210 -0
- package/src/source/markdown.ts +49 -0
- package/src/source/suppressions.ts +79 -0
- package/src/source/tsdoc.test.ts +137 -0
- package/src/source/tsdoc.ts +189 -0
- package/src/text/grammar.ts +304 -0
- package/src/text/phrases.ts +72 -0
- package/src/text/sentences.ts +148 -0
- package/src/text/text.test.ts +262 -0
- package/src/text/tokens.ts +135 -0
- package/src/text/words.ts +183 -0
- package/src/types.ts +39 -0
- package/src/units.ts +86 -0
- package/src/word-list.ts +128 -0
- package/ste.config.schema.json +87 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The local dictionary file. The format and the lookup are in
|
|
3
|
+
* `dictionary-core.ts`, which a browser can use. This module reads the file.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { DictionaryError, parseDictionary } from "./dictionary-core.js";
|
|
7
|
+
export * from "./dictionary-core.js";
|
|
8
|
+
/** This function reads a dictionary file. */
|
|
9
|
+
export function loadDictionary(path) {
|
|
10
|
+
let text;
|
|
11
|
+
try {
|
|
12
|
+
text = readFileSync(path, "utf8");
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new DictionaryError(`Cannot read the dictionary file ${path}: ${error.message}`);
|
|
16
|
+
}
|
|
17
|
+
let value;
|
|
18
|
+
try {
|
|
19
|
+
value = JSON.parse(text);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new DictionaryError(`${path}: the file is not valid JSON: ${error.message}`);
|
|
23
|
+
}
|
|
24
|
+
return parseDictionary(value, path);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=dictionary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionary.js","sourceRoot":"","sources":["../src/dictionary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAmB,MAAM,sBAAsB,CAAC;AAEzF,cAAc,sBAAsB,CAAC;AAErC,6CAA6C;AAC7C,MAAM,UAAU,cAAc,CAAC,IAAa;IACxC,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACD,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,eAAe,CAAC,mCAAmC,IAAI,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The lint engine without a file system. It extracts the prose of a text,
|
|
3
|
+
* runs the rules on each prose unit, and gives the findings with their lines
|
|
4
|
+
* and columns. A browser can use this module.
|
|
5
|
+
*/
|
|
6
|
+
import type { ResolvedConfig } from "./config-core.js";
|
|
7
|
+
import { type Lexicon } from "./lexicon.js";
|
|
8
|
+
import { type Extraction } from "./source/markdown.js";
|
|
9
|
+
import type { Finding } from "./types.js";
|
|
10
|
+
import { type ProseUnit } from "./units.js";
|
|
11
|
+
export type FileKind = "markdown" | "mdx" | "typescript";
|
|
12
|
+
/** The kind of a file, from its extension, or null when the linter cannot read it. */
|
|
13
|
+
export declare function fileKind(path: string): FileKind | null;
|
|
14
|
+
/**
|
|
15
|
+
* A function that extracts the prose of a TypeScript or JavaScript file:
|
|
16
|
+
* the doc comments, and the JSX text of a TSX or JSX file.
|
|
17
|
+
*/
|
|
18
|
+
export type CodeExtractor = (text: string, path: string) => Extraction;
|
|
19
|
+
export type ProseLinterOptions = {
|
|
20
|
+
/**
|
|
21
|
+
* The extractor for TypeScript and JavaScript files. Without it, the
|
|
22
|
+
* linter gives no findings for these files. The extractor of this
|
|
23
|
+
* package (`extractCode`) needs the `typescript` package.
|
|
24
|
+
*/
|
|
25
|
+
readonly extractCode?: CodeExtractor;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A linter for one configuration, for text in memory. It makes the lexicon
|
|
29
|
+
* and the word list matcher one time. It reads no file.
|
|
30
|
+
*/
|
|
31
|
+
export declare class ProseLinter {
|
|
32
|
+
readonly config: ResolvedConfig;
|
|
33
|
+
readonly lexicon: Lexicon;
|
|
34
|
+
private readonly wordList;
|
|
35
|
+
private readonly rules;
|
|
36
|
+
private readonly extractCode;
|
|
37
|
+
constructor(config: ResolvedConfig, lexicon?: Lexicon, options?: ProseLinterOptions);
|
|
38
|
+
/** The prose units of a file. */
|
|
39
|
+
units(text: string, path: string): ProseUnit[];
|
|
40
|
+
/** The findings in `text`. `path` gives the kind of file, and it is the file name in the findings. */
|
|
41
|
+
lintText(text: string, path: string): Finding[];
|
|
42
|
+
private extract;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAI1D,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAoB,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,YAAY,CAAC;AAEzD,sFAAsF;AACtF,wBAAgB,QAAQ,CAAC,IAAI,EAAG,MAAM,GAAI,QAAQ,GAAG,IAAI,CAMxD;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAG,MAAM,EAAE,IAAI,EAAG,MAAM,KAAK,UAAU,CAAC;AAEzE,MAAM,MAAM,kBAAkB,GAAG;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAG,aAAa,CAAC;CACzC,CAAC;AAEF;;;GAGG;AACH,qBAAa,WAAW;IAMR,QAAQ,CAAC,MAAM,EAAG,cAAc;IAL5C,QAAQ,CAAC,OAAO,EAAG,OAAO,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgF;IACtG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwB;gBAE/B,MAAM,EAAG,cAAc,EAAE,OAAO,CAAC,EAAG,OAAO,EAAE,OAAO,GAAG,kBAAuB;IAYnG,iCAAiC;IACjC,KAAK,CAAC,IAAI,EAAG,MAAM,EAAE,IAAI,EAAG,MAAM,GAAI,SAAS,EAAE;IAIjD,sGAAsG;IACtG,QAAQ,CAAC,IAAI,EAAG,MAAM,EAAE,IAAI,EAAG,MAAM,GAAI,OAAO,EAAE;IAoDlD,OAAO,CAAC,OAAO;CAMlB"}
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The lint engine without a file system. It extracts the prose of a text,
|
|
3
|
+
* runs the rules on each prose unit, and gives the findings with their lines
|
|
4
|
+
* and columns. A browser can use this module.
|
|
5
|
+
*/
|
|
6
|
+
import { buildLexicon } from "./lexicon.js";
|
|
7
|
+
import { RULES } from "./rules/index.js";
|
|
8
|
+
import { WordListMatcher } from "./rules/word-list-matcher.js";
|
|
9
|
+
import { LineIndex } from "./source/lines.js";
|
|
10
|
+
import { extractMarkdown } from "./source/markdown.js";
|
|
11
|
+
import { isSuppressed } from "./source/suppressions.js";
|
|
12
|
+
import { buildUnit } from "./units.js";
|
|
13
|
+
/** The kind of a file, from its extension, or null when the linter cannot read it. */
|
|
14
|
+
export function fileKind(path) {
|
|
15
|
+
const lower = path.toLowerCase();
|
|
16
|
+
if (lower.endsWith(".mdx"))
|
|
17
|
+
return "mdx";
|
|
18
|
+
if (lower.endsWith(".md") || lower.endsWith(".markdown"))
|
|
19
|
+
return "markdown";
|
|
20
|
+
if (/\.(?:[mc]?ts|tsx|[mc]?js|jsx)$/.test(lower) && !lower.endsWith(".d.ts"))
|
|
21
|
+
return "typescript";
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A linter for one configuration, for text in memory. It makes the lexicon
|
|
26
|
+
* and the word list matcher one time. It reads no file.
|
|
27
|
+
*/
|
|
28
|
+
export class ProseLinter {
|
|
29
|
+
config;
|
|
30
|
+
lexicon;
|
|
31
|
+
wordList;
|
|
32
|
+
rules;
|
|
33
|
+
extractCode;
|
|
34
|
+
constructor(config, lexicon, options = {}) {
|
|
35
|
+
this.config = config;
|
|
36
|
+
this.lexicon = lexicon ?? buildLexicon(config);
|
|
37
|
+
this.wordList = new WordListMatcher(config.wordList);
|
|
38
|
+
this.extractCode = options.extractCode ?? null;
|
|
39
|
+
this.rules = RULES.flatMap((rule) => {
|
|
40
|
+
const setting = config.rules[rule.id];
|
|
41
|
+
if (setting === "off")
|
|
42
|
+
return [];
|
|
43
|
+
if (rule.id === "unknown-word" && this.lexicon.dictionary === null)
|
|
44
|
+
return [];
|
|
45
|
+
return [{ rule, override: setting ?? null }];
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** The prose units of a file. */
|
|
49
|
+
units(text, path) {
|
|
50
|
+
return this.extract(text, path).blocks.flatMap((block) => buildUnit(block, this.lexicon) ?? []);
|
|
51
|
+
}
|
|
52
|
+
/** The findings in `text`. `path` gives the kind of file, and it is the file name in the findings. */
|
|
53
|
+
lintText(text, path) {
|
|
54
|
+
const extraction = this.extract(text, path);
|
|
55
|
+
const lineIndex = new LineIndex(text);
|
|
56
|
+
const raw = [];
|
|
57
|
+
for (const block of extraction.blocks) {
|
|
58
|
+
const unit = buildUnit(block, this.lexicon);
|
|
59
|
+
if (unit === null)
|
|
60
|
+
continue;
|
|
61
|
+
const wordOnly = unit.kind !== "paragraph";
|
|
62
|
+
for (const { rule, override } of this.rules) {
|
|
63
|
+
if (wordOnly && rule.scope !== "word")
|
|
64
|
+
continue;
|
|
65
|
+
rule.check(unit, {
|
|
66
|
+
config: this.config,
|
|
67
|
+
lexicon: this.lexicon,
|
|
68
|
+
wordList: this.wordList,
|
|
69
|
+
report: (report) => {
|
|
70
|
+
raw.push({
|
|
71
|
+
ruleId: rule.id,
|
|
72
|
+
severity: override ?? report.severity ?? rule.defaultSeverity,
|
|
73
|
+
start: report.start,
|
|
74
|
+
end: report.end,
|
|
75
|
+
message: report.message,
|
|
76
|
+
eachWord: reportsEachWord(rule),
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// An unknown word that another rule reports already gets no second finding. A finding for a
|
|
83
|
+
// sentence, a paragraph or a noun cluster does not report each word in it.
|
|
84
|
+
const others = raw.filter((finding) => finding.ruleId !== "unknown-word" && finding.eachWord);
|
|
85
|
+
const kept = raw.filter((finding) => finding.ruleId !== "unknown-word"
|
|
86
|
+
|| !others.some((other) => other.start < finding.end && finding.start < other.end));
|
|
87
|
+
return kept
|
|
88
|
+
.filter((finding) => !isSuppressed(extraction.suppressions, finding.ruleId, finding.start))
|
|
89
|
+
.sort((a, b) => a.start - b.start || a.end - b.end || a.ruleId.localeCompare(b.ruleId))
|
|
90
|
+
.map((finding) => {
|
|
91
|
+
const start = lineIndex.position(finding.start);
|
|
92
|
+
const end = lineIndex.position(Math.max(finding.start, finding.end));
|
|
93
|
+
return {
|
|
94
|
+
file: path,
|
|
95
|
+
line: start.line,
|
|
96
|
+
column: start.column,
|
|
97
|
+
endLine: end.line,
|
|
98
|
+
endColumn: end.column,
|
|
99
|
+
ruleId: finding.ruleId,
|
|
100
|
+
severity: finding.severity,
|
|
101
|
+
message: finding.message,
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
extract(text, path) {
|
|
106
|
+
const kind = fileKind(path);
|
|
107
|
+
if (kind === "typescript")
|
|
108
|
+
return this.extractCode === null ? { blocks: [], suppressions: [] } : this.extractCode(text, path);
|
|
109
|
+
if (kind === null)
|
|
110
|
+
return { blocks: [], suppressions: [] };
|
|
111
|
+
return extractMarkdown(text, { mdx: kind === "mdx" });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* True when a finding of the rule is about each word in its range. A word rule reports a word or a
|
|
116
|
+
* phrase, for example a modal verb or a word list phrase. The noun-cluster rule reports a group of
|
|
117
|
+
* nouns, and the sentence and paragraph rules report a full sentence or paragraph.
|
|
118
|
+
*/
|
|
119
|
+
function reportsEachWord(rule) {
|
|
120
|
+
return rule.scope === "word" && rule.id !== "noun-cluster";
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/files.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File discovery: glob patterns to files.
|
|
3
|
+
*
|
|
4
|
+
* The glob syntax:
|
|
5
|
+
*
|
|
6
|
+
* - `*` matches characters in one path segment
|
|
7
|
+
* - `**` matches zero or more segments
|
|
8
|
+
* - `?` matches one character
|
|
9
|
+
* - `{a,b}` matches one of the alternatives
|
|
10
|
+
* - `[abc]` or `[!abc]` matches one character of a set.
|
|
11
|
+
*
|
|
12
|
+
* Patterns use `/` on all platforms. An absolute pattern is also correct.
|
|
13
|
+
*/
|
|
14
|
+
/** True when `pattern` has glob characters. */
|
|
15
|
+
export declare function isGlob(pattern: string): boolean;
|
|
16
|
+
/** This function converts a glob pattern to a regular expression that matches a whole relative path. */
|
|
17
|
+
export declare function globToRegExp(glob: string): RegExp;
|
|
18
|
+
/** The part of a pattern before the first segment with glob characters. The walk starts in that directory. */
|
|
19
|
+
export declare function globBase(glob: string): string;
|
|
20
|
+
export type FindOptions = {
|
|
21
|
+
/** The directory that the include patterns are relative to. */
|
|
22
|
+
readonly root: string;
|
|
23
|
+
readonly include: readonly string[];
|
|
24
|
+
readonly ignore: readonly string[];
|
|
25
|
+
/** The directory that the ignore patterns are relative to. The default is `root`. */
|
|
26
|
+
readonly ignoreRoot?: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* This function finds the files that match the include patterns and no
|
|
30
|
+
* ignore pattern. A pattern without glob characters is a file name, and
|
|
31
|
+
* the ignore patterns do not apply to it. The result has absolute paths,
|
|
32
|
+
* in sorted order, without duplicates.
|
|
33
|
+
*/
|
|
34
|
+
export declare function findFiles(options: FindOptions): string[];
|
|
35
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,+CAA+C;AAC/C,wBAAgB,MAAM,CAAC,OAAO,EAAG,MAAM,GAAI,OAAO,CAEjD;AAuFD,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,IAAI,EAAG,MAAM,GAAI,MAAM,CAGnD;AAED,8GAA8G;AAC9G,wBAAgB,QAAQ,CAAC,IAAI,EAAG,MAAM,GAAI,MAAM,CAQ/C;AAeD,MAAM,MAAM,WAAW,GAAG;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAG,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAG,SAAS,MAAM,EAAE,CAAC;IACpC,qFAAqF;IACrF,QAAQ,CAAC,UAAU,CAAC,EAAG,MAAM,CAAC;CACjC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAG,WAAW,GAAI,MAAM,EAAE,CAoC1D"}
|
package/dist/files.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File discovery: glob patterns to files.
|
|
3
|
+
*
|
|
4
|
+
* The glob syntax:
|
|
5
|
+
*
|
|
6
|
+
* - `*` matches characters in one path segment
|
|
7
|
+
* - `**` matches zero or more segments
|
|
8
|
+
* - `?` matches one character
|
|
9
|
+
* - `{a,b}` matches one of the alternatives
|
|
10
|
+
* - `[abc]` or `[!abc]` matches one character of a set.
|
|
11
|
+
*
|
|
12
|
+
* Patterns use `/` on all platforms. An absolute pattern is also correct.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
15
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
16
|
+
const GLOB_CHARS = /[*?[\]{}]/;
|
|
17
|
+
/** True when `pattern` has glob characters. */
|
|
18
|
+
export function isGlob(pattern) {
|
|
19
|
+
return GLOB_CHARS.test(pattern);
|
|
20
|
+
}
|
|
21
|
+
function escape(char) {
|
|
22
|
+
return /[.+^$()|\\[\]{}]/.test(char) ? `\\${char}` : char;
|
|
23
|
+
}
|
|
24
|
+
/** The index of the `}` that closes the `{` at `open`, or -1. */
|
|
25
|
+
function closingBrace(glob, open) {
|
|
26
|
+
let depth = 0;
|
|
27
|
+
for (let i = open; i < glob.length; i++) {
|
|
28
|
+
if (glob[i] === "{")
|
|
29
|
+
depth++;
|
|
30
|
+
if (glob[i] === "}" && --depth === 0)
|
|
31
|
+
return i;
|
|
32
|
+
}
|
|
33
|
+
return -1;
|
|
34
|
+
}
|
|
35
|
+
/** The alternatives of a `{...}` group. A comma in a nested group does not divide alternatives. */
|
|
36
|
+
function splitAlternatives(body) {
|
|
37
|
+
const parts = [];
|
|
38
|
+
let depth = 0;
|
|
39
|
+
let start = 0;
|
|
40
|
+
for (let i = 0; i < body.length; i++) {
|
|
41
|
+
if (body[i] === "{")
|
|
42
|
+
depth++;
|
|
43
|
+
if (body[i] === "}")
|
|
44
|
+
depth--;
|
|
45
|
+
if (body[i] === "," && depth === 0) {
|
|
46
|
+
parts.push(body.slice(start, i));
|
|
47
|
+
start = i + 1;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
parts.push(body.slice(start));
|
|
51
|
+
return parts;
|
|
52
|
+
}
|
|
53
|
+
function globSource(glob) {
|
|
54
|
+
let source = "";
|
|
55
|
+
let i = 0;
|
|
56
|
+
while (i < glob.length) {
|
|
57
|
+
const char = glob[i];
|
|
58
|
+
if (char === "*") {
|
|
59
|
+
if (glob[i + 1] === "*") {
|
|
60
|
+
const atStart = i === 0 || glob[i - 1] === "/";
|
|
61
|
+
const atEnd = i + 2 === glob.length || glob[i + 2] === "/";
|
|
62
|
+
if (atStart && atEnd) {
|
|
63
|
+
if (glob[i + 2] === "/") {
|
|
64
|
+
source += "(?:.*/)?";
|
|
65
|
+
i += 3;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
source += ".*";
|
|
69
|
+
i += 2;
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
source += "[^/]*";
|
|
75
|
+
i++;
|
|
76
|
+
while (glob[i] === "*")
|
|
77
|
+
i++;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (char === "?") {
|
|
81
|
+
source += "[^/]";
|
|
82
|
+
i++;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (char === "[") {
|
|
86
|
+
const close = glob.indexOf("]", i + 1);
|
|
87
|
+
if (close !== -1) {
|
|
88
|
+
let set = glob.slice(i + 1, close);
|
|
89
|
+
if (set.startsWith("!"))
|
|
90
|
+
set = "^" + set.slice(1);
|
|
91
|
+
source += `[${set.replace(/\\/g, "\\\\")}]`;
|
|
92
|
+
i = close + 1;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (char === "{") {
|
|
97
|
+
const close = closingBrace(glob, i);
|
|
98
|
+
if (close !== -1) {
|
|
99
|
+
source += `(?:${splitAlternatives(glob.slice(i + 1, close)).map(globSource).join("|")})`;
|
|
100
|
+
i = close + 1;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
source += escape(char);
|
|
105
|
+
i++;
|
|
106
|
+
}
|
|
107
|
+
return source;
|
|
108
|
+
}
|
|
109
|
+
/** This function converts a glob pattern to a regular expression that matches a whole relative path. */
|
|
110
|
+
export function globToRegExp(glob) {
|
|
111
|
+
const normalized = glob.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
112
|
+
return new RegExp(`^${globSource(normalized)}$`);
|
|
113
|
+
}
|
|
114
|
+
/** The part of a pattern before the first segment with glob characters. The walk starts in that directory. */
|
|
115
|
+
export function globBase(glob) {
|
|
116
|
+
const segments = glob.replace(/\\/g, "/").split("/");
|
|
117
|
+
const base = [];
|
|
118
|
+
for (const segment of segments.slice(0, -1)) {
|
|
119
|
+
if (isGlob(segment))
|
|
120
|
+
break;
|
|
121
|
+
base.push(segment);
|
|
122
|
+
}
|
|
123
|
+
return base.join("/");
|
|
124
|
+
}
|
|
125
|
+
function toPosix(path) {
|
|
126
|
+
return path.split(sep).join("/");
|
|
127
|
+
}
|
|
128
|
+
/** The pattern with `/`, relative to `root`. An absolute pattern becomes relative to `root`, so that it can match a relative path. */
|
|
129
|
+
function relativePattern(root, pattern) {
|
|
130
|
+
const normalized = pattern.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
131
|
+
return isAbsolute(normalized) ? toPosix(relative(root, normalized)) : normalized;
|
|
132
|
+
}
|
|
133
|
+
/** Directories that the walk does not enter. */
|
|
134
|
+
const SKIPPED_DIRECTORIES = new Set(["node_modules", ".git"]);
|
|
135
|
+
/**
|
|
136
|
+
* This function finds the files that match the include patterns and no
|
|
137
|
+
* ignore pattern. A pattern without glob characters is a file name, and
|
|
138
|
+
* the ignore patterns do not apply to it. The result has absolute paths,
|
|
139
|
+
* in sorted order, without duplicates.
|
|
140
|
+
*/
|
|
141
|
+
export function findFiles(options) {
|
|
142
|
+
const root = resolve(options.root);
|
|
143
|
+
const ignoreRoot = resolve(options.ignoreRoot ?? root);
|
|
144
|
+
const ignore = options.ignore.map((pattern) => globToRegExp(relativePattern(ignoreRoot, pattern)));
|
|
145
|
+
const isIgnored = (path, suffix = "") => {
|
|
146
|
+
const relativePath = toPosix(relative(ignoreRoot, path)) + suffix;
|
|
147
|
+
return ignore.some((pattern) => pattern.test(relativePath));
|
|
148
|
+
};
|
|
149
|
+
const found = new Set();
|
|
150
|
+
for (const pattern of options.include) {
|
|
151
|
+
const normalized = relativePattern(root, pattern);
|
|
152
|
+
if (!isGlob(normalized)) {
|
|
153
|
+
const path = resolve(root, normalized);
|
|
154
|
+
if (existsSync(path) && statSync(path).isFile())
|
|
155
|
+
found.add(path);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const matcher = globToRegExp(normalized);
|
|
159
|
+
const base = resolve(root, globBase(normalized));
|
|
160
|
+
if (!existsSync(base))
|
|
161
|
+
continue;
|
|
162
|
+
const walk = (directory) => {
|
|
163
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
164
|
+
const path = join(directory, entry.name);
|
|
165
|
+
const relativePath = toPosix(relative(root, path));
|
|
166
|
+
if (entry.isDirectory()) {
|
|
167
|
+
// A pattern such as "**/dist/**" matches the files in a directory, so test the directory with a "/" after it.
|
|
168
|
+
if (SKIPPED_DIRECTORIES.has(entry.name) || isIgnored(path) || isIgnored(path, "/"))
|
|
169
|
+
continue;
|
|
170
|
+
walk(path);
|
|
171
|
+
}
|
|
172
|
+
else if (entry.isFile() && matcher.test(relativePath) && !isIgnored(path)) {
|
|
173
|
+
found.add(path);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
walk(base);
|
|
178
|
+
}
|
|
179
|
+
return [...found].sort();
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Finding, type RuleId } from "./types.js";
|
|
2
|
+
export type RuleCount = {
|
|
3
|
+
readonly errors: number;
|
|
4
|
+
readonly warnings: number;
|
|
5
|
+
};
|
|
6
|
+
export type Summary = {
|
|
7
|
+
/** The number of files that the linter examined. */
|
|
8
|
+
readonly files: number;
|
|
9
|
+
readonly filesWithFindings: number;
|
|
10
|
+
readonly errors: number;
|
|
11
|
+
readonly warnings: number;
|
|
12
|
+
/** The counts of each rule that has findings, in the order of the rule list. */
|
|
13
|
+
readonly byRule: Readonly<Partial<Record<RuleId, RuleCount>>>;
|
|
14
|
+
};
|
|
15
|
+
/** This function counts the findings, by severity and by rule. */
|
|
16
|
+
export declare function summarize(findings: readonly Finding[], files: number): Summary;
|
|
17
|
+
/** The findings as text: one group for each file, then a summary and the counts by rule. */
|
|
18
|
+
export declare function formatText(findings: readonly Finding[], summary: Summary): string;
|
|
19
|
+
/** The findings and the summary as JSON. */
|
|
20
|
+
export declare function formatJson(findings: readonly Finding[], summary: Summary): string;
|
|
21
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,SAAS,GAAG;IACpB,QAAQ,CAAC,MAAM,EAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAG,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IAClB,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,iBAAiB,EAAG,MAAM,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAG,MAAM,CAAC;IAC3B,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;CAClE,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,QAAQ,EAAG,SAAS,OAAO,EAAE,EAAE,KAAK,EAAG,MAAM,GAAI,OAAO,CAiBjF;AAID,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,QAAQ,EAAG,SAAS,OAAO,EAAE,EAAE,OAAO,EAAG,OAAO,GAAI,MAAM,CAgCpF;AAED,4CAA4C;AAC5C,wBAAgB,UAAU,CAAC,QAAQ,EAAG,SAAS,OAAO,EAAE,EAAE,OAAO,EAAG,OAAO,GAAI,MAAM,CAEpF"}
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { RULE_IDS } from "./types.js";
|
|
2
|
+
/** This function counts the findings, by severity and by rule. */
|
|
3
|
+
export function summarize(findings, files) {
|
|
4
|
+
const byRule = {};
|
|
5
|
+
for (const id of RULE_IDS) {
|
|
6
|
+
const own = findings.filter((finding) => finding.ruleId === id);
|
|
7
|
+
if (own.length === 0)
|
|
8
|
+
continue;
|
|
9
|
+
byRule[id] = {
|
|
10
|
+
errors: own.filter((finding) => finding.severity === "error").length,
|
|
11
|
+
warnings: own.filter((finding) => finding.severity === "warning").length,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
files,
|
|
16
|
+
filesWithFindings: new Set(findings.map((finding) => finding.file)).size,
|
|
17
|
+
errors: findings.filter((finding) => finding.severity === "error").length,
|
|
18
|
+
warnings: findings.filter((finding) => finding.severity === "warning").length,
|
|
19
|
+
byRule,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const plural = (count, word) => `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
23
|
+
/** The findings as text: one group for each file, then a summary and the counts by rule. */
|
|
24
|
+
export function formatText(findings, summary) {
|
|
25
|
+
const lines = [];
|
|
26
|
+
const byFile = new Map();
|
|
27
|
+
for (const finding of findings) {
|
|
28
|
+
const list = byFile.get(finding.file) ?? [];
|
|
29
|
+
list.push(finding);
|
|
30
|
+
byFile.set(finding.file, list);
|
|
31
|
+
}
|
|
32
|
+
for (const [file, list] of byFile) {
|
|
33
|
+
lines.push(file);
|
|
34
|
+
const positions = list.map((finding) => `${finding.line}:${finding.column}`);
|
|
35
|
+
const width = Math.max(...positions.map((position) => position.length));
|
|
36
|
+
list.forEach((finding, index) => {
|
|
37
|
+
lines.push(` ${positions[index].padEnd(width)} ${finding.severity.padEnd(7)} ${finding.message} ${finding.ruleId}`);
|
|
38
|
+
});
|
|
39
|
+
lines.push("");
|
|
40
|
+
}
|
|
41
|
+
const total = summary.errors + summary.warnings;
|
|
42
|
+
if (total === 0) {
|
|
43
|
+
lines.push(`No problems found in ${plural(summary.files, "file")}.`);
|
|
44
|
+
return lines.join("\n") + "\n";
|
|
45
|
+
}
|
|
46
|
+
lines.push(`${plural(total, "problem")} (${plural(summary.errors, "error")}, ${plural(summary.warnings, "warning")}) in ${plural(summary.filesWithFindings, "file")} of ${summary.files}.`);
|
|
47
|
+
lines.push("");
|
|
48
|
+
lines.push("Findings by rule:");
|
|
49
|
+
const entries = Object.entries(summary.byRule);
|
|
50
|
+
const width = Math.max(...entries.map(([id]) => id.length));
|
|
51
|
+
for (const [id, count] of entries) {
|
|
52
|
+
const parts = [count.errors > 0 ? plural(count.errors, "error") : null, count.warnings > 0 ? plural(count.warnings, "warning") : null].filter((part) => part !== null);
|
|
53
|
+
lines.push(` ${id.padEnd(width)} ${String(count.errors + count.warnings).padStart(5)} (${parts.join(", ")})`);
|
|
54
|
+
}
|
|
55
|
+
return lines.join("\n") + "\n";
|
|
56
|
+
}
|
|
57
|
+
/** The findings and the summary as JSON. */
|
|
58
|
+
export function formatJson(findings, summary) {
|
|
59
|
+
return JSON.stringify({ tool: "ste-lint", summary, findings }, null, 2) + "\n";
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@mark1russell7/ste-lint`: a linter for prose in Markdown, MDX and TypeScript doc
|
|
3
|
+
* comments. It is an automated approximation of the writing rules of
|
|
4
|
+
* ASD-STE100 Simplified Technical English. It does not certify that a text
|
|
5
|
+
* obeys the standard.
|
|
6
|
+
*/
|
|
7
|
+
export { baseConfig, CONFIG_FILE_NAME, ConfigError, DEFAULT_IGNORE, DEFAULT_INCLUDE, DEFAULT_LIMITS, DICTIONARY_ENV, findConfigFile, loadConfig, mergeWordList, resolveConfig, validateConfig, type BaseConfigOptions, type Limits, type LimitsConfig, type ResolvedConfig, type SteConfigFile, type WordListEntryConfig, } from "./config.js";
|
|
8
|
+
export { Dictionary, DICTIONARY_FORMAT, DictionaryError, loadDictionary, parseDictionary, type DictionaryEntry, type DictionaryLookup } from "./dictionary.js";
|
|
9
|
+
export { findFiles, globToRegExp } from "./files.js";
|
|
10
|
+
export { formatJson, formatText, summarize, type RuleCount, type Summary } from "./format.js";
|
|
11
|
+
export { buildLexicon, type Lexicon } from "./lexicon.js";
|
|
12
|
+
export { ProseLinter, type CodeExtractor, type ProseLinterOptions } from "./engine.js";
|
|
13
|
+
export { fileKind, Linter, lintText, type FileKind } from "./lint.js";
|
|
14
|
+
export { extractCode } from "./source/code.js";
|
|
15
|
+
export { getRule, RULES, type Rule } from "./rules/index.js";
|
|
16
|
+
export { parseArgs, runCli, USAGE, type CliIo, type CliOptions } from "./run-cli.js";
|
|
17
|
+
export { isRuleId, RULE_IDS, type Finding, type RuleId, type RuleSetting, type Severity } from "./types.js";
|
|
18
|
+
export { DEFAULT_WORD_LIST, type WordListEntry } from "./word-list.js";
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACH,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,UAAU,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,mBAAmB,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC/J,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@mark1russell7/ste-lint`: a linter for prose in Markdown, MDX and TypeScript doc
|
|
3
|
+
* comments. It is an automated approximation of the writing rules of
|
|
4
|
+
* ASD-STE100 Simplified Technical English. It does not certify that a text
|
|
5
|
+
* obeys the standard.
|
|
6
|
+
*/
|
|
7
|
+
export { baseConfig, CONFIG_FILE_NAME, ConfigError, DEFAULT_IGNORE, DEFAULT_INCLUDE, DEFAULT_LIMITS, DICTIONARY_ENV, findConfigFile, loadConfig, mergeWordList, resolveConfig, validateConfig, } from "./config.js";
|
|
8
|
+
export { Dictionary, DICTIONARY_FORMAT, DictionaryError, loadDictionary, parseDictionary } from "./dictionary.js";
|
|
9
|
+
export { findFiles, globToRegExp } from "./files.js";
|
|
10
|
+
export { formatJson, formatText, summarize } from "./format.js";
|
|
11
|
+
export { buildLexicon } from "./lexicon.js";
|
|
12
|
+
export { ProseLinter } from "./engine.js";
|
|
13
|
+
export { fileKind, Linter, lintText } from "./lint.js";
|
|
14
|
+
export { extractCode } from "./source/code.js";
|
|
15
|
+
export { getRule, RULES } from "./rules/index.js";
|
|
16
|
+
export { parseArgs, runCli, USAGE } from "./run-cli.js";
|
|
17
|
+
export { isRuleId, RULE_IDS } from "./types.js";
|
|
18
|
+
export { DEFAULT_WORD_LIST } from "./word-list.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACH,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,UAAU,EACV,aAAa,EACb,aAAa,EACb,cAAc,GAOjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAA+C,MAAM,iBAAiB,CAAC;AAC/J,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAgC,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAgB,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAA+C,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAiB,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAa,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAA+B,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAA8D,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,iBAAiB,EAAsB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The word sets that the rules use: the project glossary from the
|
|
3
|
+
* configuration, the built-in word lists, and the local dictionary when
|
|
4
|
+
* there is one.
|
|
5
|
+
*/
|
|
6
|
+
import type { ResolvedConfig } from "./config.js";
|
|
7
|
+
import type { Dictionary } from "./dictionary.js";
|
|
8
|
+
import { PhraseMatcher } from "./text/phrases.js";
|
|
9
|
+
export type Lexicon = {
|
|
10
|
+
/** Single-word technical nouns, in lower case. */
|
|
11
|
+
readonly technicalNouns: ReadonlySet<string>;
|
|
12
|
+
/** Single-word technical verbs, in lower case. */
|
|
13
|
+
readonly technicalVerbs: ReadonlySet<string>;
|
|
14
|
+
/** Single-word proper nouns, in lower case. */
|
|
15
|
+
readonly properNouns: ReadonlySet<string>;
|
|
16
|
+
readonly allowedWords: ReadonlySet<string>;
|
|
17
|
+
/** All glossary terms, single words and phrases, for the unknown-word rule. */
|
|
18
|
+
readonly glossaryPhrases: PhraseMatcher;
|
|
19
|
+
/** Multi-word technical nouns. The noun-cluster rule counts each one as one noun. */
|
|
20
|
+
readonly technicalNounPhrases: PhraseMatcher;
|
|
21
|
+
/** Multi-word proper nouns. Each one counts as one word (STE Rule 8.6). */
|
|
22
|
+
readonly properNounPhrases: PhraseMatcher;
|
|
23
|
+
/** Nouns for the noun-cluster rule. */
|
|
24
|
+
readonly nouns: ReadonlySet<string>;
|
|
25
|
+
/** Base forms of verbs for the imperative and missing-subject heuristics. */
|
|
26
|
+
readonly verbs: ReadonlySet<string>;
|
|
27
|
+
readonly dictionary: Dictionary | null;
|
|
28
|
+
};
|
|
29
|
+
/** This function makes the lexicon for a configuration and an optional dictionary. */
|
|
30
|
+
export declare function buildLexicon(config: ResolvedConfig, dictionary?: Dictionary | null): Lexicon;
|
|
31
|
+
/** True when the glossary permits the word: a technical noun or verb in any form, a proper noun, or a word of `allowedWords`. */
|
|
32
|
+
export declare function isGlossaryWord(word: string, lexicon: Lexicon): boolean;
|
|
33
|
+
//# sourceMappingURL=lexicon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexicon.d.ts","sourceRoot":"","sources":["../src/lexicon.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAe,MAAM,mBAAmB,CAAC;AAG/D,MAAM,MAAM,OAAO,GAAG;IAClB,kDAAkD;IAClD,QAAQ,CAAC,cAAc,EAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9C,kDAAkD;IAClD,QAAQ,CAAC,cAAc,EAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9C,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,YAAY,EAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C,+EAA+E;IAC/E,QAAQ,CAAC,eAAe,EAAG,aAAa,CAAC;IACzC,qFAAqF;IACrF,QAAQ,CAAC,oBAAoB,EAAG,aAAa,CAAC;IAC9C,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,EAAG,aAAa,CAAC;IAC3C,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAG,UAAU,GAAG,IAAI,CAAC;CAC3C,CAAC;AAaF,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,MAAM,EAAG,cAAc,EAAE,UAAU,GAAG,UAAU,GAAG,IAAW,GAAI,OAAO,CAsCrG;AAED,iIAAiI;AACjI,wBAAgB,cAAc,CAAC,IAAI,EAAG,MAAM,EAAE,OAAO,EAAG,OAAO,GAAI,OAAO,CAKzE"}
|