webforai 2.1.1 → 4.0.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.
Files changed (203) hide show
  1. package/README.md +86 -4
  2. package/dist/adapters/index.js +58 -0
  3. package/dist/adapters/registry.js +149 -0
  4. package/dist/adapters/sites/declarative.js +178 -0
  5. package/dist/adapters/sites/hackernews.js +94 -0
  6. package/dist/adapters/sites/youtube.js +165 -0
  7. package/dist/adapters/types.js +0 -0
  8. package/dist/bin.js +4142 -549
  9. package/dist/cjs/adapters/index.js +86 -0
  10. package/dist/cjs/adapters/registry.js +178 -0
  11. package/dist/cjs/adapters/sites/declarative.js +202 -0
  12. package/dist/cjs/adapters/sites/hackernews.js +117 -0
  13. package/dist/cjs/adapters/sites/youtube.js +191 -0
  14. package/dist/cjs/adapters/types.js +16 -0
  15. package/dist/cjs/constants.js +2 -2
  16. package/dist/cjs/detect-client-shell.js +78 -0
  17. package/dist/cjs/extract-meta-refresh.js +71 -0
  18. package/dist/cjs/extractors/index.js +5 -0
  19. package/dist/cjs/extractors/lib/constants.js +186 -0
  20. package/dist/cjs/extractors/lib/sanitize.js +429 -0
  21. package/dist/cjs/extractors/lib/score.js +264 -0
  22. package/dist/cjs/extractors/lib/terminators.js +131 -0
  23. package/dist/cjs/extractors/lib/ui-chrome.js +119 -0
  24. package/dist/cjs/extractors/pipeExtractors.js +12 -9
  25. package/dist/cjs/extractors/presets/auto.js +44 -0
  26. package/dist/cjs/extractors/presets/minimal-filter.js +27 -48
  27. package/dist/cjs/extractors/presets/takumi.js +84 -122
  28. package/dist/cjs/html-to-markdown.js +44 -7
  29. package/dist/cjs/html-to-mdast.js +10 -1
  30. package/dist/cjs/index.js +43 -2
  31. package/dist/cjs/link-replacer.js +19 -13
  32. package/dist/cjs/loaders/cf-puppeteer.js +14 -7
  33. package/dist/cjs/loaders/fetch.js +14 -2
  34. package/dist/cjs/loaders/playwright.js +32 -30
  35. package/dist/cjs/loaders/puppeteer.js +14 -7
  36. package/dist/cjs/md-splitter.js +24 -11
  37. package/dist/cjs/mdast-handlers/custom-a-handler.js +25 -9
  38. package/dist/cjs/mdast-handlers/custom-code-handler.js +18 -7
  39. package/dist/cjs/mdast-handlers/custom-div-handler.js +12 -33
  40. package/dist/cjs/mdast-handlers/custom-img-handler.js +23 -1
  41. package/dist/cjs/mdast-handlers/custom-table-handler.js +16 -0
  42. package/dist/cjs/mdast-handlers/definition-list-handler.js +110 -0
  43. package/dist/cjs/mdast-handlers/math-handler.js +12 -3
  44. package/dist/cjs/mdast-handlers/sup-sub-handler.js +39 -0
  45. package/dist/cjs/mdast-to-markdown.js +2 -5
  46. package/dist/cjs/metadata/index.js +223 -0
  47. package/dist/cjs/normalize/index.js +177 -0
  48. package/dist/cjs/platform/client.js +204 -0
  49. package/dist/cjs/platform/error.js +36 -0
  50. package/dist/cjs/platform/fetch.js +37 -0
  51. package/dist/cjs/platform/index.js +44 -0
  52. package/dist/cjs/platform/types.js +40 -0
  53. package/dist/cjs/utils/hast-fast.js +284 -0
  54. package/dist/constants.js +2 -2
  55. package/dist/detect-client-shell.js +53 -0
  56. package/dist/extract-meta-refresh.js +47 -0
  57. package/dist/extractors/index.js +3 -0
  58. package/dist/extractors/lib/constants.js +150 -0
  59. package/dist/extractors/lib/sanitize.js +419 -0
  60. package/dist/extractors/lib/score.js +242 -0
  61. package/dist/extractors/lib/terminators.js +107 -0
  62. package/dist/extractors/lib/ui-chrome.js +96 -0
  63. package/dist/extractors/pipeExtractors.js +12 -9
  64. package/dist/extractors/presets/auto.js +20 -0
  65. package/dist/extractors/presets/minimal-filter.js +35 -47
  66. package/dist/extractors/presets/takumi.js +91 -122
  67. package/dist/html-to-markdown.js +42 -6
  68. package/dist/html-to-mdast.js +10 -1
  69. package/dist/index.js +45 -2
  70. package/dist/link-replacer.js +19 -13
  71. package/dist/loaders/cf-puppeteer.js +15 -8
  72. package/dist/loaders/fetch.js +14 -2
  73. package/dist/loaders/playwright.js +32 -30
  74. package/dist/loaders/puppeteer.js +15 -8
  75. package/dist/md-splitter.js +24 -11
  76. package/dist/mdast-handlers/custom-a-handler.js +25 -9
  77. package/dist/mdast-handlers/custom-code-handler.js +17 -7
  78. package/dist/mdast-handlers/custom-div-handler.js +12 -33
  79. package/dist/mdast-handlers/custom-img-handler.js +23 -1
  80. package/dist/mdast-handlers/custom-table-handler.js +16 -0
  81. package/dist/mdast-handlers/definition-list-handler.js +87 -0
  82. package/dist/mdast-handlers/math-handler.js +12 -3
  83. package/dist/mdast-handlers/sup-sub-handler.js +16 -0
  84. package/dist/mdast-to-markdown.js +2 -5
  85. package/dist/metadata/index.js +198 -0
  86. package/dist/normalize/index.js +159 -0
  87. package/dist/platform/client.js +182 -0
  88. package/dist/platform/error.js +13 -0
  89. package/dist/platform/fetch.js +14 -0
  90. package/dist/platform/index.js +23 -0
  91. package/dist/platform/types.js +13 -0
  92. package/dist/types/adapters/index.d.ts +24 -0
  93. package/dist/types/adapters/index.js.map +1 -0
  94. package/dist/types/adapters/registry.d.ts +35 -0
  95. package/dist/types/adapters/registry.js.map +1 -0
  96. package/dist/types/adapters/sites/declarative.d.ts +13 -0
  97. package/dist/types/adapters/sites/declarative.js.map +1 -0
  98. package/dist/types/adapters/sites/hackernews.d.ts +13 -0
  99. package/dist/types/adapters/sites/hackernews.js.map +1 -0
  100. package/dist/types/adapters/sites/youtube.d.ts +31 -0
  101. package/dist/types/adapters/sites/youtube.js.map +1 -0
  102. package/dist/types/adapters/types.d.ts +99 -0
  103. package/dist/types/adapters/types.js.map +1 -0
  104. package/dist/types/cli/bin.js.map +1 -1
  105. package/dist/types/cli/commands/jobs/files.d.ts +28 -0
  106. package/dist/types/cli/commands/jobs/files.js.map +1 -0
  107. package/dist/types/cli/commands/jobs/llms-txt.d.ts +33 -0
  108. package/dist/types/cli/commands/jobs/llms-txt.js.map +1 -0
  109. package/dist/types/cli/commands/jobs/options.d.ts +58 -0
  110. package/dist/types/cli/commands/jobs/options.js.map +1 -0
  111. package/dist/types/cli/commands/jobs/run.d.ts +44 -0
  112. package/dist/types/cli/commands/jobs/run.js.map +1 -0
  113. package/dist/types/cli/commands/skill/content.d.ts +9 -0
  114. package/dist/types/cli/commands/skill/content.js.map +1 -0
  115. package/dist/types/cli/commands/skill/index.d.ts +19 -0
  116. package/dist/types/cli/commands/skill/index.js.map +1 -0
  117. package/dist/types/cli/commands/webforai/interactive.d.ts +7 -0
  118. package/dist/types/cli/commands/webforai/interactive.js.map +1 -0
  119. package/dist/types/cli/commands/webforai/loadHtml.js.map +1 -1
  120. package/dist/types/cli/commands/webforai/options.d.ts +62 -0
  121. package/dist/types/cli/commands/webforai/options.js.map +1 -0
  122. package/dist/types/cli/commands/webforai/run.d.ts +10 -0
  123. package/dist/types/cli/commands/webforai/run.js.map +1 -0
  124. package/dist/types/cli/constants.d.ts +14 -4
  125. package/dist/types/cli/constants.js.map +1 -1
  126. package/dist/types/cli/helpers/selectExtractMode.js.map +1 -1
  127. package/dist/types/cli/helpers/selectLoader.js.map +1 -1
  128. package/dist/types/cli/utils.d.ts +8 -1
  129. package/dist/types/cli/utils.js.map +1 -1
  130. package/dist/types/constants.d.ts +7 -1
  131. package/dist/types/constants.js.map +1 -1
  132. package/dist/types/detect-client-shell.d.ts +24 -0
  133. package/dist/types/detect-client-shell.js.map +1 -0
  134. package/dist/types/extract-meta-refresh.d.ts +29 -0
  135. package/dist/types/extract-meta-refresh.js.map +1 -0
  136. package/dist/types/extractors/index.d.ts +1 -0
  137. package/dist/types/extractors/index.js.map +1 -1
  138. package/dist/types/extractors/lib/constants.d.ts +81 -0
  139. package/dist/types/extractors/lib/constants.js.map +1 -0
  140. package/dist/types/extractors/lib/sanitize.d.ts +66 -0
  141. package/dist/types/extractors/lib/sanitize.js.map +1 -0
  142. package/dist/types/extractors/lib/score.d.ts +85 -0
  143. package/dist/types/extractors/lib/score.js.map +1 -0
  144. package/dist/types/extractors/lib/terminators.d.ts +26 -0
  145. package/dist/types/extractors/lib/terminators.js.map +1 -0
  146. package/dist/types/extractors/lib/ui-chrome.d.ts +18 -0
  147. package/dist/types/extractors/lib/ui-chrome.js.map +1 -0
  148. package/dist/types/extractors/pipeExtractors.d.ts +5 -0
  149. package/dist/types/extractors/pipeExtractors.js.map +1 -1
  150. package/dist/types/extractors/presets/auto.d.ts +30 -0
  151. package/dist/types/extractors/presets/auto.js.map +1 -0
  152. package/dist/types/extractors/presets/minimal-filter.d.ts +10 -2
  153. package/dist/types/extractors/presets/minimal-filter.js.map +1 -1
  154. package/dist/types/extractors/presets/takumi.d.ts +19 -3
  155. package/dist/types/extractors/presets/takumi.js.map +1 -1
  156. package/dist/types/extractors/types.d.ts +8 -0
  157. package/dist/types/html-to-markdown.d.ts +38 -0
  158. package/dist/types/html-to-markdown.js.map +1 -1
  159. package/dist/types/html-to-mdast.d.ts +11 -0
  160. package/dist/types/html-to-mdast.js.map +1 -1
  161. package/dist/types/index.d.ts +8 -3
  162. package/dist/types/index.js.map +1 -1
  163. package/dist/types/link-replacer.d.ts +3 -1
  164. package/dist/types/link-replacer.js.map +1 -1
  165. package/dist/types/loaders/cf-puppeteer.js.map +1 -1
  166. package/dist/types/loaders/fetch.d.ts +4 -0
  167. package/dist/types/loaders/fetch.js.map +1 -1
  168. package/dist/types/loaders/playwright.js.map +1 -1
  169. package/dist/types/loaders/puppeteer.js.map +1 -1
  170. package/dist/types/md-splitter.d.ts +1 -1
  171. package/dist/types/md-splitter.js.map +1 -1
  172. package/dist/types/mdast-handlers/custom-a-handler.js.map +1 -1
  173. package/dist/types/mdast-handlers/custom-code-handler.d.ts +2 -0
  174. package/dist/types/mdast-handlers/custom-code-handler.js.map +1 -1
  175. package/dist/types/mdast-handlers/custom-div-handler.js.map +1 -1
  176. package/dist/types/mdast-handlers/custom-img-handler.js.map +1 -1
  177. package/dist/types/mdast-handlers/custom-table-handler.js.map +1 -1
  178. package/dist/types/mdast-handlers/definition-list-handler.d.ts +2 -0
  179. package/dist/types/mdast-handlers/definition-list-handler.js.map +1 -0
  180. package/dist/types/mdast-handlers/math-handler.js.map +1 -1
  181. package/dist/types/mdast-handlers/sup-sub-handler.d.ts +10 -0
  182. package/dist/types/mdast-handlers/sup-sub-handler.js.map +1 -0
  183. package/dist/types/mdast-to-markdown.js.map +1 -1
  184. package/dist/types/metadata/index.d.ts +47 -0
  185. package/dist/types/metadata/index.js.map +1 -0
  186. package/dist/types/normalize/index.d.ts +53 -0
  187. package/dist/types/normalize/index.js.map +1 -0
  188. package/dist/types/platform/client.d.ts +55 -0
  189. package/dist/types/platform/client.js.map +1 -0
  190. package/dist/types/platform/error.d.ts +22 -0
  191. package/dist/types/platform/error.js.map +1 -0
  192. package/dist/types/platform/fetch.d.ts +36 -0
  193. package/dist/types/platform/fetch.js.map +1 -0
  194. package/dist/types/platform/index.d.ts +4 -0
  195. package/dist/types/platform/index.js.map +1 -0
  196. package/dist/types/platform/types.d.ts +164 -0
  197. package/dist/types/platform/types.js.map +1 -0
  198. package/dist/types/utils/hast-fast.d.ts +101 -0
  199. package/dist/types/utils/hast-fast.js.map +1 -0
  200. package/dist/utils/hast-fast.js +246 -0
  201. package/package.json +25 -7
  202. package/dist/types/cli/commands/webforai/index.d.ts +0 -6
  203. package/dist/types/cli/commands/webforai/index.js.map +0 -1
@@ -0,0 +1,86 @@
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 adapters_exports = {};
20
+ __export(adapters_exports, {
21
+ BUILTIN_ADAPTERS: () => BUILTIN_ADAPTERS,
22
+ DECLARATIVE_ADAPTERS: () => import_declarative2.DECLARATIVE_ADAPTERS,
23
+ adapterById: () => adapterById,
24
+ buildPageSignature: () => import_registry2.buildPageSignature,
25
+ defineSelectorAdapter: () => import_registry2.defineSelectorAdapter,
26
+ hackernewsAdapter: () => import_hackernews2.hackernewsAdapter,
27
+ removeAll: () => import_registry2.removeAll,
28
+ resolveAdapter: () => import_registry2.resolveAdapter,
29
+ runAdapters: () => runAdapters,
30
+ selectFirst: () => import_registry2.selectFirst,
31
+ youtubeAdapter: () => import_youtube2.youtubeAdapter,
32
+ youtubeCaptionTracks: () => import_youtube2.youtubeCaptionTracks
33
+ });
34
+ module.exports = __toCommonJS(adapters_exports);
35
+ var import_sanitize = require("../extractors/lib/sanitize");
36
+ var import_hast_fast = require("../utils/hast-fast");
37
+ var import_registry = require("./registry");
38
+ var import_declarative = require("./sites/declarative");
39
+ var import_hackernews = require("./sites/hackernews");
40
+ var import_youtube = require("./sites/youtube");
41
+ var import_registry2 = require("./registry");
42
+ var import_declarative2 = require("./sites/declarative");
43
+ var import_hackernews2 = require("./sites/hackernews");
44
+ var import_youtube2 = require("./sites/youtube");
45
+ const BUILTIN_ADAPTERS = [import_youtube.youtubeAdapter, import_hackernews.hackernewsAdapter, ...import_declarative.DECLARATIVE_ADAPTERS];
46
+ const adapterById = (id) => BUILTIN_ADAPTERS.find((adapter) => adapter.id === id);
47
+ const MIN_ADAPTER_TEXT = 40;
48
+ const runAdapters = (context, adapters = BUILTIN_ADAPTERS) => {
49
+ let matched = (0, import_registry.resolveAdapterByHost)(context, adapters);
50
+ let withSignature = context;
51
+ if (!matched) {
52
+ withSignature = { ...context, signature: context.signature ?? (0, import_registry.buildPageSignature)(context.hast) };
53
+ matched = (0, import_registry.resolveAdapterByFingerprint)(withSignature, adapters);
54
+ }
55
+ const adapter = matched;
56
+ if (!adapter) {
57
+ return void 0;
58
+ }
59
+ const target = withSignature.owned ? withSignature : { ...withSignature, hast: (0, import_hast_fast.cloneHast)(withSignature.hast), owned: true };
60
+ let extracted;
61
+ try {
62
+ extracted = adapter.extract(target);
63
+ } catch {
64
+ return void 0;
65
+ }
66
+ if (!extracted) {
67
+ return void 0;
68
+ }
69
+ (0, import_sanitize.stripNonContent)(extracted);
70
+ return new import_hast_fast.MetricsCollector().textLength(extracted) >= MIN_ADAPTER_TEXT ? extracted : void 0;
71
+ };
72
+ // Annotate the CommonJS export names for ESM import in node:
73
+ 0 && (module.exports = {
74
+ BUILTIN_ADAPTERS,
75
+ DECLARATIVE_ADAPTERS,
76
+ adapterById,
77
+ buildPageSignature,
78
+ defineSelectorAdapter,
79
+ hackernewsAdapter,
80
+ removeAll,
81
+ resolveAdapter,
82
+ runAdapters,
83
+ selectFirst,
84
+ youtubeAdapter,
85
+ youtubeCaptionTracks
86
+ });
@@ -0,0 +1,178 @@
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 registry_exports = {};
20
+ __export(registry_exports, {
21
+ buildPageSignature: () => buildPageSignature,
22
+ defineSelectorAdapter: () => defineSelectorAdapter,
23
+ removeAll: () => removeAll,
24
+ resolveAdapter: () => resolveAdapter,
25
+ resolveAdapterByFingerprint: () => resolveAdapterByFingerprint,
26
+ resolveAdapterByHost: () => resolveAdapterByHost,
27
+ selectFirst: () => selectFirst
28
+ });
29
+ module.exports = __toCommonJS(registry_exports);
30
+ var import_hast_util_select = require("hast-util-select");
31
+ var import_hast_fast = require("../utils/hast-fast");
32
+ const EMPTY_SIGNATURE = {
33
+ classes: /* @__PURE__ */ new Set(),
34
+ ids: /* @__PURE__ */ new Set(),
35
+ tags: /* @__PURE__ */ new Set(),
36
+ generator: "",
37
+ meta: ""
38
+ };
39
+ const buildPageSignature = (root) => {
40
+ const classes = /* @__PURE__ */ new Set();
41
+ const ids = /* @__PURE__ */ new Set();
42
+ const tags = /* @__PURE__ */ new Set();
43
+ const generatorParts = [];
44
+ const metaParts = [];
45
+ (0, import_hast_fast.walk)(root, (node) => {
46
+ if (!(0, import_hast_fast.isElement)(node)) {
47
+ return;
48
+ }
49
+ tags.add(node.tagName);
50
+ for (const name of (0, import_hast_fast.classList)(node)) {
51
+ classes.add(name);
52
+ }
53
+ const id = (0, import_hast_fast.stringProperty)(node, "id");
54
+ if (id) {
55
+ ids.add(id);
56
+ }
57
+ if (node.tagName === "meta") {
58
+ const key = (0, import_hast_fast.stringProperty)(node, "name") ?? (0, import_hast_fast.stringProperty)(node, "property") ?? "";
59
+ const content = (0, import_hast_fast.stringProperty)(node, "content") ?? "";
60
+ metaParts.push(`${key}=${content}`);
61
+ if (key.toLowerCase() === "generator") {
62
+ generatorParts.push(content);
63
+ }
64
+ }
65
+ });
66
+ return {
67
+ classes,
68
+ ids,
69
+ tags,
70
+ generator: generatorParts.join(" ").toLowerCase(),
71
+ meta: metaParts.join("\n").toLowerCase()
72
+ };
73
+ };
74
+ const DEFAULT_MIN_LENGTH = 40;
75
+ const hostOf = (url) => {
76
+ if (!url) {
77
+ return void 0;
78
+ }
79
+ try {
80
+ return new URL(url).hostname;
81
+ } catch {
82
+ return void 0;
83
+ }
84
+ };
85
+ const defineSelectorAdapter = (spec) => ({
86
+ id: spec.id,
87
+ matches: (context) => {
88
+ const host = hostOf(context.url);
89
+ return Boolean(host && spec.hosts?.test(host));
90
+ },
91
+ matchesFingerprint: (context) => {
92
+ const signature = context.signature ?? EMPTY_SIGNATURE;
93
+ return spec.fingerprint?.(signature) ?? false;
94
+ },
95
+ extract: (context) => {
96
+ for (const selector of spec.content) {
97
+ const content = tryContentSelector(selector, spec, context);
98
+ if (content) {
99
+ return content;
100
+ }
101
+ }
102
+ return void 0;
103
+ }
104
+ });
105
+ const tryContentSelector = (selector, spec, context) => {
106
+ const found = (0, import_hast_util_select.selectAll)(selector, context.hast);
107
+ if (found.length === 0) {
108
+ return void 0;
109
+ }
110
+ for (const element of found) {
111
+ removeAll(element, spec.remove);
112
+ }
113
+ const total = found.reduce((sum, element) => sum + new import_hast_fast.MetricsCollector().textLength(element), 0);
114
+ if (total < (spec.minLength ?? DEFAULT_MIN_LENGTH)) {
115
+ return void 0;
116
+ }
117
+ const decorated = spec.decorate?.(found, context);
118
+ if (decorated) {
119
+ return decorated;
120
+ }
121
+ return found.length === 1 ? found[0] : { type: "root", children: found };
122
+ };
123
+ const removeAll = (root, selectors) => {
124
+ if (!selectors || selectors.length === 0) {
125
+ return;
126
+ }
127
+ const doomed = /* @__PURE__ */ new Set();
128
+ for (const selector of selectors) {
129
+ for (const element of (0, import_hast_util_select.selectAll)(selector, root)) {
130
+ doomed.add(element);
131
+ }
132
+ }
133
+ if (doomed.size > 0) {
134
+ (0, import_hast_fast.pruneInPlace)(root, (node) => !((0, import_hast_fast.isElement)(node) && doomed.has(node)));
135
+ }
136
+ };
137
+ const selectFirst = (root, selectors) => {
138
+ for (const selector of selectors) {
139
+ const found = (0, import_hast_util_select.select)(selector, root);
140
+ if (found) {
141
+ return found;
142
+ }
143
+ }
144
+ return void 0;
145
+ };
146
+ const resolveAdapterByHost = (context, adapters) => {
147
+ for (const adapter of adapters) {
148
+ try {
149
+ if (adapter.matches(context)) {
150
+ return adapter;
151
+ }
152
+ } catch {
153
+ }
154
+ }
155
+ return void 0;
156
+ };
157
+ const resolveAdapterByFingerprint = (context, adapters) => {
158
+ for (const adapter of adapters) {
159
+ try {
160
+ if (adapter.matchesFingerprint?.(context)) {
161
+ return adapter;
162
+ }
163
+ } catch {
164
+ }
165
+ }
166
+ return void 0;
167
+ };
168
+ const resolveAdapter = (context, adapters) => resolveAdapterByHost(context, adapters) ?? resolveAdapterByFingerprint(context, adapters);
169
+ // Annotate the CommonJS export names for ESM import in node:
170
+ 0 && (module.exports = {
171
+ buildPageSignature,
172
+ defineSelectorAdapter,
173
+ removeAll,
174
+ resolveAdapter,
175
+ resolveAdapterByFingerprint,
176
+ resolveAdapterByHost,
177
+ selectFirst
178
+ });
@@ -0,0 +1,202 @@
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 declarative_exports = {};
20
+ __export(declarative_exports, {
21
+ DECLARATIVE_ADAPTERS: () => DECLARATIVE_ADAPTERS,
22
+ declarativeAdapterById: () => declarativeAdapterById
23
+ });
24
+ module.exports = __toCommonJS(declarative_exports);
25
+ var import_registry = require("../registry");
26
+ const COMMON_NOISE = [
27
+ ".sr-only",
28
+ "[aria-hidden='true'][class*='icon']",
29
+ "button",
30
+ ".social-share",
31
+ ".share-buttons",
32
+ ".newsletter-signup"
33
+ ];
34
+ const SPECS = [
35
+ {
36
+ id: "github",
37
+ hosts: /(^|\.)github\.com$/,
38
+ // Issues and PRs expose a testid; repository landing pages render the README instead.
39
+ content: ["[data-testid='issue-body']", "article.markdown-body", ".markdown-body"],
40
+ remove: [".js-comment-edit-history", ".Details-content--hidden", "clipboard-copy", ...COMMON_NOISE],
41
+ minLength: 30
42
+ },
43
+ {
44
+ id: "stackoverflow",
45
+ hosts: /(^|\.)(stackoverflow\.com|stackexchange\.com|superuser\.com|serverfault\.com|askubuntu\.com)$/,
46
+ content: ["#mainbar", ".question, .answer"],
47
+ remove: [
48
+ ".js-post-menu",
49
+ ".post-menu",
50
+ ".user-info",
51
+ ".votecell",
52
+ ".comments-link",
53
+ ".js-add-link",
54
+ ...COMMON_NOISE
55
+ ],
56
+ minLength: 100
57
+ },
58
+ {
59
+ id: "npm",
60
+ hosts: /(^|\.)npmjs\.com$/,
61
+ content: ["#readme", "#package-tab-readme", "[class*='markdown']"],
62
+ remove: COMMON_NOISE,
63
+ minLength: 50
64
+ },
65
+ {
66
+ id: "zenn",
67
+ hosts: /(^|\.)zenn\.dev$/,
68
+ content: [".znc"],
69
+ remove: COMMON_NOISE,
70
+ minLength: 50
71
+ },
72
+ {
73
+ id: "qiita",
74
+ hosts: /(^|\.)qiita\.com$/,
75
+ content: [".it-MdContent", "[class*='mdContent']", "article"],
76
+ remove: [".code-copy", ...COMMON_NOISE],
77
+ minLength: 50
78
+ },
79
+ {
80
+ id: "medium",
81
+ hosts: /(^|\.)medium\.com$/,
82
+ // Medium also powers custom domains; the fingerprint catches those.
83
+ fingerprint: (signature) => signature.meta.includes("al:android:app_name=medium"),
84
+ content: ["article section", "article", "[data-testid='storyContent']"],
85
+ remove: ["[data-testid='audioPlayButton']", "[role='separator']", ...COMMON_NOISE],
86
+ minLength: 200
87
+ },
88
+ {
89
+ id: "substack",
90
+ hosts: /(^|\.)substack\.com$/,
91
+ // Substack's custom domains are far more common than *.substack.com.
92
+ fingerprint: (signature) => signature.classes.has("available-content"),
93
+ content: [".available-content", ".body.markup", ".post-content"],
94
+ remove: [".subscription-widget-wrap", ".button-wrapper", ".paywall", ...COMMON_NOISE],
95
+ minLength: 200
96
+ },
97
+ {
98
+ id: "note",
99
+ hosts: /(^|\.)note\.com$/,
100
+ content: [".note-common-styles__textnote-body", "[class*='textnote-body']"],
101
+ remove: COMMON_NOISE,
102
+ minLength: 50
103
+ },
104
+ {
105
+ id: "hatena",
106
+ hosts: /(^|\.)(hatenablog\.com|hatenadiary\.(com|jp)|hateblo\.jp|hatenastaff\.com)$/,
107
+ fingerprint: (signature) => signature.classes.has("hatenablog-entry") || signature.classes.has("hatena-body"),
108
+ content: [".entry-content"],
109
+ remove: [".entry-footer", ".social-buttons", ".hatena-asin-detail", ...COMMON_NOISE],
110
+ minLength: 100
111
+ },
112
+ {
113
+ id: "wordpress",
114
+ // Deliberately fingerprint-only: WordPress powers a large share of the web on its own
115
+ // domains, so keying off a hostname would cover almost none of it.
116
+ fingerprint: (signature) => signature.generator.includes("wordpress") || signature.classes.has("wp-block-post-content") || signature.classes.has("wp-singular"),
117
+ content: [".wp-block-post-content", ".entry-content", ".post-content", "article .content"],
118
+ remove: [".sharedaddy", ".jp-relatedposts", ".wp-block-comments", "#comments", ...COMMON_NOISE],
119
+ minLength: 150
120
+ },
121
+ {
122
+ id: "wikipedia",
123
+ hosts: /(^|\.)(wikipedia\.org|wikimedia\.org|wikibooks\.org|wiktionary\.org|wikisource\.org)$/,
124
+ fingerprint: (signature) => signature.classes.has("mw-parser-output"),
125
+ content: [".mw-parser-output", "#mw-content-text"],
126
+ remove: [
127
+ ".mw-editsection",
128
+ ".navbox",
129
+ ".navbox-inner",
130
+ ".vertical-navbox",
131
+ ".sidebar",
132
+ ".side-box",
133
+ ".metadata",
134
+ ".reflist",
135
+ ".refbegin",
136
+ ".sistersitebox",
137
+ ".ambox",
138
+ ".hatnote",
139
+ ".shortdescription",
140
+ ".mw-jump-link",
141
+ ".printfooter",
142
+ ".catlinks",
143
+ "#toc",
144
+ ".toc",
145
+ "table.mbox-small",
146
+ ...COMMON_NOISE
147
+ ],
148
+ minLength: 200
149
+ },
150
+ {
151
+ id: "reddit",
152
+ hosts: /(^|\.)reddit\.com$/,
153
+ content: ["shreddit-post [slot='text-body']", "[data-test-id='post-content']", ".Post"],
154
+ remove: ["faceplate-tracker[noun='comment_action_bar']", "shreddit-comment-action-row", ...COMMON_NOISE],
155
+ // Reddit renders most of a thread into shadow roots that never reach the serialised HTML,
156
+ // so a weak match here is worse than generic extraction. Decline unless a substantial
157
+ // post body is actually present in the document.
158
+ minLength: 600
159
+ },
160
+ {
161
+ id: "docusaurus",
162
+ fingerprint: (signature) => signature.classes.has("theme-doc-markdown") || signature.classes.has("docusaurus-mt-lg"),
163
+ content: [".theme-doc-markdown", "article .markdown"],
164
+ remove: [".theme-doc-toc-mobile", ".pagination-nav", ".theme-doc-version-banner", ...COMMON_NOISE],
165
+ minLength: 150
166
+ },
167
+ {
168
+ id: "vitepress",
169
+ fingerprint: (signature) => signature.classes.has("vp-doc") || signature.classes.has("VPDoc"),
170
+ content: [".vp-doc > div", ".vp-doc", ".VPDoc .content-container"],
171
+ remove: [".VPDocFooter", ".vp-doc-footer", ".header-anchor", ...COMMON_NOISE],
172
+ minLength: 150
173
+ },
174
+ {
175
+ id: "mkdocs",
176
+ fingerprint: (signature) => signature.classes.has("md-content__inner"),
177
+ content: [".md-content__inner", "[data-md-component='content']"],
178
+ remove: [".md-source-file", ".md-feedback", ".headerlink", ...COMMON_NOISE],
179
+ minLength: 150
180
+ },
181
+ {
182
+ id: "readthedocs",
183
+ fingerprint: (signature) => signature.classes.has("rst-content"),
184
+ content: [".rst-content", "[role='main']"],
185
+ remove: [".headerlink", ".rst-footer-buttons", ".wy-breadcrumbs", ...COMMON_NOISE],
186
+ minLength: 150
187
+ },
188
+ {
189
+ id: "gitbook",
190
+ fingerprint: (signature) => signature.classes.has("gitbook-root"),
191
+ content: ["[data-testid='page.contentEditor']", "main article"],
192
+ remove: COMMON_NOISE,
193
+ minLength: 150
194
+ }
195
+ ];
196
+ const DECLARATIVE_ADAPTERS = SPECS.map(import_registry.defineSelectorAdapter);
197
+ const declarativeAdapterById = (id) => DECLARATIVE_ADAPTERS.find((adapter) => adapter.id === id);
198
+ // Annotate the CommonJS export names for ESM import in node:
199
+ 0 && (module.exports = {
200
+ DECLARATIVE_ADAPTERS,
201
+ declarativeAdapterById
202
+ });
@@ -0,0 +1,117 @@
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 hackernews_exports = {};
20
+ __export(hackernews_exports, {
21
+ hackernewsAdapter: () => hackernewsAdapter
22
+ });
23
+ module.exports = __toCommonJS(hackernews_exports);
24
+ var import_hast_util_select = require("hast-util-select");
25
+ var import_hast_fast = require("../../utils/hast-fast");
26
+ const MAX_QUOTE_DEPTH = 6;
27
+ const text = (value) => ({ type: "text", value });
28
+ const element = (tagName, children) => ({
29
+ type: "element",
30
+ tagName,
31
+ properties: {},
32
+ children
33
+ });
34
+ const commentDepth = (row) => {
35
+ const cell = (0, import_hast_util_select.select)("td.ind", row);
36
+ if (!cell) {
37
+ return 0;
38
+ }
39
+ const indent = (0, import_hast_fast.numericProperty)(cell, "indent");
40
+ if (indent !== void 0) {
41
+ return indent;
42
+ }
43
+ const spacer = (0, import_hast_util_select.select)("img", cell);
44
+ const width = spacer ? (0, import_hast_fast.numericProperty)(spacer, "width") : void 0;
45
+ return width === void 0 ? 0 : Math.round(width / 40);
46
+ };
47
+ const nest = (content, depth) => {
48
+ let current = content;
49
+ for (let level = 0; level < Math.min(depth, MAX_QUOTE_DEPTH); level++) {
50
+ current = [element("blockquote", current)];
51
+ }
52
+ return current[0];
53
+ };
54
+ const storyNodes = (root) => {
55
+ const nodes = [];
56
+ const titleLink = (0, import_hast_util_select.select)(".titleline > a", root);
57
+ if (titleLink) {
58
+ nodes.push(element("h1", [...titleLink.children]));
59
+ const href = (0, import_hast_fast.stringProperty)(titleLink, "href");
60
+ if (href && /^https?:/.test(href)) {
61
+ nodes.push(element("p", [{ ...titleLink, children: [text(href)] }]));
62
+ }
63
+ }
64
+ const topText = (0, import_hast_util_select.select)(".toptext", root);
65
+ if (topText) {
66
+ nodes.push(element("div", [...topText.children]));
67
+ }
68
+ return nodes;
69
+ };
70
+ const commentNodes = (root) => {
71
+ const nodes = [];
72
+ for (const row of (0, import_hast_util_select.selectAll)("tr.comtr, tr.athing.comtr", root)) {
73
+ const body = (0, import_hast_util_select.select)(".commtext", row);
74
+ if (!body) {
75
+ continue;
76
+ }
77
+ const author = (0, import_hast_util_select.select)(".hnuser", row);
78
+ const header = author ? [element("strong", [...author.children])] : [];
79
+ const content = [
80
+ ...header.length > 0 ? [element("p", header)] : [],
81
+ element("div", [...body.children])
82
+ ];
83
+ nodes.push(nest(content, commentDepth(row)));
84
+ }
85
+ return nodes;
86
+ };
87
+ const hackernewsAdapter = {
88
+ id: "hackernews",
89
+ matches: ({ url }) => {
90
+ if (!url) {
91
+ return false;
92
+ }
93
+ try {
94
+ return /(^|\.)ycombinator\.com$/.test(new URL(url).hostname);
95
+ } catch {
96
+ return false;
97
+ }
98
+ },
99
+ matchesFingerprint: ({ signature }) => Boolean(signature?.ids.has("hnmain") || signature?.classes.has("fatitem")),
100
+ extract: ({ hast }) => {
101
+ const story = storyNodes(hast);
102
+ const comments = commentNodes(hast);
103
+ if (story.length === 0 && comments.length === 0) {
104
+ return void 0;
105
+ }
106
+ const children = [...story];
107
+ if (comments.length > 0) {
108
+ children.push(element("h2", [text("Comments")]));
109
+ children.push(...comments);
110
+ }
111
+ return { type: "root", children };
112
+ }
113
+ };
114
+ // Annotate the CommonJS export names for ESM import in node:
115
+ 0 && (module.exports = {
116
+ hackernewsAdapter
117
+ });