chaffjs 0.21.0 → 0.22.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 +2 -1
- package/dist/cli-text.d.ts.map +1 -1
- package/dist/cli-text.js +4 -0
- package/dist/cli-text.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -11
- package/dist/cli.js.map +1 -1
- package/dist/commands/init-command.d.ts +4 -0
- package/dist/commands/init-command.d.ts.map +1 -0
- package/dist/commands/init-command.js +15 -0
- package/dist/commands/init-command.js.map +1 -0
- package/dist/commands/plugin-init.d.ts +20 -0
- package/dist/commands/plugin-init.d.ts.map +1 -0
- package/dist/commands/plugin-init.js +129 -0
- package/dist/commands/plugin-init.js.map +1 -0
- package/dist/commands/plugin-test.d.ts +11 -0
- package/dist/commands/plugin-test.d.ts.map +1 -0
- package/dist/commands/plugin-test.js +81 -0
- package/dist/commands/plugin-test.js.map +1 -0
- package/dist/custom/problems.d.ts.map +1 -1
- package/dist/custom/problems.js +1 -2
- package/dist/custom/problems.js.map +1 -1
- package/dist/detectors/amount-for-count.d.ts +21 -0
- package/dist/detectors/amount-for-count.d.ts.map +1 -0
- package/dist/detectors/amount-for-count.js +55 -0
- package/dist/detectors/amount-for-count.js.map +1 -0
- package/dist/detectors/currency-notation.d.ts +29 -0
- package/dist/detectors/currency-notation.d.ts.map +1 -0
- package/dist/detectors/currency-notation.js +58 -0
- package/dist/detectors/currency-notation.js.map +1 -0
- package/dist/detectors/dangling-opener.d.ts +14 -0
- package/dist/detectors/dangling-opener.d.ts.map +1 -0
- package/dist/detectors/dangling-opener.js +55 -0
- package/dist/detectors/dangling-opener.js.map +1 -0
- package/dist/detectors/footnote-mismatch.d.ts +11 -0
- package/dist/detectors/footnote-mismatch.d.ts.map +1 -0
- package/dist/detectors/footnote-mismatch.js +55 -0
- package/dist/detectors/footnote-mismatch.js.map +1 -0
- package/dist/detectors/form-minority.d.ts +13 -0
- package/dist/detectors/form-minority.d.ts.map +1 -0
- package/dist/detectors/form-minority.js +19 -0
- package/dist/detectors/form-minority.js.map +1 -0
- package/dist/detectors/heading-end-mark.d.ts +10 -0
- package/dist/detectors/heading-end-mark.d.ts.map +1 -0
- package/dist/detectors/heading-end-mark.js +59 -0
- package/dist/detectors/heading-end-mark.js.map +1 -0
- package/dist/detectors/list-marker.d.ts +7 -0
- package/dist/detectors/list-marker.d.ts.map +1 -0
- package/dist/detectors/list-marker.js +50 -0
- package/dist/detectors/list-marker.js.map +1 -0
- package/dist/detectors/markdown-slip.d.ts +19 -0
- package/dist/detectors/markdown-slip.d.ts.map +1 -0
- package/dist/detectors/markdown-slip.js +122 -0
- package/dist/detectors/markdown-slip.js.map +1 -0
- package/dist/detectors/numeral-opener.d.ts +10 -0
- package/dist/detectors/numeral-opener.d.ts.map +1 -0
- package/dist/detectors/numeral-opener.js +65 -0
- package/dist/detectors/numeral-opener.js.map +1 -0
- package/dist/detectors/ordinal-suffix.d.ts +12 -0
- package/dist/detectors/ordinal-suffix.d.ts.map +1 -0
- package/dist/detectors/ordinal-suffix.js +33 -0
- package/dist/detectors/ordinal-suffix.js.map +1 -0
- package/dist/detectors/range-notation.d.ts +15 -0
- package/dist/detectors/range-notation.d.ts.map +1 -0
- package/dist/detectors/range-notation.js +58 -0
- package/dist/detectors/range-notation.js.map +1 -0
- package/dist/detectors/registry/amount-for-count.d.ts +3 -0
- package/dist/detectors/registry/amount-for-count.d.ts.map +1 -0
- package/dist/detectors/registry/amount-for-count.js +3 -0
- package/dist/detectors/registry/amount-for-count.js.map +1 -0
- package/dist/detectors/registry/currency-notation.d.ts +3 -0
- package/dist/detectors/registry/currency-notation.d.ts.map +1 -0
- package/dist/detectors/registry/currency-notation.js +3 -0
- package/dist/detectors/registry/currency-notation.js.map +1 -0
- package/dist/detectors/registry/dangling-opener.d.ts +3 -0
- package/dist/detectors/registry/dangling-opener.d.ts.map +1 -0
- package/dist/detectors/registry/dangling-opener.js +3 -0
- package/dist/detectors/registry/dangling-opener.js.map +1 -0
- package/dist/detectors/registry/footnote-mismatch.d.ts +3 -0
- package/dist/detectors/registry/footnote-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/footnote-mismatch.js +3 -0
- package/dist/detectors/registry/footnote-mismatch.js.map +1 -0
- package/dist/detectors/registry/heading-end-punctuation.d.ts +3 -0
- package/dist/detectors/registry/heading-end-punctuation.d.ts.map +1 -0
- package/dist/detectors/registry/heading-end-punctuation.js +3 -0
- package/dist/detectors/registry/heading-end-punctuation.js.map +1 -0
- package/dist/detectors/registry/list-marker.d.ts +3 -0
- package/dist/detectors/registry/list-marker.d.ts.map +1 -0
- package/dist/detectors/registry/list-marker.js +3 -0
- package/dist/detectors/registry/list-marker.js.map +1 -0
- package/dist/detectors/registry/numeral-opener.d.ts +3 -0
- package/dist/detectors/registry/numeral-opener.d.ts.map +1 -0
- package/dist/detectors/registry/numeral-opener.js +3 -0
- package/dist/detectors/registry/numeral-opener.js.map +1 -0
- package/dist/detectors/registry/ordinal-suffix.d.ts +3 -0
- package/dist/detectors/registry/ordinal-suffix.d.ts.map +1 -0
- package/dist/detectors/registry/ordinal-suffix.js +3 -0
- package/dist/detectors/registry/ordinal-suffix.js.map +1 -0
- package/dist/detectors/registry/range-notation.d.ts +3 -0
- package/dist/detectors/registry/range-notation.d.ts.map +1 -0
- package/dist/detectors/registry/range-notation.js +3 -0
- package/dist/detectors/registry/range-notation.js.map +1 -0
- package/dist/detectors/registry/relative-pronoun-mix.d.ts +3 -0
- package/dist/detectors/registry/relative-pronoun-mix.d.ts.map +1 -0
- package/dist/detectors/registry/relative-pronoun-mix.js +3 -0
- package/dist/detectors/registry/relative-pronoun-mix.js.map +1 -0
- package/dist/detectors/registry/share-over-hundred.d.ts +3 -0
- package/dist/detectors/registry/share-over-hundred.d.ts.map +1 -0
- package/dist/detectors/registry/share-over-hundred.js +3 -0
- package/dist/detectors/registry/share-over-hundred.js.map +1 -0
- package/dist/detectors/registry/step-reference.d.ts +3 -0
- package/dist/detectors/registry/step-reference.d.ts.map +1 -0
- package/dist/detectors/registry/step-reference.js +3 -0
- package/dist/detectors/registry/step-reference.js.map +1 -0
- package/dist/detectors/registry/table-row-overflow.d.ts +3 -0
- package/dist/detectors/registry/table-row-overflow.d.ts.map +1 -0
- package/dist/detectors/registry/table-row-overflow.js +3 -0
- package/dist/detectors/registry/table-row-overflow.js.map +1 -0
- package/dist/detectors/registry/toc-heading.d.ts +3 -0
- package/dist/detectors/registry/toc-heading.d.ts.map +1 -0
- package/dist/detectors/registry/toc-heading.js +3 -0
- package/dist/detectors/registry/toc-heading.js.map +1 -0
- package/dist/detectors/registry/unclosed-code-fence.d.ts +3 -0
- package/dist/detectors/registry/unclosed-code-fence.d.ts.map +1 -0
- package/dist/detectors/registry/unclosed-code-fence.js +3 -0
- package/dist/detectors/registry/unclosed-code-fence.js.map +1 -0
- package/dist/detectors/registry/unrendered-emphasis.d.ts +3 -0
- package/dist/detectors/registry/unrendered-emphasis.d.ts.map +1 -0
- package/dist/detectors/registry/unrendered-emphasis.js +3 -0
- package/dist/detectors/registry/unrendered-emphasis.js.map +1 -0
- package/dist/detectors/relative-pronoun-mix.d.ts +19 -0
- package/dist/detectors/relative-pronoun-mix.d.ts.map +1 -0
- package/dist/detectors/relative-pronoun-mix.js +60 -0
- package/dist/detectors/relative-pronoun-mix.js.map +1 -0
- package/dist/detectors/share-over-hundred.d.ts +20 -0
- package/dist/detectors/share-over-hundred.d.ts.map +1 -0
- package/dist/detectors/share-over-hundred.js +55 -0
- package/dist/detectors/share-over-hundred.js.map +1 -0
- package/dist/detectors/step-reference.d.ts +20 -0
- package/dist/detectors/step-reference.d.ts.map +1 -0
- package/dist/detectors/step-reference.js +57 -0
- package/dist/detectors/step-reference.js.map +1 -0
- package/dist/detectors/toc-heading.d.ts +10 -0
- package/dist/detectors/toc-heading.d.ts.map +1 -0
- package/dist/detectors/toc-heading.js +99 -0
- package/dist/detectors/toc-heading.js.map +1 -0
- package/dist/list-marks.d.ts +21 -0
- package/dist/list-marks.d.ts.map +1 -0
- package/dist/list-marks.js +82 -0
- package/dist/list-marks.js.map +1 -0
- package/dist/rule-fields.d.ts +5 -0
- package/dist/rule-fields.d.ts.map +1 -1
- package/dist/rule-fields.js +21 -0
- package/dist/rule-fields.js.map +1 -1
- package/package.json +3 -3
- package/rules/cliche.yaml +67 -0
- package/rules/currency-notation-consistency.yaml +77 -0
- package/rules/dangling-participle.yaml +58 -0
- package/rules/footnote-mismatch.yaml +91 -0
- package/rules/heading-end-punctuation-mix.yaml +158 -0
- package/rules/less-for-fewer.yaml +59 -0
- package/rules/list-marker-mix.yaml +111 -0
- package/rules/nonstandard-word.yaml +80 -0
- package/rules/numeral-sentence-start.yaml +56 -0
- package/rules/ordinal-suffix-mismatch.yaml +65 -0
- package/rules/range-notation-consistency.yaml +73 -0
- package/rules/share-over-hundred.yaml +65 -0
- package/rules/step-reference-missing.yaml +85 -0
- package/rules/table-row-overflow.yaml +90 -0
- package/rules/toc-heading-mismatch.yaml +136 -0
- package/rules/unclosed-code-fence.yaml +107 -0
- package/rules/uncomparable-graded.yaml +65 -0
- package/rules/unrendered-emphasis.yaml +73 -0
- package/rules/which-that-consistency.yaml +64 -0
- package/skills/chaff/SKILL.md +7 -7
- package/src/cli-text.ts +4 -0
- package/src/cli.ts +5 -9
- package/src/commands/init-command.ts +13 -0
- package/src/commands/plugin-init.ts +150 -0
- package/src/commands/plugin-test.ts +111 -0
- package/src/custom/problems.ts +1 -3
- package/src/detectors/amount-for-count.ts +90 -0
- package/src/detectors/currency-notation.ts +90 -0
- package/src/detectors/dangling-opener.ts +74 -0
- package/src/detectors/footnote-mismatch.ts +72 -0
- package/src/detectors/form-minority.ts +21 -0
- package/src/detectors/heading-end-mark.ts +82 -0
- package/src/detectors/list-marker.ts +60 -0
- package/src/detectors/markdown-slip.ts +140 -0
- package/src/detectors/numeral-opener.ts +72 -0
- package/src/detectors/ordinal-suffix.ts +40 -0
- package/src/detectors/range-notation.ts +76 -0
- package/src/detectors/registry/amount-for-count.ts +4 -0
- package/src/detectors/registry/currency-notation.ts +4 -0
- package/src/detectors/registry/dangling-opener.ts +4 -0
- package/src/detectors/registry/footnote-mismatch.ts +4 -0
- package/src/detectors/registry/heading-end-punctuation.ts +4 -0
- package/src/detectors/registry/list-marker.ts +4 -0
- package/src/detectors/registry/numeral-opener.ts +4 -0
- package/src/detectors/registry/ordinal-suffix.ts +4 -0
- package/src/detectors/registry/range-notation.ts +4 -0
- package/src/detectors/registry/relative-pronoun-mix.ts +4 -0
- package/src/detectors/registry/share-over-hundred.ts +4 -0
- package/src/detectors/registry/step-reference.ts +4 -0
- package/src/detectors/registry/table-row-overflow.ts +4 -0
- package/src/detectors/registry/toc-heading.ts +4 -0
- package/src/detectors/registry/unclosed-code-fence.ts +4 -0
- package/src/detectors/registry/unrendered-emphasis.ts +4 -0
- package/src/detectors/relative-pronoun-mix.ts +79 -0
- package/src/detectors/share-over-hundred.ts +75 -0
- package/src/detectors/step-reference.ts +83 -0
- package/src/detectors/toc-heading.ts +125 -0
- package/src/list-marks.ts +106 -0
- package/src/rule-fields.ts +28 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-row-overflow.d.ts","sourceRoot":"","sources":["../../../src/detectors/registry/table-row-overflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD,eAAO,MAAM,QAAQ,EAAE,QAA2B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-row-overflow.js","sourceRoot":"","sources":["../../../src/detectors/registry/table-row-overflow.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,CAAC,MAAM,QAAQ,GAAa,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toc-heading.d.ts","sourceRoot":"","sources":["../../../src/detectors/registry/toc-heading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD,eAAO,MAAM,QAAQ,EAAE,QAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toc-heading.js","sourceRoot":"","sources":["../../../src/detectors/registry/toc-heading.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,MAAM,QAAQ,GAAa,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unclosed-code-fence.d.ts","sourceRoot":"","sources":["../../../src/detectors/registry/unclosed-code-fence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD,eAAO,MAAM,QAAQ,EAAE,QAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unclosed-code-fence.js","sourceRoot":"","sources":["../../../src/detectors/registry/unclosed-code-fence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,CAAC,MAAM,QAAQ,GAAa,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unrendered-emphasis.d.ts","sourceRoot":"","sources":["../../../src/detectors/registry/unrendered-emphasis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD,eAAO,MAAM,QAAQ,EAAE,QAA6B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unrendered-emphasis.js","sourceRoot":"","sources":["../../../src/detectors/registry/unrendered-emphasis.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,CAAC,MAAM,QAAQ,GAAa,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Detector, Lexicon, Token } from "../plugin.ts";
|
|
2
|
+
/**
|
|
3
|
+
* 限定の関係節を which で書く所と that で書く所が、一つの文書に混ざっている所(the file which contains / the file that contains)。
|
|
4
|
+
* どちらが正しいかは決めず、少ないほうを指す。読むのは「名詞 + which|that + 動詞」の、読点を挟まない形だけ。
|
|
5
|
+
* that の後ろに主語が来る形(the fact that it works)は、関係節か同格の節か語の並びで決まらないので数えない。
|
|
6
|
+
*/
|
|
7
|
+
export type RelativeUse = {
|
|
8
|
+
readonly word: Token;
|
|
9
|
+
readonly kind: string;
|
|
10
|
+
};
|
|
11
|
+
/** 語彙表の組(which / that)で、tokens の中の限定の関係節の頭。 */
|
|
12
|
+
export declare const relativeUses: (tokens: readonly Token[], kinds: Lexicon) => RelativeUse[];
|
|
13
|
+
/** 二通りの書き方のうち少ないほう。多いほうが MIN_USUAL に満たなければ、文書の書き方と言えないので空。 */
|
|
14
|
+
export declare const oddRelatives: (uses: readonly RelativeUse[], limit: number) => {
|
|
15
|
+
readonly odd: readonly RelativeUse[];
|
|
16
|
+
readonly usual: string;
|
|
17
|
+
};
|
|
18
|
+
export declare const relativePronounMix: Detector;
|
|
19
|
+
//# sourceMappingURL=relative-pronoun-mix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relative-pronoun-mix.d.ts","sourceRoot":"","sources":["../../src/detectors/relative-pronoun-mix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAW,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAItE;;;;GAIG;AAEH,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAiC1E,+CAA+C;AAC/C,eAAO,MAAM,YAAY,GAAI,QAAQ,SAAS,KAAK,EAAE,EAAE,OAAO,OAAO,KAAG,WAAW,EAM/E,CAAC;AAEL,8DAA8D;AAC9D,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,WAAW,EAAE,EAAE,OAAO,MAAM,KAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAOxI,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,QAgBhC,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { minorityOf } from "./technical-docs.js";
|
|
2
|
+
import { isWithinAny, quotedIn, QUOTATION_MARKS } from "../quoted-span.js";
|
|
3
|
+
/** 多いほうの書き方が、文書の書き方と言えるだけの数。 */
|
|
4
|
+
const MIN_USUAL = 3;
|
|
5
|
+
const VERBAL = new Set(["VERB", "AUX"]);
|
|
6
|
+
/** 解析器は三人称の動詞を複数の名詞と読むことがある(the script that checks links の checks)。 */
|
|
7
|
+
const isThirdPersonVerb = (token) => token.pos === "NOUN" && token.features?.["AlsoVerb"] === "Yes" && token.features["Number"] === "Plur";
|
|
8
|
+
const isTaggedFiniteVerb = (token) => token !== undefined && VERBAL.has(token.pos) && token.features?.["VerbForm"] !== "Part" && token.features?.["VerbForm"] !== "Ger";
|
|
9
|
+
/**
|
|
10
|
+
* 動詞と読める語。名詞と読まれた三人称の動詞は、後ろに動詞が無いときだけ(the idea that results matter の results は主語)。
|
|
11
|
+
*/
|
|
12
|
+
const isFiniteVerb = (token, next) => isTaggedFiniteVerb(token) || (token !== undefined && isThirdPersonVerb(token) && !isTaggedFiniteVerb(next));
|
|
13
|
+
const isBaseForm = (verb) => verb.pos === "VERB" && verb.lemma?.toLowerCase() === verb.surface.toLowerCase();
|
|
14
|
+
/**
|
|
15
|
+
* 名詞の後ろの関係節の動詞。原形の動詞は複数の名詞にだけ続く(resources which set)。単数の名詞の後ろの原形は、
|
|
16
|
+
* 関係節ではなく「どの」の which(tells the command which file to use)。
|
|
17
|
+
*/
|
|
18
|
+
const opensRelative = (noun, verb, next) => noun?.pos === "NOUN" && verb !== undefined && isFiniteVerb(verb, next) && (!isBaseForm(verb) || noun.features?.["Number"] === "Plur");
|
|
19
|
+
/** which / that の後ろの、副詞を飛ばした最初の語(the file which usually stores の stores)。 */
|
|
20
|
+
const verbAfter = (tokens, at) => {
|
|
21
|
+
const found = tokens.findIndex((token, index) => index > at && token.pos !== "ADV");
|
|
22
|
+
return found === -1 ? tokens.length : found;
|
|
23
|
+
};
|
|
24
|
+
/** 語彙表の組(which / that)で、tokens の中の限定の関係節の頭。 */
|
|
25
|
+
export const relativeUses = (tokens, kinds) => tokens.flatMap((word, at) => {
|
|
26
|
+
const entry = kinds.find((candidate) => candidate.pattern.toLowerCase() === word.surface.toLowerCase());
|
|
27
|
+
const verb = verbAfter(tokens, at);
|
|
28
|
+
if (entry?.group === undefined || !opensRelative(tokens[at - 1], tokens[verb], tokens[verb + 1]))
|
|
29
|
+
return [];
|
|
30
|
+
return [{ word, kind: entry.group }];
|
|
31
|
+
});
|
|
32
|
+
/** 二通りの書き方のうち少ないほう。多いほうが MIN_USUAL に満たなければ、文書の書き方と言えないので空。 */
|
|
33
|
+
export const oddRelatives = (uses, limit) => {
|
|
34
|
+
const kinds = [...new Set(uses.map((use) => use.kind))];
|
|
35
|
+
const [first, second] = kinds.map((kind) => uses.filter((use) => use.kind === kind));
|
|
36
|
+
if (kinds.length !== 2 || first === undefined || second === undefined)
|
|
37
|
+
return { odd: [], usual: "" };
|
|
38
|
+
const odd = minorityOf(first, second, limit);
|
|
39
|
+
const usual = odd === first ? second : first;
|
|
40
|
+
return usual.length < MIN_USUAL ? { odd: [], usual: "" } : { odd, usual: usual[0]?.word.surface.toLowerCase() ?? "" };
|
|
41
|
+
};
|
|
42
|
+
export const relativePronounMix = (doc, options) => {
|
|
43
|
+
const kinds = doc.lexicons["restrictive-relative"] ?? [];
|
|
44
|
+
const uses = doc.sentences.flatMap((sentence) => {
|
|
45
|
+
if (sentence.embeddedLanguage !== undefined)
|
|
46
|
+
return [];
|
|
47
|
+
const quoted = quotedIn(sentence, QUOTATION_MARKS);
|
|
48
|
+
return relativeUses(sentence.tokens ?? [], kinds).filter((use) => !isWithinAny(quoted, use.word.span));
|
|
49
|
+
});
|
|
50
|
+
const { odd, usual } = oddRelatives(uses, options.limit);
|
|
51
|
+
return odd.map((use) => ({
|
|
52
|
+
rule: "",
|
|
53
|
+
severity: "info",
|
|
54
|
+
line: 0,
|
|
55
|
+
column: 0,
|
|
56
|
+
quote: doc.sentences.find((sentence) => sentence.span.start <= use.word.span.start && use.word.span.start < sentence.span.end)?.text.trim() ?? "",
|
|
57
|
+
values: { word: use.word.surface, usual, count: odd.length, limit: options.limit, offset: use.word.span.start },
|
|
58
|
+
}));
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=relative-pronoun-mix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relative-pronoun-mix.js","sourceRoot":"","sources":["../../src/detectors/relative-pronoun-mix.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Detector } from "../plugin.ts";
|
|
2
|
+
export type ShareWords = {
|
|
3
|
+
readonly wholes: readonly string[];
|
|
4
|
+
readonly links: readonly {
|
|
5
|
+
readonly pattern: string;
|
|
6
|
+
readonly position: "before" | "after";
|
|
7
|
+
}[];
|
|
8
|
+
readonly units: readonly string[];
|
|
9
|
+
};
|
|
10
|
+
/** 100% を超える一部の割合 1 つ。written は百分率、whole は何の一部か。 */
|
|
11
|
+
export type ShareOverHundred = {
|
|
12
|
+
readonly offset: number;
|
|
13
|
+
readonly end: number;
|
|
14
|
+
readonly written: string;
|
|
15
|
+
readonly whole: string;
|
|
16
|
+
};
|
|
17
|
+
/** 文字列の中の、集まりの一部の割合なのに 100% を超える百分率。 */
|
|
18
|
+
export declare const sharesOverHundred: (text: string, words: ShareWords) => ShareOverHundred[];
|
|
19
|
+
export declare const shareOverHundred: Detector;
|
|
20
|
+
//# sourceMappingURL=share-over-hundred.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-over-hundred.d.ts","sourceRoot":"","sources":["../../src/detectors/share-over-hundred.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAA0B,MAAM,cAAc,CAAC;AAOrE,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAA;KAAE,EAAE,CAAC;IAC/F,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AA6BnI,wCAAwC;AACxC,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,EAAE,OAAO,UAAU,KAAG,gBAAgB,EAUnF,CAAC;AAKF,eAAO,MAAM,gBAAgB,EAAE,QAe9B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { escapeRegExp } from "../orthography.js";
|
|
2
|
+
import { quoteAround } from "./quote-around.js";
|
|
3
|
+
const WHOLE_PERCENT = 100;
|
|
4
|
+
/** 集まりの語が、より長い語の頭でないこと(users_2025、回答者数)。漢字やカタカナが続けば別の語(回答者数は人数で、割合の元ではない)。 */
|
|
5
|
+
const NOT_INSIDE_WORD = "(?![A-Za-z0-9_\\p{Script=Han}\\p{Script=Katakana}])";
|
|
6
|
+
const FULLWIDTH_OFFSET = 0xfee0;
|
|
7
|
+
const halfWidth = (text) => text.replace(/[0-9.]/gu, (char) => String.fromCharCode(char.charCodeAt(0) - FULLWIDTH_OFFSET));
|
|
8
|
+
const alternation = (words) => words
|
|
9
|
+
.toSorted((left, right) => right.length - left.length)
|
|
10
|
+
.map(escapeRegExp)
|
|
11
|
+
.join("|");
|
|
12
|
+
/** 集まりの語の前後の英字だけを語の切れ目に見る。日本語は語を続けて書く(アンケートでは回答者の、120%の回答者が)。 */
|
|
13
|
+
const wholeNear = (text, start, end, words) => {
|
|
14
|
+
const wholes = alternation(words.wholes);
|
|
15
|
+
return words.links
|
|
16
|
+
.map((link) => {
|
|
17
|
+
const near = link.position === "after"
|
|
18
|
+
? new RegExp(`^\\s*${escapeRegExp(link.pattern)}\\s*(?<whole>${wholes})${NOT_INSIDE_WORD}`, "u").exec(text.slice(end))
|
|
19
|
+
: new RegExp(`(?<![A-Za-z])(?<whole>${wholes})${escapeRegExp(link.pattern)}\\s*$`, "u").exec(text.slice(0, start));
|
|
20
|
+
return near?.groups?.["whole"];
|
|
21
|
+
})
|
|
22
|
+
.find((whole) => whole !== undefined);
|
|
23
|
+
};
|
|
24
|
+
/** 文字列の中の、集まりの一部の割合なのに 100% を超える百分率。 */
|
|
25
|
+
export const sharesOverHundred = (text, words) => {
|
|
26
|
+
if (words.wholes.length === 0 || words.units.length === 0)
|
|
27
|
+
return [];
|
|
28
|
+
const percent = new RegExp(`(?<![\\d.,,0-9])(?<value>[0-90-9]+(?:[,,][0-90-9]{3})*(?:[..][0-90-9]+)?)\\s?(?:${alternation(words.units)})`, "gu");
|
|
29
|
+
return [...text.matchAll(percent)].flatMap((match) => {
|
|
30
|
+
const value = Number(halfWidth(match.groups?.["value"] ?? "").replace(/[,,]/gu, ""));
|
|
31
|
+
if (value <= WHOLE_PERCENT)
|
|
32
|
+
return [];
|
|
33
|
+
const end = match.index + match[0].length;
|
|
34
|
+
const whole = wholeNear(text, match.index, end, words);
|
|
35
|
+
return whole === undefined ? [] : [{ offset: match.index, end, written: match[0], whole }];
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const positioned = (doc) => (doc.lexicons["share-whole-link"] ?? []).flatMap((entry) => (entry.position === undefined ? [] : [{ pattern: entry.pattern, position: entry.position }]));
|
|
39
|
+
export const shareOverHundred = (doc) => {
|
|
40
|
+
const text = doc.prose ?? doc.source;
|
|
41
|
+
const words = {
|
|
42
|
+
wholes: (doc.lexicons["share-whole"] ?? []).map((entry) => entry.pattern),
|
|
43
|
+
links: positioned(doc),
|
|
44
|
+
units: (doc.lexicons["percent-unit"] ?? []).map((entry) => entry.pattern),
|
|
45
|
+
};
|
|
46
|
+
return sharesOverHundred(text, words).map((found) => ({
|
|
47
|
+
rule: "",
|
|
48
|
+
severity: "warning",
|
|
49
|
+
line: 0,
|
|
50
|
+
column: 0,
|
|
51
|
+
quote: quoteAround(text, found.offset, found.end),
|
|
52
|
+
values: { written: found.written, whole: found.whole, offset: found.offset },
|
|
53
|
+
}));
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=share-over-hundred.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-over-hundred.js","sourceRoot":"","sources":["../../src/detectors/share-over-hundred.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Detector } from "../plugin.ts";
|
|
2
|
+
/** 無い手順を指す参照 1 つ。label は書いたままの参照、last は文書の手順の最後の番号。 */
|
|
3
|
+
export type MissingStep = {
|
|
4
|
+
readonly offset: number;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly last: number;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* 手順を読むのに要るもの。source は見出しの印(#)を残した文書、prose はコードを覆った本文(位置は source と同じ)。
|
|
10
|
+
* elsewhere は参照がほかの文書の手順を指すか(参照の始まりと終わりの位置で)。
|
|
11
|
+
*/
|
|
12
|
+
export type StepText = {
|
|
13
|
+
readonly source: string;
|
|
14
|
+
readonly prose: string;
|
|
15
|
+
readonly elsewhere: (start: number, end: number) => boolean;
|
|
16
|
+
};
|
|
17
|
+
/** 文書のどの手順にも無い番号を指す参照。手順の最後の番号を超えるものだけ(箇条書きが二つあれば、番号はどちらかにある)。 */
|
|
18
|
+
export declare const missingSteps: (text: StepText, words: readonly string[]) => MissingStep[];
|
|
19
|
+
export declare const stepReference: Detector;
|
|
20
|
+
//# sourceMappingURL=step-reference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-reference.d.ts","sourceRoot":"","sources":["../../src/detectors/step-reference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAA0B,MAAM,cAAc,CAAC;AAQrE,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErG;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,CAAC;AAkCxI,kEAAkE;AAClE,eAAO,MAAM,YAAY,GAAI,MAAM,QAAQ,EAAE,OAAO,SAAS,MAAM,EAAE,KAAG,WAAW,EASlF,CAAC;AAYF,eAAO,MAAM,aAAa,EAAE,QAW3B,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { escapeRegExp } from "../orthography.js";
|
|
2
|
+
import { quoteAround } from "./quote-around.js";
|
|
3
|
+
const FULLWIDTH_OFFSET = 0xfee0;
|
|
4
|
+
const LIST_ITEM = /^[ \t]*(?<number>\d{1,3})[.)][ \t]/u;
|
|
5
|
+
const HEADING = /^#{1,6}[ \t]+/u;
|
|
6
|
+
const halfWidth = (text) => text.replace(/[0-9]/gu, (char) => String.fromCharCode(char.charCodeAt(0) - FULLWIDTH_OFFSET));
|
|
7
|
+
const mentionPattern = (words) => new RegExp(`(?<![A-Za-z])(?:${words.map(escapeRegExp).join("|")})[ \\t\\u3000]?(?<number>[0-90-9]{1,3})(?![0-90-9A-Za-z])`, "gu");
|
|
8
|
+
const isHeadingAt = (source, offset) => HEADING.test(source.slice(source.lastIndexOf("\n", offset - 1) + 1, offset));
|
|
9
|
+
/** 本文の参照(コードを覆った prose から)と、見出しの手順(prose は見出しも覆うので source から)。 */
|
|
10
|
+
const mentionsOf = ({ source, prose }, words) => {
|
|
11
|
+
const toMention = (match, heading) => ({
|
|
12
|
+
offset: match.index ?? 0,
|
|
13
|
+
label: match[0],
|
|
14
|
+
number: Number(halfWidth(match.groups?.["number"] ?? "")),
|
|
15
|
+
heading,
|
|
16
|
+
});
|
|
17
|
+
const headings = [...source.matchAll(mentionPattern(words))].filter((match) => isHeadingAt(source, match.index)).map((match) => toMention(match, true));
|
|
18
|
+
const references = [...prose.matchAll(mentionPattern(words))].filter((match) => !isHeadingAt(source, match.index)).map((match) => toMention(match, false));
|
|
19
|
+
return [...headings, ...references];
|
|
20
|
+
};
|
|
21
|
+
const listNumbers = (prose) => prose.split("\n").flatMap((line) => {
|
|
22
|
+
const number = LIST_ITEM.exec(line)?.groups?.["number"];
|
|
23
|
+
return number === undefined ? [] : [Number(number)];
|
|
24
|
+
});
|
|
25
|
+
/** 文書のどの手順にも無い番号を指す参照。手順の最後の番号を超えるものだけ(箇条書きが二つあれば、番号はどちらかにある)。 */
|
|
26
|
+
export const missingSteps = (text, words) => {
|
|
27
|
+
if (words.length === 0)
|
|
28
|
+
return [];
|
|
29
|
+
const mentions = mentionsOf(text, words);
|
|
30
|
+
const steps = [...mentions.filter((mention) => mention.heading).map((mention) => mention.number), ...listNumbers(text.prose)];
|
|
31
|
+
if (steps.length === 0)
|
|
32
|
+
return [];
|
|
33
|
+
const last = Math.max(...steps);
|
|
34
|
+
return mentions
|
|
35
|
+
.filter((mention) => !mention.heading && mention.number > last && !text.elsewhere(mention.offset, mention.offset + mention.label.length))
|
|
36
|
+
.map((mention) => ({ offset: mention.offset, label: mention.label, last }));
|
|
37
|
+
};
|
|
38
|
+
/** 番号のすぐ後ろが figure-elsewhere の語か、すぐ前がこの文書でない文書の名前なら、ほかの文書の手順。 */
|
|
39
|
+
const elsewhereOf = (doc, text) => (start, end) => {
|
|
40
|
+
const after = text.slice(end).trimStart();
|
|
41
|
+
const placed = (doc.lexicons["figure-elsewhere"] ?? []).some((entry) => after.startsWith(`${entry.pattern} `) && /^\s/u.test(text.slice(end)));
|
|
42
|
+
const named = doc.namedDocument?.(text, start);
|
|
43
|
+
return placed || (named !== undefined && !named.self);
|
|
44
|
+
};
|
|
45
|
+
export const stepReference = (doc) => {
|
|
46
|
+
const prose = doc.prose ?? doc.source;
|
|
47
|
+
const words = (doc.lexicons["step-word"] ?? []).map((entry) => entry.pattern);
|
|
48
|
+
return missingSteps({ source: doc.source, prose, elsewhere: elsewhereOf(doc, prose) }, words).map((missing) => ({
|
|
49
|
+
rule: "",
|
|
50
|
+
severity: "warning",
|
|
51
|
+
line: 0,
|
|
52
|
+
column: 0,
|
|
53
|
+
quote: quoteAround(prose, missing.offset, missing.offset + missing.label.length),
|
|
54
|
+
values: { label: missing.label, last: missing.last, offset: missing.offset },
|
|
55
|
+
}));
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=step-reference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-reference.js","sourceRoot":"","sources":["../../src/detectors/step-reference.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Detector } from "../plugin.ts";
|
|
2
|
+
/** 見出しの無い目次の項目 1 つ。entry は項目の言葉(リンクなら字の部分)。 */
|
|
3
|
+
export type StrayTocEntry = {
|
|
4
|
+
readonly offset: number;
|
|
5
|
+
readonly entry: string;
|
|
6
|
+
};
|
|
7
|
+
/** 文書の目次の項目のうち、どの見出しとも合わないもの。 */
|
|
8
|
+
export declare const strayTocEntries: (source: string, tocWords: readonly string[]) => StrayTocEntry[];
|
|
9
|
+
export declare const tocHeading: Detector;
|
|
10
|
+
//# sourceMappingURL=toc-heading.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toc-heading.d.ts","sourceRoot":"","sources":["../../src/detectors/toc-heading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAW,MAAM,cAAc,CAAC;AAOtD,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAuFhF,iCAAiC;AACjC,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,UAAU,SAAS,MAAM,EAAE,KAAG,aAAa,EAe1F,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,QAWpB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { headingWords } from "../structure-shape/heading-words.js";
|
|
2
|
+
import { quoteAround } from "./quote-around.js";
|
|
3
|
+
const HEADING = /^[ \t]{0,3}#{1,6}[ \t]/u;
|
|
4
|
+
const FENCE = /^[ \t]*(?:```|~~~)/u;
|
|
5
|
+
const LIST_ITEM = /^[ \t]*(?:[-*+]|\d{1,3}[.)])[ \t]/u;
|
|
6
|
+
const LINK_TEXT = /^\[(?<text>[^\]]*)\]\([^)]*\)/u;
|
|
7
|
+
const ATTRIBUTES = /\{#[^}]*\}/gu;
|
|
8
|
+
const DIGIT = /[\d0-9]/u;
|
|
9
|
+
const LEADER_DOTS = new Set([".", "…", "・"]);
|
|
10
|
+
const MIN_LEADER = 2;
|
|
11
|
+
/** 目次の項目のうち見出しに合わないものがこれより多ければ、目次は別の書き方の見出し(本文に無い章立て)と読んで言わない。 */
|
|
12
|
+
const MAX_STRAY_SHARE = 0.5;
|
|
13
|
+
const linesOf = (source) => [...source.matchAll(/^.*$/gmu)].map((match) => ({ text: match[0], offset: match.index }));
|
|
14
|
+
/** コードの囲みの外の行。 */
|
|
15
|
+
const outsideFences = (lines) => {
|
|
16
|
+
const fence = { open: false };
|
|
17
|
+
return lines.filter((line) => {
|
|
18
|
+
if (FENCE.test(line.text)) {
|
|
19
|
+
fence.open = !fence.open;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return !fence.open;
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
/** 比べるための形。全角を半角にそろえ(4 と 4)、空白・記号を消し、小文字にする。 */
|
|
26
|
+
const comparable = (text) => text
|
|
27
|
+
.replace(ATTRIBUTES, "")
|
|
28
|
+
.normalize("NFKC")
|
|
29
|
+
.toLowerCase()
|
|
30
|
+
.replace(/[\s\p{P}\p{S}]/gu, "");
|
|
31
|
+
/** 頭の番号(1.2、2-1、第3章)と飾りを外した、比べるための形。 */
|
|
32
|
+
const withoutNumber = (text) => comparable(headingWords(text));
|
|
33
|
+
/** text の終わりから、isTail に当たる字を外したもの。 */
|
|
34
|
+
const trimTail = (text, isTail) => {
|
|
35
|
+
const chars = [...text];
|
|
36
|
+
return chars.slice(0, chars.findLastIndex((char) => !isTail(char)) + 1).join("");
|
|
37
|
+
};
|
|
38
|
+
/** 見出しの行の題(頭と終わりの # を外す)。見出しでなければ undefined。 */
|
|
39
|
+
const headingTitle = (line) => {
|
|
40
|
+
if (!HEADING.test(line))
|
|
41
|
+
return undefined;
|
|
42
|
+
const withoutMarks = line.trim().replace(/^#+/u, "").trim();
|
|
43
|
+
return trimTail(withoutMarks, (char) => char === "#").trim();
|
|
44
|
+
};
|
|
45
|
+
/** 終わりのページ番号(「背景 ........ 3」の 3 と点線)。点線の無い数(Step 3)は題のうち。 */
|
|
46
|
+
const withoutPageNumber = (text) => {
|
|
47
|
+
const before = trimTail(text, (char) => DIGIT.test(char)).trimEnd();
|
|
48
|
+
if (before === text.trimEnd())
|
|
49
|
+
return text;
|
|
50
|
+
const title = trimTail(before, (char) => LEADER_DOTS.has(char));
|
|
51
|
+
return before.length - title.length >= MIN_LEADER ? title.trim() : text;
|
|
52
|
+
};
|
|
53
|
+
/** 項目の言葉と、項目の行の中でそれが始まる所。リンクなら字の部分(番号の後ろのリンク「1. [概要](#…)」も)。 */
|
|
54
|
+
const entryOf = (item) => {
|
|
55
|
+
const bracket = item.indexOf("[");
|
|
56
|
+
const link = bracket === -1 ? undefined : LINK_TEXT.exec(item.slice(bracket))?.groups?.["text"];
|
|
57
|
+
if (link !== undefined)
|
|
58
|
+
return { text: withoutPageNumber(link), start: bracket + 1 };
|
|
59
|
+
return { text: withoutPageNumber(item.trim()), start: item.length - item.trimStart().length };
|
|
60
|
+
};
|
|
61
|
+
const matchesHeading = (entry, headings) => headings.some((heading) => comparable(heading.title) === comparable(entry) || (withoutNumber(entry) !== "" && withoutNumber(heading.title) === withoutNumber(entry)));
|
|
62
|
+
/** 目次の見出しの下(次の見出しまで)の箇条書きの項目。 */
|
|
63
|
+
const entriesUnder = (lines, tocAt) => {
|
|
64
|
+
const after = lines.filter((line) => line.offset > tocAt);
|
|
65
|
+
const end = after.findIndex((line) => HEADING.test(line.text));
|
|
66
|
+
return (end === -1 ? after : after.slice(0, end)).flatMap((line) => {
|
|
67
|
+
const marker = LIST_ITEM.exec(line.text)?.[0];
|
|
68
|
+
if (marker === undefined)
|
|
69
|
+
return [];
|
|
70
|
+
const entry = entryOf(line.text.slice(marker.length));
|
|
71
|
+
return [{ text: entry.text, offset: line.offset + marker.length + entry.start }];
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
/** 文書の目次の項目のうち、どの見出しとも合わないもの。 */
|
|
75
|
+
export const strayTocEntries = (source, tocWords) => {
|
|
76
|
+
const lines = outsideFences(linesOf(source));
|
|
77
|
+
const headings = lines.flatMap((line) => {
|
|
78
|
+
const title = headingTitle(line.text);
|
|
79
|
+
return title === undefined ? [] : [{ title, offset: line.offset }];
|
|
80
|
+
});
|
|
81
|
+
const tocNames = new Set(tocWords.map(comparable));
|
|
82
|
+
return headings
|
|
83
|
+
.filter((heading) => tocNames.has(comparable(heading.title)))
|
|
84
|
+
.flatMap((toc) => {
|
|
85
|
+
const entries = entriesUnder(lines, toc.offset).filter((entry) => entry.text !== "");
|
|
86
|
+
const others = headings.filter((heading) => heading !== toc);
|
|
87
|
+
const stray = entries.filter((entry) => !matchesHeading(entry.text, others));
|
|
88
|
+
return stray.length > entries.length * MAX_STRAY_SHARE ? [] : stray.map((entry) => ({ offset: entry.offset, entry: entry.text }));
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
export const tocHeading = (doc) => strayTocEntries(doc.source, (doc.lexicons["toc-heading"] ?? []).map((entry) => entry.pattern)).map((stray) => ({
|
|
92
|
+
rule: "",
|
|
93
|
+
severity: "warning",
|
|
94
|
+
line: 0,
|
|
95
|
+
column: 0,
|
|
96
|
+
quote: quoteAround(doc.source, stray.offset, stray.offset + stray.entry.length),
|
|
97
|
+
values: { entry: stray.entry, offset: stray.offset },
|
|
98
|
+
}));
|
|
99
|
+
//# sourceMappingURL=toc-heading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toc-heading.js","sourceRoot":"","sources":["../../src/detectors/toc-heading.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type MarkdownNode } from "./markdown-node.ts";
|
|
2
|
+
/** One bulleted list as the reader meets it: where its first item starts, how deep it sits among lists, and its bullet. */
|
|
3
|
+
export type ListMark = {
|
|
4
|
+
readonly start: number;
|
|
5
|
+
readonly depth: number;
|
|
6
|
+
readonly mark: string;
|
|
7
|
+
/** The list written right before it in the same parent, when there is one: Markdown splits a list where the bullet changes. */
|
|
8
|
+
readonly previous: string | undefined;
|
|
9
|
+
};
|
|
10
|
+
export type ListReading = {
|
|
11
|
+
readonly lists: readonly ListMark[];
|
|
12
|
+
/** `・` lines inside a Markdown list item's paragraph: Markdown joins them to the item above. */
|
|
13
|
+
readonly foldedTyped: readonly number[];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Every bulleted list outside quotations and code, with its depth among lists (a list in a list item is one deeper), in source
|
|
17
|
+
* order. A paragraph with two or more lines that start with `・` counts as a list at the paragraph's depth; the same lines in a
|
|
18
|
+
* list item's paragraph are folded into that item.
|
|
19
|
+
*/
|
|
20
|
+
export declare const readLists: (source: string, root: MarkdownNode) => ListReading;
|
|
21
|
+
//# sourceMappingURL=list-marks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-marks.d.ts","sourceRoot":"","sources":["../src/list-marks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG/D,2HAA2H;AAC3H,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+HAA+H;IAC/H,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC,CAAC;AA8CF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,gGAAgG;IAChG,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CAAC;AAqBF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,MAAM,YAAY,KAAG,WAiB9D,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// The bullets a document writes its lists with (`-`, `*`, `+`, and `・` typed at a line's start), where each list sits, and
|
|
2
|
+
// the `・` lines Markdown folds into the item above. Pure; reads the source's Markdown tree.
|
|
3
|
+
import { spanOf } from "./markdown-node.js";
|
|
4
|
+
/** Bullets Markdown reads as a list. */
|
|
5
|
+
const MARKDOWN_BULLETS = new Set(["-", "*", "+"]);
|
|
6
|
+
/** A bullet a Japanese writer types at a line's start. Markdown does not read it as a list, so the lines run together. */
|
|
7
|
+
const TYPED_BULLET = "・";
|
|
8
|
+
/** Blocks whose lists are someone else's or are not prose: quotations, code and HTML. */
|
|
9
|
+
const SKIPPED = new Set(["blockquote", "code", "html"]);
|
|
10
|
+
const bulletOf = (source, list) => {
|
|
11
|
+
const first = list.children?.[0];
|
|
12
|
+
const span = first === undefined ? undefined : spanOf(first);
|
|
13
|
+
const mark = span === undefined ? undefined : source.charAt(span.start);
|
|
14
|
+
return span === undefined || mark === undefined || !MARKDOWN_BULLETS.has(mark) ? undefined : { start: span.start, mark };
|
|
15
|
+
};
|
|
16
|
+
/** Where each line of a span starts, with the line's text. */
|
|
17
|
+
const linesIn = (source, span) => {
|
|
18
|
+
const lines = source.slice(span.start, span.end).split("\n");
|
|
19
|
+
const read = [];
|
|
20
|
+
lines.forEach((text) => {
|
|
21
|
+
const previous = read.at(-1);
|
|
22
|
+
read.push({ start: previous === undefined ? span.start : previous.start + previous.text.length + 1, text });
|
|
23
|
+
});
|
|
24
|
+
return read;
|
|
25
|
+
};
|
|
26
|
+
/** The start of each line after the first that begins with a typed bullet. */
|
|
27
|
+
const typedLineStarts = (source, paragraph) => linesIn(source, paragraph).flatMap((line, at) => {
|
|
28
|
+
const indent = line.text.length - line.text.trimStart().length;
|
|
29
|
+
return at > 0 && line.text.trimStart().startsWith(TYPED_BULLET) ? [line.start + indent] : [];
|
|
30
|
+
});
|
|
31
|
+
/** Lines of a paragraph that start with a typed bullet; two or more in a row are a list the writer typed. */
|
|
32
|
+
const typedListStart = (source, paragraph) => {
|
|
33
|
+
const lines = linesIn(source, paragraph).filter((line) => line.text.trim() !== "");
|
|
34
|
+
const typed = lines.filter((line) => line.text.trimStart().startsWith(TYPED_BULLET));
|
|
35
|
+
const first = typed[0];
|
|
36
|
+
return typed.length >= 2 && first !== undefined ? first.start + first.text.length - first.text.trimStart().length : undefined;
|
|
37
|
+
};
|
|
38
|
+
const listsOf = (source, node, depth) => {
|
|
39
|
+
const children = node.children ?? [];
|
|
40
|
+
return children.flatMap((child, at) => {
|
|
41
|
+
if (child.type !== "list")
|
|
42
|
+
return [];
|
|
43
|
+
const bullet = bulletOf(source, child);
|
|
44
|
+
const before = children[at - 1];
|
|
45
|
+
const previous = before?.type === "list" ? bulletOf(source, before)?.mark : undefined;
|
|
46
|
+
return bullet === undefined ? [] : [{ ...bullet, depth, previous }];
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
const typedOf = (source, node, depth, inItem) => {
|
|
50
|
+
const span = spanOf(node);
|
|
51
|
+
if (node.type !== "paragraph" || span === undefined)
|
|
52
|
+
return { lists: [], folded: [] };
|
|
53
|
+
if (inItem)
|
|
54
|
+
return { lists: [], folded: typedLineStarts(source, span) };
|
|
55
|
+
const start = typedListStart(source, span);
|
|
56
|
+
return { lists: start === undefined ? [] : [{ start, depth, mark: TYPED_BULLET, previous: undefined }], folded: [] };
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Every bulleted list outside quotations and code, with its depth among lists (a list in a list item is one deeper), in source
|
|
60
|
+
* order. A paragraph with two or more lines that start with `・` counts as a list at the paragraph's depth; the same lines in a
|
|
61
|
+
* list item's paragraph are folded into that item.
|
|
62
|
+
*/
|
|
63
|
+
export const readLists = (source, root) => {
|
|
64
|
+
const lists = [];
|
|
65
|
+
const folded = [];
|
|
66
|
+
const pending = [{ node: root, depth: 0, inItem: false }];
|
|
67
|
+
for (let frame = pending.pop(); frame !== undefined; frame = pending.pop()) {
|
|
68
|
+
const { node, depth, inItem } = frame;
|
|
69
|
+
if (SKIPPED.has(node.type))
|
|
70
|
+
continue;
|
|
71
|
+
lists.push(...listsOf(source, node, depth));
|
|
72
|
+
const typed = typedOf(source, node, depth, inItem);
|
|
73
|
+
lists.push(...typed.lists);
|
|
74
|
+
folded.push(...typed.folded);
|
|
75
|
+
const childDepth = node.type === "list" ? depth + 1 : depth;
|
|
76
|
+
const childInItem = node.type === "listItem" || (inItem && node.type !== "list");
|
|
77
|
+
(node.children ?? []).forEach((child) => pending.push({ node: child, depth: childDepth, inItem: childInItem }));
|
|
78
|
+
}
|
|
79
|
+
const byStart = (left, right) => left - right;
|
|
80
|
+
return { lists: lists.toSorted((left, right) => byStart(left.start, right.start)), foldedTyped: folded.toSorted(byStart) };
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=list-marks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-marks.js","sourceRoot":"","sources":["../src/list-marks.ts"],"names":[],"mappings":"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"}
|