slopless 0.2.7 → 0.2.8
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 +19 -3
- package/dist/adapters/textlint/rule.js +21 -0
- package/dist/adapters/textlint/rule.js.map +1 -0
- package/dist/adapters/textlint/units.js +133 -1
- package/dist/adapters/textlint/units.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/presets/everything.js +2 -0
- package/dist/presets/everything.js.map +1 -1
- package/dist/registries/orthography.js +4 -0
- package/dist/registries/orthography.js.map +1 -1
- package/dist/reporting/reports.js +50 -0
- package/dist/reporting/reports.js.map +1 -1
- package/dist/rules/academic-slop/tortured-phrases.js +13 -23
- package/dist/rules/academic-slop/tortured-phrases.js.map +1 -1
- package/dist/rules/metrics/avg-sentence-length.js +23 -21
- package/dist/rules/metrics/avg-sentence-length.js.map +1 -1
- package/dist/rules/metrics/coleman-liau.js +23 -23
- package/dist/rules/metrics/coleman-liau.js.map +1 -1
- package/dist/rules/metrics/flesch-kincaid.js +23 -23
- package/dist/rules/metrics/flesch-kincaid.js.map +1 -1
- package/dist/rules/metrics/gunning-fog.js +23 -23
- package/dist/rules/metrics/gunning-fog.js.map +1 -1
- package/dist/rules/metrics/paragraph-length.js +19 -20
- package/dist/rules/metrics/paragraph-length.js.map +1 -1
- package/dist/rules/metrics/word-repetition.js +20 -21
- package/dist/rules/metrics/word-repetition.js.map +1 -1
- package/dist/rules/narrative-slop/body-action-density.js +60 -23
- package/dist/rules/narrative-slop/body-action-density.js.map +1 -1
- package/dist/rules/narrative-slop/data/narrative-cliches.json +27 -0
- package/dist/rules/narrative-slop/flat-action-cadence.js +23 -26
- package/dist/rules/narrative-slop/flat-action-cadence.js.map +1 -1
- package/dist/rules/narrative-slop/narrative-cliches.js +35 -33
- package/dist/rules/narrative-slop/narrative-cliches.js.map +1 -1
- package/dist/rules/narrative-slop/perception-verb-density.js +22 -23
- package/dist/rules/narrative-slop/perception-verb-density.js.map +1 -1
- package/dist/rules/orthography/artifact-placeholders.js +110 -0
- package/dist/rules/orthography/artifact-placeholders.js.map +1 -0
- package/dist/rules/orthography/colon-dramatic.js +24 -32
- package/dist/rules/orthography/colon-dramatic.js.map +1 -1
- package/dist/rules/orthography/em-dashes.js +19 -33
- package/dist/rules/orthography/em-dashes.js.map +1 -1
- package/dist/rules/orthography/exclamation-density.js +20 -34
- package/dist/rules/orthography/exclamation-density.js.map +1 -1
- package/dist/rules/orthography/fake-timestamps.js +12 -32
- package/dist/rules/orthography/fake-timestamps.js.map +1 -1
- package/dist/rules/orthography/hidden-unicode-controls.js +51 -0
- package/dist/rules/orthography/hidden-unicode-controls.js.map +1 -0
- package/dist/rules/orthography/sentence-case.js +24 -32
- package/dist/rules/orthography/sentence-case.js.map +1 -1
- package/dist/rules/orthography/smart-quotes.js +12 -32
- package/dist/rules/orthography/smart-quotes.js.map +1 -1
- package/dist/rules/phrases/cliches.js +16 -27
- package/dist/rules/phrases/cliches.js.map +1 -1
- package/dist/rules/phrases/corporate-speak.js +16 -27
- package/dist/rules/phrases/corporate-speak.js.map +1 -1
- package/dist/rules/phrases/data/llm-disclaimer-expansions.json +9 -2
- package/dist/rules/phrases/data/redundancy-patterns.json +7 -0
- package/dist/rules/phrases/data/wordiness-patterns.json +2 -0
- package/dist/rules/phrases/humble-bragger.js +12 -22
- package/dist/rules/phrases/humble-bragger.js.map +1 -1
- package/dist/rules/phrases/jargon-faker.js +14 -25
- package/dist/rules/phrases/jargon-faker.js.map +1 -1
- package/dist/rules/phrases/llm-disclaimer.js +19 -23
- package/dist/rules/phrases/llm-disclaimer.js.map +1 -1
- package/dist/rules/phrases/prohibited-phrases.js +13 -23
- package/dist/rules/phrases/prohibited-phrases.js.map +1 -1
- package/dist/rules/phrases/redundancy.js +13 -23
- package/dist/rules/phrases/redundancy.js.map +1 -1
- package/dist/rules/phrases/skunked-terms.js +13 -23
- package/dist/rules/phrases/skunked-terms.js.map +1 -1
- package/dist/rules/phrases/uncomparables.js +15 -26
- package/dist/rules/phrases/uncomparables.js.map +1 -1
- package/dist/rules/phrases/wordiness.js +13 -23
- package/dist/rules/phrases/wordiness.js.map +1 -1
- package/dist/rules/private/textlint-rule-builders.js +46 -0
- package/dist/rules/private/textlint-rule-builders.js.map +1 -0
- package/dist/rules/semantic-thinness/patterns/puffery-evaluative-claim.json +56 -0
- package/dist/rules/semantic-thinness/private/pattern-data-d.js +2 -0
- package/dist/rules/semantic-thinness/private/pattern-data-d.js.map +1 -1
- package/dist/rules/semantic-thinness/semantic-thinness.js +27 -23
- package/dist/rules/semantic-thinness/semantic-thinness.js.map +1 -1
- package/dist/rules/syntactic-patterns/authority/authority-padding.js +19 -23
- package/dist/rules/syntactic-patterns/authority/authority-padding.js.map +1 -1
- package/dist/rules/syntactic-patterns/closers/affirmation-closers.js +45 -43
- package/dist/rules/syntactic-patterns/closers/affirmation-closers.js.map +1 -1
- package/dist/rules/syntactic-patterns/closers/boilerplate-conclusion.js +25 -22
- package/dist/rules/syntactic-patterns/closers/boilerplate-conclusion.js.map +1 -1
- package/dist/rules/syntactic-patterns/closers/false-question.js +20 -24
- package/dist/rules/syntactic-patterns/closers/false-question.js.map +1 -1
- package/dist/rules/syntactic-patterns/closers/summative-closer.js +20 -24
- package/dist/rules/syntactic-patterns/closers/summative-closer.js.map +1 -1
- package/dist/rules/syntactic-patterns/contrast/blame-reframe.js +19 -23
- package/dist/rules/syntactic-patterns/contrast/blame-reframe.js.map +1 -1
- package/dist/rules/syntactic-patterns/contrast/contrastive-aphorism.js +39 -31
- package/dist/rules/syntactic-patterns/contrast/contrastive-aphorism.js.map +1 -1
- package/dist/rules/syntactic-patterns/contrast/negation-reframe.js +12 -21
- package/dist/rules/syntactic-patterns/contrast/negation-reframe.js.map +1 -1
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-parts.js +4 -2
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-parts.js.map +1 -1
- package/dist/rules/syntactic-patterns/contrast/private/negative-slop-frames.js +33 -2
- package/dist/rules/syntactic-patterns/contrast/private/negative-slop-frames.js.map +1 -1
- package/dist/rules/syntactic-patterns/generalization/softening-language.js +19 -23
- package/dist/rules/syntactic-patterns/generalization/softening-language.js.map +1 -1
- package/dist/rules/syntactic-patterns/generalization/universalizing-claims.js +19 -23
- package/dist/rules/syntactic-patterns/generalization/universalizing-claims.js.map +1 -1
- package/dist/rules/syntactic-patterns/lead-ins/boilerplate-framing.js +12 -22
- package/dist/rules/syntactic-patterns/lead-ins/boilerplate-framing.js.map +1 -1
- package/dist/rules/syntactic-patterns/lead-ins/generic-signposting.js +19 -23
- package/dist/rules/syntactic-patterns/lead-ins/generic-signposting.js.map +1 -1
- package/dist/rules/syntactic-patterns/lead-ins/lesson-framing.js +19 -23
- package/dist/rules/syntactic-patterns/lead-ins/lesson-framing.js.map +1 -1
- package/dist/rules/syntactic-patterns/lead-ins/llm-openers.js +28 -25
- package/dist/rules/syntactic-patterns/lead-ins/llm-openers.js.map +1 -1
- package/dist/rules/syntactic-patterns/lead-ins/observer-guidance.js +19 -23
- package/dist/rules/syntactic-patterns/lead-ins/observer-guidance.js.map +1 -1
- package/dist/rules/syntactic-patterns/llm-artifacts/data/response-wrapper-patterns.json +6 -0
- package/dist/rules/syntactic-patterns/llm-artifacts/response-wrapper.js +21 -26
- package/dist/rules/syntactic-patterns/llm-artifacts/response-wrapper.js.map +1 -1
- package/dist/rules/syntactic-patterns/repetition/demonstrative-emphasis.js +28 -51
- package/dist/rules/syntactic-patterns/repetition/demonstrative-emphasis.js.map +1 -1
- package/dist/rules/syntactic-patterns/repetition/empty-emphasis.js +19 -23
- package/dist/rules/syntactic-patterns/repetition/empty-emphasis.js.map +1 -1
- package/dist/rules/syntactic-patterns/repetition/fragment-stacking.js +12 -32
- package/dist/rules/syntactic-patterns/repetition/fragment-stacking.js.map +1 -1
- package/dist/rules/syntactic-patterns/repetition/triple-repeat.js +15 -38
- package/dist/rules/syntactic-patterns/repetition/triple-repeat.js.map +1 -1
- package/dist/rules/term-policy/recommended-terms.js +24 -22
- package/dist/rules/term-policy/recommended-terms.js.map +1 -1
- package/dist/rules/term-policy/required-terms.js +20 -24
- package/dist/rules/term-policy/required-terms.js.map +1 -1
- package/dist/rules/words/hedge-stacking.js +19 -23
- package/dist/rules/words/hedge-stacking.js.map +1 -1
- package/dist/rules/words/llm-vocabulary.js +14 -20
- package/dist/rules/words/llm-vocabulary.js.map +1 -1
- package/dist/rules/words/prohibited-words.js +12 -17
- package/dist/rules/words/prohibited-words.js.map +1 -1
- package/dist/rules/words/simplicity.js +20 -25
- package/dist/rules/words/simplicity.js.map +1 -1
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redundancy.js","sourceRoot":"","sources":["../../../src/rules/phrases/redundancy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"redundancy.js","sourceRoot":"","sources":["../../../src/rules/phrases/redundancy.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,iCAAiC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACvF,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEpE,MAAM,IAAI,GAAG,YAAY,CAAC;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,yBAAyB,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACvE,QAAQ,EAAE,KAAK,CAAC,IAAI;QACpB,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE;KAC9C,CAAC,CAAC;IACL,MAAM,EAAE,SAAS;IACjB,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CACxB,4BAA4B,MAAM,CAAC,QAAQ,iCAAiC;IAC9E,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;IAC/C,MAAM,EAAE,oBAAoB;IAC5B,QAAQ,EAAE,KAAK;CAChB,CAAC,CAAC;AAEH,eAAe,IAAI,CAAC"}
|
|
@@ -1,27 +1,17 @@
|
|
|
1
|
-
import { RuleHelper } from "textlint-rule-helper";
|
|
2
1
|
import skunkedTerms from "./data/skunked-terms.json" with { type: "json" };
|
|
3
2
|
import { findUnquotedPhraseMatches } from "../../shared/matchers/phrases.js";
|
|
4
|
-
import {
|
|
5
|
-
const rule = (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
node: node,
|
|
18
|
-
ruleId: "phrases:skunked-terms",
|
|
19
|
-
message: `Skunked term found: "${match.text}". Replace it with a less disputed word.`,
|
|
20
|
-
range: { start: match.start, end: match.end }
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
};
|
|
3
|
+
import { oneToOneRule } from "../private/textlint-rule-builders.js";
|
|
4
|
+
const rule = oneToOneRule({
|
|
5
|
+
detect: (unit) => findUnquotedPhraseMatches(unit.text, skunkedTerms).map((match) => ({
|
|
6
|
+
evidence: match.text,
|
|
7
|
+
label: match.text,
|
|
8
|
+
range: { start: match.start, end: match.end }
|
|
9
|
+
})),
|
|
10
|
+
family: "phrases",
|
|
11
|
+
formatMessage: (report) => `Skunked term found: "${report.evidence}". Replace it with a less disputed word.`,
|
|
12
|
+
ignoredAncestorTypes: ["Link", "LinkReference"],
|
|
13
|
+
ruleId: "phrases:skunked-terms",
|
|
14
|
+
unitKind: "str"
|
|
15
|
+
});
|
|
26
16
|
export default rule;
|
|
27
17
|
//# sourceMappingURL=skunked-terms.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skunked-terms.js","sourceRoot":"","sources":["../../../src/rules/phrases/skunked-terms.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skunked-terms.js","sourceRoot":"","sources":["../../../src/rules/phrases/skunked-terms.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,2BAA2B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEpE,MAAM,IAAI,GAAG,YAAY,CAAC;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,yBAAyB,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjE,QAAQ,EAAE,KAAK,CAAC,IAAI;QACpB,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE;KAC9C,CAAC,CAAC;IACL,MAAM,EAAE,SAAS;IACjB,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CACxB,wBAAwB,MAAM,CAAC,QAAQ,0CAA0C;IACnF,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;IAC/C,MAAM,EAAE,uBAAuB;IAC/B,QAAQ,EAAE,KAAK;CAChB,CAAC,CAAC;AAEH,eAAe,IAAI,CAAC"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { RuleHelper } from "textlint-rule-helper";
|
|
2
1
|
import uncomparables from "./data/uncomparables.json" with { type: "json" };
|
|
3
2
|
import { findUnquotedPhraseMatches } from "../../shared/matchers/phrases.js";
|
|
4
3
|
import { normalizeForMatch } from "../../shared/text/normalize.js";
|
|
5
4
|
import { wordTokens } from "../../shared/text/tokens.js";
|
|
6
|
-
import {
|
|
5
|
+
import { oneToOneRule } from "../private/textlint-rule-builders.js";
|
|
7
6
|
const EXCEPTION_SEPARATOR = "\u0000";
|
|
8
7
|
function exceptionKey(comparator, adjective) {
|
|
9
8
|
return `${normalizeForMatch(comparator)}${EXCEPTION_SEPARATOR}${normalizeForMatch(adjective)}`;
|
|
@@ -54,29 +53,19 @@ function shouldReport(text, match) {
|
|
|
54
53
|
}
|
|
55
54
|
return !previousTokenIsAt(text, match);
|
|
56
55
|
}
|
|
57
|
-
const rule = (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
emitTextlintFinding(context, {
|
|
72
|
-
node: node,
|
|
73
|
-
ruleId: "phrases:uncomparables",
|
|
74
|
-
message: `Uncomparable phrase found: "${match.text}". Remove the modifier.`,
|
|
75
|
-
range: { start: match.start, end: match.end }
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
};
|
|
56
|
+
const rule = oneToOneRule({
|
|
57
|
+
detect: (unit) => findUnquotedPhraseMatches(unit.text, UNCOMPARABLE_PHRASES)
|
|
58
|
+
.filter((match) => shouldReport(unit.text, match))
|
|
59
|
+
.map((match) => ({
|
|
60
|
+
evidence: match.text,
|
|
61
|
+
label: match.text,
|
|
62
|
+
range: { start: match.start, end: match.end }
|
|
63
|
+
})),
|
|
64
|
+
family: "phrases",
|
|
65
|
+
formatMessage: (report) => `Uncomparable phrase found: "${report.evidence}". Remove the modifier.`,
|
|
66
|
+
ignoredAncestorTypes: ["Link", "LinkReference"],
|
|
67
|
+
ruleId: "phrases:uncomparables",
|
|
68
|
+
unitKind: "str"
|
|
69
|
+
});
|
|
81
70
|
export default rule;
|
|
82
71
|
//# sourceMappingURL=uncomparables.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uncomparables.js","sourceRoot":"","sources":["../../../src/rules/phrases/uncomparables.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"uncomparables.js","sourceRoot":"","sources":["../../../src/rules/phrases/uncomparables.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,27 +1,17 @@
|
|
|
1
|
-
import { RuleHelper } from "textlint-rule-helper";
|
|
2
1
|
import wordinessPatterns from "./data/wordiness-patterns.json" with { type: "json" };
|
|
3
2
|
import { findUnquotedPhraseMatches } from "../../shared/matchers/phrases.js";
|
|
4
|
-
import {
|
|
5
|
-
const rule = (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
node: node,
|
|
18
|
-
ruleId: "phrases:wordiness",
|
|
19
|
-
message: `Wordy phrase found: "${match.text}". Replace it with direct wording.`,
|
|
20
|
-
range: { start: match.start, end: match.end }
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
};
|
|
3
|
+
import { oneToOneRule } from "../private/textlint-rule-builders.js";
|
|
4
|
+
const rule = oneToOneRule({
|
|
5
|
+
detect: (unit) => findUnquotedPhraseMatches(unit.text, wordinessPatterns).map((match) => ({
|
|
6
|
+
evidence: match.text,
|
|
7
|
+
label: match.text,
|
|
8
|
+
range: { start: match.start, end: match.end }
|
|
9
|
+
})),
|
|
10
|
+
family: "phrases",
|
|
11
|
+
formatMessage: (report) => `Wordy phrase found: "${report.evidence}". Replace it with direct wording.`,
|
|
12
|
+
ignoredAncestorTypes: ["Link", "LinkReference"],
|
|
13
|
+
ruleId: "phrases:wordiness",
|
|
14
|
+
unitKind: "str"
|
|
15
|
+
});
|
|
26
16
|
export default rule;
|
|
27
17
|
//# sourceMappingURL=wordiness.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wordiness.js","sourceRoot":"","sources":["../../../src/rules/phrases/wordiness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wordiness.js","sourceRoot":"","sources":["../../../src/rules/phrases/wordiness.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,gCAAgC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEpE,MAAM,IAAI,GAAG,YAAY,CAAC;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,yBAAyB,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtE,QAAQ,EAAE,KAAK,CAAC,IAAI;QACpB,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE;KAC9C,CAAC,CAAC;IACL,MAAM,EAAE,SAAS;IACjB,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CACxB,wBAAwB,MAAM,CAAC,QAAQ,oCAAoC;IAC7E,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;IAC/C,MAAM,EAAE,mBAAmB;IAC3B,QAAQ,EAAE,KAAK;CAChB,CAAC,CAAC;AAEH,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { defineTextlintRule } from "../../adapters/textlint/rule.js";
|
|
2
|
+
import { documentUnit, allParagraphUnits, headingUnits, paragraphUnits, linkUnits, sectionFirstSentenceUnits, sectionLastSentenceUnits, sentenceUnits, strUnits } from "../../adapters/textlint/units.js";
|
|
3
|
+
function detector(input) {
|
|
4
|
+
return {
|
|
5
|
+
detect: ({ options, units }) => units.flatMap((unit) => input.detect(unit, options).map((detection) => ({
|
|
6
|
+
...(detection.data === undefined ? {} : { data: detection.data }),
|
|
7
|
+
evidence: detection.evidence,
|
|
8
|
+
label: detection.label,
|
|
9
|
+
range: detection.range,
|
|
10
|
+
ruleId: input.ruleId,
|
|
11
|
+
unitId: unit.id
|
|
12
|
+
}))),
|
|
13
|
+
family: input.family,
|
|
14
|
+
id: input.ruleId
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function oneToOneRule(input) {
|
|
18
|
+
return defineTextlintRule({
|
|
19
|
+
detector: detector(input),
|
|
20
|
+
formatMessage: input.formatMessage,
|
|
21
|
+
reportPolicy: { kind: "one-to-one" },
|
|
22
|
+
units: (document) => {
|
|
23
|
+
switch (input.unitKind) {
|
|
24
|
+
case "document":
|
|
25
|
+
return [documentUnit(document)];
|
|
26
|
+
case "all-paragraph":
|
|
27
|
+
return allParagraphUnits(document, input.ignoredAncestorTypes);
|
|
28
|
+
case "heading":
|
|
29
|
+
return headingUnits(document, input.ignoredAncestorTypes);
|
|
30
|
+
case "paragraph":
|
|
31
|
+
return paragraphUnits(document);
|
|
32
|
+
case "link":
|
|
33
|
+
return linkUnits(document, input.ignoredAncestorTypes);
|
|
34
|
+
case "section-first-sentence":
|
|
35
|
+
return sectionFirstSentenceUnits(document);
|
|
36
|
+
case "section-last-sentence":
|
|
37
|
+
return sectionLastSentenceUnits(document);
|
|
38
|
+
case "sentence":
|
|
39
|
+
return sentenceUnits(document);
|
|
40
|
+
case "str":
|
|
41
|
+
return strUnits(document, input.ignoredAncestorTypes);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=textlint-rule-builders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textlint-rule-builders.js","sourceRoot":"","sources":["../../../src/rules/private/textlint-rule-builders.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,SAAS,EACT,yBAAyB,EACzB,wBAAwB,EACxB,aAAa,EACb,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAwC1C,SAAS,QAAQ,CACf,KAAwE;IAExE,OAAO;QACL,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAC7B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CACrB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC9C,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;YACjE,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,IAAI,CAAC,EAAE;SAChB,CAAC,CAAC,CACJ;QACH,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,EAAE,EAAE,KAAK,CAAC,MAAM;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,KAAkC;IAElC,OAAO,kBAAkB,CAAC;QACxB,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC;QACzB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,YAAY,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;QACpC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YAClB,QAAQ,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACvB,KAAK,UAAU;oBACb,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAClC,KAAK,eAAe;oBAClB,OAAO,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;gBACjE,KAAK,SAAS;oBACZ,OAAO,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;gBAC5D,KAAK,WAAW;oBACd,OAAO,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAClC,KAAK,MAAM;oBACT,OAAO,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;gBACzD,KAAK,wBAAwB;oBAC3B,OAAO,yBAAyB,CAAC,QAAQ,CAAC,CAAC;gBAC7C,KAAK,uBAAuB;oBAC1B,OAAO,wBAAwB,CAAC,QAAQ,CAAC,CAAC;gBAC5C,KAAK,UAAU;oBACb,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACjC,KAAK,KAAK;oBACR,OAAO,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "puffery-evaluative-claim",
|
|
3
|
+
"class": "puffery",
|
|
4
|
+
"purpose": "Catch evaluative praise frames that assert prestige, breakthrough value, or greatness without naming concrete evidence.",
|
|
5
|
+
"matchMode": "full",
|
|
6
|
+
"maxTokens": 12,
|
|
7
|
+
"templates": [
|
|
8
|
+
"the {prestigeRole} {impactVerb} the {genericObject} forever.",
|
|
9
|
+
"the {productSubject} represents an unprecedented {breakthroughNoun}.",
|
|
10
|
+
"the {productSubject} is a masterpiece of {domainNoun}.",
|
|
11
|
+
"the {eventSubject} created the best version of the {workflowNoun}.",
|
|
12
|
+
"the golden standard for {domainNoun} has arrived.",
|
|
13
|
+
"the {eventSubject} marks a very special achievement.",
|
|
14
|
+
"the {actorSubject} delivered excellent infrastructure for every user."
|
|
15
|
+
],
|
|
16
|
+
"slots": {
|
|
17
|
+
"prestigeRole": [
|
|
18
|
+
"renowned architect",
|
|
19
|
+
"renowned researcher",
|
|
20
|
+
"esteemed researcher",
|
|
21
|
+
"famous founder",
|
|
22
|
+
"famous architect"
|
|
23
|
+
],
|
|
24
|
+
"impactVerb": ["changed", "transformed", "reshaped", "redefined"],
|
|
25
|
+
"genericObject": ["city", "field", "industry", "workflow", "world"],
|
|
26
|
+
"productSubject": ["product", "platform", "tool", "system", "service"],
|
|
27
|
+
"breakthroughNoun": ["breakthrough", "achievement", "advance", "milestone"],
|
|
28
|
+
"domainNoun": ["automation", "education", "modern design", "operations"],
|
|
29
|
+
"eventSubject": ["launch", "release", "update", "rollout"],
|
|
30
|
+
"workflowNoun": ["workflow", "process", "system", "platform"],
|
|
31
|
+
"actorSubject": ["team", "company", "group", "organization"]
|
|
32
|
+
},
|
|
33
|
+
"rejectIf": [
|
|
34
|
+
"sentence names a concrete metric, date, source, citation, title, quote, or named person",
|
|
35
|
+
"sentence uses an evaluative term inside a quotation",
|
|
36
|
+
"sentence provides a concrete basis for the evaluation"
|
|
37
|
+
],
|
|
38
|
+
"positiveExamples": [
|
|
39
|
+
"The renowned architect changed the city forever.",
|
|
40
|
+
"The product represents an unprecedented breakthrough.",
|
|
41
|
+
"The tool is a masterpiece of modern design.",
|
|
42
|
+
"The launch created the best version of the workflow.",
|
|
43
|
+
"The golden standard for automation has arrived.",
|
|
44
|
+
"The team delivered excellent infrastructure for every user."
|
|
45
|
+
],
|
|
46
|
+
"negativeExamples": [
|
|
47
|
+
"The renowned architect Lina Bo Bardi designed the museum in 1951.",
|
|
48
|
+
"The benchmark reported the best score, 94.1 percent, on the validation set.",
|
|
49
|
+
"The review quoted \"masterpiece\" while disagreeing with the marketing copy.",
|
|
50
|
+
"The 1918 armistice was unprecedented in the regiment's records."
|
|
51
|
+
],
|
|
52
|
+
"notes": [
|
|
53
|
+
"This uses source-backed puffery terms from the Wikipedia puffery material.",
|
|
54
|
+
"Broad words are intentionally not banned by themselves."
|
|
55
|
+
]
|
|
56
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import bodyKnows from "../patterns/body-knows.json" with { type: "json" };
|
|
2
2
|
import deicticSummary from "../patterns/deictic-summary.json" with { type: "json" };
|
|
3
3
|
import pointIsFrame from "../patterns/point-is-frame.json" with { type: "json" };
|
|
4
|
+
import pufferyEvaluativeClaim from "../patterns/puffery-evaluative-claim.json" with { type: "json" };
|
|
4
5
|
import realWorkBegins from "../patterns/real-work-begins.json" with { type: "json" };
|
|
5
6
|
import silenceAsActor from "../patterns/silence-as-actor.json" with { type: "json" };
|
|
6
7
|
import somethingShifted from "../patterns/something-shifted.json" with { type: "json" };
|
|
@@ -9,6 +10,7 @@ export const semanticThinnessPatternSetD = [
|
|
|
9
10
|
bodyKnows,
|
|
10
11
|
deicticSummary,
|
|
11
12
|
pointIsFrame,
|
|
13
|
+
pufferyEvaluativeClaim,
|
|
12
14
|
realWorkBegins,
|
|
13
15
|
silenceAsActor,
|
|
14
16
|
somethingShifted,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pattern-data-d.js","sourceRoot":"","sources":["../../../../src/rules/semantic-thinness/private/pattern-data-d.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,6BAA6B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1E,OAAO,cAAc,MAAM,kCAAkC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACpF,OAAO,YAAY,MAAM,iCAAiC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACjF,OAAO,cAAc,MAAM,mCAAmC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrF,OAAO,cAAc,MAAM,mCAAmC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrF,OAAO,gBAAgB,MAAM,oCAAoC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxF,OAAO,gBAAgB,MAAM,qCAAqC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAGzF,MAAM,CAAC,MAAM,2BAA2B,GAAuC;IAC7E,SAAS;IACT,cAAc;IACd,YAAY;IACZ,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,gBAAgB;CACjB,CAAC"}
|
|
1
|
+
{"version":3,"file":"pattern-data-d.js","sourceRoot":"","sources":["../../../../src/rules/semantic-thinness/private/pattern-data-d.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,6BAA6B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1E,OAAO,cAAc,MAAM,kCAAkC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACpF,OAAO,YAAY,MAAM,iCAAiC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACjF,OAAO,sBAAsB,MAAM,2CAA2C,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrG,OAAO,cAAc,MAAM,mCAAmC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrF,OAAO,cAAc,MAAM,mCAAmC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACrF,OAAO,gBAAgB,MAAM,oCAAoC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxF,OAAO,gBAAgB,MAAM,qCAAqC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAGzF,MAAM,CAAC,MAAM,2BAA2B,GAAuC;IAC7E,SAAS;IACT,cAAc;IACd,YAAY;IACZ,sBAAsB;IACtB,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,gBAAgB;CACjB,CAAC"}
|
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
import { allParagraphSentences } from "../../shared/text/sections.js";
|
|
2
1
|
import { semanticThinnessPatterns } from "./private/pattern-data.js";
|
|
3
|
-
import { emitTextlintFinding } from "../../adapters/textlint/report.js";
|
|
4
2
|
import { compileSemanticThinnessPatterns, findSemanticThinnessMatch } from "./private/pattern-matcher.js";
|
|
3
|
+
import { oneToOneRule } from "../private/textlint-rule-builders.js";
|
|
5
4
|
const COMPILED_PATTERNS = compileSemanticThinnessPatterns(semanticThinnessPatterns);
|
|
6
|
-
const rule = (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const match = findSemanticThinnessMatch(item.sentence.text, COMPILED_PATTERNS);
|
|
12
|
-
if (match === undefined) {
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
emitTextlintFinding(context, {
|
|
16
|
-
node: item.paragraph,
|
|
17
|
-
ruleId: "semantic-thinness:semantic-thinness",
|
|
18
|
-
message: `Semantic thinness (${match.patternId}): ${match.purpose} Matched template: ${match.signal}`,
|
|
19
|
-
range: {
|
|
20
|
-
start: item.source.originalStartFor(item.sentence.start),
|
|
21
|
-
end: item.source.originalEndFor(item.sentence.end)
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
}
|
|
5
|
+
const rule = oneToOneRule({
|
|
6
|
+
detect: (unit) => {
|
|
7
|
+
const match = findSemanticThinnessMatch(unit.text, COMPILED_PATTERNS);
|
|
8
|
+
if (match === undefined) {
|
|
9
|
+
return [];
|
|
25
10
|
}
|
|
26
|
-
|
|
27
|
-
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
data: {
|
|
14
|
+
patternId: match.patternId,
|
|
15
|
+
purpose: match.purpose,
|
|
16
|
+
signal: match.signal
|
|
17
|
+
},
|
|
18
|
+
evidence: unit.text,
|
|
19
|
+
label: match.patternId,
|
|
20
|
+
range: { start: 0, end: unit.text.length }
|
|
21
|
+
}
|
|
22
|
+
];
|
|
23
|
+
},
|
|
24
|
+
family: "semantic-thinness",
|
|
25
|
+
formatMessage: (report) => {
|
|
26
|
+
const data = report.detections[0]?.data;
|
|
27
|
+
return `Semantic thinness (${data?.["patternId"]}): ${data?.["purpose"]} Matched template: ${data?.["signal"]}`;
|
|
28
|
+
},
|
|
29
|
+
ruleId: "semantic-thinness:semantic-thinness",
|
|
30
|
+
unitKind: "sentence"
|
|
31
|
+
});
|
|
28
32
|
export default rule;
|
|
29
33
|
//# sourceMappingURL=semantic-thinness.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic-thinness.js","sourceRoot":"","sources":["../../../src/rules/semantic-thinness/semantic-thinness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"semantic-thinness.js","sourceRoot":"","sources":["../../../src/rules/semantic-thinness/semantic-thinness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEpE,MAAM,iBAAiB,GAAG,+BAA+B,CACvD,wBAAwB,CACzB,CAAC;AAEF,MAAM,IAAI,GAAG,YAAY,CAAC;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACf,MAAM,KAAK,GAAG,yBAAyB,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QACtE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;YACL;gBACE,IAAI,EAAE;oBACJ,SAAS,EAAE,KAAK,CAAC,SAAS;oBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,MAAM,EAAE,KAAK,CAAC,MAAM;iBACrB;gBACD,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;aAC3C;SACF,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,mBAAmB;IAC3B,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE;QACxB,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACxC,OAAO,sBAAsB,IAAI,EAAE,CAAC,WAAW,CAAC,MAAM,IAAI,EAAE,CAAC,SAAS,CAAC,sBAAsB,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;IAClH,CAAC;IACD,MAAM,EAAE,qCAAqC;IAC7C,QAAQ,EAAE,UAAU;CACrB,CAAC,CAAC;AAEH,eAAe,IAAI,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { cleanSentence } from "../../../shared/matchers/prose-patterns.js";
|
|
2
|
-
import {
|
|
3
|
-
import { emitTextlintFinding } from "../../../adapters/textlint/report.js";
|
|
2
|
+
import { oneToOneRule } from "../../private/textlint-rule-builders.js";
|
|
4
3
|
const PREFIXES = ["however, ", "but ", "and ", "so "];
|
|
5
4
|
const EVIDENCE_SUBJECTS = [
|
|
6
5
|
"the evidence",
|
|
@@ -59,27 +58,24 @@ function matchAuthorityPadding(sentence) {
|
|
|
59
58
|
}
|
|
60
59
|
return undefined;
|
|
61
60
|
}
|
|
62
|
-
const rule = (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const matched = matchAuthorityPadding(item.sentence.text);
|
|
68
|
-
if (matched === undefined) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
emitTextlintFinding(context, {
|
|
72
|
-
node: item.paragraph,
|
|
73
|
-
ruleId: "syntactic-patterns:authority-padding",
|
|
74
|
-
message: `Authority padding found: ${matched.signal}. Cite the actual evidence or remove the frame.`,
|
|
75
|
-
range: {
|
|
76
|
-
start: item.source.originalStartFor(item.sentence.start),
|
|
77
|
-
end: item.source.originalEndFor(item.sentence.end)
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
61
|
+
const rule = oneToOneRule({
|
|
62
|
+
detect: (unit) => {
|
|
63
|
+
const matched = matchAuthorityPadding(unit.text);
|
|
64
|
+
if (matched === undefined) {
|
|
65
|
+
return [];
|
|
81
66
|
}
|
|
82
|
-
|
|
83
|
-
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
evidence: matched.signal,
|
|
70
|
+
label: matched.kind,
|
|
71
|
+
range: { start: 0, end: unit.text.length }
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
},
|
|
75
|
+
family: "syntactic-patterns",
|
|
76
|
+
formatMessage: (report) => `Authority padding found: ${report.evidence}. Cite the actual evidence or remove the frame.`,
|
|
77
|
+
ruleId: "syntactic-patterns:authority-padding",
|
|
78
|
+
unitKind: "sentence"
|
|
79
|
+
});
|
|
84
80
|
export default rule;
|
|
85
81
|
//# sourceMappingURL=authority-padding.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authority-padding.js","sourceRoot":"","sources":["../../../../src/rules/syntactic-patterns/authority/authority-padding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authority-padding.js","sourceRoot":"","sources":["../../../../src/rules/syntactic-patterns/authority/authority-padding.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,55 +1,57 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineTextlintRule } from "../../../adapters/textlint/rule.js";
|
|
2
|
+
import { sectionLastSentenceUnits, sentenceUnits } from "../../../adapters/textlint/units.js";
|
|
2
3
|
import { wordTokens } from "../../../shared/text/tokens.js";
|
|
3
|
-
import { emitTextlintFinding } from "../../../adapters/textlint/report.js";
|
|
4
4
|
const CLOSERS = ["and that's the key.", "that's what matters."];
|
|
5
5
|
function isFormulaLine(text) {
|
|
6
6
|
const lower = text.toLocaleLowerCase("en");
|
|
7
7
|
return (wordTokens(text).length <= 6 &&
|
|
8
8
|
(lower.startsWith("that's the ") || lower.startsWith("that is the ")));
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
emitTextlintFinding(context, {
|
|
26
|
-
node: item.paragraph,
|
|
27
|
-
ruleId: "syntactic-patterns:affirmation-closers",
|
|
28
|
-
message: `Affirmation closer found: "${closer}". Replace the empty affirmation with the actual conclusion.`,
|
|
29
|
-
range: {
|
|
30
|
-
start: item.source.originalStartFor(item.sentence.start),
|
|
31
|
-
end: item.source.originalEndFor(item.sentence.end)
|
|
10
|
+
const rule = defineTextlintRule({
|
|
11
|
+
detector: {
|
|
12
|
+
detect: ({ units }) => units.flatMap((unit) => {
|
|
13
|
+
const lower = unit.text.toLocaleLowerCase("en");
|
|
14
|
+
const closer = unit.id.startsWith("section-last-sentence:")
|
|
15
|
+
? CLOSERS.find((phrase) => lower.endsWith(phrase))
|
|
16
|
+
: undefined;
|
|
17
|
+
if (closer !== undefined) {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
evidence: closer,
|
|
21
|
+
label: "affirmation-closer",
|
|
22
|
+
range: { start: 0, end: unit.text.length },
|
|
23
|
+
ruleId: "syntactic-patterns:affirmation-closers",
|
|
24
|
+
unitId: unit.id
|
|
32
25
|
}
|
|
33
|
-
|
|
26
|
+
];
|
|
34
27
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (reported.has(key) || !isFormulaLine(item.sentence.text)) {
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
reported.add(key);
|
|
41
|
-
emitTextlintFinding(context, {
|
|
42
|
-
node: item.paragraph,
|
|
43
|
-
ruleId: "syntactic-patterns:affirmation-closers",
|
|
44
|
-
message: `Formula affirmation found: "${item.sentence.text}". Replace the empty formula line with substance.`,
|
|
45
|
-
range: {
|
|
46
|
-
start: item.source.originalStartFor(item.sentence.start),
|
|
47
|
-
end: item.source.originalEndFor(item.sentence.end)
|
|
48
|
-
}
|
|
49
|
-
});
|
|
28
|
+
if (!isFormulaLine(unit.text)) {
|
|
29
|
+
return [];
|
|
50
30
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
evidence: unit.text,
|
|
34
|
+
label: "formula-affirmation",
|
|
35
|
+
range: { start: 0, end: unit.text.length },
|
|
36
|
+
ruleId: "syntactic-patterns:affirmation-closers",
|
|
37
|
+
unitId: unit.id
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
}),
|
|
41
|
+
family: "syntactic-patterns",
|
|
42
|
+
id: "syntactic-patterns:affirmation-closers"
|
|
43
|
+
},
|
|
44
|
+
formatMessage: (report) => report.detections[0]?.label === "affirmation-closer"
|
|
45
|
+
? `Affirmation closer found: "${report.evidence}". Replace the empty affirmation with the actual conclusion.`
|
|
46
|
+
: `Formula affirmation found: "${report.evidence}". Replace the empty formula line with substance.`,
|
|
47
|
+
reportPolicy: { kind: "one-to-one" },
|
|
48
|
+
units: (document) => {
|
|
49
|
+
const tailUnits = sectionLastSentenceUnits(document);
|
|
50
|
+
return [
|
|
51
|
+
...tailUnits,
|
|
52
|
+
...sentenceUnits(document).filter((unit) => !tailUnits.some((tailUnit) => tailUnit.text === unit.text && tailUnit.node === unit.node))
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
});
|
|
54
56
|
export default rule;
|
|
55
57
|
//# sourceMappingURL=affirmation-closers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affirmation-closers.js","sourceRoot":"","sources":["../../../../src/rules/syntactic-patterns/closers/affirmation-closers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"affirmation-closers.js","sourceRoot":"","sources":["../../../../src/rules/syntactic-patterns/closers/affirmation-closers.ts"],"names":[],"mappings":"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"}
|