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/index.cjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
require('
|
|
4
|
-
require('
|
|
3
|
+
var aiSlopLinter = require('ai-slop-linter');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
var path = require('path');
|
|
5
6
|
require('url');
|
|
6
7
|
var isThisAiSlop = require('is-this-ai-slop');
|
|
7
8
|
var module$1 = require('module');
|
|
@@ -568,6 +569,9 @@ var ENGINE_PRESETS = {
|
|
|
568
569
|
isThisAiSlop: true,
|
|
569
570
|
veldica: true,
|
|
570
571
|
cleanWriting: true,
|
|
572
|
+
aiSlopLinter: true,
|
|
573
|
+
slopDetector: true,
|
|
574
|
+
proseSlop: true,
|
|
571
575
|
vale: true
|
|
572
576
|
},
|
|
573
577
|
strict: {
|
|
@@ -578,6 +582,9 @@ var ENGINE_PRESETS = {
|
|
|
578
582
|
isThisAiSlop: true,
|
|
579
583
|
veldica: true,
|
|
580
584
|
cleanWriting: true,
|
|
585
|
+
aiSlopLinter: true,
|
|
586
|
+
slopDetector: true,
|
|
587
|
+
proseSlop: true,
|
|
581
588
|
vale: true
|
|
582
589
|
},
|
|
583
590
|
ai: {
|
|
@@ -588,6 +595,9 @@ var ENGINE_PRESETS = {
|
|
|
588
595
|
isThisAiSlop: true,
|
|
589
596
|
veldica: true,
|
|
590
597
|
cleanWriting: true,
|
|
598
|
+
aiSlopLinter: true,
|
|
599
|
+
slopDetector: true,
|
|
600
|
+
proseSlop: true,
|
|
591
601
|
vale: true
|
|
592
602
|
},
|
|
593
603
|
grammar: {
|
|
@@ -598,6 +608,9 @@ var ENGINE_PRESETS = {
|
|
|
598
608
|
isThisAiSlop: false,
|
|
599
609
|
veldica: false,
|
|
600
610
|
cleanWriting: true,
|
|
611
|
+
aiSlopLinter: false,
|
|
612
|
+
slopDetector: false,
|
|
613
|
+
proseSlop: false,
|
|
601
614
|
vale: true
|
|
602
615
|
}
|
|
603
616
|
};
|
|
@@ -618,6 +631,9 @@ var ENGINE_KEYS = [
|
|
|
618
631
|
"isThisAiSlop",
|
|
619
632
|
"veldica",
|
|
620
633
|
"cleanWriting",
|
|
634
|
+
"aiSlopLinter",
|
|
635
|
+
"slopDetector",
|
|
636
|
+
"proseSlop",
|
|
621
637
|
"vale"
|
|
622
638
|
];
|
|
623
639
|
function isObject(value) {
|
|
@@ -737,6 +753,14 @@ function validateUserConfig(value) {
|
|
|
737
753
|
config.ignoreRules = value.ignoreRules;
|
|
738
754
|
}
|
|
739
755
|
}
|
|
756
|
+
const ignoreEmojis = expectBoolean(
|
|
757
|
+
value.ignoreEmojis,
|
|
758
|
+
"ignoreEmojis",
|
|
759
|
+
errors
|
|
760
|
+
);
|
|
761
|
+
if (ignoreEmojis !== void 0) {
|
|
762
|
+
config.ignoreEmojis = ignoreEmojis;
|
|
763
|
+
}
|
|
740
764
|
if (value.include !== void 0) {
|
|
741
765
|
if (!isStringArray(value.include)) {
|
|
742
766
|
errors.push("include must be an array of strings");
|
|
@@ -870,6 +894,7 @@ function validateUserConfig(value) {
|
|
|
870
894
|
"failOn",
|
|
871
895
|
"minScore",
|
|
872
896
|
"ignoreRules",
|
|
897
|
+
"ignoreEmojis",
|
|
873
898
|
"include",
|
|
874
899
|
"exclude",
|
|
875
900
|
"extensions",
|
|
@@ -893,7 +918,14 @@ function resolveConfig(user = {}) {
|
|
|
893
918
|
format: user.format ?? "auto",
|
|
894
919
|
failOn: user.failOn ?? "warn",
|
|
895
920
|
minScore: user.minScore ?? 0,
|
|
896
|
-
ignoreRules:
|
|
921
|
+
ignoreRules: (() => {
|
|
922
|
+
const rules = [...user.ignoreRules ?? []];
|
|
923
|
+
if (user.ignoreEmojis ?? false) {
|
|
924
|
+
rules.push("ai-emojis");
|
|
925
|
+
}
|
|
926
|
+
return rules;
|
|
927
|
+
})(),
|
|
928
|
+
ignoreEmojis: user.ignoreEmojis ?? false,
|
|
897
929
|
include: user.include ?? [],
|
|
898
930
|
exclude: user.exclude ?? [],
|
|
899
931
|
extensions: (user.extensions ?? DEFAULT_EXTENSIONS).map(
|
|
@@ -930,6 +962,27 @@ function defineConfig(config) {
|
|
|
930
962
|
function isStrictPreset(config) {
|
|
931
963
|
return config.preset === "strict";
|
|
932
964
|
}
|
|
965
|
+
function toSeverity(value) {
|
|
966
|
+
if (value === "error") return "error";
|
|
967
|
+
if (value === "warning" || value === "warn") return "warn";
|
|
968
|
+
return "info";
|
|
969
|
+
}
|
|
970
|
+
function runAiSlopLinter(text, options = {}) {
|
|
971
|
+
const result = aiSlopLinter.lintText(options.source ?? "<text>", text, { floor: 0 });
|
|
972
|
+
return result.findings.map((finding) => {
|
|
973
|
+
const issue = {
|
|
974
|
+
rule: `asl-${finding.rule}`,
|
|
975
|
+
engine: "ai-slop-linter",
|
|
976
|
+
category: "ai",
|
|
977
|
+
severity: toSeverity(finding.severity),
|
|
978
|
+
message: finding.message,
|
|
979
|
+
line: finding.line,
|
|
980
|
+
column: finding.column,
|
|
981
|
+
excerpt: finding.excerpt
|
|
982
|
+
};
|
|
983
|
+
return issue;
|
|
984
|
+
});
|
|
985
|
+
}
|
|
933
986
|
|
|
934
987
|
// node_modules/clean-writing-lint/src/mask.js
|
|
935
988
|
function blank(text) {
|
|
@@ -1899,7 +1952,7 @@ var AI_RULES = /* @__PURE__ */ new Set([
|
|
|
1899
1952
|
"banned-construction",
|
|
1900
1953
|
"em-dash"
|
|
1901
1954
|
]);
|
|
1902
|
-
function
|
|
1955
|
+
function toSeverity2(value) {
|
|
1903
1956
|
if (value === "error") return "error";
|
|
1904
1957
|
if (value === "warn") return "warn";
|
|
1905
1958
|
return "info";
|
|
@@ -1919,7 +1972,7 @@ function runCleanWriting(text) {
|
|
|
1919
1972
|
rule: `cws-${violation.rule}`,
|
|
1920
1973
|
engine: "clean-writing",
|
|
1921
1974
|
category: AI_RULES.has(violation.rule) ? "ai" : "grammar",
|
|
1922
|
-
severity:
|
|
1975
|
+
severity: toSeverity2(violation.severity),
|
|
1923
1976
|
message: violation.message,
|
|
1924
1977
|
line: violation.line,
|
|
1925
1978
|
column: violation.column,
|
|
@@ -1946,6 +1999,33 @@ function runIsThisAiSlop(text) {
|
|
|
1946
1999
|
return issue;
|
|
1947
2000
|
});
|
|
1948
2001
|
}
|
|
2002
|
+
var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
2003
|
+
var { check } = require2("prose-slop");
|
|
2004
|
+
function toSeverity3(value) {
|
|
2005
|
+
if (value === "error") return "error";
|
|
2006
|
+
if (value === "warning" || value === "warn") return "warn";
|
|
2007
|
+
return "info";
|
|
2008
|
+
}
|
|
2009
|
+
function runProseSlop(text, options = {}) {
|
|
2010
|
+
const findings = check(text, {
|
|
2011
|
+
format: options.format ?? "plain",
|
|
2012
|
+
lang: "en"
|
|
2013
|
+
});
|
|
2014
|
+
return findings.map((finding) => {
|
|
2015
|
+
const issue = {
|
|
2016
|
+
rule: `prose-${finding.ruleId}`,
|
|
2017
|
+
engine: "prose-slop",
|
|
2018
|
+
category: "ai",
|
|
2019
|
+
severity: toSeverity3(finding.severity),
|
|
2020
|
+
message: finding.message,
|
|
2021
|
+
line: finding.line,
|
|
2022
|
+
column: finding.column,
|
|
2023
|
+
excerpt: excerptAround(text, finding.index),
|
|
2024
|
+
match: finding.match
|
|
2025
|
+
};
|
|
2026
|
+
return issue;
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
1949
2029
|
|
|
1950
2030
|
// node_modules/nlcst-to-string/lib/index.js
|
|
1951
2031
|
var emptyNodes = [];
|
|
@@ -2907,10 +2987,10 @@ function anyFactory(tests) {
|
|
|
2907
2987
|
return false;
|
|
2908
2988
|
}
|
|
2909
2989
|
}
|
|
2910
|
-
function propertiesFactory(
|
|
2990
|
+
function propertiesFactory(check2) {
|
|
2911
2991
|
const checkAsRecord = (
|
|
2912
2992
|
/** @type {Record<string, unknown>} */
|
|
2913
|
-
|
|
2993
|
+
check2
|
|
2914
2994
|
);
|
|
2915
2995
|
return castFactory(all);
|
|
2916
2996
|
function all(node) {
|
|
@@ -2920,21 +3000,21 @@ function propertiesFactory(check) {
|
|
|
2920
3000
|
node
|
|
2921
3001
|
);
|
|
2922
3002
|
let key;
|
|
2923
|
-
for (key in
|
|
3003
|
+
for (key in check2) {
|
|
2924
3004
|
if (nodeAsRecord[key] !== checkAsRecord[key]) return false;
|
|
2925
3005
|
}
|
|
2926
3006
|
return true;
|
|
2927
3007
|
}
|
|
2928
3008
|
}
|
|
2929
|
-
function typeFactory(
|
|
3009
|
+
function typeFactory(check2) {
|
|
2930
3010
|
return castFactory(type);
|
|
2931
3011
|
function type(node) {
|
|
2932
|
-
return node && node.type ===
|
|
3012
|
+
return node && node.type === check2;
|
|
2933
3013
|
}
|
|
2934
3014
|
}
|
|
2935
3015
|
function castFactory(testFunction) {
|
|
2936
|
-
return
|
|
2937
|
-
function
|
|
3016
|
+
return check2;
|
|
3017
|
+
function check2(value, index2, parent) {
|
|
2938
3018
|
return Boolean(
|
|
2939
3019
|
looksLikeANode(value) && testFunction.call(
|
|
2940
3020
|
this,
|
|
@@ -2963,14 +3043,14 @@ var CONTINUE = true;
|
|
|
2963
3043
|
var EXIT = false;
|
|
2964
3044
|
var SKIP = "skip";
|
|
2965
3045
|
function visitParents(tree, test, visitor, reverse) {
|
|
2966
|
-
let
|
|
3046
|
+
let check2;
|
|
2967
3047
|
if (typeof test === "function" && typeof visitor !== "function") {
|
|
2968
3048
|
reverse = visitor;
|
|
2969
3049
|
visitor = test;
|
|
2970
3050
|
} else {
|
|
2971
|
-
|
|
3051
|
+
check2 = test;
|
|
2972
3052
|
}
|
|
2973
|
-
const is2 = convert(
|
|
3053
|
+
const is2 = convert(check2);
|
|
2974
3054
|
const step = reverse ? -1 : 1;
|
|
2975
3055
|
factory(tree, void 0, [])();
|
|
2976
3056
|
function factory(node, index2, parents) {
|
|
@@ -9863,9 +9943,9 @@ var VFile = class {
|
|
|
9863
9943
|
* @returns {undefined}
|
|
9864
9944
|
* Nothing.
|
|
9865
9945
|
*/
|
|
9866
|
-
set dirname(
|
|
9946
|
+
set dirname(dirname4) {
|
|
9867
9947
|
assertPath2(this.basename, "dirname");
|
|
9868
|
-
this.path = minpath.join(
|
|
9948
|
+
this.path = minpath.join(dirname4 || "", this.basename);
|
|
9869
9949
|
}
|
|
9870
9950
|
/**
|
|
9871
9951
|
* Get the extname (including dot) (example: `'.js'`).
|
|
@@ -10888,6 +10968,160 @@ function runRetext(text) {
|
|
|
10888
10968
|
return issue;
|
|
10889
10969
|
});
|
|
10890
10970
|
}
|
|
10971
|
+
var WEIGHT_WORD = 0.5;
|
|
10972
|
+
var WEIGHT_PATTERN = 0.2;
|
|
10973
|
+
var WEIGHT_TRIGRAM = 0.12;
|
|
10974
|
+
var WEIGHT_TROPE = 0.18;
|
|
10975
|
+
var WORD_MULTIPLIER = 1e3;
|
|
10976
|
+
var TRIGRAM_MULTIPLIER = 1e3;
|
|
10977
|
+
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;
|
|
10978
|
+
var NOT_BUT_PATTERN = /\bnot\b[\s\S]{0,60}?\bbut\b/gi;
|
|
10979
|
+
var require3 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
10980
|
+
var assetsDir = path.join(
|
|
10981
|
+
path.dirname(require3.resolve("slop-detector/package.json")),
|
|
10982
|
+
"dist",
|
|
10983
|
+
"assets"
|
|
10984
|
+
);
|
|
10985
|
+
var cachedAssets = null;
|
|
10986
|
+
function computeRange(values) {
|
|
10987
|
+
if (values.length === 0) return { min: 0, max: 1 };
|
|
10988
|
+
const min = Math.min(...values);
|
|
10989
|
+
const max = Math.max(...values);
|
|
10990
|
+
const range = max - min || 1;
|
|
10991
|
+
return { min: min - range * 0.1, max: max + range * 0.1 };
|
|
10992
|
+
}
|
|
10993
|
+
function loadAssets() {
|
|
10994
|
+
if (cachedAssets) return cachedAssets;
|
|
10995
|
+
const wordsRaw = JSON.parse(
|
|
10996
|
+
fs.readFileSync(path.join(assetsDir, "slop_list.json"), "utf8")
|
|
10997
|
+
);
|
|
10998
|
+
const trigramsRaw = JSON.parse(
|
|
10999
|
+
fs.readFileSync(path.join(assetsDir, "slop_list_trigrams.json"), "utf8")
|
|
11000
|
+
);
|
|
11001
|
+
const leaderboard = JSON.parse(
|
|
11002
|
+
fs.readFileSync(path.join(assetsDir, "leaderboard_results.json"), "utf8")
|
|
11003
|
+
);
|
|
11004
|
+
const words = /* @__PURE__ */ new Set();
|
|
11005
|
+
for (const item of wordsRaw) {
|
|
11006
|
+
if (Array.isArray(item) && item[0]) words.add(item[0].toLowerCase());
|
|
11007
|
+
}
|
|
11008
|
+
const trigrams = /* @__PURE__ */ new Set();
|
|
11009
|
+
for (const item of trigramsRaw) {
|
|
11010
|
+
if (Array.isArray(item) && item[0]) trigrams.add(item[0].toLowerCase());
|
|
11011
|
+
}
|
|
11012
|
+
const metrics = {
|
|
11013
|
+
slop_words: [],
|
|
11014
|
+
slop_trigrams: [],
|
|
11015
|
+
contrast: []
|
|
11016
|
+
};
|
|
11017
|
+
for (const res of leaderboard.results ?? []) {
|
|
11018
|
+
if (!res.metrics) continue;
|
|
11019
|
+
metrics.slop_words.push(res.metrics.slop_list_matches_per_1k_words || 0);
|
|
11020
|
+
metrics.slop_trigrams.push(
|
|
11021
|
+
res.metrics.slop_trigram_matches_per_1k_words || 0
|
|
11022
|
+
);
|
|
11023
|
+
metrics.contrast.push(res.metrics.not_x_but_y_per_1k_chars || 0);
|
|
11024
|
+
}
|
|
11025
|
+
cachedAssets = {
|
|
11026
|
+
words,
|
|
11027
|
+
trigrams,
|
|
11028
|
+
normalizationRanges: {
|
|
11029
|
+
slop_words: computeRange(metrics.slop_words),
|
|
11030
|
+
slop_trigrams: computeRange(metrics.slop_trigrams),
|
|
11031
|
+
contrast: computeRange(metrics.contrast)
|
|
11032
|
+
}
|
|
11033
|
+
};
|
|
11034
|
+
return cachedAssets;
|
|
11035
|
+
}
|
|
11036
|
+
function normalizeValue(value, range) {
|
|
11037
|
+
const normalized = (value - range.min) / (range.max - range.min);
|
|
11038
|
+
return Math.max(0, Math.min(1, normalized));
|
|
11039
|
+
}
|
|
11040
|
+
function toPlainText(text) {
|
|
11041
|
+
return text.replace(/```[\s\S]*?```/g, " ").replace(/`[^`\n]+`/g, " ").replace(/<[^>]+>/g, " ").replace(/!\[[^\]]*]\([^)]*\)/g, " ").replace(/\[[^\]]*]\([^)]*\)/g, " ").replace(/^#{1,6}\s+/gm, "").replace(/[*_~>#-]+/g, " ");
|
|
11042
|
+
}
|
|
11043
|
+
function tokenize(text) {
|
|
11044
|
+
return text.toLowerCase().match(/[a-z]+(?:'[a-z]+)?/g) ?? [];
|
|
11045
|
+
}
|
|
11046
|
+
function collectMatches(pattern, text) {
|
|
11047
|
+
return [...text.matchAll(pattern)].map((match) => match[0] ?? "");
|
|
11048
|
+
}
|
|
11049
|
+
function runSlopDetector(text) {
|
|
11050
|
+
if (!text.trim()) return [];
|
|
11051
|
+
const assets = loadAssets();
|
|
11052
|
+
const plain = toPlainText(text);
|
|
11053
|
+
const tokens = tokenize(plain);
|
|
11054
|
+
const nTokens = tokens.length || 1;
|
|
11055
|
+
let wordHitCount = 0;
|
|
11056
|
+
const wordHitMap = /* @__PURE__ */ new Map();
|
|
11057
|
+
for (const token of tokens) {
|
|
11058
|
+
if (!assets.words.has(token)) continue;
|
|
11059
|
+
wordHitCount++;
|
|
11060
|
+
wordHitMap.set(token, (wordHitMap.get(token) || 0) + 1);
|
|
11061
|
+
}
|
|
11062
|
+
let trigramHitCount = 0;
|
|
11063
|
+
if (tokens.length >= 3) {
|
|
11064
|
+
for (let i = 0; i < tokens.length - 2; i++) {
|
|
11065
|
+
const tg = `${tokens[i]} ${tokens[i + 1]} ${tokens[i + 2]}`;
|
|
11066
|
+
if (assets.trigrams.has(tg)) trigramHitCount++;
|
|
11067
|
+
}
|
|
11068
|
+
}
|
|
11069
|
+
const contrastMatches = [
|
|
11070
|
+
.../* @__PURE__ */ new Set([
|
|
11071
|
+
...collectMatches(CONTRAST_PATTERN, plain),
|
|
11072
|
+
...collectMatches(NOT_BUT_PATTERN, plain)
|
|
11073
|
+
])
|
|
11074
|
+
];
|
|
11075
|
+
const emDashCount = (text.match(/—/g) ?? []).length;
|
|
11076
|
+
const tropeRate = emDashCount / Math.max(plain.length, 1) * 1e3;
|
|
11077
|
+
const wordScore = wordHitCount / nTokens * WORD_MULTIPLIER;
|
|
11078
|
+
const trigramScore = trigramHitCount / nTokens * TRIGRAM_MULTIPLIER;
|
|
11079
|
+
const contrastScore = contrastMatches.length / Math.max(plain.length, 1) * 1e3;
|
|
11080
|
+
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;
|
|
11081
|
+
const slopScore = Math.round(rawSlopScore * 10) / 10;
|
|
11082
|
+
const issues = [];
|
|
11083
|
+
if (slopScore >= 40) {
|
|
11084
|
+
issues.push({
|
|
11085
|
+
rule: "eqbench-slop-score",
|
|
11086
|
+
engine: "slop-detector",
|
|
11087
|
+
category: "ai",
|
|
11088
|
+
severity: slopScore >= 60 ? "warn" : "info",
|
|
11089
|
+
message: `EQBench SLOP score ${slopScore}/100 (higher = more AI-like).`,
|
|
11090
|
+
suggestion: slopScore >= 60 ? "Rewrite stock phrasing and contrast constructions." : "Review flagged vocabulary and contrast patterns."
|
|
11091
|
+
});
|
|
11092
|
+
}
|
|
11093
|
+
for (const [word2, count] of [...wordHitMap.entries()].sort((a, b) => b[1] - a[1]).slice(0, 8)) {
|
|
11094
|
+
issues.push({
|
|
11095
|
+
rule: `eqbench-word-${word2.replace(/\s+/g, "-")}`,
|
|
11096
|
+
engine: "slop-detector",
|
|
11097
|
+
category: "ai",
|
|
11098
|
+
severity: "info",
|
|
11099
|
+
message: `EQBench slop vocabulary: \u201C${word2}\u201D (${count}\xD7).`,
|
|
11100
|
+
match: word2
|
|
11101
|
+
});
|
|
11102
|
+
}
|
|
11103
|
+
for (const match of contrastMatches.slice(0, 5)) {
|
|
11104
|
+
issues.push({
|
|
11105
|
+
rule: "eqbench-contrast",
|
|
11106
|
+
engine: "slop-detector",
|
|
11107
|
+
category: "ai",
|
|
11108
|
+
severity: "info",
|
|
11109
|
+
message: `EQBench contrast pattern: \u201C${match.trim()}\u201D`,
|
|
11110
|
+
match
|
|
11111
|
+
});
|
|
11112
|
+
}
|
|
11113
|
+
if (emDashCount >= 3) {
|
|
11114
|
+
issues.push({
|
|
11115
|
+
rule: "eqbench-trope-em-dash",
|
|
11116
|
+
engine: "slop-detector",
|
|
11117
|
+
category: "ai",
|
|
11118
|
+
severity: "info",
|
|
11119
|
+
message: `EQBench typography trope: ${emDashCount} em dash(es).`,
|
|
11120
|
+
match: "\u2014"
|
|
11121
|
+
});
|
|
11122
|
+
}
|
|
11123
|
+
return issues;
|
|
11124
|
+
}
|
|
10891
11125
|
|
|
10892
11126
|
// src/engines/tag.ts
|
|
10893
11127
|
function tagEngine(issues, engine) {
|
|
@@ -11259,7 +11493,7 @@ function countListItems(input) {
|
|
|
11259
11493
|
function countBlockquotes(input) {
|
|
11260
11494
|
return getLineMetadata(input).blockquote_count;
|
|
11261
11495
|
}
|
|
11262
|
-
function
|
|
11496
|
+
function tokenize2(text) {
|
|
11263
11497
|
const blocks = splitParagraphBlocks(text);
|
|
11264
11498
|
const paragraphs2 = blocks.map((block) => block.text);
|
|
11265
11499
|
const sentences2 = splitSentencesFromBlocks(blocks);
|
|
@@ -11281,7 +11515,7 @@ function tokenize(text) {
|
|
|
11281
11515
|
}
|
|
11282
11516
|
};
|
|
11283
11517
|
}
|
|
11284
|
-
var tokenizeProse =
|
|
11518
|
+
var tokenizeProse = tokenize2;
|
|
11285
11519
|
|
|
11286
11520
|
// node_modules/@veldica/prose-analyzer/dist/utils.js
|
|
11287
11521
|
function round(value, decimals = 4) {
|
|
@@ -12025,7 +12259,7 @@ function inventoryMarkers(text, options = {}) {
|
|
|
12025
12259
|
}
|
|
12026
12260
|
|
|
12027
12261
|
// src/engines/veldica.ts
|
|
12028
|
-
function
|
|
12262
|
+
function toSeverity4(value) {
|
|
12029
12263
|
if (value === "high") return "warn";
|
|
12030
12264
|
return "info";
|
|
12031
12265
|
}
|
|
@@ -12040,7 +12274,7 @@ function runVeldica(text) {
|
|
|
12040
12274
|
rule: `veldica-${match.category || "marker"}`,
|
|
12041
12275
|
engine: "veldica",
|
|
12042
12276
|
category: "ai",
|
|
12043
|
-
severity:
|
|
12277
|
+
severity: toSeverity4(match.severity),
|
|
12044
12278
|
message: `AI-style marker (${match.category}): \u201C${match.matched_text}\u201D`,
|
|
12045
12279
|
excerpt: excerptAround(text, offset),
|
|
12046
12280
|
match: match.matched_text
|
|
@@ -12053,8 +12287,8 @@ function runVeldica(text) {
|
|
|
12053
12287
|
return issue;
|
|
12054
12288
|
});
|
|
12055
12289
|
}
|
|
12056
|
-
var
|
|
12057
|
-
var writeGood =
|
|
12290
|
+
var require4 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
12291
|
+
var writeGood = require4("write-good");
|
|
12058
12292
|
function runWriteGood(text) {
|
|
12059
12293
|
const suggestions = writeGood(text, {
|
|
12060
12294
|
so: false,
|
|
@@ -12278,6 +12512,14 @@ var AI_PATTERN_RULES = [
|
|
|
12278
12512
|
severity: "info",
|
|
12279
12513
|
minCount: ({ words }) => Math.max(6, words / 250)
|
|
12280
12514
|
},
|
|
12515
|
+
{
|
|
12516
|
+
id: "ai-emojis",
|
|
12517
|
+
category: "ai",
|
|
12518
|
+
pattern: new RegExp("\\p{Extended_Pictographic}", "gu"),
|
|
12519
|
+
message: "Emoji can read as chatty or AI-styled in formal prose.",
|
|
12520
|
+
severity: "info",
|
|
12521
|
+
suggestion: "Prefer plain prose, or set ignoreEmojis: true to allow them."
|
|
12522
|
+
},
|
|
12281
12523
|
{
|
|
12282
12524
|
id: "double-space",
|
|
12283
12525
|
category: "typography",
|
|
@@ -13146,7 +13388,7 @@ function computeStats(body, titleLength, descriptionLength, issues) {
|
|
|
13146
13388
|
descriptionLength
|
|
13147
13389
|
};
|
|
13148
13390
|
}
|
|
13149
|
-
function collectIssues(body, frontmatter, format, config) {
|
|
13391
|
+
function collectIssues(body, frontmatter, format, config, source2) {
|
|
13150
13392
|
const ignoreRules = new Set(config.ignoreRules);
|
|
13151
13393
|
const issues = [];
|
|
13152
13394
|
const enginesRun = [];
|
|
@@ -13219,6 +13461,18 @@ function collectIssues(body, frontmatter, format, config) {
|
|
|
13219
13461
|
enginesRun.push("clean-writing");
|
|
13220
13462
|
issues.push(...runCleanWriting(body));
|
|
13221
13463
|
}
|
|
13464
|
+
if (config.engines.aiSlopLinter && config.checks.ai) {
|
|
13465
|
+
enginesRun.push("ai-slop-linter");
|
|
13466
|
+
issues.push(...runAiSlopLinter(body, { source: source2 }));
|
|
13467
|
+
}
|
|
13468
|
+
if (config.engines.slopDetector && config.checks.ai) {
|
|
13469
|
+
enginesRun.push("slop-detector");
|
|
13470
|
+
issues.push(...runSlopDetector(body));
|
|
13471
|
+
}
|
|
13472
|
+
if (config.engines.proseSlop && config.checks.ai) {
|
|
13473
|
+
enginesRun.push("prose-slop");
|
|
13474
|
+
issues.push(...runProseSlop(body, { format }));
|
|
13475
|
+
}
|
|
13222
13476
|
return {
|
|
13223
13477
|
issues: issues.filter((issue) => !ignoreRules.has(issue.rule)),
|
|
13224
13478
|
enginesRun: uniqueEngines(enginesRun)
|
|
@@ -13234,7 +13488,8 @@ function checkText(text, options = {}) {
|
|
|
13234
13488
|
body,
|
|
13235
13489
|
parsed.frontmatter,
|
|
13236
13490
|
format,
|
|
13237
|
-
config
|
|
13491
|
+
config,
|
|
13492
|
+
source2
|
|
13238
13493
|
);
|
|
13239
13494
|
const title = String(parsed.frontmatter.title ?? pathBasename(source2));
|
|
13240
13495
|
const report = {
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CheckOptions, a as CheckReport, U as UserConfig, R as ResolvedConfig, b as ReplacementStats, S as SanitizeOptions, c as Severity, I as Issue } from './types-
|
|
2
|
-
export { d as Category, e as CheckName, f as CheckSummary, g as ChecksConfig, E as EngineName, h as EnginesConfig, M as MarkdownConfig, P as PatternRule, i as PresetName, j as ReadabilityThresholds, k as SeoThresholds, T as TextFormat, l as TextStats } from './types-
|
|
1
|
+
import { C as CheckOptions, a as CheckReport, U as UserConfig, R as ResolvedConfig, b as ReplacementStats, S as SanitizeOptions, c as Severity, I as Issue } from './types-B6cMXIul.cjs';
|
|
2
|
+
export { d as Category, e as CheckName, f as CheckSummary, g as ChecksConfig, E as EngineName, h as EnginesConfig, M as MarkdownConfig, P as PatternRule, i as PresetName, j as ReadabilityThresholds, k as SeoThresholds, T as TextFormat, l as TextStats } from './types-B6cMXIul.cjs';
|
|
3
3
|
|
|
4
4
|
declare function checkText(text: string, options?: CheckOptions): CheckReport;
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CheckOptions, a as CheckReport, U as UserConfig, R as ResolvedConfig, b as ReplacementStats, S as SanitizeOptions, c as Severity, I as Issue } from './types-
|
|
2
|
-
export { d as Category, e as CheckName, f as CheckSummary, g as ChecksConfig, E as EngineName, h as EnginesConfig, M as MarkdownConfig, P as PatternRule, i as PresetName, j as ReadabilityThresholds, k as SeoThresholds, T as TextFormat, l as TextStats } from './types-
|
|
1
|
+
import { C as CheckOptions, a as CheckReport, U as UserConfig, R as ResolvedConfig, b as ReplacementStats, S as SanitizeOptions, c as Severity, I as Issue } from './types-B6cMXIul.js';
|
|
2
|
+
export { d as Category, e as CheckName, f as CheckSummary, g as ChecksConfig, E as EngineName, h as EnginesConfig, M as MarkdownConfig, P as PatternRule, i as PresetName, j as ReadabilityThresholds, k as SeoThresholds, T as TextFormat, l as TextStats } from './types-B6cMXIul.js';
|
|
3
3
|
|
|
4
4
|
declare function checkText(text: string, options?: CheckOptions): CheckReport;
|
|
5
5
|
|