slopless 0.2.23 → 0.2.25
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/dist/rules/semantic-thinness/patterns/abstract-metaphor-claim.json +83 -1
- package/dist/rules/semantic-thinness/patterns/deictic-summary.json +31 -2
- package/dist/rules/semantic-thinness/patterns/empty-quantification.json +33 -0
- package/dist/rules/semantic-thinness/patterns/empty-scene-transition.json +2 -1
- package/dist/rules/semantic-thinness/private/concrete-guards.js +2 -0
- package/dist/rules/semantic-thinness/private/pattern-data-e.js +2 -0
- package/dist/rules/semantic-thinness/private/pattern-matcher.js +28 -7
- package/dist/rules/syntactic-patterns/closers/affirmation-closers.js +13 -3
- package/dist/rules/syntactic-patterns/contrast/contrastive-aphorism.js +2 -0
- package/dist/rules/syntactic-patterns/contrast/negation-reframe.js +1 -1
- package/dist/rules/syntactic-patterns/contrast/private/action-reframe-vocabulary.js +47 -0
- package/dist/rules/syntactic-patterns/contrast/private/audience-replacement.js +267 -0
- package/dist/rules/syntactic-patterns/contrast/private/copular-reframe.js +79 -0
- package/dist/rules/syntactic-patterns/contrast/private/evidence-limitation-pair.js +307 -0
- package/dist/rules/syntactic-patterns/contrast/private/inline-semicolon-reframe.js +50 -0
- package/dist/rules/syntactic-patterns/contrast/private/inline-short-negation.js +1 -0
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-matcher.js +78 -73
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-parts.js +99 -31
- package/dist/rules/syntactic-patterns/contrast/private/negation-vocabulary.js +27 -0
- package/dist/rules/syntactic-patterns/contrast/private/negative-consequence.js +301 -0
- package/dist/rules/syntactic-patterns/contrast/private/negative-slop-frames.js +155 -39
- package/dist/rules/syntactic-patterns/contrast/private/policy-object.js +55 -0
- package/dist/rules/syntactic-patterns/contrast/private/reframe-classification.js +214 -0
- package/dist/rules/syntactic-patterns/contrast/private/sequence-reframes.js +9 -0
- package/dist/rules/syntactic-patterns/contrast/private/temporal-reframe.js +318 -0
- package/dist/rules/syntactic-patterns/lead-ins/generic-signposting.js +96 -102
- package/dist/rules/syntactic-patterns/lead-ins/private/component-assignment-frame.js +239 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/discourse-evaluation.js +150 -4
- package/dist/rules/syntactic-patterns/lead-ins/private/evaluative-colon-frame.js +166 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/reaction-frame.js +29 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/relative-discourse-frame.js +119 -0
- package/package.json +1 -1
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { wordTokens } from "../../../../shared/text/tokens.js";
|
|
2
|
+
const HUMAN_AUDIENCES = new Set([
|
|
3
|
+
"buyers",
|
|
4
|
+
"customers",
|
|
5
|
+
"people",
|
|
6
|
+
"readers",
|
|
7
|
+
"researchers",
|
|
8
|
+
"shoppers",
|
|
9
|
+
"users",
|
|
10
|
+
"visitors"
|
|
11
|
+
]);
|
|
12
|
+
const MACHINE_ACTORS = new Set([
|
|
13
|
+
"agent",
|
|
14
|
+
"agents",
|
|
15
|
+
"ai",
|
|
16
|
+
"algorithm",
|
|
17
|
+
"algorithms",
|
|
18
|
+
"assistant",
|
|
19
|
+
"assistants",
|
|
20
|
+
"bot",
|
|
21
|
+
"bots",
|
|
22
|
+
"crawler",
|
|
23
|
+
"crawlers",
|
|
24
|
+
"machine",
|
|
25
|
+
"machines",
|
|
26
|
+
"model",
|
|
27
|
+
"models",
|
|
28
|
+
"system",
|
|
29
|
+
"systems"
|
|
30
|
+
]);
|
|
31
|
+
const PREDICATES = new Map([
|
|
32
|
+
["buy", "buy"],
|
|
33
|
+
["buys", "buy"],
|
|
34
|
+
["bought", "buy"],
|
|
35
|
+
["choose", "choose"],
|
|
36
|
+
["chooses", "choose"],
|
|
37
|
+
["chose", "choose"],
|
|
38
|
+
["compare", "compare"],
|
|
39
|
+
["compares", "compare"],
|
|
40
|
+
["compared", "compare"],
|
|
41
|
+
["evaluate", "evaluate"],
|
|
42
|
+
["evaluates", "evaluate"],
|
|
43
|
+
["evaluated", "evaluate"],
|
|
44
|
+
["find", "find"],
|
|
45
|
+
["finds", "find"],
|
|
46
|
+
["found", "find"],
|
|
47
|
+
["inspect", "inspect"],
|
|
48
|
+
["inspects", "inspect"],
|
|
49
|
+
["inspected", "inspect"],
|
|
50
|
+
["purchase", "purchase"],
|
|
51
|
+
["purchases", "purchase"],
|
|
52
|
+
["purchased", "purchase"],
|
|
53
|
+
["read", "read"],
|
|
54
|
+
["reads", "read"],
|
|
55
|
+
["review", "review"],
|
|
56
|
+
["reviews", "review"],
|
|
57
|
+
["reviewed", "review"],
|
|
58
|
+
["search", "search"],
|
|
59
|
+
["searches", "search"],
|
|
60
|
+
["searched", "search"],
|
|
61
|
+
["select", "select"],
|
|
62
|
+
["selects", "select"],
|
|
63
|
+
["selected", "select"],
|
|
64
|
+
["scan", "scan"],
|
|
65
|
+
["scans", "scan"],
|
|
66
|
+
["scanned", "scan"]
|
|
67
|
+
]);
|
|
68
|
+
const CAUSAL_CONNECTORS = new Set([
|
|
69
|
+
"after",
|
|
70
|
+
"because",
|
|
71
|
+
"if",
|
|
72
|
+
"since",
|
|
73
|
+
"therefore",
|
|
74
|
+
"until",
|
|
75
|
+
"when",
|
|
76
|
+
"while"
|
|
77
|
+
]);
|
|
78
|
+
const OBJECT_FILLERS = new Set([
|
|
79
|
+
"a",
|
|
80
|
+
"an",
|
|
81
|
+
"and",
|
|
82
|
+
"at",
|
|
83
|
+
"for",
|
|
84
|
+
"from",
|
|
85
|
+
"in",
|
|
86
|
+
"its",
|
|
87
|
+
"my",
|
|
88
|
+
"of",
|
|
89
|
+
"on",
|
|
90
|
+
"our",
|
|
91
|
+
"the",
|
|
92
|
+
"their",
|
|
93
|
+
"to",
|
|
94
|
+
"your"
|
|
95
|
+
]);
|
|
96
|
+
const OBJECT_PRONOUNS = new Set([
|
|
97
|
+
"he",
|
|
98
|
+
"her",
|
|
99
|
+
"him",
|
|
100
|
+
"it",
|
|
101
|
+
"me",
|
|
102
|
+
"she",
|
|
103
|
+
"them",
|
|
104
|
+
"they",
|
|
105
|
+
"us",
|
|
106
|
+
"we",
|
|
107
|
+
"you"
|
|
108
|
+
]);
|
|
109
|
+
const ARTIFACT_SURFACES = new Set([
|
|
110
|
+
"catalog",
|
|
111
|
+
"dashboard",
|
|
112
|
+
"database",
|
|
113
|
+
"feed",
|
|
114
|
+
"index",
|
|
115
|
+
"listing",
|
|
116
|
+
"page",
|
|
117
|
+
"report",
|
|
118
|
+
"site"
|
|
119
|
+
]);
|
|
120
|
+
function words(text) {
|
|
121
|
+
return wordTokens(text).map((token) => token.normalized);
|
|
122
|
+
}
|
|
123
|
+
function hasQuote(text) {
|
|
124
|
+
return [...text].some((character) => character === '"' ||
|
|
125
|
+
character === "\u201c" ||
|
|
126
|
+
character === "\u201d" ||
|
|
127
|
+
character === "`");
|
|
128
|
+
}
|
|
129
|
+
function hasDigit(word) {
|
|
130
|
+
return [...word].some((character) => character >= "0" && character <= "9");
|
|
131
|
+
}
|
|
132
|
+
function hasRejectedSurface(text, sentenceWords) {
|
|
133
|
+
return (hasQuote(text) ||
|
|
134
|
+
sentenceWords.some((word) => CAUSAL_CONNECTORS.has(word) || hasDigit(word)));
|
|
135
|
+
}
|
|
136
|
+
function stripTimeMarker(sentenceWords) {
|
|
137
|
+
const suffixes = [
|
|
138
|
+
["anymore"],
|
|
139
|
+
["now"],
|
|
140
|
+
["any", "longer"],
|
|
141
|
+
["these", "days"]
|
|
142
|
+
];
|
|
143
|
+
for (const suffix of suffixes) {
|
|
144
|
+
const start = sentenceWords.length - suffix.length;
|
|
145
|
+
if (start > 0 &&
|
|
146
|
+
suffix.every((word, index) => sentenceWords[start + index] === word)) {
|
|
147
|
+
return sentenceWords.slice(0, start);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
function humanAudienceEnd(sentenceWords) {
|
|
153
|
+
const first = sentenceWords[0];
|
|
154
|
+
if (first === "nobody") {
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
if (first === "no" && sentenceWords[1] === "one") {
|
|
158
|
+
return 2;
|
|
159
|
+
}
|
|
160
|
+
const headIndex = first === "the" || first === "most" || first === "many" ? 1 : 0;
|
|
161
|
+
return HUMAN_AUDIENCES.has(sentenceWords[headIndex] ?? "")
|
|
162
|
+
? headIndex + 1
|
|
163
|
+
: undefined;
|
|
164
|
+
}
|
|
165
|
+
function firstClaim(sentenceWords) {
|
|
166
|
+
const originalSubjectEnd = humanAudienceEnd(sentenceWords);
|
|
167
|
+
const withoutTime = stripTimeMarker(sentenceWords) ??
|
|
168
|
+
(originalSubjectEnd !== undefined &&
|
|
169
|
+
sentenceWords[originalSubjectEnd] === "no" &&
|
|
170
|
+
sentenceWords[originalSubjectEnd + 1] === "longer"
|
|
171
|
+
? sentenceWords
|
|
172
|
+
: undefined);
|
|
173
|
+
if (withoutTime === undefined) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
const subjectEnd = humanAudienceEnd(withoutTime);
|
|
177
|
+
if (subjectEnd === undefined) {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
let predicateIndex = subjectEnd;
|
|
181
|
+
const subjectStart = withoutTime[0];
|
|
182
|
+
if (subjectStart !== "nobody" && subjectStart !== "no") {
|
|
183
|
+
if (withoutTime[predicateIndex] === "don't" ||
|
|
184
|
+
withoutTime[predicateIndex] === "doesn't" ||
|
|
185
|
+
withoutTime[predicateIndex] === "didn't") {
|
|
186
|
+
predicateIndex += 1;
|
|
187
|
+
}
|
|
188
|
+
else if (withoutTime[predicateIndex] === "do" &&
|
|
189
|
+
withoutTime[predicateIndex + 1] === "not") {
|
|
190
|
+
predicateIndex += 2;
|
|
191
|
+
}
|
|
192
|
+
else if (withoutTime[predicateIndex] === "no" &&
|
|
193
|
+
withoutTime[predicateIndex + 1] === "longer") {
|
|
194
|
+
predicateIndex += 2;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const predicate = PREDICATES.get(withoutTime[predicateIndex] ?? "");
|
|
201
|
+
const object = withoutTime.slice(predicateIndex + 1);
|
|
202
|
+
return predicate !== undefined && object.length > 0
|
|
203
|
+
? { object, predicate }
|
|
204
|
+
: undefined;
|
|
205
|
+
}
|
|
206
|
+
function machineActorEnd(sentenceWords) {
|
|
207
|
+
let index = sentenceWords[0] === "a" ||
|
|
208
|
+
sentenceWords[0] === "an" ||
|
|
209
|
+
sentenceWords[0] === "the"
|
|
210
|
+
? 1
|
|
211
|
+
: 0;
|
|
212
|
+
const actorStart = index;
|
|
213
|
+
while (index < actorStart + 2 &&
|
|
214
|
+
MACHINE_ACTORS.has(sentenceWords[index] ?? "")) {
|
|
215
|
+
index += 1;
|
|
216
|
+
}
|
|
217
|
+
return index > actorStart ? index : undefined;
|
|
218
|
+
}
|
|
219
|
+
function secondClaim(sentenceWords) {
|
|
220
|
+
const actorEnd = machineActorEnd(sentenceWords);
|
|
221
|
+
if (actorEnd === undefined) {
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
const predicate = PREDICATES.get(sentenceWords[actorEnd] ?? "");
|
|
225
|
+
const object = sentenceWords.slice(actorEnd + 1);
|
|
226
|
+
return predicate !== undefined && object.length > 0
|
|
227
|
+
? { object, predicate }
|
|
228
|
+
: undefined;
|
|
229
|
+
}
|
|
230
|
+
function contentWords(object) {
|
|
231
|
+
return new Set(object.filter((word) => !OBJECT_FILLERS.has(word) && !OBJECT_PRONOUNS.has(word)));
|
|
232
|
+
}
|
|
233
|
+
function sharesContent(firstObject, secondObject) {
|
|
234
|
+
if (secondObject.length === 0 ||
|
|
235
|
+
secondObject.every((word) => OBJECT_PRONOUNS.has(word))) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
const firstContent = contentWords(firstObject);
|
|
239
|
+
const secondContent = contentWords(secondObject);
|
|
240
|
+
const sameContent = firstContent.size === secondContent.size &&
|
|
241
|
+
[...firstContent].every((word) => secondContent.has(word));
|
|
242
|
+
const firstCore = [...firstContent].filter((word) => !ARTIFACT_SURFACES.has(word));
|
|
243
|
+
const secondCore = [...secondContent].filter((word) => !ARTIFACT_SURFACES.has(word));
|
|
244
|
+
return (sameContent ||
|
|
245
|
+
(firstCore.length > 0 &&
|
|
246
|
+
firstCore.length === secondCore.length &&
|
|
247
|
+
firstCore.every((word) => secondCore.includes(word))));
|
|
248
|
+
}
|
|
249
|
+
export function matchAudienceReplacement(first, second) {
|
|
250
|
+
const firstWords = words(first);
|
|
251
|
+
const secondWords = words(second);
|
|
252
|
+
if (firstWords.length > 24 ||
|
|
253
|
+
secondWords.length > 20 ||
|
|
254
|
+
hasRejectedSurface(first, firstWords) ||
|
|
255
|
+
hasRejectedSurface(second, secondWords)) {
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
const humanClaim = firstClaim(firstWords);
|
|
259
|
+
const machineClaim = secondClaim(secondWords);
|
|
260
|
+
if (humanClaim === undefined ||
|
|
261
|
+
machineClaim?.predicate !== humanClaim.predicate ||
|
|
262
|
+
!sharesContent(humanClaim.object, machineClaim.object)) {
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
return `${first} ${second}`;
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=audience-replacement.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { FACTUAL_NEGATION_CONNECTORS, NEGATION_WORDS, findCopularNegation, pronounCopulaStart, skipOptionalAdverbs, startsWithPronounCopula, startsWithWords, startsWithSubjectCopula, validSubject, words } from "./negation-reframe-parts.js";
|
|
2
|
+
const AGENTIC_SYSTEM_SUBJECTS = new Set([
|
|
3
|
+
"agent",
|
|
4
|
+
"assistant",
|
|
5
|
+
"engine",
|
|
6
|
+
"model",
|
|
7
|
+
"system",
|
|
8
|
+
"tool"
|
|
9
|
+
]);
|
|
10
|
+
const PAYOFF_VERBS = new Set([
|
|
11
|
+
"compared",
|
|
12
|
+
"considered",
|
|
13
|
+
"encountered",
|
|
14
|
+
"entered",
|
|
15
|
+
"evaluated",
|
|
16
|
+
"found",
|
|
17
|
+
"met",
|
|
18
|
+
"qualified",
|
|
19
|
+
"ranked",
|
|
20
|
+
"reached",
|
|
21
|
+
"reviewed",
|
|
22
|
+
"selected",
|
|
23
|
+
"seen"
|
|
24
|
+
]);
|
|
25
|
+
export function sameSubjectCopularReframe(aTokens, bTokens) {
|
|
26
|
+
const negation = findCopularNegation(aTokens);
|
|
27
|
+
if (negation === undefined || !validSubject(negation.subject)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return startsWithSubjectCopula(bTokens, negation.subject, negation.affirmativeAux);
|
|
31
|
+
}
|
|
32
|
+
export function pronounCopularReframe(aTokens, bTokens) {
|
|
33
|
+
const negation = findCopularNegation(aTokens);
|
|
34
|
+
return (negation !== undefined &&
|
|
35
|
+
validSubject(negation.subject) &&
|
|
36
|
+
!startsWithNegatedPronounCopula(bTokens) &&
|
|
37
|
+
startsWithPronounCopula(bTokens));
|
|
38
|
+
}
|
|
39
|
+
export function progressiveVerbMirror(aTokens, bTokens) {
|
|
40
|
+
const negation = findCopularNegation(aTokens);
|
|
41
|
+
if (negation === undefined || !validSubject(negation.subject)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const tokenWords = words(aTokens);
|
|
45
|
+
const predicateIndex = skipOptionalAdverbs(tokenWords, negation.negatedPredicateStart);
|
|
46
|
+
const verb = tokenWords[predicateIndex];
|
|
47
|
+
return (verb !== undefined &&
|
|
48
|
+
verb.endsWith("ing") &&
|
|
49
|
+
startsWithWords(bTokens, [
|
|
50
|
+
...negation.subject,
|
|
51
|
+
negation.affirmativeAux,
|
|
52
|
+
verb
|
|
53
|
+
]));
|
|
54
|
+
}
|
|
55
|
+
export function startsWithNegatedPronounCopula(tokens) {
|
|
56
|
+
const start = pronounCopulaStart(tokens);
|
|
57
|
+
if (start === undefined) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
const tokenWords = words(tokens);
|
|
61
|
+
const predicateIndex = skipOptionalAdverbs(tokenWords, start.predicateStart);
|
|
62
|
+
return NEGATION_WORDS.has(tokenWords[predicateIndex] ?? "");
|
|
63
|
+
}
|
|
64
|
+
export function negatedProgressiveNeverPayoff(first, second) {
|
|
65
|
+
const negation = findCopularNegation(first);
|
|
66
|
+
if (negation === undefined ||
|
|
67
|
+
!AGENTIC_SYSTEM_SUBJECTS.has(negation.subject.at(-1) ?? "") ||
|
|
68
|
+
words(first)[negation.negatedPredicateStart]?.endsWith("ing") !== true) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const secondWords = words(second);
|
|
72
|
+
const neverIndex = secondWords.slice(1, 4).indexOf("never") + 1;
|
|
73
|
+
return (["it", "they"].includes(secondWords[0] ?? "") &&
|
|
74
|
+
neverIndex > 0 &&
|
|
75
|
+
PAYOFF_VERBS.has(secondWords[neverIndex + 1] ?? "") &&
|
|
76
|
+
!secondWords.some((word) => FACTUAL_NEGATION_CONNECTORS.has(word)) &&
|
|
77
|
+
secondWords.length <= 10);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=copular-reframe.js.map
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { cleanSentence, tokens } from "../../../../shared/matchers/prose-patterns.js";
|
|
2
|
+
const PREFIXES = ["and ", "but ", "so "];
|
|
3
|
+
const SIMPLE_SUBJECT_STARTERS = new Set([
|
|
4
|
+
"a",
|
|
5
|
+
"an",
|
|
6
|
+
"my",
|
|
7
|
+
"our",
|
|
8
|
+
"that",
|
|
9
|
+
"the",
|
|
10
|
+
"their",
|
|
11
|
+
"these",
|
|
12
|
+
"this",
|
|
13
|
+
"those",
|
|
14
|
+
"your"
|
|
15
|
+
]);
|
|
16
|
+
const EVIDENCE_PROXY_HEADS = new Set([
|
|
17
|
+
"award",
|
|
18
|
+
"awards",
|
|
19
|
+
"benchmark",
|
|
20
|
+
"benchmarks",
|
|
21
|
+
"case",
|
|
22
|
+
"cases",
|
|
23
|
+
"comment",
|
|
24
|
+
"comments",
|
|
25
|
+
"dashboard",
|
|
26
|
+
"dashboards",
|
|
27
|
+
"demo",
|
|
28
|
+
"demos",
|
|
29
|
+
"example",
|
|
30
|
+
"examples",
|
|
31
|
+
"metric",
|
|
32
|
+
"metrics",
|
|
33
|
+
"number",
|
|
34
|
+
"numbers",
|
|
35
|
+
"rating",
|
|
36
|
+
"ratings",
|
|
37
|
+
"review",
|
|
38
|
+
"reviews",
|
|
39
|
+
"score",
|
|
40
|
+
"scores",
|
|
41
|
+
"screenshot",
|
|
42
|
+
"screenshots",
|
|
43
|
+
"signal",
|
|
44
|
+
"signals",
|
|
45
|
+
"survey",
|
|
46
|
+
"surveys",
|
|
47
|
+
"testimonial",
|
|
48
|
+
"testimonials"
|
|
49
|
+
]);
|
|
50
|
+
const PLURAL_EVIDENCE_PROXY_HEADS = new Set([
|
|
51
|
+
"awards",
|
|
52
|
+
"benchmarks",
|
|
53
|
+
"cases",
|
|
54
|
+
"comments",
|
|
55
|
+
"dashboards",
|
|
56
|
+
"demos",
|
|
57
|
+
"examples",
|
|
58
|
+
"metrics",
|
|
59
|
+
"numbers",
|
|
60
|
+
"ratings",
|
|
61
|
+
"reviews",
|
|
62
|
+
"scores",
|
|
63
|
+
"screenshots",
|
|
64
|
+
"signals",
|
|
65
|
+
"surveys",
|
|
66
|
+
"testimonials"
|
|
67
|
+
]);
|
|
68
|
+
const COMPLEX_SUBJECT_MARKERS = new Set([
|
|
69
|
+
"about",
|
|
70
|
+
"against",
|
|
71
|
+
"among",
|
|
72
|
+
"around",
|
|
73
|
+
"as",
|
|
74
|
+
"at",
|
|
75
|
+
"beside",
|
|
76
|
+
"between",
|
|
77
|
+
"by",
|
|
78
|
+
"compared",
|
|
79
|
+
"containing",
|
|
80
|
+
"for",
|
|
81
|
+
"from",
|
|
82
|
+
"in",
|
|
83
|
+
"including",
|
|
84
|
+
"near",
|
|
85
|
+
"of",
|
|
86
|
+
"on",
|
|
87
|
+
"or",
|
|
88
|
+
"over",
|
|
89
|
+
"under",
|
|
90
|
+
"with",
|
|
91
|
+
"without",
|
|
92
|
+
"and"
|
|
93
|
+
]);
|
|
94
|
+
const EVIDENCE_AUXILIARIES = new Set([
|
|
95
|
+
"can",
|
|
96
|
+
"could",
|
|
97
|
+
"had",
|
|
98
|
+
"has",
|
|
99
|
+
"have",
|
|
100
|
+
"may",
|
|
101
|
+
"might",
|
|
102
|
+
"will",
|
|
103
|
+
"would"
|
|
104
|
+
]);
|
|
105
|
+
const EVIDENCE_ASSERTION_VERBS = new Set([
|
|
106
|
+
"confirm",
|
|
107
|
+
"confirmed",
|
|
108
|
+
"confirms",
|
|
109
|
+
"demonstrate",
|
|
110
|
+
"demonstrated",
|
|
111
|
+
"demonstrates",
|
|
112
|
+
"document",
|
|
113
|
+
"documented",
|
|
114
|
+
"documents",
|
|
115
|
+
"establish",
|
|
116
|
+
"established",
|
|
117
|
+
"establishes",
|
|
118
|
+
"imply",
|
|
119
|
+
"implied",
|
|
120
|
+
"implies",
|
|
121
|
+
"indicate",
|
|
122
|
+
"indicated",
|
|
123
|
+
"indicates",
|
|
124
|
+
"prove",
|
|
125
|
+
"proved",
|
|
126
|
+
"proven",
|
|
127
|
+
"proves",
|
|
128
|
+
"reveal",
|
|
129
|
+
"revealed",
|
|
130
|
+
"reveals",
|
|
131
|
+
"show",
|
|
132
|
+
"showed",
|
|
133
|
+
"shown",
|
|
134
|
+
"shows",
|
|
135
|
+
"signal",
|
|
136
|
+
"signaled",
|
|
137
|
+
"signalled",
|
|
138
|
+
"signals",
|
|
139
|
+
"suggest",
|
|
140
|
+
"suggested",
|
|
141
|
+
"suggests",
|
|
142
|
+
"support",
|
|
143
|
+
"supported",
|
|
144
|
+
"supports",
|
|
145
|
+
"tell",
|
|
146
|
+
"told",
|
|
147
|
+
"validate",
|
|
148
|
+
"validated",
|
|
149
|
+
"validates",
|
|
150
|
+
"verified",
|
|
151
|
+
"verifies",
|
|
152
|
+
"verify"
|
|
153
|
+
]);
|
|
154
|
+
const LIMITATION_REPORTING_VERBS = new Set([
|
|
155
|
+
"communicate",
|
|
156
|
+
"communicated",
|
|
157
|
+
"communicates",
|
|
158
|
+
"convey",
|
|
159
|
+
"conveyed",
|
|
160
|
+
"conveys",
|
|
161
|
+
"demonstrate",
|
|
162
|
+
"demonstrated",
|
|
163
|
+
"demonstrates",
|
|
164
|
+
"establish",
|
|
165
|
+
"established",
|
|
166
|
+
"establishes",
|
|
167
|
+
"explain",
|
|
168
|
+
"explained",
|
|
169
|
+
"explains",
|
|
170
|
+
"indicate",
|
|
171
|
+
"indicated",
|
|
172
|
+
"indicates",
|
|
173
|
+
"offer",
|
|
174
|
+
"offered",
|
|
175
|
+
"offers",
|
|
176
|
+
"provide",
|
|
177
|
+
"provided",
|
|
178
|
+
"provides",
|
|
179
|
+
"prove",
|
|
180
|
+
"proved",
|
|
181
|
+
"proves",
|
|
182
|
+
"reveal",
|
|
183
|
+
"revealed",
|
|
184
|
+
"reveals",
|
|
185
|
+
"say",
|
|
186
|
+
"said",
|
|
187
|
+
"says",
|
|
188
|
+
"show",
|
|
189
|
+
"showed",
|
|
190
|
+
"shows",
|
|
191
|
+
"signal",
|
|
192
|
+
"signaled",
|
|
193
|
+
"signalled",
|
|
194
|
+
"signals",
|
|
195
|
+
"suggest",
|
|
196
|
+
"suggested",
|
|
197
|
+
"suggests",
|
|
198
|
+
"tell",
|
|
199
|
+
"told",
|
|
200
|
+
"tells"
|
|
201
|
+
]);
|
|
202
|
+
const LIMITATION_AUXILIARIES = new Set(["did", "does"]);
|
|
203
|
+
const CONTRACTED_LIMITATION_AUXILIARIES = new Set(["didn't", "doesn't"]);
|
|
204
|
+
const REPORTING_OBJECTS = new Set(["buyers", "readers", "us", "you"]);
|
|
205
|
+
const LIMITATION_PRONOUNS = new Set([
|
|
206
|
+
"it",
|
|
207
|
+
"that",
|
|
208
|
+
"these",
|
|
209
|
+
"they",
|
|
210
|
+
"this",
|
|
211
|
+
"those"
|
|
212
|
+
]);
|
|
213
|
+
const LOW_INFORMATION_LIMITS = [
|
|
214
|
+
["little"],
|
|
215
|
+
["very", "little"],
|
|
216
|
+
["nothing"],
|
|
217
|
+
["not", "much"],
|
|
218
|
+
["only", "so", "much"],
|
|
219
|
+
["something"],
|
|
220
|
+
["no", "context"],
|
|
221
|
+
["no", "evidence"],
|
|
222
|
+
["no", "information"],
|
|
223
|
+
["no", "insight"]
|
|
224
|
+
];
|
|
225
|
+
function evidenceSubjectHead(words) {
|
|
226
|
+
const firstWord = words[0] ?? "";
|
|
227
|
+
if (firstWord === "that" && SIMPLE_SUBJECT_STARTERS.has(words[1] ?? "")) {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
if (!SIMPLE_SUBJECT_STARTERS.has(firstWord) &&
|
|
231
|
+
!EVIDENCE_PROXY_HEADS.has(firstWord)) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
const verbIndex = words.findIndex((word) => EVIDENCE_ASSERTION_VERBS.has(word));
|
|
235
|
+
const headIndex = EVIDENCE_AUXILIARIES.has(words[verbIndex - 1] ?? "")
|
|
236
|
+
? verbIndex - 2
|
|
237
|
+
: verbIndex - 1;
|
|
238
|
+
const head = words[headIndex];
|
|
239
|
+
const subjectModifiers = words.slice(0, headIndex);
|
|
240
|
+
return verbIndex > 0 &&
|
|
241
|
+
verbIndex < words.length - 1 &&
|
|
242
|
+
head !== undefined &&
|
|
243
|
+
EVIDENCE_PROXY_HEADS.has(head) &&
|
|
244
|
+
!subjectModifiers.some((word) => COMPLEX_SUBJECT_MARKERS.has(word))
|
|
245
|
+
? head
|
|
246
|
+
: undefined;
|
|
247
|
+
}
|
|
248
|
+
function startsWithLimit(words, start, limit) {
|
|
249
|
+
return limit.every((word, index) => words[start + index] === word);
|
|
250
|
+
}
|
|
251
|
+
function hasVagueContinuation(words, start, limit) {
|
|
252
|
+
const next = words[start + limit.length];
|
|
253
|
+
const finalWord = limit.at(-1);
|
|
254
|
+
if (["context", "evidence", "information", "insight"].includes(finalWord ?? "")) {
|
|
255
|
+
return next === undefined || next === "about" || next === "into";
|
|
256
|
+
}
|
|
257
|
+
return (!["anything", "little", "much", "nothing", "something"].includes(finalWord ?? "") ||
|
|
258
|
+
next === undefined ||
|
|
259
|
+
next === "about");
|
|
260
|
+
}
|
|
261
|
+
function limitationStart(words) {
|
|
262
|
+
if (LIMITATION_REPORTING_VERBS.has(words[1] ?? "")) {
|
|
263
|
+
return REPORTING_OBJECTS.has(words[2] ?? "") ? 3 : 2;
|
|
264
|
+
}
|
|
265
|
+
if (LIMITATION_AUXILIARIES.has(words[1] ?? "") &&
|
|
266
|
+
words[2] === "not" &&
|
|
267
|
+
LIMITATION_REPORTING_VERBS.has(words[3] ?? "")) {
|
|
268
|
+
return 4;
|
|
269
|
+
}
|
|
270
|
+
return CONTRACTED_LIMITATION_AUXILIARIES.has(words[1] ?? "") &&
|
|
271
|
+
LIMITATION_REPORTING_VERBS.has(words[2] ?? "")
|
|
272
|
+
? 3
|
|
273
|
+
: -1;
|
|
274
|
+
}
|
|
275
|
+
function hasLowInformationLimitation(words, pluralSubject) {
|
|
276
|
+
const pronoun = words[0] ?? "";
|
|
277
|
+
const pluralPronoun = ["these", "they", "those"].includes(pronoun);
|
|
278
|
+
if (!LIMITATION_PRONOUNS.has(pronoun) || pluralPronoun !== pluralSubject) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const start = limitationStart(words);
|
|
282
|
+
if (start >= 3 &&
|
|
283
|
+
(LIMITATION_AUXILIARIES.has(words[1] ?? "") ||
|
|
284
|
+
CONTRACTED_LIMITATION_AUXILIARIES.has(words[1] ?? ""))) {
|
|
285
|
+
return (["anything", "much"].includes(words[start] ?? "") &&
|
|
286
|
+
(words[start + 1] === undefined || words[start + 1] === "about"));
|
|
287
|
+
}
|
|
288
|
+
if (start < 0) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
return LOW_INFORMATION_LIMITS.some((limit) => {
|
|
292
|
+
if (!startsWithLimit(words, start, limit)) {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
return hasVagueContinuation(words, start, limit);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
export function matchEvidenceLimitationPair(first, second) {
|
|
299
|
+
const firstWords = tokens(cleanSentence(first, PREFIXES));
|
|
300
|
+
const secondWords = tokens(cleanSentence(second, PREFIXES));
|
|
301
|
+
const subjectHead = evidenceSubjectHead(firstWords);
|
|
302
|
+
return subjectHead !== undefined &&
|
|
303
|
+
hasLowInformationLimitation(secondWords, PLURAL_EVIDENCE_PROXY_HEADS.has(subjectHead))
|
|
304
|
+
? "evidence-limitation-pair"
|
|
305
|
+
: undefined;
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=evidence-limitation-pair.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { wordTokens } from "../../../../shared/text/tokens.js";
|
|
2
|
+
import { findCopularNegation, pronounCopulaStart, words } from "./negation-reframe-parts.js";
|
|
3
|
+
const EVALUATIVE_PREDICATES = new Set([
|
|
4
|
+
"bad",
|
|
5
|
+
"broken",
|
|
6
|
+
"empty",
|
|
7
|
+
"incomplete",
|
|
8
|
+
"messy",
|
|
9
|
+
"sloppy",
|
|
10
|
+
"untidy",
|
|
11
|
+
"useless"
|
|
12
|
+
]);
|
|
13
|
+
const IDENTITY_METAPHOR_HEADS = new Set([
|
|
14
|
+
"barrier",
|
|
15
|
+
"bottleneck",
|
|
16
|
+
"bridge",
|
|
17
|
+
"dead-end",
|
|
18
|
+
"door",
|
|
19
|
+
"gate",
|
|
20
|
+
"market",
|
|
21
|
+
"shelf",
|
|
22
|
+
"wall",
|
|
23
|
+
"window"
|
|
24
|
+
]);
|
|
25
|
+
const IDENTITY_DETERMINERS = new Set(["a", "an", "the"]);
|
|
26
|
+
function startsWithIdentityMetaphor(text) {
|
|
27
|
+
const tokens = wordTokens(text);
|
|
28
|
+
const copula = pronounCopulaStart(tokens);
|
|
29
|
+
if (copula === undefined) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
const predicate = words(tokens).slice(copula.predicateStart);
|
|
33
|
+
const headIndex = IDENTITY_DETERMINERS.has(predicate[0] ?? "") ? 1 : 0;
|
|
34
|
+
return IDENTITY_METAPHOR_HEADS.has(predicate[headIndex] ?? "");
|
|
35
|
+
}
|
|
36
|
+
export function matchesInlineSemicolonReframe(text) {
|
|
37
|
+
const clauses = text.split(";");
|
|
38
|
+
if (clauses.length !== 2) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const firstTokens = wordTokens(clauses[0] ?? "");
|
|
42
|
+
const negation = findCopularNegation(firstTokens);
|
|
43
|
+
if (negation === undefined) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const predicate = words(firstTokens).slice(negation.negatedPredicateStart);
|
|
47
|
+
return (predicate.some((word) => EVALUATIVE_PREDICATES.has(word)) &&
|
|
48
|
+
startsWithIdentityMetaphor(clauses[1] ?? ""));
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=inline-semicolon-reframe.js.map
|