text-sanctifier 1.3.8 → 1.3.9
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/ADDITIONAL_TERMS.md +122 -122
- package/LICENSE +694 -694
- package/README.md +438 -437
- package/bin/text-sanctifier.js +31 -8
- package/dist/text-sanctifier.min.js +1 -1
- package/dist/types/hiddenText.d.ts +4 -1
- package/dist/types/sanctifyText.d.ts +1 -1
- package/dist/types/version.generated.d.ts +1 -1
- package/package.json +89 -83
- package/robots.txt +79 -79
- package/src/hiddenText.js +243 -233
- package/src/index.d.ts +22 -22
- package/src/index.js +29 -29
- package/src/sanctifyText.js +4 -4
- package/src/version.generated.js +5 -5
package/bin/text-sanctifier.js
CHANGED
|
@@ -378,18 +378,22 @@ function collectInputs(args, cwd, warn, aiConfig = false) {
|
|
|
378
378
|
// --- Reading ---
|
|
379
379
|
|
|
380
380
|
const utf8 = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
381
|
+
const utf8Lenient = new TextDecoder('utf-8', { ignoreBOM: true });
|
|
381
382
|
|
|
382
383
|
/**
|
|
383
|
-
* Decodes UTF-8, keeping a leading BOM.
|
|
384
|
+
* Decodes UTF-8, keeping a leading BOM. With `sniff`, data with a NUL in its first
|
|
385
|
+
* BINARY_SNIFF_BYTES is binary and not decoded. Bytes that are not UTF-8 become U+FFFD
|
|
386
|
+
* and set `lossy`, so one bad byte cannot hide the rest of a file from `check`.
|
|
384
387
|
* @param {Uint8Array} bytes
|
|
385
|
-
* @
|
|
388
|
+
* @param {boolean} sniff
|
|
389
|
+
* @returns {{ text: string|null, reason?: string, lossy?: boolean }}
|
|
386
390
|
*/
|
|
387
|
-
function decode(bytes) {
|
|
388
|
-
if (bytes.subarray(0, BINARY_SNIFF_BYTES).includes(0)) return { text: null, reason: 'binary' };
|
|
391
|
+
function decode(bytes, sniff) {
|
|
392
|
+
if (sniff && bytes.subarray(0, BINARY_SNIFF_BYTES).includes(0)) return { text: null, reason: 'binary' };
|
|
389
393
|
try {
|
|
390
394
|
return { text: utf8.decode(bytes) };
|
|
391
395
|
} catch {
|
|
392
|
-
return { text:
|
|
396
|
+
return { text: utf8Lenient.decode(bytes), lossy: true };
|
|
393
397
|
}
|
|
394
398
|
}
|
|
395
399
|
|
|
@@ -612,6 +616,8 @@ async function main(argv) {
|
|
|
612
616
|
|
|
613
617
|
const cwd = process.cwd();
|
|
614
618
|
let paths = opts.paths;
|
|
619
|
+
// --ai-config with no paths searches the current directory even when stdin is not a
|
|
620
|
+
// terminal, so a CI job with no stdin still scans the repository; `-` reads stdin.
|
|
615
621
|
if (paths.length === 0 && opts.aiConfig) {
|
|
616
622
|
paths = ['.'];
|
|
617
623
|
} else if (paths.length === 0) {
|
|
@@ -627,6 +633,8 @@ async function main(argv) {
|
|
|
627
633
|
let errors = pathErrors;
|
|
628
634
|
/** @type {Array<{ path: string, reason: string }>} */
|
|
629
635
|
const skipped = [];
|
|
636
|
+
/** @type {string[]} */
|
|
637
|
+
const notUtf8 = [];
|
|
630
638
|
|
|
631
639
|
/**
|
|
632
640
|
* Reads every input in order, calling `visit(label, text, input)` for each decodable one.
|
|
@@ -643,12 +651,24 @@ async function main(argv) {
|
|
|
643
651
|
errors++;
|
|
644
652
|
continue;
|
|
645
653
|
}
|
|
646
|
-
|
|
654
|
+
// Files that look binary are skipped. Stdin and AI configuration files are text
|
|
655
|
+
// by intent, so a NUL in one is a finding, not a reason to skip it.
|
|
656
|
+
const { text, reason, lossy } = decode(bytes, input.path !== STDIN && !opts.aiConfig);
|
|
647
657
|
if (text === null) {
|
|
648
658
|
skipped.push({ path: label, reason });
|
|
649
659
|
if (input.explicit) warn(`${label}: skipped (${reason})`);
|
|
650
660
|
continue;
|
|
651
661
|
}
|
|
662
|
+
if (lossy) {
|
|
663
|
+
// fix never rewrites bytes it could not decode
|
|
664
|
+
if (opts.command === 'fix') {
|
|
665
|
+
skipped.push({ path: label, reason: 'not UTF-8' });
|
|
666
|
+
warn(`${label}: skipped (not UTF-8)`);
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
notUtf8.push(label);
|
|
670
|
+
warn(`${label}: not valid UTF-8; checked with invalid bytes read as U+FFFD`);
|
|
671
|
+
}
|
|
652
672
|
visit(label, text, input);
|
|
653
673
|
}
|
|
654
674
|
};
|
|
@@ -691,14 +711,17 @@ async function main(argv) {
|
|
|
691
711
|
|
|
692
712
|
const kind = opts.aiConfig ? 'AI configuration file' : 'file';
|
|
693
713
|
if (opts.format === 'json') {
|
|
694
|
-
const summary = { files, total, filesScanned: scanned, filesWithFindings: files.length, skipped };
|
|
714
|
+
const summary = { files, total, filesScanned: scanned, filesWithFindings: files.length, skipped, notUtf8 };
|
|
695
715
|
if (opts.aiConfig) summary.hiddenRunCount = hiddenRunCount;
|
|
696
716
|
out(JSON.stringify(summary, null, 2));
|
|
697
717
|
} else if (opts.format === 'sarif') {
|
|
698
718
|
out(JSON.stringify(sarifLog(files, { cwd, total, filesScanned: scanned, skipped, succeeded: errors === 0 }), null, 2));
|
|
699
719
|
} else {
|
|
700
720
|
for (const line of lines) out(line);
|
|
701
|
-
if (opts.aiConfig && scanned === 0 && skipped.length === 0)
|
|
721
|
+
if (opts.aiConfig && scanned === 0 && skipped.length === 0) {
|
|
722
|
+
out('No AI configuration files found.');
|
|
723
|
+
if (opts.paths.length === 0 && !process.stdin.isTTY) out('To check piped text, pass "-": text-sanctifier check --ai-config -');
|
|
724
|
+
}
|
|
702
725
|
else if (total === 0) out(`No ${opts.aiConfig ? 'hidden text, ' : ''}invisible or control characters in ${plural(scanned, kind)}.`);
|
|
703
726
|
else out(`${plural(total, 'finding')}${opts.aiConfig ? ` (${plural(hiddenRunCount, 'hidden run')})` : ''} in ${files.length} of ${plural(scanned, kind)}.`);
|
|
704
727
|
}
|
|
@@ -3,4 +3,4 @@ var y=/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F\u061C\u200E\u200F\u2
|
|
|
3
3
|
`){return e.replace(Q,r)}var re=/[ \t]*(\n+)[ \t]*/g;function ne(e){return e.replace(re,"$1")}var te=/\n{2,}/g,ie=/\n{3,}/g;function oe(e,r){return r?e.replace(ie,`
|
|
4
4
|
|
|
5
5
|
`):e.replace(te,`
|
|
6
|
-
`)}var ue=/ {2,}/g;function se(e){return e.replace(ue," ")}function le(e){return e.replace(y,"")}function ae(e,r={}){if(typeof e!="string")throw new TypeError("revealInvisible expects a string input.");let n=r&&typeof r.format=="function"?r.format:i=>"<U+"+i.toString(16).toUpperCase().padStart(4,"0")+">",u="",o=0;for(let i of C(e,{maxFindings:1/0}).findings)u+=e.slice(o,i.offset)+n(i.codePoint,i.category),o=i.offset+(i.codePoint>65535?2:1);return u+e.slice(o)}var fe="1.3.
|
|
6
|
+
`)}var ue=/ {2,}/g;function se(e){return e.replace(ue," ")}function le(e){return e.replace(y,"")}function ae(e,r={}){if(typeof e!="string")throw new TypeError("revealInvisible expects a string input.");let n=r&&typeof r.format=="function"?r.format:i=>"<U+"+i.toString(16).toUpperCase().padStart(4,"0")+">",u="",o=0;for(let i of C(e,{maxFindings:1/0}).findings)u+=e.slice(o,i.offset)+n(i.codePoint,i.category),o=i.offset+(i.codePoint>65535?2:1);return u+e.slice(o)}var fe="1.3.9";export{fe as VERSION,b as getNewlineStats,K as getRecommendedSanctifierOptions,j as inspectText,C as inspectTextDetailed,ae as revealInvisible,T as sanctifyKeyboardOnly,N as sanctifyKeyboardOnlyEmoji,w as sanctifyLoose,L as sanctifyPasted,R as sanctifyStrict,W as summonSanctifier};
|
|
@@ -13,7 +13,10 @@ export function decodeTagText(text: string): string;
|
|
|
13
13
|
* legitimate and listed under `benign` instead of `runs`:
|
|
14
14
|
* - the subdivision flags of England, Scotland and Wales: U+1F3F4 followed by the
|
|
15
15
|
* tags for "gbeng", "gbsct" or "gbwls" and U+E007F
|
|
16
|
-
* - a single U+FE0E or U+FE0F (text or emoji presentation) after
|
|
16
|
+
* - a single U+FE0E or U+FE0F (text or emoji presentation) after an
|
|
17
|
+
* Extended_Pictographic character, or between #, * or a digit and U+20E3 (a keycap),
|
|
18
|
+
* the same rule as text-sanctifier/context. After a letter it is a run: one selector
|
|
19
|
+
* per letter can carry a bit each.
|
|
17
20
|
*
|
|
18
21
|
* `line` and `column` are counted as in inspectTextDetailed. Every run and benign
|
|
19
22
|
* span is counted; only the first `maxRuns` of each are listed. With the caps set,
|
|
@@ -52,7 +52,7 @@ export function sanctifyPasted(text: string): string;
|
|
|
52
52
|
* Brutal text normalizer and invisible trash scrubber,
|
|
53
53
|
* configurable to kill whatever ghosts you want dead.
|
|
54
54
|
*
|
|
55
|
-
*
|
|
55
|
+
* Note: This is plain-text normalization/filtering — not an HTML/XSS sanitizer.
|
|
56
56
|
*
|
|
57
57
|
* @param {string} text
|
|
58
58
|
* @param {boolean} [purgeInvisibleChars=false] - Remove ZWSP, NBSP, bidi, tags, variation selectors, etc.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** The installed version of text-sanctifier, as in its package.json. */
|
|
2
|
-
export const VERSION: "1.3.
|
|
2
|
+
export const VERSION: "1.3.9";
|
package/package.json
CHANGED
|
@@ -1,83 +1,89 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "text-sanctifier",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "A brutal text normalizer and invisible trash scrubber for modern web projects.",
|
|
6
|
-
"engines": {
|
|
7
|
-
"node": ">=18"
|
|
8
|
-
},
|
|
9
|
-
"main": "./src/index.js",
|
|
10
|
-
"module": "./src/index.js",
|
|
11
|
-
"browser": "./dist/text-sanctifier.min.js",
|
|
12
|
-
"bin": {
|
|
13
|
-
"text-sanctifier": "bin/text-sanctifier.js"
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"src",
|
|
17
|
-
"bin",
|
|
18
|
-
"dist/text-sanctifier.min.js",
|
|
19
|
-
"dist/types",
|
|
20
|
-
"LICENSE",
|
|
21
|
-
"README.md",
|
|
22
|
-
"ADDITIONAL_TERMS.md",
|
|
23
|
-
"robots.txt"
|
|
24
|
-
],
|
|
25
|
-
"exports": {
|
|
26
|
-
".": {
|
|
27
|
-
"types": "./dist/types/index.d.ts",
|
|
28
|
-
"default": "./src/index.js"
|
|
29
|
-
},
|
|
30
|
-
"./hidden": {
|
|
31
|
-
"types": "./dist/types/hiddenText.d.ts",
|
|
32
|
-
"default": "./src/hiddenText.js"
|
|
33
|
-
},
|
|
34
|
-
"./context": {
|
|
35
|
-
"types": "./dist/types/context.d.ts",
|
|
36
|
-
"default": "./src/context.js"
|
|
37
|
-
},
|
|
38
|
-
"./browser": {
|
|
39
|
-
"types": "./dist/types/index.d.ts",
|
|
40
|
-
"default": "./dist/text-sanctifier.min.js"
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
"types": "./dist/types/index.d.ts",
|
|
44
|
-
"sideEffects": false,
|
|
45
|
-
"scripts": {
|
|
46
|
-
"gen": "node scripts/gen-categories.js && node scripts/gen-version.js && node scripts/gen-virama.js",
|
|
47
|
-
"gen:check": "node scripts/gen-categories.js --check && node scripts/gen-version.js --check && node scripts/gen-virama.js --check",
|
|
48
|
-
"build": "node scripts/build.js",
|
|
49
|
-
"build:types": "tsc -p tsconfig.types.json",
|
|
50
|
-
"test:types": "tsc -p tests/types/tsconfig.json",
|
|
51
|
-
"test": "node tests/sanctifyText.test.js && node tests/inspectTextDetailed.test.js && node --expose-gc tests/hiddenText.test.js && node --expose-gc tests/context.test.js && node tests/cli.test.js",
|
|
52
|
-
"test-min": "node tests/sanctifyText.test.min.js",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "text-sanctifier",
|
|
3
|
+
"version": "1.3.9",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A brutal text normalizer and invisible trash scrubber for modern web projects.",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=18"
|
|
8
|
+
},
|
|
9
|
+
"main": "./src/index.js",
|
|
10
|
+
"module": "./src/index.js",
|
|
11
|
+
"browser": "./dist/text-sanctifier.min.js",
|
|
12
|
+
"bin": {
|
|
13
|
+
"text-sanctifier": "bin/text-sanctifier.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"bin",
|
|
18
|
+
"dist/text-sanctifier.min.js",
|
|
19
|
+
"dist/types",
|
|
20
|
+
"LICENSE",
|
|
21
|
+
"README.md",
|
|
22
|
+
"ADDITIONAL_TERMS.md",
|
|
23
|
+
"robots.txt"
|
|
24
|
+
],
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/types/index.d.ts",
|
|
28
|
+
"default": "./src/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./hidden": {
|
|
31
|
+
"types": "./dist/types/hiddenText.d.ts",
|
|
32
|
+
"default": "./src/hiddenText.js"
|
|
33
|
+
},
|
|
34
|
+
"./context": {
|
|
35
|
+
"types": "./dist/types/context.d.ts",
|
|
36
|
+
"default": "./src/context.js"
|
|
37
|
+
},
|
|
38
|
+
"./browser": {
|
|
39
|
+
"types": "./dist/types/index.d.ts",
|
|
40
|
+
"default": "./dist/text-sanctifier.min.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"types": "./dist/types/index.d.ts",
|
|
44
|
+
"sideEffects": false,
|
|
45
|
+
"scripts": {
|
|
46
|
+
"gen": "node scripts/gen-categories.js && node scripts/gen-version.js && node scripts/gen-virama.js && node scripts/gen-docs.js",
|
|
47
|
+
"gen:check": "node scripts/gen-categories.js --check && node scripts/gen-version.js --check && node scripts/gen-virama.js --check && node scripts/gen-docs.js --check",
|
|
48
|
+
"build": "node scripts/build.js",
|
|
49
|
+
"build:types": "tsc -p tsconfig.types.json",
|
|
50
|
+
"test:types": "tsc -p tests/types/tsconfig.json",
|
|
51
|
+
"test": "node tests/sanctifyText.test.js && node tests/inspectTextDetailed.test.js && node --expose-gc tests/hiddenText.test.js && node --expose-gc tests/context.test.js && node tests/cli.test.js && node tests/release.test.js",
|
|
52
|
+
"test-min": "node tests/sanctifyText.test.min.js",
|
|
53
|
+
"check:self": "node bin/text-sanctifier.js check .",
|
|
54
|
+
"check:names": "node scripts/check-names.js",
|
|
55
|
+
"ci": "npm run gen:check && npm run check:names && npm run check:self && npm run test && npm run build && npm run size && npm run build:types && npm run test:types && npm run test-min",
|
|
56
|
+
"size": "node scripts/check-size.js",
|
|
57
|
+
"bench": "node --expose-gc scripts/bench.js",
|
|
58
|
+
"release:prep": "node scripts/release.js prep",
|
|
59
|
+
"release:verify": "node scripts/release.js verify",
|
|
60
|
+
"hooks:install": "git config core.hooksPath scripts/hooks"
|
|
61
|
+
},
|
|
62
|
+
"keywords": [
|
|
63
|
+
"text",
|
|
64
|
+
"sanitize",
|
|
65
|
+
"normalize",
|
|
66
|
+
"invisible",
|
|
67
|
+
"scrubber",
|
|
68
|
+
"unicode",
|
|
69
|
+
"clean",
|
|
70
|
+
"sanctify"
|
|
71
|
+
],
|
|
72
|
+
"author": "WATT3D <WATT3D@protonmail.com>",
|
|
73
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
74
|
+
"repository": {
|
|
75
|
+
"type": "git",
|
|
76
|
+
"url": "git+https://github.com/iWhatty/text-sanctifier.git"
|
|
77
|
+
},
|
|
78
|
+
"bugs": {
|
|
79
|
+
"url": "https://github.com/iWhatty/text-sanctifier/issues"
|
|
80
|
+
},
|
|
81
|
+
"homepage": "https://github.com/iWhatty/text-sanctifier#readme",
|
|
82
|
+
"directories": {
|
|
83
|
+
"test": "tests"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"esbuild": "^0.25.3",
|
|
87
|
+
"typescript": "^5.9.3"
|
|
88
|
+
}
|
|
89
|
+
}
|
package/robots.txt
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
# WATT3D — AI scraping policy
|
|
2
|
-
#
|
|
3
|
-
# This file enumerates known AI / LLM training and inference crawlers
|
|
4
|
-
# that the WATT3D AI Training Rider does not consent to. See
|
|
5
|
-
# ./ADDITIONAL_TERMS.md for the legal scope and definitions.
|
|
6
|
-
#
|
|
7
|
-
# Honoring robots.txt is voluntary. The rider applies whether or not
|
|
8
|
-
# a bot respects this file. The enumeration is non-exhaustive — bots
|
|
9
|
-
# not listed here are still bound by the rider if they perform
|
|
10
|
-
# Training Use as defined in ADDITIONAL_TERMS.md §1.
|
|
11
|
-
|
|
12
|
-
User-agent: GPTBot
|
|
13
|
-
Disallow: /
|
|
14
|
-
|
|
15
|
-
User-agent: ChatGPT-User
|
|
16
|
-
Disallow: /
|
|
17
|
-
|
|
18
|
-
User-agent: OAI-SearchBot
|
|
19
|
-
Disallow: /
|
|
20
|
-
|
|
21
|
-
User-agent: anthropic-ai
|
|
22
|
-
Disallow: /
|
|
23
|
-
|
|
24
|
-
User-agent: ClaudeBot
|
|
25
|
-
Disallow: /
|
|
26
|
-
|
|
27
|
-
User-agent: Claude-Web
|
|
28
|
-
Disallow: /
|
|
29
|
-
|
|
30
|
-
User-agent: Claude-SearchBot
|
|
31
|
-
Disallow: /
|
|
32
|
-
|
|
33
|
-
User-agent: Google-Extended
|
|
34
|
-
Disallow: /
|
|
35
|
-
|
|
36
|
-
User-agent: Applebot-Extended
|
|
37
|
-
Disallow: /
|
|
38
|
-
|
|
39
|
-
User-agent: Meta-ExternalAgent
|
|
40
|
-
Disallow: /
|
|
41
|
-
|
|
42
|
-
User-agent: Meta-ExternalFetcher
|
|
43
|
-
Disallow: /
|
|
44
|
-
|
|
45
|
-
User-agent: FacebookBot
|
|
46
|
-
Disallow: /
|
|
47
|
-
|
|
48
|
-
User-agent: CCBot
|
|
49
|
-
Disallow: /
|
|
50
|
-
|
|
51
|
-
User-agent: PerplexityBot
|
|
52
|
-
Disallow: /
|
|
53
|
-
|
|
54
|
-
User-agent: Perplexity-User
|
|
55
|
-
Disallow: /
|
|
56
|
-
|
|
57
|
-
User-agent: cohere-ai
|
|
58
|
-
Disallow: /
|
|
59
|
-
|
|
60
|
-
User-agent: Bytespider
|
|
61
|
-
Disallow: /
|
|
62
|
-
|
|
63
|
-
User-agent: Amazonbot
|
|
64
|
-
Disallow: /
|
|
65
|
-
|
|
66
|
-
User-agent: Omgilibot
|
|
67
|
-
Disallow: /
|
|
68
|
-
|
|
69
|
-
User-agent: AI2Bot
|
|
70
|
-
Disallow: /
|
|
71
|
-
|
|
72
|
-
User-agent: Diffbot
|
|
73
|
-
Disallow: /
|
|
74
|
-
|
|
75
|
-
# Everyone else: full access. Search engines and human-driven crawlers
|
|
76
|
-
# remain welcome.
|
|
77
|
-
|
|
78
|
-
User-agent: *
|
|
79
|
-
Allow: /
|
|
1
|
+
# WATT3D — AI scraping policy
|
|
2
|
+
#
|
|
3
|
+
# This file enumerates known AI / LLM training and inference crawlers
|
|
4
|
+
# that the WATT3D AI Training Rider does not consent to. See
|
|
5
|
+
# ./ADDITIONAL_TERMS.md for the legal scope and definitions.
|
|
6
|
+
#
|
|
7
|
+
# Honoring robots.txt is voluntary. The rider applies whether or not
|
|
8
|
+
# a bot respects this file. The enumeration is non-exhaustive — bots
|
|
9
|
+
# not listed here are still bound by the rider if they perform
|
|
10
|
+
# Training Use as defined in ADDITIONAL_TERMS.md §1.
|
|
11
|
+
|
|
12
|
+
User-agent: GPTBot
|
|
13
|
+
Disallow: /
|
|
14
|
+
|
|
15
|
+
User-agent: ChatGPT-User
|
|
16
|
+
Disallow: /
|
|
17
|
+
|
|
18
|
+
User-agent: OAI-SearchBot
|
|
19
|
+
Disallow: /
|
|
20
|
+
|
|
21
|
+
User-agent: anthropic-ai
|
|
22
|
+
Disallow: /
|
|
23
|
+
|
|
24
|
+
User-agent: ClaudeBot
|
|
25
|
+
Disallow: /
|
|
26
|
+
|
|
27
|
+
User-agent: Claude-Web
|
|
28
|
+
Disallow: /
|
|
29
|
+
|
|
30
|
+
User-agent: Claude-SearchBot
|
|
31
|
+
Disallow: /
|
|
32
|
+
|
|
33
|
+
User-agent: Google-Extended
|
|
34
|
+
Disallow: /
|
|
35
|
+
|
|
36
|
+
User-agent: Applebot-Extended
|
|
37
|
+
Disallow: /
|
|
38
|
+
|
|
39
|
+
User-agent: Meta-ExternalAgent
|
|
40
|
+
Disallow: /
|
|
41
|
+
|
|
42
|
+
User-agent: Meta-ExternalFetcher
|
|
43
|
+
Disallow: /
|
|
44
|
+
|
|
45
|
+
User-agent: FacebookBot
|
|
46
|
+
Disallow: /
|
|
47
|
+
|
|
48
|
+
User-agent: CCBot
|
|
49
|
+
Disallow: /
|
|
50
|
+
|
|
51
|
+
User-agent: PerplexityBot
|
|
52
|
+
Disallow: /
|
|
53
|
+
|
|
54
|
+
User-agent: Perplexity-User
|
|
55
|
+
Disallow: /
|
|
56
|
+
|
|
57
|
+
User-agent: cohere-ai
|
|
58
|
+
Disallow: /
|
|
59
|
+
|
|
60
|
+
User-agent: Bytespider
|
|
61
|
+
Disallow: /
|
|
62
|
+
|
|
63
|
+
User-agent: Amazonbot
|
|
64
|
+
Disallow: /
|
|
65
|
+
|
|
66
|
+
User-agent: Omgilibot
|
|
67
|
+
Disallow: /
|
|
68
|
+
|
|
69
|
+
User-agent: AI2Bot
|
|
70
|
+
Disallow: /
|
|
71
|
+
|
|
72
|
+
User-agent: Diffbot
|
|
73
|
+
Disallow: /
|
|
74
|
+
|
|
75
|
+
# Everyone else: full access. Search engines and human-driven crawlers
|
|
76
|
+
# remain welcome.
|
|
77
|
+
|
|
78
|
+
User-agent: *
|
|
79
|
+
Allow: /
|