ai-text-check 1.0.0 → 1.2.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 +21 -11
- package/SOURCES.md +8 -3
- package/dist/cli.js +312 -38
- package/dist/index.cjs +280 -25
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +280 -25
- package/dist/node.cjs +286 -31
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +288 -33
- package/dist/{types-BlvvRFG5.d.cts → types-B6cMXIul.d.cts} +7 -1
- package/dist/{types-BlvvRFG5.d.ts → types-B6cMXIul.d.ts} +7 -1
- package/package.json +4 -1
package/dist/node.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var fs3 = require('fs');
|
|
4
4
|
var path3 = require('path');
|
|
5
5
|
var url$1 = require('url');
|
|
6
|
+
var aiSlopLinter = require('ai-slop-linter');
|
|
6
7
|
var isThisAiSlop = require('is-this-ai-slop');
|
|
7
8
|
var module$1 = require('module');
|
|
8
9
|
var child_process = require('child_process');
|
|
@@ -573,6 +574,9 @@ var ENGINE_PRESETS = {
|
|
|
573
574
|
isThisAiSlop: true,
|
|
574
575
|
veldica: true,
|
|
575
576
|
cleanWriting: true,
|
|
577
|
+
aiSlopLinter: true,
|
|
578
|
+
slopDetector: true,
|
|
579
|
+
proseSlop: true,
|
|
576
580
|
vale: true
|
|
577
581
|
},
|
|
578
582
|
strict: {
|
|
@@ -583,6 +587,9 @@ var ENGINE_PRESETS = {
|
|
|
583
587
|
isThisAiSlop: true,
|
|
584
588
|
veldica: true,
|
|
585
589
|
cleanWriting: true,
|
|
590
|
+
aiSlopLinter: true,
|
|
591
|
+
slopDetector: true,
|
|
592
|
+
proseSlop: true,
|
|
586
593
|
vale: true
|
|
587
594
|
},
|
|
588
595
|
ai: {
|
|
@@ -593,6 +600,9 @@ var ENGINE_PRESETS = {
|
|
|
593
600
|
isThisAiSlop: true,
|
|
594
601
|
veldica: true,
|
|
595
602
|
cleanWriting: true,
|
|
603
|
+
aiSlopLinter: true,
|
|
604
|
+
slopDetector: true,
|
|
605
|
+
proseSlop: true,
|
|
596
606
|
vale: true
|
|
597
607
|
},
|
|
598
608
|
grammar: {
|
|
@@ -603,6 +613,9 @@ var ENGINE_PRESETS = {
|
|
|
603
613
|
isThisAiSlop: false,
|
|
604
614
|
veldica: false,
|
|
605
615
|
cleanWriting: true,
|
|
616
|
+
aiSlopLinter: false,
|
|
617
|
+
slopDetector: false,
|
|
618
|
+
proseSlop: false,
|
|
606
619
|
vale: true
|
|
607
620
|
}
|
|
608
621
|
};
|
|
@@ -623,6 +636,9 @@ var ENGINE_KEYS = [
|
|
|
623
636
|
"isThisAiSlop",
|
|
624
637
|
"veldica",
|
|
625
638
|
"cleanWriting",
|
|
639
|
+
"aiSlopLinter",
|
|
640
|
+
"slopDetector",
|
|
641
|
+
"proseSlop",
|
|
626
642
|
"vale"
|
|
627
643
|
];
|
|
628
644
|
function isObject(value) {
|
|
@@ -742,6 +758,14 @@ function validateUserConfig(value) {
|
|
|
742
758
|
config.ignoreRules = value.ignoreRules;
|
|
743
759
|
}
|
|
744
760
|
}
|
|
761
|
+
const ignoreEmojis = expectBoolean(
|
|
762
|
+
value.ignoreEmojis,
|
|
763
|
+
"ignoreEmojis",
|
|
764
|
+
errors
|
|
765
|
+
);
|
|
766
|
+
if (ignoreEmojis !== void 0) {
|
|
767
|
+
config.ignoreEmojis = ignoreEmojis;
|
|
768
|
+
}
|
|
745
769
|
if (value.include !== void 0) {
|
|
746
770
|
if (!isStringArray(value.include)) {
|
|
747
771
|
errors.push("include must be an array of strings");
|
|
@@ -875,6 +899,7 @@ function validateUserConfig(value) {
|
|
|
875
899
|
"failOn",
|
|
876
900
|
"minScore",
|
|
877
901
|
"ignoreRules",
|
|
902
|
+
"ignoreEmojis",
|
|
878
903
|
"include",
|
|
879
904
|
"exclude",
|
|
880
905
|
"extensions",
|
|
@@ -898,7 +923,14 @@ function resolveConfig(user = {}) {
|
|
|
898
923
|
format: user.format ?? "auto",
|
|
899
924
|
failOn: user.failOn ?? "warn",
|
|
900
925
|
minScore: user.minScore ?? 0,
|
|
901
|
-
ignoreRules:
|
|
926
|
+
ignoreRules: (() => {
|
|
927
|
+
const rules = [...user.ignoreRules ?? []];
|
|
928
|
+
if (user.ignoreEmojis ?? false) {
|
|
929
|
+
rules.push("ai-emojis");
|
|
930
|
+
}
|
|
931
|
+
return rules;
|
|
932
|
+
})(),
|
|
933
|
+
ignoreEmojis: user.ignoreEmojis ?? false,
|
|
902
934
|
include: user.include ?? [],
|
|
903
935
|
exclude: user.exclude ?? [],
|
|
904
936
|
extensions: (user.extensions ?? DEFAULT_EXTENSIONS).map(
|
|
@@ -1025,6 +1057,27 @@ function collectFiles(roots, config) {
|
|
|
1025
1057
|
}
|
|
1026
1058
|
return [...files].sort();
|
|
1027
1059
|
}
|
|
1060
|
+
function toSeverity(value) {
|
|
1061
|
+
if (value === "error") return "error";
|
|
1062
|
+
if (value === "warning" || value === "warn") return "warn";
|
|
1063
|
+
return "info";
|
|
1064
|
+
}
|
|
1065
|
+
function runAiSlopLinter(text, options = {}) {
|
|
1066
|
+
const result = aiSlopLinter.lintText(options.source ?? "<text>", text, { floor: 0 });
|
|
1067
|
+
return result.findings.map((finding) => {
|
|
1068
|
+
const issue = {
|
|
1069
|
+
rule: `asl-${finding.rule}`,
|
|
1070
|
+
engine: "ai-slop-linter",
|
|
1071
|
+
category: "ai",
|
|
1072
|
+
severity: toSeverity(finding.severity),
|
|
1073
|
+
message: finding.message,
|
|
1074
|
+
line: finding.line,
|
|
1075
|
+
column: finding.column,
|
|
1076
|
+
excerpt: finding.excerpt
|
|
1077
|
+
};
|
|
1078
|
+
return issue;
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1028
1081
|
|
|
1029
1082
|
// node_modules/clean-writing-lint/src/mask.js
|
|
1030
1083
|
function blank(text) {
|
|
@@ -1994,7 +2047,7 @@ var AI_RULES = /* @__PURE__ */ new Set([
|
|
|
1994
2047
|
"banned-construction",
|
|
1995
2048
|
"em-dash"
|
|
1996
2049
|
]);
|
|
1997
|
-
function
|
|
2050
|
+
function toSeverity2(value) {
|
|
1998
2051
|
if (value === "error") return "error";
|
|
1999
2052
|
if (value === "warn") return "warn";
|
|
2000
2053
|
return "info";
|
|
@@ -2014,7 +2067,7 @@ function runCleanWriting(text) {
|
|
|
2014
2067
|
rule: `cws-${violation.rule}`,
|
|
2015
2068
|
engine: "clean-writing",
|
|
2016
2069
|
category: AI_RULES.has(violation.rule) ? "ai" : "grammar",
|
|
2017
|
-
severity:
|
|
2070
|
+
severity: toSeverity2(violation.severity),
|
|
2018
2071
|
message: violation.message,
|
|
2019
2072
|
line: violation.line,
|
|
2020
2073
|
column: violation.column,
|
|
@@ -2041,6 +2094,33 @@ function runIsThisAiSlop(text) {
|
|
|
2041
2094
|
return issue;
|
|
2042
2095
|
});
|
|
2043
2096
|
}
|
|
2097
|
+
var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('node.cjs', document.baseURI).href)));
|
|
2098
|
+
var { check } = require2("prose-slop");
|
|
2099
|
+
function toSeverity3(value) {
|
|
2100
|
+
if (value === "error") return "error";
|
|
2101
|
+
if (value === "warning" || value === "warn") return "warn";
|
|
2102
|
+
return "info";
|
|
2103
|
+
}
|
|
2104
|
+
function runProseSlop(text, options = {}) {
|
|
2105
|
+
const findings = check(text, {
|
|
2106
|
+
format: options.format ?? "plain",
|
|
2107
|
+
lang: "en"
|
|
2108
|
+
});
|
|
2109
|
+
return findings.map((finding) => {
|
|
2110
|
+
const issue = {
|
|
2111
|
+
rule: `prose-${finding.ruleId}`,
|
|
2112
|
+
engine: "prose-slop",
|
|
2113
|
+
category: "ai",
|
|
2114
|
+
severity: toSeverity3(finding.severity),
|
|
2115
|
+
message: finding.message,
|
|
2116
|
+
line: finding.line,
|
|
2117
|
+
column: finding.column,
|
|
2118
|
+
excerpt: excerptAround(text, finding.index),
|
|
2119
|
+
match: finding.match
|
|
2120
|
+
};
|
|
2121
|
+
return issue;
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2044
2124
|
|
|
2045
2125
|
// node_modules/nlcst-to-string/lib/index.js
|
|
2046
2126
|
var emptyNodes = [];
|
|
@@ -3002,10 +3082,10 @@ function anyFactory(tests) {
|
|
|
3002
3082
|
return false;
|
|
3003
3083
|
}
|
|
3004
3084
|
}
|
|
3005
|
-
function propertiesFactory(
|
|
3085
|
+
function propertiesFactory(check2) {
|
|
3006
3086
|
const checkAsRecord = (
|
|
3007
3087
|
/** @type {Record<string, unknown>} */
|
|
3008
|
-
|
|
3088
|
+
check2
|
|
3009
3089
|
);
|
|
3010
3090
|
return castFactory(all);
|
|
3011
3091
|
function all(node) {
|
|
@@ -3015,21 +3095,21 @@ function propertiesFactory(check) {
|
|
|
3015
3095
|
node
|
|
3016
3096
|
);
|
|
3017
3097
|
let key;
|
|
3018
|
-
for (key in
|
|
3098
|
+
for (key in check2) {
|
|
3019
3099
|
if (nodeAsRecord[key] !== checkAsRecord[key]) return false;
|
|
3020
3100
|
}
|
|
3021
3101
|
return true;
|
|
3022
3102
|
}
|
|
3023
3103
|
}
|
|
3024
|
-
function typeFactory(
|
|
3104
|
+
function typeFactory(check2) {
|
|
3025
3105
|
return castFactory(type);
|
|
3026
3106
|
function type(node) {
|
|
3027
|
-
return node && node.type ===
|
|
3107
|
+
return node && node.type === check2;
|
|
3028
3108
|
}
|
|
3029
3109
|
}
|
|
3030
3110
|
function castFactory(testFunction) {
|
|
3031
|
-
return
|
|
3032
|
-
function
|
|
3111
|
+
return check2;
|
|
3112
|
+
function check2(value, index2, parent) {
|
|
3033
3113
|
return Boolean(
|
|
3034
3114
|
looksLikeANode(value) && testFunction.call(
|
|
3035
3115
|
this,
|
|
@@ -3058,14 +3138,14 @@ var CONTINUE = true;
|
|
|
3058
3138
|
var EXIT = false;
|
|
3059
3139
|
var SKIP = "skip";
|
|
3060
3140
|
function visitParents(tree, test, visitor, reverse) {
|
|
3061
|
-
let
|
|
3141
|
+
let check2;
|
|
3062
3142
|
if (typeof test === "function" && typeof visitor !== "function") {
|
|
3063
3143
|
reverse = visitor;
|
|
3064
3144
|
visitor = test;
|
|
3065
3145
|
} else {
|
|
3066
|
-
|
|
3146
|
+
check2 = test;
|
|
3067
3147
|
}
|
|
3068
|
-
const is2 = convert(
|
|
3148
|
+
const is2 = convert(check2);
|
|
3069
3149
|
const step = reverse ? -1 : 1;
|
|
3070
3150
|
factory(tree, void 0, [])();
|
|
3071
3151
|
function factory(node, index2, parents) {
|
|
@@ -9958,9 +10038,9 @@ var VFile = class {
|
|
|
9958
10038
|
* @returns {undefined}
|
|
9959
10039
|
* Nothing.
|
|
9960
10040
|
*/
|
|
9961
|
-
set dirname(
|
|
10041
|
+
set dirname(dirname4) {
|
|
9962
10042
|
assertPath2(this.basename, "dirname");
|
|
9963
|
-
this.path = minpath.join(
|
|
10043
|
+
this.path = minpath.join(dirname4 || "", this.basename);
|
|
9964
10044
|
}
|
|
9965
10045
|
/**
|
|
9966
10046
|
* Get the extname (including dot) (example: `'.js'`).
|
|
@@ -10983,6 +11063,160 @@ function runRetext(text) {
|
|
|
10983
11063
|
return issue;
|
|
10984
11064
|
});
|
|
10985
11065
|
}
|
|
11066
|
+
var WEIGHT_WORD = 0.5;
|
|
11067
|
+
var WEIGHT_PATTERN = 0.2;
|
|
11068
|
+
var WEIGHT_TRIGRAM = 0.12;
|
|
11069
|
+
var WEIGHT_TROPE = 0.18;
|
|
11070
|
+
var WORD_MULTIPLIER = 1e3;
|
|
11071
|
+
var TRIGRAM_MULTIPLIER = 1e3;
|
|
11072
|
+
var CONTRAST_PATTERN = /\b(?:it(?:'s| is)|this is|that(?:'s| is)|(?:it|this|that) isn'?t)\s+(?:just |only |merely |simply )?[a-z][\s\S]{0,80}?\b(?:it(?:'s| is)|this is|that(?:'s| is)|but)\b/gi;
|
|
11073
|
+
var NOT_BUT_PATTERN = /\bnot\b[\s\S]{0,60}?\bbut\b/gi;
|
|
11074
|
+
var require3 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('node.cjs', document.baseURI).href)));
|
|
11075
|
+
var assetsDir = path3.join(
|
|
11076
|
+
path3.dirname(require3.resolve("slop-detector/package.json")),
|
|
11077
|
+
"dist",
|
|
11078
|
+
"assets"
|
|
11079
|
+
);
|
|
11080
|
+
var cachedAssets = null;
|
|
11081
|
+
function computeRange(values) {
|
|
11082
|
+
if (values.length === 0) return { min: 0, max: 1 };
|
|
11083
|
+
const min = Math.min(...values);
|
|
11084
|
+
const max = Math.max(...values);
|
|
11085
|
+
const range = max - min || 1;
|
|
11086
|
+
return { min: min - range * 0.1, max: max + range * 0.1 };
|
|
11087
|
+
}
|
|
11088
|
+
function loadAssets() {
|
|
11089
|
+
if (cachedAssets) return cachedAssets;
|
|
11090
|
+
const wordsRaw = JSON.parse(
|
|
11091
|
+
fs3.readFileSync(path3.join(assetsDir, "slop_list.json"), "utf8")
|
|
11092
|
+
);
|
|
11093
|
+
const trigramsRaw = JSON.parse(
|
|
11094
|
+
fs3.readFileSync(path3.join(assetsDir, "slop_list_trigrams.json"), "utf8")
|
|
11095
|
+
);
|
|
11096
|
+
const leaderboard = JSON.parse(
|
|
11097
|
+
fs3.readFileSync(path3.join(assetsDir, "leaderboard_results.json"), "utf8")
|
|
11098
|
+
);
|
|
11099
|
+
const words = /* @__PURE__ */ new Set();
|
|
11100
|
+
for (const item of wordsRaw) {
|
|
11101
|
+
if (Array.isArray(item) && item[0]) words.add(item[0].toLowerCase());
|
|
11102
|
+
}
|
|
11103
|
+
const trigrams = /* @__PURE__ */ new Set();
|
|
11104
|
+
for (const item of trigramsRaw) {
|
|
11105
|
+
if (Array.isArray(item) && item[0]) trigrams.add(item[0].toLowerCase());
|
|
11106
|
+
}
|
|
11107
|
+
const metrics = {
|
|
11108
|
+
slop_words: [],
|
|
11109
|
+
slop_trigrams: [],
|
|
11110
|
+
contrast: []
|
|
11111
|
+
};
|
|
11112
|
+
for (const res of leaderboard.results ?? []) {
|
|
11113
|
+
if (!res.metrics) continue;
|
|
11114
|
+
metrics.slop_words.push(res.metrics.slop_list_matches_per_1k_words || 0);
|
|
11115
|
+
metrics.slop_trigrams.push(
|
|
11116
|
+
res.metrics.slop_trigram_matches_per_1k_words || 0
|
|
11117
|
+
);
|
|
11118
|
+
metrics.contrast.push(res.metrics.not_x_but_y_per_1k_chars || 0);
|
|
11119
|
+
}
|
|
11120
|
+
cachedAssets = {
|
|
11121
|
+
words,
|
|
11122
|
+
trigrams,
|
|
11123
|
+
normalizationRanges: {
|
|
11124
|
+
slop_words: computeRange(metrics.slop_words),
|
|
11125
|
+
slop_trigrams: computeRange(metrics.slop_trigrams),
|
|
11126
|
+
contrast: computeRange(metrics.contrast)
|
|
11127
|
+
}
|
|
11128
|
+
};
|
|
11129
|
+
return cachedAssets;
|
|
11130
|
+
}
|
|
11131
|
+
function normalizeValue(value, range) {
|
|
11132
|
+
const normalized = (value - range.min) / (range.max - range.min);
|
|
11133
|
+
return Math.max(0, Math.min(1, normalized));
|
|
11134
|
+
}
|
|
11135
|
+
function toPlainText(text) {
|
|
11136
|
+
return text.replace(/```[\s\S]*?```/g, " ").replace(/`[^`\n]+`/g, " ").replace(/<[^>]+>/g, " ").replace(/!\[[^\]]*]\([^)]*\)/g, " ").replace(/\[[^\]]*]\([^)]*\)/g, " ").replace(/^#{1,6}\s+/gm, "").replace(/[*_~>#-]+/g, " ");
|
|
11137
|
+
}
|
|
11138
|
+
function tokenize(text) {
|
|
11139
|
+
return text.toLowerCase().match(/[a-z]+(?:'[a-z]+)?/g) ?? [];
|
|
11140
|
+
}
|
|
11141
|
+
function collectMatches(pattern, text) {
|
|
11142
|
+
return [...text.matchAll(pattern)].map((match) => match[0] ?? "");
|
|
11143
|
+
}
|
|
11144
|
+
function runSlopDetector(text) {
|
|
11145
|
+
if (!text.trim()) return [];
|
|
11146
|
+
const assets = loadAssets();
|
|
11147
|
+
const plain = toPlainText(text);
|
|
11148
|
+
const tokens = tokenize(plain);
|
|
11149
|
+
const nTokens = tokens.length || 1;
|
|
11150
|
+
let wordHitCount = 0;
|
|
11151
|
+
const wordHitMap = /* @__PURE__ */ new Map();
|
|
11152
|
+
for (const token of tokens) {
|
|
11153
|
+
if (!assets.words.has(token)) continue;
|
|
11154
|
+
wordHitCount++;
|
|
11155
|
+
wordHitMap.set(token, (wordHitMap.get(token) || 0) + 1);
|
|
11156
|
+
}
|
|
11157
|
+
let trigramHitCount = 0;
|
|
11158
|
+
if (tokens.length >= 3) {
|
|
11159
|
+
for (let i = 0; i < tokens.length - 2; i++) {
|
|
11160
|
+
const tg = `${tokens[i]} ${tokens[i + 1]} ${tokens[i + 2]}`;
|
|
11161
|
+
if (assets.trigrams.has(tg)) trigramHitCount++;
|
|
11162
|
+
}
|
|
11163
|
+
}
|
|
11164
|
+
const contrastMatches = [
|
|
11165
|
+
.../* @__PURE__ */ new Set([
|
|
11166
|
+
...collectMatches(CONTRAST_PATTERN, plain),
|
|
11167
|
+
...collectMatches(NOT_BUT_PATTERN, plain)
|
|
11168
|
+
])
|
|
11169
|
+
];
|
|
11170
|
+
const emDashCount = (text.match(/—/g) ?? []).length;
|
|
11171
|
+
const tropeRate = emDashCount / Math.max(plain.length, 1) * 1e3;
|
|
11172
|
+
const wordScore = wordHitCount / nTokens * WORD_MULTIPLIER;
|
|
11173
|
+
const trigramScore = trigramHitCount / nTokens * TRIGRAM_MULTIPLIER;
|
|
11174
|
+
const contrastScore = contrastMatches.length / Math.max(plain.length, 1) * 1e3;
|
|
11175
|
+
const rawSlopScore = (normalizeValue(wordScore, assets.normalizationRanges.slop_words) * WEIGHT_WORD + normalizeValue(contrastScore, assets.normalizationRanges.contrast) * WEIGHT_PATTERN + normalizeValue(trigramScore, assets.normalizationRanges.slop_trigrams) * WEIGHT_TRIGRAM + normalizeValue(tropeRate, { min: 0, max: 5 }) * WEIGHT_TROPE) * 100;
|
|
11176
|
+
const slopScore = Math.round(rawSlopScore * 10) / 10;
|
|
11177
|
+
const issues = [];
|
|
11178
|
+
if (slopScore >= 40) {
|
|
11179
|
+
issues.push({
|
|
11180
|
+
rule: "eqbench-slop-score",
|
|
11181
|
+
engine: "slop-detector",
|
|
11182
|
+
category: "ai",
|
|
11183
|
+
severity: slopScore >= 60 ? "warn" : "info",
|
|
11184
|
+
message: `EQBench SLOP score ${slopScore}/100 (higher = more AI-like).`,
|
|
11185
|
+
suggestion: slopScore >= 60 ? "Rewrite stock phrasing and contrast constructions." : "Review flagged vocabulary and contrast patterns."
|
|
11186
|
+
});
|
|
11187
|
+
}
|
|
11188
|
+
for (const [word2, count] of [...wordHitMap.entries()].sort((a, b) => b[1] - a[1]).slice(0, 8)) {
|
|
11189
|
+
issues.push({
|
|
11190
|
+
rule: `eqbench-word-${word2.replace(/\s+/g, "-")}`,
|
|
11191
|
+
engine: "slop-detector",
|
|
11192
|
+
category: "ai",
|
|
11193
|
+
severity: "info",
|
|
11194
|
+
message: `EQBench slop vocabulary: \u201C${word2}\u201D (${count}\xD7).`,
|
|
11195
|
+
match: word2
|
|
11196
|
+
});
|
|
11197
|
+
}
|
|
11198
|
+
for (const match of contrastMatches.slice(0, 5)) {
|
|
11199
|
+
issues.push({
|
|
11200
|
+
rule: "eqbench-contrast",
|
|
11201
|
+
engine: "slop-detector",
|
|
11202
|
+
category: "ai",
|
|
11203
|
+
severity: "info",
|
|
11204
|
+
message: `EQBench contrast pattern: \u201C${match.trim()}\u201D`,
|
|
11205
|
+
match
|
|
11206
|
+
});
|
|
11207
|
+
}
|
|
11208
|
+
if (emDashCount >= 3) {
|
|
11209
|
+
issues.push({
|
|
11210
|
+
rule: "eqbench-trope-em-dash",
|
|
11211
|
+
engine: "slop-detector",
|
|
11212
|
+
category: "ai",
|
|
11213
|
+
severity: "info",
|
|
11214
|
+
message: `EQBench typography trope: ${emDashCount} em dash(es).`,
|
|
11215
|
+
match: "\u2014"
|
|
11216
|
+
});
|
|
11217
|
+
}
|
|
11218
|
+
return issues;
|
|
11219
|
+
}
|
|
10986
11220
|
|
|
10987
11221
|
// src/engines/tag.ts
|
|
10988
11222
|
function tagEngine(issues, engine) {
|
|
@@ -11354,7 +11588,7 @@ function countListItems(input) {
|
|
|
11354
11588
|
function countBlockquotes(input) {
|
|
11355
11589
|
return getLineMetadata(input).blockquote_count;
|
|
11356
11590
|
}
|
|
11357
|
-
function
|
|
11591
|
+
function tokenize2(text) {
|
|
11358
11592
|
const blocks = splitParagraphBlocks(text);
|
|
11359
11593
|
const paragraphs2 = blocks.map((block) => block.text);
|
|
11360
11594
|
const sentences2 = splitSentencesFromBlocks(blocks);
|
|
@@ -11376,7 +11610,7 @@ function tokenize(text) {
|
|
|
11376
11610
|
}
|
|
11377
11611
|
};
|
|
11378
11612
|
}
|
|
11379
|
-
var tokenizeProse =
|
|
11613
|
+
var tokenizeProse = tokenize2;
|
|
11380
11614
|
|
|
11381
11615
|
// node_modules/@veldica/prose-analyzer/dist/utils.js
|
|
11382
11616
|
function round(value, decimals = 4) {
|
|
@@ -12120,7 +12354,7 @@ function inventoryMarkers(text, options = {}) {
|
|
|
12120
12354
|
}
|
|
12121
12355
|
|
|
12122
12356
|
// src/engines/veldica.ts
|
|
12123
|
-
function
|
|
12357
|
+
function toSeverity4(value) {
|
|
12124
12358
|
if (value === "high") return "warn";
|
|
12125
12359
|
return "info";
|
|
12126
12360
|
}
|
|
@@ -12135,7 +12369,7 @@ function runVeldica(text) {
|
|
|
12135
12369
|
rule: `veldica-${match.category || "marker"}`,
|
|
12136
12370
|
engine: "veldica",
|
|
12137
12371
|
category: "ai",
|
|
12138
|
-
severity:
|
|
12372
|
+
severity: toSeverity4(match.severity),
|
|
12139
12373
|
message: `AI-style marker (${match.category}): \u201C${match.matched_text}\u201D`,
|
|
12140
12374
|
excerpt: excerptAround(text, offset),
|
|
12141
12375
|
match: match.matched_text
|
|
@@ -12148,8 +12382,8 @@ function runVeldica(text) {
|
|
|
12148
12382
|
return issue;
|
|
12149
12383
|
});
|
|
12150
12384
|
}
|
|
12151
|
-
var
|
|
12152
|
-
var writeGood =
|
|
12385
|
+
var require4 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('node.cjs', document.baseURI).href)));
|
|
12386
|
+
var writeGood = require4("write-good");
|
|
12153
12387
|
function runWriteGood(text) {
|
|
12154
12388
|
const suggestions = writeGood(text, {
|
|
12155
12389
|
so: false,
|
|
@@ -12373,6 +12607,14 @@ var AI_PATTERN_RULES = [
|
|
|
12373
12607
|
severity: "info",
|
|
12374
12608
|
minCount: ({ words }) => Math.max(6, words / 250)
|
|
12375
12609
|
},
|
|
12610
|
+
{
|
|
12611
|
+
id: "ai-emojis",
|
|
12612
|
+
category: "ai",
|
|
12613
|
+
pattern: new RegExp("\\p{Extended_Pictographic}", "gu"),
|
|
12614
|
+
message: "Emoji can read as chatty or AI-styled in formal prose.",
|
|
12615
|
+
severity: "info",
|
|
12616
|
+
suggestion: "Prefer plain prose, or set ignoreEmojis: true to allow them."
|
|
12617
|
+
},
|
|
12376
12618
|
{
|
|
12377
12619
|
id: "double-space",
|
|
12378
12620
|
category: "typography",
|
|
@@ -13183,7 +13425,7 @@ function computeStats(body, titleLength, descriptionLength, issues) {
|
|
|
13183
13425
|
descriptionLength
|
|
13184
13426
|
};
|
|
13185
13427
|
}
|
|
13186
|
-
function collectIssues(body, frontmatter, format, config) {
|
|
13428
|
+
function collectIssues(body, frontmatter, format, config, source2) {
|
|
13187
13429
|
const ignoreRules = new Set(config.ignoreRules);
|
|
13188
13430
|
const issues = [];
|
|
13189
13431
|
const enginesRun = [];
|
|
@@ -13256,6 +13498,18 @@ function collectIssues(body, frontmatter, format, config) {
|
|
|
13256
13498
|
enginesRun.push("clean-writing");
|
|
13257
13499
|
issues.push(...runCleanWriting(body));
|
|
13258
13500
|
}
|
|
13501
|
+
if (config.engines.aiSlopLinter && config.checks.ai) {
|
|
13502
|
+
enginesRun.push("ai-slop-linter");
|
|
13503
|
+
issues.push(...runAiSlopLinter(body, { source: source2 }));
|
|
13504
|
+
}
|
|
13505
|
+
if (config.engines.slopDetector && config.checks.ai) {
|
|
13506
|
+
enginesRun.push("slop-detector");
|
|
13507
|
+
issues.push(...runSlopDetector(body));
|
|
13508
|
+
}
|
|
13509
|
+
if (config.engines.proseSlop && config.checks.ai) {
|
|
13510
|
+
enginesRun.push("prose-slop");
|
|
13511
|
+
issues.push(...runProseSlop(body, { format }));
|
|
13512
|
+
}
|
|
13259
13513
|
return {
|
|
13260
13514
|
issues: issues.filter((issue) => !ignoreRules.has(issue.rule)),
|
|
13261
13515
|
enginesRun: uniqueEngines(enginesRun)
|
|
@@ -13271,7 +13525,8 @@ function checkText(text, options = {}) {
|
|
|
13271
13525
|
body,
|
|
13272
13526
|
parsed.frontmatter,
|
|
13273
13527
|
format,
|
|
13274
|
-
config
|
|
13528
|
+
config,
|
|
13529
|
+
source2
|
|
13275
13530
|
);
|
|
13276
13531
|
const title = String(parsed.frontmatter.title ?? pathBasename(source2));
|
|
13277
13532
|
const report = {
|
|
@@ -13298,7 +13553,7 @@ function checkText(text, options = {}) {
|
|
|
13298
13553
|
}
|
|
13299
13554
|
return report;
|
|
13300
13555
|
}
|
|
13301
|
-
var
|
|
13556
|
+
var require5 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('node.cjs', document.baseURI).href)));
|
|
13302
13557
|
function packageRoot() {
|
|
13303
13558
|
let current = path3__default.default.dirname(url$1.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('node.cjs', document.baseURI).href))));
|
|
13304
13559
|
while (true) {
|
|
@@ -13337,7 +13592,7 @@ function findValeBinary(cwd2 = process.cwd()) {
|
|
|
13337
13592
|
const fromPackage = firstExisting(valeNativeCandidates(packageRoot()));
|
|
13338
13593
|
if (fromPackage) return fromPackage;
|
|
13339
13594
|
try {
|
|
13340
|
-
const pkg =
|
|
13595
|
+
const pkg = require5.resolve("@vvago/vale/package.json");
|
|
13341
13596
|
const dir = path3__default.default.dirname(pkg);
|
|
13342
13597
|
const resolved = firstExisting([
|
|
13343
13598
|
path3__default.default.join(
|
|
@@ -13394,8 +13649,8 @@ function valeSeverity(value) {
|
|
|
13394
13649
|
if (value === "suggestion") return "info";
|
|
13395
13650
|
return "warn";
|
|
13396
13651
|
}
|
|
13397
|
-
function valeCategory(
|
|
13398
|
-
if (
|
|
13652
|
+
function valeCategory(check2) {
|
|
13653
|
+
if (check2.startsWith("write-good.") || check2.startsWith("Google.")) {
|
|
13399
13654
|
return "grammar";
|
|
13400
13655
|
}
|
|
13401
13656
|
return "ai";
|
|
@@ -13421,13 +13676,13 @@ function collectValeIssues(files, options = {}) {
|
|
|
13421
13676
|
const issues = [];
|
|
13422
13677
|
for (const raw of alerts) {
|
|
13423
13678
|
const alert = raw;
|
|
13424
|
-
const
|
|
13679
|
+
const check2 = alert.Check ?? "vale";
|
|
13425
13680
|
const issue = {
|
|
13426
|
-
rule:
|
|
13681
|
+
rule: check2,
|
|
13427
13682
|
engine: "vale",
|
|
13428
|
-
category: valeCategory(
|
|
13683
|
+
category: valeCategory(check2),
|
|
13429
13684
|
severity: valeSeverity(alert.Severity),
|
|
13430
|
-
message: alert.Message ??
|
|
13685
|
+
message: alert.Message ?? check2
|
|
13431
13686
|
};
|
|
13432
13687
|
if (alert.Line) issue.line = alert.Line;
|
|
13433
13688
|
if (alert.Span?.[0]) issue.column = alert.Span[0];
|
package/dist/node.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as UserConfig, R as ResolvedConfig, C as CheckOptions, a as CheckReport, f as CheckSummary } from './types-
|
|
1
|
+
import { U as UserConfig, R as ResolvedConfig, C as CheckOptions, a as CheckReport, f as CheckSummary } from './types-B6cMXIul.cjs';
|
|
2
2
|
|
|
3
3
|
declare class ConfigError extends Error {
|
|
4
4
|
readonly name = "ConfigError";
|
package/dist/node.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as UserConfig, R as ResolvedConfig, C as CheckOptions, a as CheckReport, f as CheckSummary } from './types-
|
|
1
|
+
import { U as UserConfig, R as ResolvedConfig, C as CheckOptions, a as CheckReport, f as CheckSummary } from './types-B6cMXIul.js';
|
|
2
2
|
|
|
3
3
|
declare class ConfigError extends Error {
|
|
4
4
|
readonly name = "ConfigError";
|