slopless 0.2.18 → 0.2.19

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.
@@ -49,6 +49,7 @@ export const everything = {
49
49
  "required-terms": true,
50
50
  "sentence-case": true,
51
51
  "semantic-thinness": true,
52
+ "significance-density": true,
52
53
  simplicity: true,
53
54
  "skunked-terms": true,
54
55
  "softening-language": true,
@@ -4,12 +4,14 @@ import genericSignposting from "../../rules/syntactic-patterns/lead-ins/generic-
4
4
  import lessonFraming from "../../rules/syntactic-patterns/lead-ins/lesson-framing.js";
5
5
  import llmOpeners from "../../rules/syntactic-patterns/lead-ins/llm-openers.js";
6
6
  import observerGuidance from "../../rules/syntactic-patterns/lead-ins/observer-guidance.js";
7
+ import significanceDensity from "../../rules/syntactic-patterns/lead-ins/significance-density.js";
7
8
  export const leadInRules = {
8
9
  "boilerplate-framing": boilerplateFraming,
9
10
  "formal-transition-density": formalTransitionDensity,
10
11
  "generic-signposting": genericSignposting,
11
12
  "lesson-framing": lessonFraming,
12
13
  "llm-openers": llmOpeners,
13
- "observer-guidance": observerGuidance
14
+ "observer-guidance": observerGuidance,
15
+ "significance-density": significanceDensity
14
16
  };
15
17
  //# sourceMappingURL=lead-ins.js.map
@@ -634,6 +634,29 @@
634
634
  "spring to life",
635
635
  "squeaky wheel gets the grease",
636
636
  "stands as a testament to",
637
+ "serves as a reminder that",
638
+ "serves as a testament to",
639
+ "paves the way for",
640
+ "ushers in a new era",
641
+ "speaks volumes about",
642
+ "reflects a broader",
643
+ "stands as a beacon of",
644
+ "represents a paradigm shift",
645
+ "embodies the spirit of",
646
+ "cements its place as",
647
+ "leaves an indelible mark",
648
+ "heralds a new era",
649
+ "signals a seismic shift",
650
+ "drives home the point",
651
+ "brings to the fore",
652
+ "takes center stage",
653
+ "reshapes the landscape",
654
+ "charts a new course",
655
+ "shines a spotlight on",
656
+ "amplifies the need for",
657
+ "redefines the boundaries of",
658
+ "paints a vivid picture of",
659
+ "holds the key to",
637
660
  "stands out like a sore thumb",
638
661
  "start from scratch",
639
662
  "stick in the mud",
@@ -45,5 +45,22 @@
45
45
  "unlock our full potential",
46
46
  "unlock their full potential",
47
47
  "unlock your full potential",
48
- "win-win"
48
+ "win-win",
49
+ "secret sauce",
50
+ "force multiplier",
51
+ "boil the ocean",
52
+ "best-of-breed",
53
+ "go-to-market motion",
54
+ "bleeding-edge",
55
+ "drive value",
56
+ "deliver impact",
57
+ "move fast and break things",
58
+ "10x your",
59
+ "data-driven insights",
60
+ "actionable insights",
61
+ "empower your team",
62
+ "ecosystem of partners",
63
+ "innovate at the speed of",
64
+ "reimagine the future of",
65
+ "built for the enterprise"
49
66
  ]
@@ -49,7 +49,22 @@ const FILLER_OPENERS = [
49
49
  "here's the kicker",
50
50
  "honestly",
51
51
  "frankly",
52
- "candidly"
52
+ "candidly",
53
+ "truth be told",
54
+ "if i'm being honest",
55
+ "if i'm being perfectly honest",
56
+ "let me level with you",
57
+ "i'll be straight with you",
58
+ "i'll be frank",
59
+ "no sugarcoating",
60
+ "i won't sugarcoat it",
61
+ "not to put too fine a point on it",
62
+ "let's be real",
63
+ "here's the deal",
64
+ "here's what's really going on",
65
+ "when all is said and done",
66
+ "the fact of the matter is",
67
+ "the bottom line is"
53
68
  ];
54
69
  function matchEnumerationPreface(words) {
55
70
  if (words.some((word) => VAGUE_INTROS.includes(word)) &&
@@ -3,12 +3,6 @@ import { cleanSentence, containsAny, tokens } from "../../../shared/matchers/pro
3
3
  import { oneToOneRule } from "../../private/textlint-rule-builders.js";
4
4
  import { matchDiscourseEvaluationFrame } from "./private/discourse-evaluation.js";
5
5
  const PREFIXES = ["however, ", "but ", "and ", "so "];
6
- const IMPORTANT_TO_PATTERNS = [
7
- "it's important to note",
8
- "it is important to note",
9
- "it's important to remember",
10
- "it is important to remember"
11
- ];
12
6
  const TRANSITION_PATTERNS = ["that being said", "as such"];
13
7
  const CONSULTATION_PATTERNS = [
14
8
  "it's always best to consult",
@@ -284,7 +278,6 @@ function matchSignposting(sentence) {
284
278
  return { kind: "formulaic-content-setup", signal: formulaicSetup };
285
279
  }
286
280
  const checks = [
287
- ["important-to", IMPORTANT_TO_PATTERNS],
288
281
  ["transition", TRANSITION_PATTERNS],
289
282
  ["consultation-signpost", CONSULTATION_PATTERNS],
290
283
  ["note-signpost", NOTE_PATTERNS],
@@ -0,0 +1,95 @@
1
+ import { splitSentences } from "../../../shared/text/sentences.js";
2
+ import { wordTokens } from "../../../shared/text/tokens.js";
3
+ import { isWhitespace } from "../../../shared/text/whitespace.js";
4
+ import { oneToOneRule } from "../../private/textlint-rule-builders.js";
5
+ // Document-level significance signposting. A single "Notably," or "It's worth noting
6
+ // that" is legitimate (technical and academic writing use them), so this is NOT a
7
+ // per-instance flag. The slop tic is sprinkling several across a short piece: AI prose
8
+ // does this constantly, technical prose almost never (0% of 600 PEP/MDN/RFC docs reach
9
+ // the threshold; ~90% of synthetic marketing slop does). Fires once per document when
10
+ // there are enough sentence-initial significance markers AND they are dense enough.
11
+ const MARKERS = [
12
+ ["notably"],
13
+ ["importantly"],
14
+ ["crucially"],
15
+ ["significantly"],
16
+ ["interestingly"],
17
+ ["remarkably"],
18
+ ["curiously"],
19
+ ["tellingly"],
20
+ ["strikingly"],
21
+ ["worth", "noting"],
22
+ ["it's", "worth", "noting"],
23
+ ["it", "is", "worth", "noting"],
24
+ ["it's", "important", "to", "note"],
25
+ ["it", "is", "important", "to", "note"],
26
+ ["it's", "important", "to", "remember"],
27
+ ["it", "is", "important", "to", "remember"],
28
+ ["it", "bears", "mentioning"]
29
+ ];
30
+ const MINIMUM_COUNT = 3;
31
+ const MINIMUM_RATE_PER_1000 = 3;
32
+ function markerLength(tokens) {
33
+ for (const marker of MARKERS) {
34
+ if (marker.every((word, index) => tokens[index]?.normalized === word)) {
35
+ return marker.length;
36
+ }
37
+ }
38
+ return 0;
39
+ }
40
+ function countWords(text) {
41
+ let count = 0;
42
+ let inWord = false;
43
+ for (const character of text) {
44
+ if (isWhitespace(character)) {
45
+ inWord = false;
46
+ }
47
+ else if (!inWord) {
48
+ count += 1;
49
+ inWord = true;
50
+ }
51
+ }
52
+ return count;
53
+ }
54
+ const rule = oneToOneRule({
55
+ detect: (unit) => {
56
+ const hits = [];
57
+ for (const sentence of splitSentences(unit.text)) {
58
+ const tokens = wordTokens(sentence.text);
59
+ const length = markerLength(tokens);
60
+ if (length === 0) {
61
+ continue;
62
+ }
63
+ const first = tokens[0];
64
+ const last = tokens[length - 1];
65
+ if (first === undefined || last === undefined) {
66
+ continue;
67
+ }
68
+ hits.push({
69
+ end: sentence.start + last.end,
70
+ start: sentence.start + first.start
71
+ });
72
+ }
73
+ const words = countWords(unit.text);
74
+ const rate = words === 0 ? 0 : (hits.length * 1000) / words;
75
+ const firstHit = hits[0];
76
+ if (hits.length < MINIMUM_COUNT ||
77
+ rate < MINIMUM_RATE_PER_1000 ||
78
+ firstHit === undefined) {
79
+ return [];
80
+ }
81
+ return [
82
+ {
83
+ evidence: `${hits.length} significance signposts in ${words} words`,
84
+ label: "significance-signposting",
85
+ range: { end: firstHit.end, start: firstHit.start }
86
+ }
87
+ ];
88
+ },
89
+ family: "syntactic-patterns",
90
+ formatMessage: (report) => `Significance signposting density: ${report.evidence}. Cut the signposting and lead with the point.`,
91
+ ruleId: "syntactic-patterns:significance-density",
92
+ unitKind: "document"
93
+ });
94
+ export default rule;
95
+ //# sourceMappingURL=significance-density.js.map
@@ -19,12 +19,7 @@
19
19
  "hope this message finds you well",
20
20
  "this is not an exhaustive list"
21
21
  ],
22
- "paragraphStartsWith": [
23
- "it is important to note",
24
- "it's important to note",
25
- "it is worth noting",
26
- "it's worth noting"
27
- ],
22
+ "paragraphStartsWith": [],
28
23
  "contains": [
29
24
  "want me to delve deeper",
30
25
  "would you like me to delve",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slopless",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "description": "Deterministic textlint rules and CLI for catching prose slop in English Markdown.",
5
5
  "keywords": [
6
6
  "textlint",