webforai 1.2.2 → 1.2.3
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/LICENSE +21 -0
- package/README.md +74 -74
- package/dist/cjs/extract-hast/index.js +35 -3
- package/dist/cjs/extract-hast/readability.js +57 -29
- package/dist/cjs/extract-hast/strongly.js +6 -3
- package/dist/cjs/extract-hast/utils.js +8 -4
- package/dist/cjs/html-to-mdast.js +6 -19
- package/dist/cjs/index.js +18 -9
- package/dist/cjs/link-replacer.js +2 -1
- package/dist/cjs/loaders/playwright.js +8 -16
- package/dist/cjs/md-splitter.js +5 -3
- package/dist/cjs/mdast-handlers/custom-a-handler.js +2 -1
- package/dist/cjs/mdast-handlers/custom-code-handler.js +43 -0
- package/dist/cjs/mdast-handlers/custom-div-handler.js +15 -9
- package/dist/cjs/mdast-handlers/custom-img-handler.js +2 -1
- package/dist/cjs/mdast-handlers/empty-handler.js +29 -0
- package/dist/cjs/mdast-to-markdown.js +2 -1
- package/dist/cjs/utils/mdast-utils.js +6 -3
- package/dist/extract-hast/index.js +28 -1
- package/dist/extract-hast/readability.js +62 -34
- package/dist/extract-hast/strongly.js +6 -3
- package/dist/extract-hast/utils.js +8 -4
- package/dist/html-to-mdast.js +7 -20
- package/dist/index.js +10 -4
- package/dist/link-replacer.js +2 -1
- package/dist/loaders/playwright.js +8 -6
- package/dist/md-splitter.js +5 -3
- package/dist/mdast-handlers/custom-a-handler.js +4 -3
- package/dist/mdast-handlers/custom-code-handler.js +20 -0
- package/dist/mdast-handlers/custom-div-handler.js +17 -11
- package/dist/mdast-handlers/custom-img-handler.js +2 -1
- package/dist/mdast-handlers/empty-handler.js +6 -0
- package/dist/mdast-to-markdown.js +2 -1
- package/dist/types/extract-hast/index.d.ts +10 -1
- package/dist/types/extract-hast/index.js.map +1 -1
- package/dist/types/extract-hast/readability.js.map +1 -1
- package/dist/types/extract-hast/strongly.js.map +1 -1
- package/dist/types/extract-hast/utils.js.map +1 -1
- package/dist/types/html-to-markdown.d.ts +1 -1
- package/dist/types/html-to-markdown.js.map +1 -1
- package/dist/types/html-to-mdast.d.ts +2 -4
- package/dist/types/html-to-mdast.js.map +1 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/index.js.map +1 -1
- package/dist/types/link-replacer.js.map +1 -1
- package/dist/types/loaders/playwright.d.ts +2 -2
- package/dist/types/loaders/playwright.js.map +1 -1
- package/dist/types/md-splitter.d.ts +1 -1
- package/dist/types/md-splitter.js.map +1 -1
- package/dist/types/mdast-handlers/custom-a-handler.js.map +1 -1
- package/dist/types/mdast-handlers/custom-code-handler.d.ts +2 -0
- package/dist/types/mdast-handlers/custom-code-handler.js.map +1 -0
- package/dist/types/mdast-handlers/custom-div-handler.js.map +1 -1
- package/dist/types/mdast-handlers/custom-img-handler.js.map +1 -1
- package/dist/types/mdast-handlers/empty-handler.d.ts +1 -0
- package/dist/types/mdast-handlers/empty-handler.js.map +1 -0
- package/dist/types/mdast-to-markdown.js.map +1 -1
- package/dist/types/utils/mdast-utils.js.map +1 -1
- package/dist/utils/mdast-utils.js +6 -3
- package/package.json +118 -118
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var custom_code_handler_exports = {};
|
|
20
|
+
__export(custom_code_handler_exports, {
|
|
21
|
+
customCodeHandler: () => customCodeHandler
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(custom_code_handler_exports);
|
|
24
|
+
var import_hast_util_to_text = require("hast-util-to-text");
|
|
25
|
+
var import_trim_trailing_lines = require("trim-trailing-lines");
|
|
26
|
+
var import_detect_code_lang = require("../utils/detect-code-lang");
|
|
27
|
+
const LANGUAGE_MATCH_REGEX = [/language-(\w+)/, /highlight-source-(\w+)/, /CodeBlock--language-(\w+)/];
|
|
28
|
+
const customCodeHandler = (state, node) => {
|
|
29
|
+
const classNames = node.properties?.className || [];
|
|
30
|
+
const codeValue = (0, import_trim_trailing_lines.trimTrailingLines)((0, import_hast_util_to_text.toText)(node)).trim();
|
|
31
|
+
const classLang = classNames.map((className) => {
|
|
32
|
+
const match = LANGUAGE_MATCH_REGEX.map((regex) => className.match(regex)).find((match2) => match2);
|
|
33
|
+
return match?.[1];
|
|
34
|
+
}).find((className) => className);
|
|
35
|
+
const lang = classLang || (0, import_detect_code_lang.detectLanguage)(codeValue) || null;
|
|
36
|
+
const result = { type: "code", lang, meta: null, value: codeValue };
|
|
37
|
+
state.patch(node, result);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
41
|
+
0 && (module.exports = {
|
|
42
|
+
customCodeHandler
|
|
43
|
+
});
|
|
@@ -29,35 +29,41 @@ var import_trim_trailing_lines = require("trim-trailing-lines");
|
|
|
29
29
|
var import_detect_code_lang = require("../utils/detect-code-lang");
|
|
30
30
|
const CODE_BLOCK_REGEX = /highlight-source|language-|codegroup|codeblock|code-block/i;
|
|
31
31
|
const CODE_FILENAME_SELECTORS = "[class*='fileName'],[class*='fileName'],[class*='title'],[class*='Title']";
|
|
32
|
-
const LANGUAGE_MATCH_REGEX = /language-(\w+)
|
|
32
|
+
const LANGUAGE_MATCH_REGEX = [/language-(\w+)/, /highlight-source-(\w+)/, /CodeBlock--language-(\w+)/];
|
|
33
33
|
const findRecursive = (array, condition, maxDepth = 3) => {
|
|
34
|
-
if (maxDepth <= 0)
|
|
34
|
+
if (maxDepth <= 0) {
|
|
35
35
|
return null;
|
|
36
|
+
}
|
|
36
37
|
for (const value of array) {
|
|
37
38
|
const result = condition(value);
|
|
38
|
-
if (Array.isArray(result))
|
|
39
|
+
if (Array.isArray(result)) {
|
|
39
40
|
return findRecursive(result, condition, maxDepth - 1);
|
|
40
|
-
|
|
41
|
+
}
|
|
42
|
+
if (result) {
|
|
41
43
|
return value;
|
|
44
|
+
}
|
|
42
45
|
}
|
|
43
46
|
return null;
|
|
44
47
|
};
|
|
45
48
|
const customDivHandler = (state, node) => {
|
|
46
49
|
const classNames = Array.isArray(node.properties.className) ? node.properties.className : [];
|
|
47
50
|
const codeBlock = findRecursive(node.children, (child) => {
|
|
48
|
-
if (child.type !== "element")
|
|
51
|
+
if (child.type !== "element") {
|
|
49
52
|
return false;
|
|
50
|
-
|
|
53
|
+
}
|
|
54
|
+
if (child.tagName === "pre") {
|
|
51
55
|
return true;
|
|
56
|
+
}
|
|
52
57
|
return child.children.filter((child2) => child2.type === "element");
|
|
53
58
|
});
|
|
54
59
|
if (codeBlock && classNames.some((className) => CODE_BLOCK_REGEX.test(className))) {
|
|
60
|
+
const codeBlockClassNames = codeBlock.type === "element" ? codeBlock.properties.className ?? [] : [];
|
|
55
61
|
const codeValue = (0, import_trim_trailing_lines.trimTrailingLines)((0, import_hast_util_to_text.toText)(codeBlock)).trim();
|
|
56
62
|
const filenameElement = (0, import_hast_util_select.select)(CODE_FILENAME_SELECTORS, node);
|
|
57
63
|
const fileLang = filenameElement ? (0, import_hast_util_to_string.toString)(filenameElement).match(/\.(\w+)$/)?.[1] : null;
|
|
58
|
-
const classLang = classNames.map((className) => {
|
|
59
|
-
const match = className.match(
|
|
60
|
-
return match?.[1]
|
|
64
|
+
const classLang = [...classNames, ...codeBlockClassNames].map((className) => {
|
|
65
|
+
const match = LANGUAGE_MATCH_REGEX.map((regex) => className.match(regex)).find((match2) => match2);
|
|
66
|
+
return match?.[1];
|
|
61
67
|
}).find((className) => className);
|
|
62
68
|
const lang = fileLang || classLang || (0, import_detect_code_lang.detectLanguage)(codeValue) || null;
|
|
63
69
|
const result = { type: "code", lang, meta: null, value: codeValue };
|
|
@@ -23,8 +23,9 @@ __export(custom_img_handler_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(custom_img_handler_exports);
|
|
24
24
|
var import_hast_util_to_mdast = require("hast-util-to-mdast");
|
|
25
25
|
const customImgHandler = (options) => (state, node) => {
|
|
26
|
-
if (options?.hideImage)
|
|
26
|
+
if (options?.hideImage) {
|
|
27
27
|
return void 0;
|
|
28
|
+
}
|
|
28
29
|
return import_hast_util_to_mdast.defaultHandlers.image(state, node);
|
|
29
30
|
};
|
|
30
31
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var empty_handler_exports = {};
|
|
20
|
+
__export(empty_handler_exports, {
|
|
21
|
+
emptyHandler: () => emptyHandler
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(empty_handler_exports);
|
|
24
|
+
const emptyHandler = () => {
|
|
25
|
+
};
|
|
26
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
27
|
+
0 && (module.exports = {
|
|
28
|
+
emptyHandler
|
|
29
|
+
});
|
|
@@ -30,8 +30,9 @@ const mdastToMarkdown = (mdast, options) => {
|
|
|
30
30
|
let markdown = (0, import_mdast_util_to_markdown.toMarkdown)((0, import_mdast_utils.warpRoot)(mdast), {
|
|
31
31
|
extensions: [(0, import_mdast_util_gfm.gfmToMarkdown)(), (0, import_mdast_util_math.mathToMarkdown)()]
|
|
32
32
|
});
|
|
33
|
-
if (options?.url)
|
|
33
|
+
if (options?.url) {
|
|
34
34
|
markdown = (0, import_link_replacer.linkReplacer)(markdown, options.url);
|
|
35
|
+
}
|
|
35
36
|
return markdown;
|
|
36
37
|
};
|
|
37
38
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -24,18 +24,21 @@ __export(mdast_utils_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(mdast_utils_exports);
|
|
26
26
|
const unwarpRoot = (mdast) => {
|
|
27
|
-
if (mdast.type === "root")
|
|
27
|
+
if (mdast.type === "root") {
|
|
28
28
|
return mdast.children;
|
|
29
|
+
}
|
|
29
30
|
return [mdast];
|
|
30
31
|
};
|
|
31
32
|
const warpRoot = (mdast) => {
|
|
32
|
-
if (Array.isArray(mdast))
|
|
33
|
+
if (Array.isArray(mdast)) {
|
|
33
34
|
return { type: "root", children: mdast };
|
|
35
|
+
}
|
|
34
36
|
return mdast;
|
|
35
37
|
};
|
|
36
38
|
const internalType = (content) => {
|
|
37
|
-
if (content.type === "heading")
|
|
39
|
+
if (content.type === "heading") {
|
|
38
40
|
return `h${content.depth}`;
|
|
41
|
+
}
|
|
39
42
|
return content.type;
|
|
40
43
|
};
|
|
41
44
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1,2 +1,29 @@
|
|
|
1
1
|
// src/extract-hast/index.ts
|
|
2
|
-
|
|
2
|
+
import { readabilityExtractHast } from "./readability.js";
|
|
3
|
+
import { stronglyExtractHast } from "./strongly.js";
|
|
4
|
+
var PRESET_EXTRACT_HAST = {
|
|
5
|
+
strongly: stronglyExtractHast,
|
|
6
|
+
readability: readabilityExtractHast
|
|
7
|
+
};
|
|
8
|
+
var DEFAULT_EXTRACT_HAST = ["readability"];
|
|
9
|
+
var extractHast = (hast, extractors = DEFAULT_EXTRACT_HAST) => {
|
|
10
|
+
const _extractors = Array.isArray(extractors) ? extractors : [extractors];
|
|
11
|
+
const extracted = _extractors.reduce((acc, extractor) => {
|
|
12
|
+
if (extractor === false) {
|
|
13
|
+
return acc;
|
|
14
|
+
}
|
|
15
|
+
if (typeof extractor === "string" && extractor in DEFAULT_EXTRACT_HAST) {
|
|
16
|
+
return PRESET_EXTRACT_HAST[extractor](acc);
|
|
17
|
+
}
|
|
18
|
+
if (typeof extractor === "function") {
|
|
19
|
+
return extractor(acc);
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`Invalid extractor: ${extractor}`);
|
|
22
|
+
}, hast) || hast;
|
|
23
|
+
return extracted;
|
|
24
|
+
};
|
|
25
|
+
export {
|
|
26
|
+
DEFAULT_EXTRACT_HAST,
|
|
27
|
+
PRESET_EXTRACT_HAST,
|
|
28
|
+
extractHast
|
|
29
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/extract-hast/readability.ts
|
|
2
2
|
import { select, selectAll } from "hast-util-select";
|
|
3
|
-
import { toString } from "hast-util-to-string";
|
|
3
|
+
import { toString as hastToString } from "hast-util-to-string";
|
|
4
4
|
import { filter } from "unist-util-filter";
|
|
5
5
|
import { parents } from "unist-util-parents";
|
|
6
6
|
import { classnames, hasAncestors, isStrInclude, matchString } from "./utils.js";
|
|
@@ -9,7 +9,7 @@ var REGEXPS = {
|
|
|
9
9
|
hidden: /hidden|invisible|fallback-image/i,
|
|
10
10
|
byline: /byline|author|dateline|writtenby|p-author/i,
|
|
11
11
|
unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote|speechify-ignore/i,
|
|
12
|
-
|
|
12
|
+
okMaybeItsaCandidate: /and|article|body|column|content|main|shadow|code/i
|
|
13
13
|
};
|
|
14
14
|
var BODY_SELECTORS = ["article", "#article", ".article_body", ".article-body", "#content", ".entry", "main"];
|
|
15
15
|
var PARAGRAPH_TAGS = ["p", "div", "section", "article", "main", "ul", "ol", "li"];
|
|
@@ -18,60 +18,79 @@ var BASE_MINIMAL_LENGTH = {
|
|
|
18
18
|
en: 500
|
|
19
19
|
};
|
|
20
20
|
var tryGetLang = (node) => {
|
|
21
|
-
if (node.type !== "element")
|
|
21
|
+
if (node.type !== "element") {
|
|
22
22
|
return;
|
|
23
|
+
}
|
|
23
24
|
const element = node;
|
|
24
|
-
if (element.tagName !== "html")
|
|
25
|
+
if (element.tagName !== "html") {
|
|
25
26
|
return;
|
|
27
|
+
}
|
|
26
28
|
const langAttr = element.properties.lang || element.properties["xml:lang"];
|
|
27
|
-
if (langAttr)
|
|
29
|
+
if (langAttr) {
|
|
28
30
|
return langAttr;
|
|
31
|
+
}
|
|
29
32
|
};
|
|
30
33
|
var metadataFilter = (node) => !["comment", "doctype"].includes(node.type);
|
|
31
34
|
var universalElementFilter = (node) => {
|
|
32
|
-
if (node.type !== "element")
|
|
35
|
+
if (node.type !== "element") {
|
|
33
36
|
return true;
|
|
37
|
+
}
|
|
34
38
|
const element = node;
|
|
35
|
-
if (["script", "aside"].includes(element.tagName))
|
|
39
|
+
if (["script", "aside"].includes(element.tagName)) {
|
|
36
40
|
return false;
|
|
37
|
-
|
|
41
|
+
}
|
|
42
|
+
if (["hidden", "aria-hidden"].some((key) => element.properties[key])) {
|
|
38
43
|
return false;
|
|
39
|
-
|
|
44
|
+
}
|
|
45
|
+
if (classnames(element).some((classname) => REGEXPS.hidden.test(classname))) {
|
|
40
46
|
return false;
|
|
41
|
-
|
|
47
|
+
}
|
|
48
|
+
if (element.tagName === "dialog") {
|
|
42
49
|
return false;
|
|
43
|
-
|
|
50
|
+
}
|
|
51
|
+
if (element.properties.role === "dialog" && element.properties["aria-modal"]) {
|
|
44
52
|
return false;
|
|
45
|
-
|
|
53
|
+
}
|
|
54
|
+
if (element.properties.rel === "author" && isStrInclude(element.properties.itemprop, "author")) {
|
|
46
55
|
return false;
|
|
47
|
-
|
|
56
|
+
}
|
|
57
|
+
if (REGEXPS.byline.test(matchString(element))) {
|
|
48
58
|
return false;
|
|
49
|
-
|
|
59
|
+
}
|
|
60
|
+
if (element.properties.role && UNLIKELY_ROLES.includes(element.properties.role)) {
|
|
50
61
|
return false;
|
|
62
|
+
}
|
|
51
63
|
return true;
|
|
52
64
|
};
|
|
53
65
|
var unlikelyElementFilter = (node) => {
|
|
54
|
-
if (node.type !== "element")
|
|
66
|
+
if (node.type !== "element") {
|
|
55
67
|
return true;
|
|
68
|
+
}
|
|
56
69
|
const element = node;
|
|
57
70
|
const match = matchString(element);
|
|
58
|
-
if (["body", "article", "main", "section", "a"].includes(element.tagName))
|
|
71
|
+
if (["body", "article", "main", "section", "a"].includes(element.tagName)) {
|
|
59
72
|
return true;
|
|
60
|
-
|
|
73
|
+
}
|
|
74
|
+
if (hasAncestors(element, ["table", "code"], 3)) {
|
|
61
75
|
return true;
|
|
62
|
-
|
|
76
|
+
}
|
|
77
|
+
if (REGEXPS.unlikelyCandidates.test(match) && !REGEXPS.okMaybeItsaCandidate.test(match)) {
|
|
63
78
|
return false;
|
|
79
|
+
}
|
|
64
80
|
return true;
|
|
65
81
|
};
|
|
66
82
|
var removeEmptyFilter = (node) => {
|
|
67
|
-
if (node.type !== "element")
|
|
83
|
+
if (node.type !== "element") {
|
|
68
84
|
return true;
|
|
85
|
+
}
|
|
69
86
|
const element = node;
|
|
70
|
-
if (!PARAGRAPH_TAGS.includes(element.tagName))
|
|
87
|
+
if (!PARAGRAPH_TAGS.includes(element.tagName)) {
|
|
71
88
|
return true;
|
|
72
|
-
|
|
73
|
-
|
|
89
|
+
}
|
|
90
|
+
const text = hastToString(element);
|
|
91
|
+
if (text.length < 10) {
|
|
74
92
|
return false;
|
|
93
|
+
}
|
|
75
94
|
return true;
|
|
76
95
|
};
|
|
77
96
|
var readabilityExtractHast = (hast) => {
|
|
@@ -79,45 +98,54 @@ var readabilityExtractHast = (hast) => {
|
|
|
79
98
|
const body = select("body", hast) ?? hast;
|
|
80
99
|
const proxiedHast = parents(body);
|
|
81
100
|
let baseFilterd = filter(proxiedHast, (node) => {
|
|
82
|
-
if (!metadataFilter(node))
|
|
101
|
+
if (!metadataFilter(node)) {
|
|
83
102
|
return false;
|
|
84
|
-
|
|
103
|
+
}
|
|
104
|
+
if (!universalElementFilter(node)) {
|
|
85
105
|
return false;
|
|
106
|
+
}
|
|
86
107
|
return true;
|
|
87
108
|
});
|
|
88
|
-
if (!baseFilterd)
|
|
109
|
+
if (!baseFilterd) {
|
|
89
110
|
return { type: "root", children: [] };
|
|
90
|
-
|
|
111
|
+
}
|
|
112
|
+
const baseText = hastToString(baseFilterd);
|
|
91
113
|
let minimalLength = lang in BASE_MINIMAL_LENGTH ? BASE_MINIMAL_LENGTH[lang] : 500;
|
|
92
114
|
if (baseText.length > minimalLength) {
|
|
93
115
|
const filterd = filter(baseFilterd, (node) => {
|
|
94
|
-
if (!unlikelyElementFilter(node))
|
|
116
|
+
if (!unlikelyElementFilter(node)) {
|
|
95
117
|
return false;
|
|
118
|
+
}
|
|
96
119
|
return true;
|
|
97
120
|
});
|
|
98
|
-
if (filterd)
|
|
121
|
+
if (filterd) {
|
|
99
122
|
baseFilterd = filterd;
|
|
100
|
-
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
101
125
|
minimalLength = Math.max(0, baseText.length - 200);
|
|
126
|
+
}
|
|
102
127
|
let bodyTree = baseFilterd;
|
|
103
128
|
for (const selector of BODY_SELECTORS) {
|
|
104
129
|
const body2 = { type: "root", children: selectAll(selector, baseFilterd) };
|
|
105
|
-
const bodyText =
|
|
106
|
-
if (bodyText.length < 25)
|
|
130
|
+
const bodyText = hastToString(body2);
|
|
131
|
+
if (bodyText.length < 25) {
|
|
107
132
|
continue;
|
|
133
|
+
}
|
|
108
134
|
const links = selectAll("a", body2);
|
|
109
|
-
const linkText = links.map((link) =>
|
|
135
|
+
const linkText = links.map((link) => hastToString(link)).join("");
|
|
110
136
|
const linkDensity = linkText.length / bodyText.length;
|
|
111
|
-
if (linkDensity > 0.4)
|
|
137
|
+
if (linkDensity > 0.4) {
|
|
112
138
|
continue;
|
|
139
|
+
}
|
|
113
140
|
if (bodyText.length > minimalLength) {
|
|
114
141
|
bodyTree = body2;
|
|
115
142
|
break;
|
|
116
143
|
}
|
|
117
144
|
}
|
|
118
145
|
const finalTree = filter(bodyTree, (node) => {
|
|
119
|
-
if (!removeEmptyFilter(node))
|
|
146
|
+
if (!removeEmptyFilter(node)) {
|
|
120
147
|
return false;
|
|
148
|
+
}
|
|
121
149
|
return true;
|
|
122
150
|
});
|
|
123
151
|
return finalTree;
|
|
@@ -13,14 +13,17 @@ var stronglyExtractHast = (hast) => {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
const removedElements = filter(selectedElement, (node) => {
|
|
16
|
-
if (node.type === "comment")
|
|
16
|
+
if (node.type === "comment") {
|
|
17
17
|
return false;
|
|
18
|
-
|
|
18
|
+
}
|
|
19
|
+
if (node.type !== "element") {
|
|
19
20
|
return true;
|
|
21
|
+
}
|
|
20
22
|
const element = node;
|
|
21
23
|
const elementName = `${element.tagName} ${element.properties.id} ${element.properties.className}`;
|
|
22
|
-
if (REMOVE_REGEX.test(elementName))
|
|
24
|
+
if (REMOVE_REGEX.test(elementName)) {
|
|
23
25
|
return false;
|
|
26
|
+
}
|
|
24
27
|
return true;
|
|
25
28
|
});
|
|
26
29
|
return removedElements;
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
// src/extract-hast/utils.ts
|
|
2
2
|
var matchString = (element) => `${element.tagName} ${element.properties.id} ${classnames(element).join(" ")} }`;
|
|
3
3
|
var classnames = (element) => {
|
|
4
|
-
if (Array.isArray(element.properties.className))
|
|
4
|
+
if (Array.isArray(element.properties.className)) {
|
|
5
5
|
return element.properties.className;
|
|
6
|
+
}
|
|
6
7
|
return [];
|
|
7
8
|
};
|
|
8
9
|
var isStrInclude = (value, match) => {
|
|
9
|
-
if (typeof value === "string")
|
|
10
|
+
if (typeof value === "string") {
|
|
10
11
|
return value.includes(match);
|
|
12
|
+
}
|
|
11
13
|
return false;
|
|
12
14
|
};
|
|
13
15
|
var hasAncestors = (element, tagNames, depth = 3) => {
|
|
14
16
|
let parent = element.parent;
|
|
15
17
|
for (let i = 0; i < depth; i++) {
|
|
16
|
-
if (!parent || parent.type !== "element")
|
|
18
|
+
if (!parent || parent.type !== "element") {
|
|
17
19
|
return false;
|
|
18
|
-
|
|
20
|
+
}
|
|
21
|
+
if (tagNames.includes(parent.tagName)) {
|
|
19
22
|
return true;
|
|
23
|
+
}
|
|
20
24
|
parent = parent.parent;
|
|
21
25
|
}
|
|
22
26
|
return false;
|
package/dist/html-to-mdast.js
CHANGED
|
@@ -1,40 +1,27 @@
|
|
|
1
1
|
// src/html-to-mdast.ts
|
|
2
2
|
import { fromHtml } from "hast-util-from-html";
|
|
3
3
|
import { toMdast } from "hast-util-to-mdast";
|
|
4
|
-
import {
|
|
5
|
-
import { readabilityExtractHast } from "./extract-hast/readability.js";
|
|
4
|
+
import { extractHast } from "./extract-hast/index.js";
|
|
6
5
|
import { customAHandler } from "./mdast-handlers/custom-a-handler.js";
|
|
6
|
+
import { customCodeHandler } from "./mdast-handlers/custom-code-handler.js";
|
|
7
7
|
import { customDivHandler } from "./mdast-handlers/custom-div-handler.js";
|
|
8
8
|
import { customImgHandler } from "./mdast-handlers/custom-img-handler.js";
|
|
9
9
|
import { customTableHandler } from "./mdast-handlers/custom-table-handler.js";
|
|
10
|
+
import { emptyHandler } from "./mdast-handlers/empty-handler.js";
|
|
10
11
|
import { mathHandler } from "./mdast-handlers/math-handler.js";
|
|
11
|
-
var PRESET_EXTRACT_HAST = {
|
|
12
|
-
strongly: stronglyExtractHast,
|
|
13
|
-
readability: readabilityExtractHast
|
|
14
|
-
};
|
|
15
|
-
var DEFAULT_EXTRACT_HAST = ["readability"];
|
|
16
12
|
var htmlToMdast = (html, options) => {
|
|
17
|
-
const { extractHast
|
|
18
|
-
const _extractHast = Array.isArray(extractHast) ? extractHast : [extractHast];
|
|
13
|
+
const { extractHast: _extractHast } = options || {};
|
|
19
14
|
const hast = fromHtml(html, { fragment: true });
|
|
20
|
-
const extractedHast =
|
|
21
|
-
if (extractHast2 === false)
|
|
22
|
-
return acc;
|
|
23
|
-
if (typeof extractHast2 === "string" && extractHast2 in PRESET_EXTRACT_HAST)
|
|
24
|
-
return PRESET_EXTRACT_HAST[extractHast2](acc);
|
|
25
|
-
if (typeof extractHast2 === "function")
|
|
26
|
-
return extractHast2(acc);
|
|
27
|
-
throw new Error(`Invalid extractHast: ${extractHast2}`);
|
|
28
|
-
}, hast) || hast;
|
|
15
|
+
const extractedHast = extractHast(hast, _extractHast);
|
|
29
16
|
const mdast = toMdast(extractedHast, {
|
|
30
17
|
handlers: {
|
|
31
18
|
math: mathHandler,
|
|
32
19
|
div: customDivHandler,
|
|
20
|
+
pre: customCodeHandler,
|
|
33
21
|
a: customAHandler({ asText: options?.linkAsText }),
|
|
34
22
|
img: customImgHandler({ hideImage: options?.hideImage }),
|
|
35
23
|
table: customTableHandler({ asText: options?.tableAsText }),
|
|
36
|
-
br:
|
|
37
|
-
}
|
|
24
|
+
br: emptyHandler
|
|
38
25
|
}
|
|
39
26
|
});
|
|
40
27
|
return mdast;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { htmlToMarkdown } from "./html-to-markdown.js";
|
|
3
|
+
import { mdastSplitter } from "./md-splitter.js";
|
|
4
|
+
import { htmlToMdast } from "./html-to-mdast.js";
|
|
5
|
+
import { mdastToMarkdown } from "./mdast-to-markdown.js";
|
|
6
|
+
export {
|
|
7
|
+
htmlToMarkdown,
|
|
8
|
+
htmlToMdast,
|
|
9
|
+
mdastSplitter,
|
|
10
|
+
mdastToMarkdown
|
|
11
|
+
};
|
package/dist/link-replacer.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
var linkReplacer = (markdown, link) => {
|
|
3
3
|
const regex = /(!?\[.*?\]\()(.+?)(\))/g;
|
|
4
4
|
return markdown.replace(regex, (match, pre, thisUrl, post) => {
|
|
5
|
-
if (thisUrl.startsWith("http") || thisUrl.startsWith("#"))
|
|
5
|
+
if (thisUrl.startsWith("http") || thisUrl.startsWith("#")) {
|
|
6
6
|
return match;
|
|
7
|
+
}
|
|
7
8
|
return `${pre}${new URL(thisUrl, link).href}${post}`;
|
|
8
9
|
});
|
|
9
10
|
};
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
// src/loaders/playwright.ts
|
|
2
|
-
import
|
|
2
|
+
import { chromium } from "playwright";
|
|
3
3
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
4
4
|
var loadHtml = async (url, context) => {
|
|
5
5
|
let _browser = null;
|
|
6
6
|
let _context;
|
|
7
|
-
if (
|
|
8
|
-
_browser = await playwright.chromium.launch({ headless: true });
|
|
9
|
-
_context = await _browser.newContext();
|
|
10
|
-
} else
|
|
7
|
+
if (context) {
|
|
11
8
|
_context = context;
|
|
9
|
+
} else {
|
|
10
|
+
_browser = await chromium.launch({ headless: true });
|
|
11
|
+
_context = await _browser.newContext();
|
|
12
|
+
}
|
|
12
13
|
const page = await _context.newPage();
|
|
13
14
|
await page.goto(url);
|
|
14
15
|
await Promise.race([page.waitForLoadState("networkidle"), sleep(1e4)]);
|
|
15
16
|
const html = await page.content();
|
|
16
17
|
await page.close();
|
|
17
|
-
if (_browser)
|
|
18
|
+
if (_browser) {
|
|
18
19
|
await _browser.close();
|
|
20
|
+
}
|
|
19
21
|
return html;
|
|
20
22
|
};
|
|
21
23
|
export {
|
package/dist/md-splitter.js
CHANGED
|
@@ -4,14 +4,16 @@ import { chunk } from "./utils/common.js";
|
|
|
4
4
|
import { internalType, unwarpRoot, warpRoot } from "./utils/mdast-utils.js";
|
|
5
5
|
var PRIORITY_SPLITTERS = ["h1", "h2", "h3", "h4", "h5", "h6", "list", "table", "code"];
|
|
6
6
|
var getSplitterGenerator = function* () {
|
|
7
|
-
for (const splitter of PRIORITY_SPLITTERS)
|
|
7
|
+
for (const splitter of PRIORITY_SPLITTERS) {
|
|
8
8
|
yield splitter;
|
|
9
|
+
}
|
|
9
10
|
};
|
|
10
11
|
var _mdastSplitter = async (contents, checker, splitterGenerator) => {
|
|
11
12
|
const splitter = splitterGenerator.next().value;
|
|
12
13
|
const markdown = mdastToMarkdown(warpRoot(contents));
|
|
13
|
-
if (await checker(markdown) || contents.length === 1)
|
|
14
|
+
if (await checker(markdown) || contents.length === 1) {
|
|
14
15
|
return [contents];
|
|
16
|
+
}
|
|
15
17
|
const chunked = splitter ? contents.reduce((acc, content) => {
|
|
16
18
|
if (internalType(content) === splitter || acc.length === 0) {
|
|
17
19
|
acc.push([content]);
|
|
@@ -23,7 +25,7 @@ var _mdastSplitter = async (contents, checker, splitterGenerator) => {
|
|
|
23
25
|
const splitting = chunked.map((chunk2) => _mdastSplitter(chunk2, checker, splitterGenerator));
|
|
24
26
|
return Promise.all(splitting).then((chunks) => chunks.flat());
|
|
25
27
|
};
|
|
26
|
-
var mdastSplitter =
|
|
28
|
+
var mdastSplitter = (mdast, checker, _options) => {
|
|
27
29
|
return _mdastSplitter(unwarpRoot(mdast), checker, getSplitterGenerator());
|
|
28
30
|
};
|
|
29
31
|
export {
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// src/mdast-handlers/custom-a-handler.ts
|
|
2
2
|
import { defaultHandlers } from "hast-util-to-mdast";
|
|
3
|
-
import { toString } from "hast-util-to-string";
|
|
3
|
+
import { toString as hastToString } from "hast-util-to-string";
|
|
4
4
|
var customAHandler = (options) => (state, node) => {
|
|
5
5
|
if (options?.asText) {
|
|
6
|
-
const link2 = { type: "text", value:
|
|
6
|
+
const link2 = { type: "text", value: hastToString(node) };
|
|
7
7
|
state.patch(node, link2);
|
|
8
8
|
return link2;
|
|
9
9
|
}
|
|
10
10
|
const link = defaultHandlers.a(state, node);
|
|
11
|
-
if (link.children.length > 0)
|
|
11
|
+
if (link.children.length > 0) {
|
|
12
12
|
return link;
|
|
13
|
+
}
|
|
13
14
|
return void 0;
|
|
14
15
|
};
|
|
15
16
|
export {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/mdast-handlers/custom-code-handler.ts
|
|
2
|
+
import { toText } from "hast-util-to-text";
|
|
3
|
+
import { trimTrailingLines } from "trim-trailing-lines";
|
|
4
|
+
import { detectLanguage } from "../utils/detect-code-lang.js";
|
|
5
|
+
var LANGUAGE_MATCH_REGEX = [/language-(\w+)/, /highlight-source-(\w+)/, /CodeBlock--language-(\w+)/];
|
|
6
|
+
var customCodeHandler = (state, node) => {
|
|
7
|
+
const classNames = node.properties?.className || [];
|
|
8
|
+
const codeValue = trimTrailingLines(toText(node)).trim();
|
|
9
|
+
const classLang = classNames.map((className) => {
|
|
10
|
+
const match = LANGUAGE_MATCH_REGEX.map((regex) => className.match(regex)).find((match2) => match2);
|
|
11
|
+
return match?.[1];
|
|
12
|
+
}).find((className) => className);
|
|
13
|
+
const lang = classLang || detectLanguage(codeValue) || null;
|
|
14
|
+
const result = { type: "code", lang, meta: null, value: codeValue };
|
|
15
|
+
state.patch(node, result);
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
customCodeHandler
|
|
20
|
+
};
|