page-markdown 0.1.5 → 0.3.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/ADDITIONAL_TERMS.md +122 -122
- package/CHANGELOG.md +353 -186
- package/LICENSE +694 -694
- package/README.md +113 -41
- package/THIRD_PARTY_NOTICES.md +264 -264
- package/dist/types/concealed.d.ts +59 -0
- package/dist/types/extract.d.ts +10 -4
- package/dist/types/facts.d.ts +1 -0
- package/dist/types/index.d.ts +20 -6
- package/dist/types/sanitize.d.ts +22 -3
- package/dist/types/standardize.d.ts +15 -1
- package/dist/types/types.d.ts +51 -2
- package/package.json +69 -68
- package/robots.txt +79 -79
- package/src/clean.js +1 -1
- package/src/concealed.js +418 -0
- package/src/convert.js +95 -13
- package/src/extract.js +178 -8
- package/src/facts.js +6 -3
- package/src/index.js +219 -178
- package/src/refine.js +9 -3
- package/src/sanitize.js +106 -57
- package/src/standardize.js +167 -3
- package/src/types.js +23 -2
package/dist/types/index.d.ts
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
* @property {string} [url] page URL for absolute links (default: the document's URL)
|
|
4
4
|
* @property {"full"|"no_links"|"text_only"} [mode="full"]
|
|
5
5
|
* @property {"readable"|"full"|import("./extract.js").Extractor} [extract="readable"]
|
|
6
|
-
* "readable": Readability with full-page fallback; "full": the whole body;
|
|
6
|
+
* "readable": Readability with main-content or full-page fallback; "full": the whole body;
|
|
7
7
|
* or a custom extractor receiving a copy of the standardized document.
|
|
8
|
-
* @property {number} [minExtractChars=100] below this, fall back to the
|
|
8
|
+
* @property {number} [minExtractChars=100] below this, fall back to the page's <main>
|
|
9
|
+
* if it marks one and it holds enough, else to the full page
|
|
10
|
+
* @property {number} [minExtractShare=0.4] when Readability keeps less than this
|
|
11
|
+
* share of the page's main content, use the main content instead; 0 turns it off
|
|
9
12
|
* @property {boolean} [includeFullPage=false] also return the full-page Markdown
|
|
13
|
+
* @property {boolean} [detectConcealedText=false] opt-in live computed-style check, default false
|
|
10
14
|
* @property {boolean} [includeTitle=true] start readable output with "# <headline>"
|
|
11
15
|
* @property {boolean} [recoverLead=true] restore a dropped lead paragraph that matches the meta description
|
|
12
16
|
* @property {boolean} [pageFacts=false] append "## Page facts": short label/value pairs
|
|
@@ -27,7 +31,7 @@
|
|
|
27
31
|
* @returns {import("./types.js").PageMarkdownResult}
|
|
28
32
|
*/
|
|
29
33
|
export function pageToMarkdown(input: Document | Element, options?: PageMarkdownOptions): import("./types.js").PageMarkdownResult;
|
|
30
|
-
export const VERSION: "0.
|
|
34
|
+
export const VERSION: "0.3.0";
|
|
31
35
|
export { standardizeDocument } from "./standardize.js";
|
|
32
36
|
export { collectMetadata } from "./metadata.js";
|
|
33
37
|
export * from "./types.js";
|
|
@@ -38,18 +42,28 @@ export type PageMarkdownOptions = {
|
|
|
38
42
|
url?: string | undefined;
|
|
39
43
|
mode?: "full" | "no_links" | "text_only" | undefined;
|
|
40
44
|
/**
|
|
41
|
-
* "readable": Readability with full-page fallback; "full": the whole body;
|
|
45
|
+
* "readable": Readability with main-content or full-page fallback; "full": the whole body;
|
|
42
46
|
* or a custom extractor receiving a copy of the standardized document.
|
|
43
47
|
*/
|
|
44
48
|
extract?: import("./extract.js").Extractor | "readable" | "full" | undefined;
|
|
45
49
|
/**
|
|
46
|
-
* below this, fall back to the
|
|
50
|
+
* below this, fall back to the page's <main>
|
|
51
|
+
* if it marks one and it holds enough, else to the full page
|
|
47
52
|
*/
|
|
48
53
|
minExtractChars?: number | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* when Readability keeps less than this
|
|
56
|
+
* share of the page's main content, use the main content instead; 0 turns it off
|
|
57
|
+
*/
|
|
58
|
+
minExtractShare?: number | undefined;
|
|
49
59
|
/**
|
|
50
60
|
* also return the full-page Markdown
|
|
51
61
|
*/
|
|
52
62
|
includeFullPage?: boolean | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* opt-in live computed-style check, default false
|
|
65
|
+
*/
|
|
66
|
+
detectConcealedText?: boolean | undefined;
|
|
53
67
|
/**
|
|
54
68
|
* start readable output with "# <headline>"
|
|
55
69
|
*/
|
|
@@ -90,7 +104,7 @@ export type PageMarkdownOptions = {
|
|
|
90
104
|
} | undefined;
|
|
91
105
|
};
|
|
92
106
|
export { sanitizeToInertDocument, DEFAULT_SANITIZE_OPTIONS, isAdvertisementElement, createInertDocument } from "./sanitize.js";
|
|
93
|
-
export { extractContent, DEFAULT_MIN_EXTRACT_CHARS } from "./extract.js";
|
|
107
|
+
export { extractContent, DEFAULT_MIN_EXTRACT_CHARS, DEFAULT_MIN_EXTRACT_SHARE } from "./extract.js";
|
|
94
108
|
export { htmlToMarkdown, createTurndown, TURNDOWN_OPTIONS } from "./convert.js";
|
|
95
109
|
export { cleanMarkdown, applyMode, mapOutsideFences } from "./clean.js";
|
|
96
110
|
export { recoverLeadParagraph, chooseHeadline } from "./refine.js";
|
package/dist/types/sanitize.d.ts
CHANGED
|
@@ -9,18 +9,37 @@ export function createInertDocument(doc: Document): Document;
|
|
|
9
9
|
/**
|
|
10
10
|
* Clones `root` (a Document or Element) into a new inert document.
|
|
11
11
|
* Open shadow roots replace their host's light children (native slots supply
|
|
12
|
-
* assigned children). Limits apply only to shadow content
|
|
13
|
-
*
|
|
12
|
+
* assigned children). Limits apply only to shadow content, per host in the
|
|
13
|
+
* page's own tree, so slotted page content is not charged: docs sites put a
|
|
14
|
+
* whole article in one host's slot. A host over the limit keeps what fits and
|
|
15
|
+
* is counted as an omission.
|
|
14
16
|
*
|
|
15
17
|
* @param {Document|Element} root
|
|
16
18
|
* @param {import("./types.js").SanitizeOptions} [options]
|
|
17
|
-
* @returns {{ document: Document, omissions: { shadowHosts: number } }}
|
|
18
19
|
*/
|
|
19
20
|
export function sanitizeToInertDocument(root: Document | Element, options?: import("./types.js").SanitizeOptions): {
|
|
20
21
|
document: Document;
|
|
21
22
|
omissions: {
|
|
22
23
|
shadowHosts: number;
|
|
23
24
|
};
|
|
25
|
+
concealment: {
|
|
26
|
+
process: (el: any, copy: any, work: any, pairs: any) => void;
|
|
27
|
+
initial: (source: any) => any;
|
|
28
|
+
inherit: (work: any, child: any, clone: any) => any;
|
|
29
|
+
exempt: (el: any) => void;
|
|
30
|
+
lift: (inert: any) => void;
|
|
31
|
+
entries: import("./types.js").ConcealedText[];
|
|
32
|
+
summary: {
|
|
33
|
+
count: number;
|
|
34
|
+
chars: number;
|
|
35
|
+
truncated: boolean;
|
|
36
|
+
};
|
|
37
|
+
readonly counters: {
|
|
38
|
+
[k: string]: number;
|
|
39
|
+
};
|
|
40
|
+
readonly check: import("./types.js").ConcealmentCheck;
|
|
41
|
+
readonly pendingOpacity: number;
|
|
42
|
+
};
|
|
24
43
|
};
|
|
25
44
|
/** @type {Readonly<Required<import("./types.js").SanitizeOptions>>} */
|
|
26
45
|
export const DEFAULT_SANITIZE_OPTIONS: Readonly<Required<import("./types.js").SanitizeOptions>>;
|
|
@@ -1,15 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tabs read as one document: inactive panels are shown, each under its tab's
|
|
3
|
+
* name, in place of a tab strip that points nowhere. A long inactive panel is
|
|
4
|
+
* left out, and named in stats.omittedTabs.
|
|
5
|
+
*/
|
|
6
|
+
export function prepareConcealment(doc: any, concealment: any): {
|
|
7
|
+
panels: any[];
|
|
8
|
+
hasProvenance: any;
|
|
9
|
+
inactive: Map<any, boolean>;
|
|
10
|
+
panelLengths: Map<any, any>;
|
|
11
|
+
};
|
|
1
12
|
/**
|
|
2
13
|
* @param {Document} doc the inert clone (mutated in place)
|
|
3
|
-
* @param {{ url?: string }} [options]
|
|
14
|
+
* @param {{ url?: string, concealment?: ReturnType<typeof import('./concealed.js').createConcealmentWalk> }} [options]
|
|
4
15
|
*/
|
|
5
16
|
export function standardizeDocument(doc: Document, options?: {
|
|
6
17
|
url?: string;
|
|
18
|
+
concealment?: ReturnType<typeof import("./concealed.js").createConcealmentWalk>;
|
|
7
19
|
}): {
|
|
8
20
|
lazyImagesResolved: number;
|
|
9
21
|
inlineImagesDropped: number;
|
|
10
22
|
scriptLinksUnwrapped: number;
|
|
23
|
+
invalidLinksUnwrapped: number;
|
|
11
24
|
emptyLinksRemoved: number;
|
|
12
25
|
preWrapped: number;
|
|
13
26
|
headingWidgetsRemoved: number;
|
|
14
27
|
headingsUnwrapped: number;
|
|
28
|
+
omittedTabs: string[];
|
|
15
29
|
};
|
package/dist/types/types.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export type SanitizeOptions = {
|
|
|
7
7
|
stripMeta?: boolean | undefined;
|
|
8
8
|
stripLinkTags?: boolean | undefined;
|
|
9
9
|
stripAds?: boolean | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* opt-in computed-style check, default false
|
|
12
|
+
*/
|
|
13
|
+
detectConcealedText?: boolean | undefined;
|
|
10
14
|
/**
|
|
11
15
|
* app-specific overlays or widgets to drop, e.g. "[data-app-overlay]"
|
|
12
16
|
*/
|
|
@@ -37,7 +41,7 @@ export type PageMarkdownMetadata = CollectedMetadata & ExtractedMetadata;
|
|
|
37
41
|
export type PageMarkdownExtraction = {
|
|
38
42
|
method: Extraction["method"];
|
|
39
43
|
/**
|
|
40
|
-
* why extraction fell back to the full page
|
|
44
|
+
* why extraction fell back to the full page or the main content
|
|
41
45
|
*/
|
|
42
46
|
fallbackReason?: string | undefined;
|
|
43
47
|
/**
|
|
@@ -97,7 +101,8 @@ export type HiddenTextOmission = {
|
|
|
97
101
|
note: string;
|
|
98
102
|
};
|
|
99
103
|
/**
|
|
100
|
-
* Check `kind` before reading `chars`:
|
|
104
|
+
* Check `kind` before reading `chars`: hidden Unicode omissions use code points;
|
|
105
|
+
* concealed_text uses UTF-16 units. Other kinds do not have it.
|
|
101
106
|
*/
|
|
102
107
|
export type PageMarkdownOmission = {
|
|
103
108
|
kind: "shadow_content";
|
|
@@ -107,6 +112,19 @@ export type PageMarkdownOmission = {
|
|
|
107
112
|
kind: "json_line";
|
|
108
113
|
count: number;
|
|
109
114
|
note: string;
|
|
115
|
+
} | {
|
|
116
|
+
kind: "inactive_tabs";
|
|
117
|
+
count: number;
|
|
118
|
+
note: string;
|
|
119
|
+
} | {
|
|
120
|
+
kind: "comments";
|
|
121
|
+
count: number;
|
|
122
|
+
note: string;
|
|
123
|
+
} | {
|
|
124
|
+
kind: "concealed_text";
|
|
125
|
+
count: number;
|
|
126
|
+
chars: number;
|
|
127
|
+
note: string;
|
|
110
128
|
} | HiddenTextOmission;
|
|
111
129
|
export type StandardizationStats = ReturnType<typeof import("./standardize.js").standardizeDocument>;
|
|
112
130
|
export type PageMarkdownStats = {
|
|
@@ -114,6 +132,11 @@ export type PageMarkdownStats = {
|
|
|
114
132
|
extractedHtmlChars: number;
|
|
115
133
|
convertedChars: number;
|
|
116
134
|
markdownChars: number;
|
|
135
|
+
/**
|
|
136
|
+
* the page's text at capture time: a capture is a
|
|
137
|
+
* snapshot of the DOM, so a caller can re-capture until this number settles
|
|
138
|
+
*/
|
|
139
|
+
pageTextChars: number;
|
|
117
140
|
standardization: StandardizationStats;
|
|
118
141
|
};
|
|
119
142
|
export type PageMarkdownResult = {
|
|
@@ -121,6 +144,18 @@ export type PageMarkdownResult = {
|
|
|
121
144
|
* the package version that made this result
|
|
122
145
|
*/
|
|
123
146
|
version: string;
|
|
147
|
+
/**
|
|
148
|
+
* capped captured blocks, raw text in UTF-16 units
|
|
149
|
+
*/
|
|
150
|
+
concealedText: ConcealedText[];
|
|
151
|
+
/**
|
|
152
|
+
* source computed-style capability
|
|
153
|
+
*/
|
|
154
|
+
concealmentCheck: ConcealmentCheck;
|
|
155
|
+
/**
|
|
156
|
+
* true if any block, text or entry cap omitted report text
|
|
157
|
+
*/
|
|
158
|
+
concealedTextTruncated: boolean;
|
|
124
159
|
markdown: string;
|
|
125
160
|
metadata: PageMarkdownMetadata;
|
|
126
161
|
extraction: PageMarkdownExtraction;
|
|
@@ -136,6 +171,20 @@ export type PageFact = {
|
|
|
136
171
|
label: string;
|
|
137
172
|
value: string;
|
|
138
173
|
};
|
|
174
|
+
/**
|
|
175
|
+
* The one-time probe establishes that the document's view can return every
|
|
176
|
+
* required field and exposed optional field. Afterwards, incomplete means a
|
|
177
|
+
* CONSULTED value was empty or threw; unread irrelevant values are not checked.
|
|
178
|
+
* Computed means no such failure; static-only means no computed-style API;
|
|
179
|
+
* disabled means detection was turned off.
|
|
180
|
+
*/
|
|
181
|
+
export type ConcealmentCheck = "computed" | "static-only" | "disabled" | "incomplete";
|
|
182
|
+
export type ConcealmentReason = "display_none" | "visibility_hidden" | "opacity_zero" | "font_size_zero" | "clipped" | "transparent_text" | "same_color";
|
|
183
|
+
export type ConcealedText = {
|
|
184
|
+
reason: ConcealmentReason;
|
|
185
|
+
chars: number;
|
|
186
|
+
text: string;
|
|
187
|
+
};
|
|
139
188
|
export type TurndownFilter = string | string[] | ((node: HTMLElement, options: Record<string, unknown>) => boolean);
|
|
140
189
|
/**
|
|
141
190
|
* Turndown's public methods; Turndown ships no types of its own.
|
package/package.json
CHANGED
|
@@ -1,68 +1,69 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "page-markdown",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Faithful page-to-Markdown for humans and agents: sanitize, extract the readable article, convert with GFM, and clean without losing content.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"exports": {
|
|
7
|
-
".": {
|
|
8
|
-
"types": "./dist/types/index.d.ts",
|
|
9
|
-
"default": "./src/index.js"
|
|
10
|
-
}
|
|
11
|
-
},
|
|
12
|
-
"types": "./dist/types/index.d.ts",
|
|
13
|
-
"files": [
|
|
14
|
-
"src",
|
|
15
|
-
"dist/types",
|
|
16
|
-
"LICENSE",
|
|
17
|
-
"ADDITIONAL_TERMS.md",
|
|
18
|
-
"THIRD_PARTY_NOTICES.md",
|
|
19
|
-
"README.md",
|
|
20
|
-
"CHANGELOG.md",
|
|
21
|
-
"robots.txt"
|
|
22
|
-
],
|
|
23
|
-
"sideEffects": false,
|
|
24
|
-
"packageManager": "pnpm@10.33.0",
|
|
25
|
-
"engines": {
|
|
26
|
-
"node": ">=20"
|
|
27
|
-
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"test": "node --test \"test/**/*.test.mjs\"",
|
|
30
|
-
"build:types": "tsc -p tsconfig.json",
|
|
31
|
-
"typecheck": "npm run build:types && node test/types/real-output.mjs && tsc -p test/types && tsc -p test/types/linkedom",
|
|
32
|
-
"size": "node bench/size.mjs",
|
|
33
|
-
"test:browser": "node test/browser/run.mjs",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"bench
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "page-markdown",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Faithful page-to-Markdown for humans and agents: sanitize, extract the readable article, convert with GFM, and clean without losing content.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/types/index.d.ts",
|
|
9
|
+
"default": "./src/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"types": "./dist/types/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"src",
|
|
15
|
+
"dist/types",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"ADDITIONAL_TERMS.md",
|
|
18
|
+
"THIRD_PARTY_NOTICES.md",
|
|
19
|
+
"README.md",
|
|
20
|
+
"CHANGELOG.md",
|
|
21
|
+
"robots.txt"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"packageManager": "pnpm@10.33.0",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=20"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"test": "node --test \"test/**/*.test.mjs\"",
|
|
30
|
+
"build:types": "tsc -p tsconfig.json",
|
|
31
|
+
"typecheck": "npm run build:types && node test/types/real-output.mjs && tsc -p test/types && tsc -p test/types/linkedom",
|
|
32
|
+
"size": "node bench/size.mjs",
|
|
33
|
+
"test:browser": "node test/browser/run.mjs",
|
|
34
|
+
"report:build": "node test/browser/build-report.mjs",
|
|
35
|
+
"ci": "npm test && npm run typecheck && npm run size",
|
|
36
|
+
"prepack": "npm run build:types",
|
|
37
|
+
"prepublishOnly": "npm run ci",
|
|
38
|
+
"bench": "node bench/compare.mjs",
|
|
39
|
+
"bench:write": "node bench/compare.mjs --write"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"markdown",
|
|
43
|
+
"readability",
|
|
44
|
+
"html-to-markdown",
|
|
45
|
+
"reader-mode",
|
|
46
|
+
"web-clipper",
|
|
47
|
+
"browser-extension"
|
|
48
|
+
],
|
|
49
|
+
"author": "WATT3D <WATT3D@protonmail.com>",
|
|
50
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/iWhatty/page-markdown.git"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/iWhatty/page-markdown#readme",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/iWhatty/page-markdown/issues"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@mozilla/readability": "0.6.0",
|
|
61
|
+
"text-sanctifier": "1.3.8",
|
|
62
|
+
"turndown": "7.2.4"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"esbuild": "0.27.0",
|
|
66
|
+
"linkedom": "0.18.12",
|
|
67
|
+
"typescript": "5.9.3"
|
|
68
|
+
}
|
|
69
|
+
}
|
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: /
|
package/src/clean.js
CHANGED
|
@@ -103,7 +103,7 @@ const stripEmphasis = (md) => replaceOutsideCode(
|
|
|
103
103
|
/(?<![\w*])([*_])(?!\s)(.+?)(?<!\s)\1(?![\w*])/,
|
|
104
104
|
(all, mark, text) => text,
|
|
105
105
|
);
|
|
106
|
-
const stripImages = (md) => replaceOutsideCode(md,
|
|
106
|
+
const stripImages = (md) => replaceOutsideCode(md, INLINE_LINK, (all, bang, text) => text);
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* Output modes. "no_links" keeps link text. "text_only" also drops headings,
|