@wenathlan/saddle 1.8.17 → 2.0.2

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 (1005) hide show
  1. package/Dockerfile +1339 -0
  2. package/README.md +68 -22
  3. package/alternatives.ts +1218 -0
  4. package/biome.json +153 -0
  5. package/boards.json +1517 -0
  6. package/compute.ts +3144 -0
  7. package/cores.json +1801 -0
  8. package/dist/acquisition.d.ts +359 -0
  9. package/dist/acquisition.d.ts.map +1 -0
  10. package/dist/acquisition.js +629 -0
  11. package/dist/acquisition.js.map +1 -0
  12. package/dist/alternatives.d.ts +509 -0
  13. package/dist/alternatives.d.ts.map +1 -0
  14. package/dist/alternatives.js +951 -0
  15. package/dist/alternatives.js.map +1 -0
  16. package/dist/automation.d.ts +426 -0
  17. package/dist/automation.d.ts.map +1 -0
  18. package/dist/automation.js +561 -0
  19. package/dist/automation.js.map +1 -0
  20. package/dist/browser.d.ts +562 -0
  21. package/dist/browser.d.ts.map +1 -0
  22. package/dist/browser.js +1057 -0
  23. package/dist/browser.js.map +1 -0
  24. package/dist/capacitor.config.d.ts +13 -0
  25. package/dist/capacitor.config.d.ts.map +1 -0
  26. package/dist/capacitor.config.js +26 -0
  27. package/dist/capacitor.config.js.map +1 -0
  28. package/dist/cli.d.ts +17 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +111 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/communication.d.ts +192 -0
  33. package/dist/communication.d.ts.map +1 -0
  34. package/dist/communication.js +418 -0
  35. package/dist/communication.js.map +1 -0
  36. package/dist/compute.d.ts +1161 -0
  37. package/dist/compute.d.ts.map +1 -0
  38. package/dist/compute.js +2273 -0
  39. package/dist/compute.js.map +1 -0
  40. package/dist/distribution.d.ts +529 -0
  41. package/dist/distribution.d.ts.map +1 -0
  42. package/dist/distribution.js +811 -0
  43. package/dist/distribution.js.map +1 -0
  44. package/dist/execution.d.ts +530 -0
  45. package/dist/execution.d.ts.map +1 -0
  46. package/dist/execution.js +761 -0
  47. package/dist/execution.js.map +1 -0
  48. package/dist/format.d.ts +19 -0
  49. package/dist/format.d.ts.map +1 -0
  50. package/dist/format.js +60 -0
  51. package/dist/format.js.map +1 -0
  52. package/dist/foundation.d.ts +176 -0
  53. package/dist/foundation.d.ts.map +1 -0
  54. package/dist/foundation.js +309 -0
  55. package/dist/foundation.js.map +1 -0
  56. package/dist/index.d.ts +733 -122
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +1018 -122
  59. package/dist/index.js.map +1 -1
  60. package/dist/integration.d.ts +236 -0
  61. package/dist/integration.d.ts.map +1 -0
  62. package/dist/integration.js +236 -0
  63. package/dist/integration.js.map +1 -0
  64. package/dist/intelligence.d.ts +94 -0
  65. package/dist/intelligence.d.ts.map +1 -0
  66. package/dist/intelligence.js +145 -0
  67. package/dist/intelligence.js.map +1 -0
  68. package/dist/isolation.d.ts +129 -0
  69. package/dist/isolation.d.ts.map +1 -0
  70. package/dist/isolation.js +96 -0
  71. package/dist/isolation.js.map +1 -0
  72. package/dist/media.d.ts +344 -0
  73. package/dist/media.d.ts.map +1 -0
  74. package/dist/media.js +986 -0
  75. package/dist/media.js.map +1 -0
  76. package/dist/modes.d.ts +359 -0
  77. package/dist/modes.d.ts.map +1 -0
  78. package/dist/modes.js +134 -0
  79. package/dist/modes.js.map +1 -0
  80. package/dist/{library/public.d.ts → operations.d.ts} +15 -1
  81. package/dist/operations.d.ts.map +1 -0
  82. package/dist/{library/public.js → operations.js} +18 -7
  83. package/dist/operations.js.map +1 -0
  84. package/dist/orchestrator.d.ts +1339 -0
  85. package/dist/orchestrator.d.ts.map +1 -0
  86. package/dist/orchestrator.js +4308 -0
  87. package/dist/orchestrator.js.map +1 -0
  88. package/dist/performance.d.ts +416 -0
  89. package/dist/performance.d.ts.map +1 -0
  90. package/dist/performance.js +827 -0
  91. package/dist/performance.js.map +1 -0
  92. package/dist/quantum.d.ts +810 -0
  93. package/dist/quantum.d.ts.map +1 -0
  94. package/dist/quantum.js +2073 -0
  95. package/dist/quantum.js.map +1 -0
  96. package/dist/render.d.ts +381 -0
  97. package/dist/render.d.ts.map +1 -0
  98. package/dist/render.js +1073 -0
  99. package/dist/render.js.map +1 -0
  100. package/dist/scheduler.d.ts +596 -0
  101. package/dist/scheduler.d.ts.map +1 -0
  102. package/dist/scheduler.js +1259 -0
  103. package/dist/scheduler.js.map +1 -0
  104. package/dist/security.d.ts +501 -0
  105. package/dist/security.d.ts.map +1 -0
  106. package/dist/security.js +1170 -0
  107. package/dist/security.js.map +1 -0
  108. package/dist/server.d.ts +21 -0
  109. package/dist/server.d.ts.map +1 -0
  110. package/dist/{server/node.js → server.js} +16 -2
  111. package/dist/server.js.map +1 -0
  112. package/dist/tiers.d.ts +1002 -0
  113. package/dist/tiers.d.ts.map +1 -0
  114. package/dist/tiers.js +2165 -0
  115. package/dist/tiers.js.map +1 -0
  116. package/dist/virtual.d.ts +641 -0
  117. package/dist/virtual.d.ts.map +1 -0
  118. package/dist/virtual.js +1285 -0
  119. package/dist/virtual.js.map +1 -0
  120. package/dist/virtualcpu.d.ts +316 -0
  121. package/dist/virtualcpu.d.ts.map +1 -0
  122. package/dist/virtualcpu.js +1180 -0
  123. package/dist/virtualcpu.js.map +1 -0
  124. package/dist/virtualgpu.d.ts +345 -0
  125. package/dist/virtualgpu.d.ts.map +1 -0
  126. package/dist/virtualgpu.js +1000 -0
  127. package/dist/virtualgpu.js.map +1 -0
  128. package/dist/virtualization.d.ts +607 -0
  129. package/dist/virtualization.d.ts.map +1 -0
  130. package/dist/virtualization.js +1187 -0
  131. package/dist/virtualization.js.map +1 -0
  132. package/dist/virtualmemory.d.ts +818 -0
  133. package/dist/virtualmemory.d.ts.map +1 -0
  134. package/dist/virtualmemory.js +1796 -0
  135. package/dist/virtualmemory.js.map +1 -0
  136. package/dist/webscrape.d.ts +720 -0
  137. package/dist/webscrape.d.ts.map +1 -0
  138. package/dist/webscrape.js +2697 -0
  139. package/dist/webscrape.js.map +1 -0
  140. package/docker.config +769 -0
  141. package/docs/CONVERSA.txt +1523 -0
  142. package/docs/alternatives.md +499 -0
  143. package/docs/architecture-1.8.19.md +76 -0
  144. package/docs/architecture-1.8.19.mmd +33 -0
  145. package/docs/architecture-1.8.19.png +0 -0
  146. package/docs/architecture.md +355 -0
  147. package/docs/artifactavailability.md +6 -0
  148. package/docs/brancharchive-2026-08-18.md +18 -0
  149. package/docs/browser.md +7 -0
  150. package/docs/consolidation.md +70 -0
  151. package/docs/e2ugh-engine.md +528 -0
  152. package/{dist/examples/localjob.js → docs/example-localjob.ts} +3 -3
  153. package/{dist/examples/publicapi.js → docs/example-publicapi.ts} +2 -2
  154. package/docs/hardware.md +342 -0
  155. package/docs/optimization.md +126 -0
  156. package/docs/performance.md +499 -0
  157. package/docs/planning.1.8.18.md +94 -0
  158. package/docs/planning.1.8.19.md +49 -0
  159. package/docs/releasenotes-1.8.17.md +6 -0
  160. package/docs/releasenotes-1.8.18.md +32 -0
  161. package/docs/releasenotes-1.8.19.md +35 -0
  162. package/docs/research-1.8.18-isolation.md +43 -0
  163. package/docs/research-1.8.19-virtual-browser.md +27 -0
  164. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  165. package/docs/security.md +454 -0
  166. package/docs/todo-1.8.16.md +56 -1
  167. package/docs/todo-1.8.18.md +164 -0
  168. package/docs/todo-1.8.19.md +241 -0
  169. package/docs/viability.md +777 -0
  170. package/docs/virtualization.md +335 -0
  171. package/docs/web-duplicatecleanup.md +9 -0
  172. package/docs/web-ideas.md +106 -0
  173. package/docs/workflowimprovements-2026-08-19.md +70 -0
  174. package/gpumonitor.cpp +1543 -0
  175. package/gpus.json +2408 -0
  176. package/index.ts +1478 -0
  177. package/media.ts +1337 -0
  178. package/mttg.config +1549 -0
  179. package/orchestrator.ts +5462 -0
  180. package/package.json +304 -55
  181. package/passage.config +1331 -0
  182. package/performance.ts +1049 -0
  183. package/processors.json +2217 -0
  184. package/qemu.config +1062 -0
  185. package/qemubridge.py +1340 -0
  186. package/quantum.ts +2393 -0
  187. package/render.ts +1325 -0
  188. package/scheduler.ts +1600 -0
  189. package/security.ts +1449 -0
  190. package/tiers.ts +2871 -0
  191. package/tsconfig.json +29 -0
  192. package/virtualcpu.ts +1273 -0
  193. package/virtualgpu.ts +1181 -0
  194. package/virtualhardware.c +1011 -0
  195. package/virtualhardware.json +739 -0
  196. package/virtualization.ts +1628 -0
  197. package/virtualizationcore.cpp +4635 -0
  198. package/virtualmemory.ts +2303 -0
  199. package/vm.config.json +1910 -0
  200. package/{extension → web/extension}/manifest.json +1 -1
  201. package/web/readme.md +382 -0
  202. package/web/tsconfig.json +25 -0
  203. package/dist/adapters/forge.d.ts +0 -17
  204. package/dist/adapters/forge.d.ts.map +0 -1
  205. package/dist/adapters/forge.js +0 -19
  206. package/dist/adapters/forge.js.map +0 -1
  207. package/dist/adapters/forgejo.d.ts +0 -49
  208. package/dist/adapters/forgejo.d.ts.map +0 -1
  209. package/dist/adapters/forgejo.js +0 -8
  210. package/dist/adapters/forgejo.js.map +0 -1
  211. package/dist/adapters/github.d.ts +0 -12
  212. package/dist/adapters/github.d.ts.map +0 -1
  213. package/dist/adapters/github.js +0 -20
  214. package/dist/adapters/github.js.map +0 -1
  215. package/dist/adapters/gitlab.d.ts +0 -17
  216. package/dist/adapters/gitlab.d.ts.map +0 -1
  217. package/dist/adapters/gitlab.js +0 -10
  218. package/dist/adapters/gitlab.js.map +0 -1
  219. package/dist/adapters/huggingface.d.ts +0 -17
  220. package/dist/adapters/huggingface.d.ts.map +0 -1
  221. package/dist/adapters/huggingface.js +0 -6
  222. package/dist/adapters/huggingface.js.map +0 -1
  223. package/dist/adapters/socket.d.ts +0 -11
  224. package/dist/adapters/socket.d.ts.map +0 -1
  225. package/dist/adapters/socket.js +0 -17
  226. package/dist/adapters/socket.js.map +0 -1
  227. package/dist/adapters/transport.d.ts +0 -7
  228. package/dist/adapters/transport.d.ts.map +0 -1
  229. package/dist/adapters/transport.js +0 -36
  230. package/dist/adapters/transport.js.map +0 -1
  231. package/dist/ai/chunk.d.ts +0 -2
  232. package/dist/ai/chunk.d.ts.map +0 -1
  233. package/dist/ai/chunk.js +0 -36
  234. package/dist/ai/chunk.js.map +0 -1
  235. package/dist/ai/llmstxt.d.ts +0 -6
  236. package/dist/ai/llmstxt.d.ts.map +0 -1
  237. package/dist/ai/llmstxt.js +0 -12
  238. package/dist/ai/llmstxt.js.map +0 -1
  239. package/dist/ai/provenance.d.ts +0 -22
  240. package/dist/ai/provenance.d.ts.map +0 -1
  241. package/dist/ai/provenance.js +0 -25
  242. package/dist/ai/provenance.js.map +0 -1
  243. package/dist/ai/rag.d.ts +0 -26
  244. package/dist/ai/rag.d.ts.map +0 -1
  245. package/dist/ai/rag.js +0 -22
  246. package/dist/ai/rag.js.map +0 -1
  247. package/dist/ai/tokens.d.ts +0 -15
  248. package/dist/ai/tokens.d.ts.map +0 -1
  249. package/dist/ai/tokens.js +0 -9
  250. package/dist/ai/tokens.js.map +0 -1
  251. package/dist/api/auth.d.ts +0 -16
  252. package/dist/api/auth.d.ts.map +0 -1
  253. package/dist/api/auth.js +0 -19
  254. package/dist/api/auth.js.map +0 -1
  255. package/dist/api/contracts.d.ts +0 -28
  256. package/dist/api/contracts.d.ts.map +0 -1
  257. package/dist/api/contracts.js +0 -14
  258. package/dist/api/contracts.js.map +0 -1
  259. package/dist/api/control.d.ts +0 -10
  260. package/dist/api/control.d.ts.map +0 -1
  261. package/dist/api/control.js +0 -35
  262. package/dist/api/control.js.map +0 -1
  263. package/dist/api/http.d.ts +0 -7
  264. package/dist/api/http.d.ts.map +0 -1
  265. package/dist/api/http.js +0 -12
  266. package/dist/api/http.js.map +0 -1
  267. package/dist/api/rate.d.ts +0 -28
  268. package/dist/api/rate.d.ts.map +0 -1
  269. package/dist/api/rate.js +0 -36
  270. package/dist/api/rate.js.map +0 -1
  271. package/dist/api/security.d.ts +0 -12
  272. package/dist/api/security.d.ts.map +0 -1
  273. package/dist/api/security.js +0 -56
  274. package/dist/api/security.js.map +0 -1
  275. package/dist/api/service.d.ts +0 -5
  276. package/dist/api/service.d.ts.map +0 -1
  277. package/dist/api/service.js +0 -70
  278. package/dist/api/service.js.map +0 -1
  279. package/dist/apps/registry.d.ts +0 -33
  280. package/dist/apps/registry.d.ts.map +0 -1
  281. package/dist/apps/registry.js +0 -24
  282. package/dist/apps/registry.js.map +0 -1
  283. package/dist/binary/archive.d.ts +0 -27
  284. package/dist/binary/archive.d.ts.map +0 -1
  285. package/dist/binary/archive.js +0 -46
  286. package/dist/binary/archive.js.map +0 -1
  287. package/dist/binary/build.d.ts +0 -29
  288. package/dist/binary/build.d.ts.map +0 -1
  289. package/dist/binary/build.js +0 -17
  290. package/dist/binary/build.js.map +0 -1
  291. package/dist/binary/transform.d.ts +0 -70
  292. package/dist/binary/transform.d.ts.map +0 -1
  293. package/dist/binary/transform.js +0 -105
  294. package/dist/binary/transform.js.map +0 -1
  295. package/dist/bot/adapter.d.ts +0 -5
  296. package/dist/bot/adapter.d.ts.map +0 -1
  297. package/dist/bot/adapter.js +0 -11
  298. package/dist/bot/adapter.js.map +0 -1
  299. package/dist/bot/bot.d.ts +0 -28
  300. package/dist/bot/bot.d.ts.map +0 -1
  301. package/dist/bot/bot.js +0 -52
  302. package/dist/bot/bot.js.map +0 -1
  303. package/dist/bot/commands.d.ts +0 -8
  304. package/dist/bot/commands.d.ts.map +0 -1
  305. package/dist/bot/commands.js +0 -19
  306. package/dist/bot/commands.js.map +0 -1
  307. package/dist/bot/permissions.d.ts +0 -13
  308. package/dist/bot/permissions.d.ts.map +0 -1
  309. package/dist/bot/permissions.js +0 -16
  310. package/dist/bot/permissions.js.map +0 -1
  311. package/dist/browser/actions.d.ts +0 -33
  312. package/dist/browser/actions.d.ts.map +0 -1
  313. package/dist/browser/actions.js +0 -44
  314. package/dist/browser/actions.js.map +0 -1
  315. package/dist/browser/agent.d.ts +0 -21
  316. package/dist/browser/agent.d.ts.map +0 -1
  317. package/dist/browser/agent.js +0 -13
  318. package/dist/browser/agent.js.map +0 -1
  319. package/dist/browser/context.d.ts +0 -43
  320. package/dist/browser/context.d.ts.map +0 -1
  321. package/dist/browser/context.js +0 -54
  322. package/dist/browser/context.js.map +0 -1
  323. package/dist/browser/fingerprint.d.ts +0 -4
  324. package/dist/browser/fingerprint.d.ts.map +0 -1
  325. package/dist/browser/fingerprint.js +0 -12
  326. package/dist/browser/fingerprint.js.map +0 -1
  327. package/dist/browser/index.d.ts +0 -11
  328. package/dist/browser/index.d.ts.map +0 -1
  329. package/dist/browser/index.js +0 -11
  330. package/dist/browser/index.js.map +0 -1
  331. package/dist/browser/playwright.d.ts +0 -11
  332. package/dist/browser/playwright.d.ts.map +0 -1
  333. package/dist/browser/playwright.js +0 -24
  334. package/dist/browser/playwright.js.map +0 -1
  335. package/dist/browser/recorder.d.ts +0 -21
  336. package/dist/browser/recorder.d.ts.map +0 -1
  337. package/dist/browser/recorder.js +0 -58
  338. package/dist/browser/recorder.js.map +0 -1
  339. package/dist/browser/session.d.ts +0 -14
  340. package/dist/browser/session.d.ts.map +0 -1
  341. package/dist/browser/session.js +0 -21
  342. package/dist/browser/session.js.map +0 -1
  343. package/dist/browser/snapshot.d.ts +0 -69
  344. package/dist/browser/snapshot.d.ts.map +0 -1
  345. package/dist/browser/snapshot.js +0 -133
  346. package/dist/browser/snapshot.js.map +0 -1
  347. package/dist/captcha/contract.d.ts +0 -35
  348. package/dist/captcha/contract.d.ts.map +0 -1
  349. package/dist/captcha/contract.js +0 -17
  350. package/dist/captcha/contract.js.map +0 -1
  351. package/dist/captcha/evidence.d.ts +0 -10
  352. package/dist/captcha/evidence.d.ts.map +0 -1
  353. package/dist/captcha/evidence.js +0 -9
  354. package/dist/captcha/evidence.js.map +0 -1
  355. package/dist/captcha/guard.d.ts +0 -23
  356. package/dist/captcha/guard.d.ts.map +0 -1
  357. package/dist/captcha/guard.js +0 -12
  358. package/dist/captcha/guard.js.map +0 -1
  359. package/dist/cli/main.d.ts +0 -4
  360. package/dist/cli/main.d.ts.map +0 -1
  361. package/dist/cli/main.js +0 -46
  362. package/dist/cli/main.js.map +0 -1
  363. package/dist/core/errors.d.ts +0 -84
  364. package/dist/core/errors.d.ts.map +0 -1
  365. package/dist/core/errors.js +0 -54
  366. package/dist/core/errors.js.map +0 -1
  367. package/dist/core/events.d.ts +0 -9
  368. package/dist/core/events.d.ts.map +0 -1
  369. package/dist/core/events.js +0 -21
  370. package/dist/core/events.js.map +0 -1
  371. package/dist/core/hash.d.ts +0 -10
  372. package/dist/core/hash.d.ts.map +0 -1
  373. package/dist/core/hash.js +0 -82
  374. package/dist/core/hash.js.map +0 -1
  375. package/dist/core/ids.d.ts +0 -10
  376. package/dist/core/ids.d.ts.map +0 -1
  377. package/dist/core/ids.js +0 -15
  378. package/dist/core/ids.js.map +0 -1
  379. package/dist/delivery/manifest.d.ts +0 -35
  380. package/dist/delivery/manifest.d.ts.map +0 -1
  381. package/dist/delivery/manifest.js +0 -68
  382. package/dist/delivery/manifest.js.map +0 -1
  383. package/dist/deploy/index.d.ts +0 -6
  384. package/dist/deploy/index.d.ts.map +0 -1
  385. package/dist/deploy/index.js +0 -6
  386. package/dist/deploy/index.js.map +0 -1
  387. package/dist/dispatch/resumable.d.ts +0 -102
  388. package/dist/dispatch/resumable.d.ts.map +0 -1
  389. package/dist/dispatch/resumable.js +0 -64
  390. package/dist/dispatch/resumable.js.map +0 -1
  391. package/dist/dispatch/workflow.d.ts +0 -6
  392. package/dist/dispatch/workflow.d.ts.map +0 -1
  393. package/dist/dispatch/workflow.js +0 -37
  394. package/dist/dispatch/workflow.js.map +0 -1
  395. package/dist/domain/artifacts.d.ts +0 -12
  396. package/dist/domain/artifacts.d.ts.map +0 -1
  397. package/dist/domain/artifacts.js +0 -14
  398. package/dist/domain/artifacts.js.map +0 -1
  399. package/dist/domain/jobs.d.ts +0 -12
  400. package/dist/domain/jobs.d.ts.map +0 -1
  401. package/dist/domain/jobs.js +0 -20
  402. package/dist/domain/jobs.js.map +0 -1
  403. package/dist/domain/providers.d.ts +0 -10
  404. package/dist/domain/providers.d.ts.map +0 -1
  405. package/dist/domain/providers.js +0 -8
  406. package/dist/domain/providers.js.map +0 -1
  407. package/dist/domain/runtime.d.ts +0 -14
  408. package/dist/domain/runtime.d.ts.map +0 -1
  409. package/dist/domain/runtime.js +0 -10
  410. package/dist/domain/runtime.js.map +0 -1
  411. package/dist/domain/sessions.d.ts +0 -12
  412. package/dist/domain/sessions.d.ts.map +0 -1
  413. package/dist/domain/sessions.js +0 -57
  414. package/dist/domain/sessions.js.map +0 -1
  415. package/dist/examples/localjob.d.ts +0 -2
  416. package/dist/examples/localjob.d.ts.map +0 -1
  417. package/dist/examples/localjob.js.map +0 -1
  418. package/dist/examples/publicapi.d.ts +0 -2
  419. package/dist/examples/publicapi.d.ts.map +0 -1
  420. package/dist/examples/publicapi.js.map +0 -1
  421. package/dist/extension/build.d.ts +0 -9
  422. package/dist/extension/build.d.ts.map +0 -1
  423. package/dist/extension/build.js +0 -85
  424. package/dist/extension/build.js.map +0 -1
  425. package/dist/extension/content.d.ts +0 -6
  426. package/dist/extension/content.d.ts.map +0 -1
  427. package/dist/extension/content.js +0 -135
  428. package/dist/extension/content.js.map +0 -1
  429. package/dist/extension/index.d.ts +0 -7
  430. package/dist/extension/index.d.ts.map +0 -1
  431. package/dist/extension/index.js +0 -7
  432. package/dist/extension/index.js.map +0 -1
  433. package/dist/extension/pagebridge.d.ts +0 -6
  434. package/dist/extension/pagebridge.d.ts.map +0 -1
  435. package/dist/extension/pagebridge.js +0 -42
  436. package/dist/extension/pagebridge.js.map +0 -1
  437. package/dist/extension/permissions.d.ts +0 -26
  438. package/dist/extension/permissions.d.ts.map +0 -1
  439. package/dist/extension/permissions.js +0 -28
  440. package/dist/extension/permissions.js.map +0 -1
  441. package/dist/extension/popup.d.ts +0 -5
  442. package/dist/extension/popup.d.ts.map +0 -1
  443. package/dist/extension/popup.js +0 -26
  444. package/dist/extension/popup.js.map +0 -1
  445. package/dist/extension/protocol.d.ts +0 -58
  446. package/dist/extension/protocol.d.ts.map +0 -1
  447. package/dist/extension/protocol.js +0 -101
  448. package/dist/extension/protocol.js.map +0 -1
  449. package/dist/extension/serviceworker.d.ts +0 -25
  450. package/dist/extension/serviceworker.d.ts.map +0 -1
  451. package/dist/extension/serviceworker.js +0 -102
  452. package/dist/extension/serviceworker.js.map +0 -1
  453. package/dist/extension/worker.d.ts +0 -28
  454. package/dist/extension/worker.d.ts.map +0 -1
  455. package/dist/extension/worker.js +0 -22
  456. package/dist/extension/worker.js.map +0 -1
  457. package/dist/format/check.d.ts +0 -8
  458. package/dist/format/check.d.ts.map +0 -1
  459. package/dist/format/check.js +0 -38
  460. package/dist/format/check.js.map +0 -1
  461. package/dist/library/public.d.ts.map +0 -1
  462. package/dist/library/public.js.map +0 -1
  463. package/dist/mcp/browser.d.ts +0 -9
  464. package/dist/mcp/browser.d.ts.map +0 -1
  465. package/dist/mcp/browser.js +0 -13
  466. package/dist/mcp/browser.js.map +0 -1
  467. package/dist/mcp/server.d.ts +0 -35
  468. package/dist/mcp/server.d.ts.map +0 -1
  469. package/dist/mcp/server.js +0 -40
  470. package/dist/mcp/server.js.map +0 -1
  471. package/dist/mcp/transport.d.ts +0 -7
  472. package/dist/mcp/transport.d.ts.map +0 -1
  473. package/dist/mcp/transport.js +0 -17
  474. package/dist/mcp/transport.js.map +0 -1
  475. package/dist/memory/bridge.d.ts +0 -14
  476. package/dist/memory/bridge.d.ts.map +0 -1
  477. package/dist/memory/bridge.js +0 -16
  478. package/dist/memory/bridge.js.map +0 -1
  479. package/dist/memory/engine.d.ts +0 -38
  480. package/dist/memory/engine.d.ts.map +0 -1
  481. package/dist/memory/engine.js +0 -109
  482. package/dist/memory/engine.js.map +0 -1
  483. package/dist/memory/modes.d.ts +0 -43
  484. package/dist/memory/modes.d.ts.map +0 -1
  485. package/dist/memory/modes.js +0 -66
  486. package/dist/memory/modes.js.map +0 -1
  487. package/dist/memory/objects.d.ts +0 -21
  488. package/dist/memory/objects.d.ts.map +0 -1
  489. package/dist/memory/objects.js +0 -20
  490. package/dist/memory/objects.js.map +0 -1
  491. package/dist/memory/planner.d.ts +0 -66
  492. package/dist/memory/planner.d.ts.map +0 -1
  493. package/dist/memory/planner.js +0 -108
  494. package/dist/memory/planner.js.map +0 -1
  495. package/dist/memory/targets.d.ts +0 -78
  496. package/dist/memory/targets.d.ts.map +0 -1
  497. package/dist/memory/targets.js +0 -29
  498. package/dist/memory/targets.js.map +0 -1
  499. package/dist/memory/transforms.d.ts +0 -19
  500. package/dist/memory/transforms.d.ts.map +0 -1
  501. package/dist/memory/transforms.js +0 -14
  502. package/dist/memory/transforms.js.map +0 -1
  503. package/dist/modes/matrix.d.ts +0 -23
  504. package/dist/modes/matrix.d.ts.map +0 -1
  505. package/dist/modes/matrix.js +0 -18
  506. package/dist/modes/matrix.js.map +0 -1
  507. package/dist/modes/modes.d.ts +0 -33
  508. package/dist/modes/modes.d.ts.map +0 -1
  509. package/dist/modes/modes.js +0 -15
  510. package/dist/modes/modes.js.map +0 -1
  511. package/dist/modes/resolve.d.ts +0 -96
  512. package/dist/modes/resolve.d.ts.map +0 -1
  513. package/dist/modes/resolve.js +0 -48
  514. package/dist/modes/resolve.js.map +0 -1
  515. package/dist/observability/metrics.d.ts +0 -14
  516. package/dist/observability/metrics.d.ts.map +0 -1
  517. package/dist/observability/metrics.js +0 -18
  518. package/dist/observability/metrics.js.map +0 -1
  519. package/dist/packager/manifest.d.ts +0 -66
  520. package/dist/packager/manifest.d.ts.map +0 -1
  521. package/dist/packager/manifest.js +0 -94
  522. package/dist/packager/manifest.js.map +0 -1
  523. package/dist/packager/publish.d.ts +0 -51
  524. package/dist/packager/publish.d.ts.map +0 -1
  525. package/dist/packager/publish.js +0 -18
  526. package/dist/packager/publish.js.map +0 -1
  527. package/dist/packager/targetcli.d.ts +0 -7
  528. package/dist/packager/targetcli.d.ts.map +0 -1
  529. package/dist/packager/targetcli.js +0 -22
  530. package/dist/packager/targetcli.js.map +0 -1
  531. package/dist/persistence/adapter.d.ts +0 -5
  532. package/dist/persistence/adapter.d.ts.map +0 -1
  533. package/dist/persistence/adapter.js +0 -11
  534. package/dist/persistence/adapter.js.map +0 -1
  535. package/dist/persistence/drizzle.d.ts +0 -2
  536. package/dist/persistence/drizzle.d.ts.map +0 -1
  537. package/dist/persistence/drizzle.js +0 -12
  538. package/dist/persistence/drizzle.js.map +0 -1
  539. package/dist/persistence/memory.d.ts +0 -2
  540. package/dist/persistence/memory.d.ts.map +0 -1
  541. package/dist/persistence/memory.js +0 -27
  542. package/dist/persistence/memory.js.map +0 -1
  543. package/dist/persistence/migrations.d.ts +0 -19
  544. package/dist/persistence/migrations.d.ts.map +0 -1
  545. package/dist/persistence/migrations.js +0 -13
  546. package/dist/persistence/migrations.js.map +0 -1
  547. package/dist/persistence/prisma.d.ts +0 -2
  548. package/dist/persistence/prisma.d.ts.map +0 -1
  549. package/dist/persistence/prisma.js +0 -25
  550. package/dist/persistence/prisma.js.map +0 -1
  551. package/dist/persistence/schema.d.ts +0 -63
  552. package/dist/persistence/schema.d.ts.map +0 -1
  553. package/dist/persistence/schema.js +0 -28
  554. package/dist/persistence/schema.js.map +0 -1
  555. package/dist/persistence/sql.d.ts +0 -3
  556. package/dist/persistence/sql.d.ts.map +0 -1
  557. package/dist/persistence/sql.js +0 -37
  558. package/dist/persistence/sql.js.map +0 -1
  559. package/dist/protocol/blocks.d.ts +0 -10
  560. package/dist/protocol/blocks.d.ts.map +0 -1
  561. package/dist/protocol/blocks.js +0 -26
  562. package/dist/protocol/blocks.js.map +0 -1
  563. package/dist/protocol/json.d.ts +0 -6
  564. package/dist/protocol/json.d.ts.map +0 -1
  565. package/dist/protocol/json.js +0 -6
  566. package/dist/protocol/json.js.map +0 -1
  567. package/dist/protocol/ndjson.d.ts +0 -3
  568. package/dist/protocol/ndjson.d.ts.map +0 -1
  569. package/dist/protocol/ndjson.js +0 -20
  570. package/dist/protocol/ndjson.js.map +0 -1
  571. package/dist/protocol/sse.d.ts +0 -7
  572. package/dist/protocol/sse.d.ts.map +0 -1
  573. package/dist/protocol/sse.js +0 -25
  574. package/dist/protocol/sse.js.map +0 -1
  575. package/dist/proxy/pool.d.ts +0 -9
  576. package/dist/proxy/pool.d.ts.map +0 -1
  577. package/dist/proxy/pool.js +0 -27
  578. package/dist/proxy/pool.js.map +0 -1
  579. package/dist/queue/idempotency.d.ts +0 -10
  580. package/dist/queue/idempotency.d.ts.map +0 -1
  581. package/dist/queue/idempotency.js +0 -13
  582. package/dist/queue/idempotency.js.map +0 -1
  583. package/dist/queue/persistent.d.ts +0 -14
  584. package/dist/queue/persistent.d.ts.map +0 -1
  585. package/dist/queue/persistent.js +0 -66
  586. package/dist/queue/persistent.js.map +0 -1
  587. package/dist/queue/queue.d.ts +0 -7
  588. package/dist/queue/queue.d.ts.map +0 -1
  589. package/dist/queue/queue.js +0 -55
  590. package/dist/queue/queue.js.map +0 -1
  591. package/dist/queue/saga.d.ts +0 -5
  592. package/dist/queue/saga.d.ts.map +0 -1
  593. package/dist/queue/saga.js +0 -20
  594. package/dist/queue/saga.js.map +0 -1
  595. package/dist/release/assets.d.ts +0 -144
  596. package/dist/release/assets.d.ts.map +0 -1
  597. package/dist/release/assets.js +0 -157
  598. package/dist/release/assets.js.map +0 -1
  599. package/dist/release/evidence.d.ts +0 -92
  600. package/dist/release/evidence.d.ts.map +0 -1
  601. package/dist/release/evidence.js +0 -148
  602. package/dist/release/evidence.js.map +0 -1
  603. package/dist/release/verify.d.ts +0 -12
  604. package/dist/release/verify.d.ts.map +0 -1
  605. package/dist/release/verify.js +0 -112
  606. package/dist/release/verify.js.map +0 -1
  607. package/dist/runners/chain.d.ts +0 -125
  608. package/dist/runners/chain.d.ts.map +0 -1
  609. package/dist/runners/chain.js +0 -95
  610. package/dist/runners/chain.js.map +0 -1
  611. package/dist/runners/health.d.ts +0 -36
  612. package/dist/runners/health.d.ts.map +0 -1
  613. package/dist/runners/health.js +0 -26
  614. package/dist/runners/health.js.map +0 -1
  615. package/dist/runners/heartbeat.d.ts +0 -23
  616. package/dist/runners/heartbeat.d.ts.map +0 -1
  617. package/dist/runners/heartbeat.js +0 -29
  618. package/dist/runners/heartbeat.js.map +0 -1
  619. package/dist/runners/inprocess.d.ts +0 -17
  620. package/dist/runners/inprocess.d.ts.map +0 -1
  621. package/dist/runners/inprocess.js +0 -20
  622. package/dist/runners/inprocess.js.map +0 -1
  623. package/dist/runners/scheduler.d.ts +0 -5
  624. package/dist/runners/scheduler.d.ts.map +0 -1
  625. package/dist/runners/scheduler.js +0 -19
  626. package/dist/runners/scheduler.js.map +0 -1
  627. package/dist/runtime/abort.d.ts +0 -8
  628. package/dist/runtime/abort.d.ts.map +0 -1
  629. package/dist/runtime/abort.js +0 -13
  630. package/dist/runtime/abort.js.map +0 -1
  631. package/dist/runtime/compatibility.d.ts +0 -37
  632. package/dist/runtime/compatibility.d.ts.map +0 -1
  633. package/dist/runtime/compatibility.js +0 -10
  634. package/dist/runtime/compatibility.js.map +0 -1
  635. package/dist/runtime/detect.d.ts +0 -13
  636. package/dist/runtime/detect.d.ts.map +0 -1
  637. package/dist/runtime/detect.js +0 -18
  638. package/dist/runtime/detect.js.map +0 -1
  639. package/dist/runtime/engine.d.ts +0 -20
  640. package/dist/runtime/engine.d.ts.map +0 -1
  641. package/dist/runtime/engine.js +0 -61
  642. package/dist/runtime/engine.js.map +0 -1
  643. package/dist/runtime/retry.d.ts +0 -19
  644. package/dist/runtime/retry.d.ts.map +0 -1
  645. package/dist/runtime/retry.js +0 -54
  646. package/dist/runtime/retry.js.map +0 -1
  647. package/dist/runtime/worker.d.ts +0 -10
  648. package/dist/runtime/worker.d.ts.map +0 -1
  649. package/dist/runtime/worker.js +0 -25
  650. package/dist/runtime/worker.js.map +0 -1
  651. package/dist/scrape/cache.d.ts +0 -45
  652. package/dist/scrape/cache.d.ts.map +0 -1
  653. package/dist/scrape/cache.js +0 -45
  654. package/dist/scrape/cache.js.map +0 -1
  655. package/dist/scrape/crawl.d.ts +0 -47
  656. package/dist/scrape/crawl.d.ts.map +0 -1
  657. package/dist/scrape/crawl.js +0 -114
  658. package/dist/scrape/crawl.js.map +0 -1
  659. package/dist/scrape/extract.d.ts +0 -63
  660. package/dist/scrape/extract.d.ts.map +0 -1
  661. package/dist/scrape/extract.js +0 -47
  662. package/dist/scrape/extract.js.map +0 -1
  663. package/dist/scrape/normalize.d.ts +0 -52
  664. package/dist/scrape/normalize.d.ts.map +0 -1
  665. package/dist/scrape/normalize.js +0 -102
  666. package/dist/scrape/normalize.js.map +0 -1
  667. package/dist/scrape/robots.d.ts +0 -37
  668. package/dist/scrape/robots.d.ts.map +0 -1
  669. package/dist/scrape/robots.js +0 -71
  670. package/dist/scrape/robots.js.map +0 -1
  671. package/dist/scrape/schema.d.ts +0 -23
  672. package/dist/scrape/schema.d.ts.map +0 -1
  673. package/dist/scrape/schema.js +0 -92
  674. package/dist/scrape/schema.js.map +0 -1
  675. package/dist/scrape/scraper.d.ts +0 -6
  676. package/dist/scrape/scraper.d.ts.map +0 -1
  677. package/dist/scrape/scraper.js +0 -46
  678. package/dist/scrape/scraper.js.map +0 -1
  679. package/dist/scrape/semantic.d.ts +0 -25
  680. package/dist/scrape/semantic.d.ts.map +0 -1
  681. package/dist/scrape/semantic.js +0 -27
  682. package/dist/scrape/semantic.js.map +0 -1
  683. package/dist/server/node.d.ts +0 -7
  684. package/dist/server/node.d.ts.map +0 -1
  685. package/dist/server/node.js.map +0 -1
  686. package/dist/sessions/file.d.ts +0 -25
  687. package/dist/sessions/file.d.ts.map +0 -1
  688. package/dist/sessions/file.js +0 -13
  689. package/dist/sessions/file.js.map +0 -1
  690. package/dist/sessions/replay.d.ts +0 -9
  691. package/dist/sessions/replay.d.ts.map +0 -1
  692. package/dist/sessions/replay.js +0 -70
  693. package/dist/sessions/replay.js.map +0 -1
  694. package/dist/sessions/store.d.ts +0 -25
  695. package/dist/sessions/store.d.ts.map +0 -1
  696. package/dist/sessions/store.js +0 -13
  697. package/dist/sessions/store.js.map +0 -1
  698. package/dist/storage/adapter.d.ts +0 -5
  699. package/dist/storage/adapter.d.ts.map +0 -1
  700. package/dist/storage/adapter.js +0 -11
  701. package/dist/storage/adapter.js.map +0 -1
  702. package/dist/storage/cache.d.ts +0 -23
  703. package/dist/storage/cache.d.ts.map +0 -1
  704. package/dist/storage/cache.js +0 -79
  705. package/dist/storage/cache.js.map +0 -1
  706. package/dist/storage/checksum.d.ts +0 -3
  707. package/dist/storage/checksum.d.ts.map +0 -1
  708. package/dist/storage/checksum.js +0 -19
  709. package/dist/storage/checksum.js.map +0 -1
  710. package/dist/storage/chunked.d.ts +0 -21
  711. package/dist/storage/chunked.d.ts.map +0 -1
  712. package/dist/storage/chunked.js +0 -67
  713. package/dist/storage/chunked.js.map +0 -1
  714. package/dist/storage/content.d.ts +0 -24
  715. package/dist/storage/content.d.ts.map +0 -1
  716. package/dist/storage/content.js +0 -44
  717. package/dist/storage/content.js.map +0 -1
  718. package/dist/storage/filehosting.d.ts +0 -2
  719. package/dist/storage/filehosting.d.ts.map +0 -1
  720. package/dist/storage/filehosting.js +0 -24
  721. package/dist/storage/filehosting.js.map +0 -1
  722. package/dist/storage/githubcontents.d.ts +0 -2
  723. package/dist/storage/githubcontents.d.ts.map +0 -1
  724. package/dist/storage/githubcontents.js +0 -29
  725. package/dist/storage/githubcontents.js.map +0 -1
  726. package/dist/storage/index.d.ts +0 -12
  727. package/dist/storage/index.d.ts.map +0 -1
  728. package/dist/storage/index.js +0 -12
  729. package/dist/storage/index.js.map +0 -1
  730. package/dist/storage/local.d.ts +0 -2
  731. package/dist/storage/local.d.ts.map +0 -1
  732. package/dist/storage/local.js +0 -72
  733. package/dist/storage/local.js.map +0 -1
  734. package/dist/storage/memory.d.ts +0 -6
  735. package/dist/storage/memory.d.ts.map +0 -1
  736. package/dist/storage/memory.js +0 -36
  737. package/dist/storage/memory.js.map +0 -1
  738. package/dist/storage/pool.d.ts +0 -95
  739. package/dist/storage/pool.d.ts.map +0 -1
  740. package/dist/storage/pool.js +0 -202
  741. package/dist/storage/pool.js.map +0 -1
  742. package/dist/storage/s3compatible.d.ts +0 -3
  743. package/dist/storage/s3compatible.d.ts.map +0 -1
  744. package/dist/storage/s3compatible.js +0 -70
  745. package/dist/storage/s3compatible.js.map +0 -1
  746. package/dist/storage/sync.d.ts +0 -47
  747. package/dist/storage/sync.d.ts.map +0 -1
  748. package/dist/storage/sync.js +0 -75
  749. package/dist/storage/sync.js.map +0 -1
  750. package/dist/surfaces/adapters.d.ts +0 -97
  751. package/dist/surfaces/adapters.d.ts.map +0 -1
  752. package/dist/surfaces/adapters.js +0 -50
  753. package/dist/surfaces/adapters.js.map +0 -1
  754. package/dist/surfaces/controls.d.ts +0 -18
  755. package/dist/surfaces/controls.d.ts.map +0 -1
  756. package/dist/surfaces/controls.js +0 -45
  757. package/dist/surfaces/controls.js.map +0 -1
  758. package/dist/surfaces/manifest.d.ts +0 -68
  759. package/dist/surfaces/manifest.d.ts.map +0 -1
  760. package/dist/surfaces/manifest.js +0 -42
  761. package/dist/surfaces/manifest.js.map +0 -1
  762. package/dist/surfaces/n8n.d.ts +0 -25
  763. package/dist/surfaces/n8n.d.ts.map +0 -1
  764. package/dist/surfaces/n8n.js +0 -31
  765. package/dist/surfaces/n8n.js.map +0 -1
  766. package/dist/surfaces/operations.d.ts +0 -32
  767. package/dist/surfaces/operations.d.ts.map +0 -1
  768. package/dist/surfaces/operations.js +0 -53
  769. package/dist/surfaces/operations.js.map +0 -1
  770. package/dist/surfaces/requirements.d.ts +0 -29
  771. package/dist/surfaces/requirements.d.ts.map +0 -1
  772. package/dist/surfaces/requirements.js +0 -50
  773. package/dist/surfaces/requirements.js.map +0 -1
  774. package/dist/surfaces/targets.d.ts +0 -196
  775. package/dist/surfaces/targets.d.ts.map +0 -1
  776. package/dist/surfaces/targets.js +0 -27
  777. package/dist/surfaces/targets.js.map +0 -1
  778. package/dist/webhook/delivery.d.ts +0 -18
  779. package/dist/webhook/delivery.d.ts.map +0 -1
  780. package/dist/webhook/delivery.js +0 -36
  781. package/dist/webhook/delivery.js.map +0 -1
  782. package/dist/webhook/receiver.d.ts +0 -26
  783. package/dist/webhook/receiver.d.ts.map +0 -1
  784. package/dist/webhook/receiver.js +0 -24
  785. package/dist/webhook/receiver.js.map +0 -1
  786. package/dist/webhook/signature.d.ts +0 -3
  787. package/dist/webhook/signature.d.ts.map +0 -1
  788. package/dist/webhook/signature.js +0 -7
  789. package/dist/webhook/signature.js.map +0 -1
  790. package/dist/workflow/manifest.d.ts +0 -22
  791. package/dist/workflow/manifest.d.ts.map +0 -1
  792. package/dist/workflow/manifest.js +0 -21
  793. package/dist/workflow/manifest.js.map +0 -1
  794. package/dist/workflow/registry.d.ts +0 -7
  795. package/dist/workflow/registry.d.ts.map +0 -1
  796. package/dist/workflow/registry.js +0 -18
  797. package/dist/workflow/registry.js.map +0 -1
  798. package/dist/workflow/templates.d.ts +0 -6
  799. package/dist/workflow/templates.d.ts.map +0 -1
  800. package/dist/workflow/templates.js +0 -18
  801. package/dist/workflow/templates.js.map +0 -1
  802. package/dist/workflow/triggers.d.ts +0 -64
  803. package/dist/workflow/triggers.d.ts.map +0 -1
  804. package/dist/workflow/triggers.js +0 -99
  805. package/dist/workflow/triggers.js.map +0 -1
  806. package/docs/logs/.gitkeep +0 -0
  807. package/docs/plans/00.index.md +0 -50
  808. package/docs/plans/01.architecture.md +0 -86
  809. package/docs/plans/02.research.computer.use.md +0 -58
  810. package/docs/plans/03.research.captcha.bypass.md +0 -68
  811. package/docs/plans/04.research.sandbox.ai.md +0 -52
  812. package/docs/plans/05.capture.platform.md +0 -57
  813. package/docs/plans/06.dependencies.md +0 -97
  814. package/docs/plans/07.captcha.test.page.md +0 -41
  815. package/docs/plans/08.production.infra.md +0 -70
  816. package/docs/plans/09.database.schema.md +0 -121
  817. package/docs/plans/10.cloudinary.storage.md +0 -57
  818. package/docs/plans/11.movement.logs.json.md +0 -72
  819. package/docs/plans/12.research.atlas.agent.browser.md +0 -79
  820. package/docs/plans/13.research.anti.detection.md +0 -898
  821. package/docs/plans/14.research.proxy.md +0 -1495
  822. package/docs/plans/15.research.retry.rate.limit.md +0 -1958
  823. package/docs/plans/16.research.crawling.md +0 -1417
  824. package/docs/plans/17.research.caching.md +0 -1610
  825. package/docs/plans/18.research.content.extraction.md +0 -1952
  826. package/docs/plans/19.research.errors.events.md +0 -1523
  827. package/docs/plans/20.research.zod.validation.md +0 -1350
  828. package/docs/plans/21.research.batch.concurrency.md +0 -1888
  829. package/docs/plans/22.research.universal.runtime.md +0 -944
  830. package/docs/plans/23.research.ai.integration.md +0 -1465
  831. package/docs/plans/24.research.memory.persistence.md +0 -1979
  832. package/docs/plans/25.research.server.api.md +0 -342
  833. package/docs/plans/26.research.compilation.md +0 -249
  834. package/docs/plans/27.research.html.parsing.md +0 -251
  835. package/docs/plans/28.action.plan.md +0 -50
  836. package/docs/plans/29.api.reference.md +0 -174
  837. package/docs/plans/30.architecture.plan.md +0 -94
  838. package/docs/plans/31.auditoria.dados.md +0 -163
  839. package/docs/plans/32.bots.automacao.computacional.md +0 -214
  840. package/docs/plans/33.bots.codigo.revisao.md +0 -220
  841. package/docs/plans/34.bots.seguranca.cicd.md +0 -366
  842. package/docs/plans/35.comparativo.concorrencia.md +0 -464
  843. package/docs/plans/36.computational.memory.md +0 -340
  844. package/docs/plans/37.deploystrategy.md +0 -394
  845. package/docs/plans/38.flow.md +0 -155
  846. package/docs/plans/39.multi.platform.bot.md +0 -252
  847. package/docs/plans/40.npm.publish.md +0 -250
  848. package/docs/plans/41.o.que.falta.md +0 -407
  849. package/docs/plans/42.pesquisa.concorrencia.md +0 -721
  850. package/docs/plans/43.plan.universal.architecture.md +0 -496
  851. package/docs/plans/44.reference.md +0 -100
  852. package/docs/plans/45.robotarchitecture.md +0 -237
  853. package/docs/plans/46.scdnintegration.md +0 -284
  854. package/docs/plans/47.multiforge.readme.md +0 -129
  855. package/docs/plans/48.theory.v4.repo.os.md +0 -152
  856. package/docs/plans/49.third.party.infra.md +0 -12
  857. package/docs/plans/50.file.as.compute.md +0 -39
  858. package/docs/plans/51.architecture.virtual.processor.md +0 -80
  859. package/docs/plans/52.manifesto.v8.md +0 -11
  860. package/docs/plans/58.cdn.list.md +0 -23
  861. package/docs/plans/59.sql.frameworks.md +0 -33
  862. package/docs/plans/60.sql.thirdparty.md +0 -26
  863. package/docs/plans/61.objective.multiforge.md +0 -63
  864. package/docs/plans/62.huggingface.upload.md +0 -26
  865. package/docs/plans/63.kaggle.upload.md +0 -24
  866. package/docs/plans/64.npm.storage.md +0 -30
  867. package/docs/plans/65.rclone.terabox.md +0 -32
  868. package/docs/plans/66.buckets.and.models.todo.md +0 -14
  869. package/docs/plans/67.database.todo.md +0 -13
  870. package/docs/plans/68.deploy.packages.todo.md +0 -12
  871. package/docs/plans/69.report.human.operator.md +0 -133
  872. package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
  873. package/docs/plans/71.report.hd.infinito.vram.md +0 -155
  874. package/docs/plans/72.plan.hd.infinito.node.md +0 -146
  875. package/docs/plans/73.plan.scifi.repos.md +0 -125
  876. package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
  877. package/docs/plans/README.md +0 -489
  878. package/docs/plans/aggregate_platforms.mjs +0 -146
  879. package/docs/plans/examplesession.json +0 -36
  880. package/docs/plans/missing-facts.md +0 -192
  881. package/docs/plans/models.md +0 -64
  882. package/docs/plans/organize.cjs +0 -270
  883. package/docs/plans/platforms.md +0 -2887
  884. package/docs/plans/sites.md +0 -31322
  885. package/docs/sources/farm.py +0 -117
  886. package/docs/sources/html/saddle1.html +0 -132
  887. package/docs/sources/html/saddle2.html +0 -157
  888. package/docs/sources/html/saddle3.html +0 -119
  889. package/docs/sources/html/saddle4.html +0 -144
  890. package/docs/sources/html/saddle5.html +0 -72
  891. package/docs/sources/html/saddle6.html +0 -171
  892. package/docs/sources/html/saddle7.html +0 -236
  893. package/docs/sources/saddle.ts +0 -74
  894. package/docs/sources/schema.prisma +0 -88
  895. package/docs/sources/script.sh +0 -64
  896. package/docs/sources/workflows.yml +0 -458
  897. package/docs/talks1/_body.txt +0 -14
  898. package/docs/talks1/_index.md +0 -15
  899. package/docs/talks1/_screenshot.png +0 -0
  900. package/docs/talks1/assistant-01.md +0 -5
  901. package/docs/talks1/assistant-02.md +0 -5
  902. package/docs/talks1/assistant-03.md +0 -531
  903. package/docs/talks1/assistant-04.md +0 -26
  904. package/docs/talks1/assistant-05.md +0 -774
  905. package/docs/talks1/assistant-06.md +0 -1718
  906. package/docs/talks1/scrape-share.cjs +0 -185
  907. package/docs/talks1/scrape-share.ts +0 -183
  908. package/docs/talks1/user-01.md +0 -3
  909. package/docs/talks1/user-02.md +0 -3
  910. package/docs/talks1/user-03.md +0 -88
  911. package/docs/talks1/user-04.md +0 -3
  912. package/docs/talks1/user-05.md +0 -3
  913. package/docs/talks1/user-06.md +0 -88
  914. package/docs/talks1/user-07.md +0 -88
  915. package/docs/talks2/_body.txt +0 -14
  916. package/docs/talks2/_index.md +0 -16
  917. package/docs/talks2/_screenshot.png +0 -0
  918. package/docs/talks2/assistant-01.md +0 -5
  919. package/docs/talks2/assistant-02.md +0 -5
  920. package/docs/talks2/assistant-03.md +0 -424
  921. package/docs/talks2/assistant-04.md +0 -598
  922. package/docs/talks2/assistant-05.md +0 -1280
  923. package/docs/talks2/assistant-06.md +0 -1227
  924. package/docs/talks2/assistant-07.md +0 -1252
  925. package/docs/talks2/user-01.md +0 -3
  926. package/docs/talks2/user-02.md +0 -3
  927. package/docs/talks2/user-03.md +0 -88
  928. package/docs/talks2/user-04.md +0 -88
  929. package/docs/talks2/user-05.md +0 -88
  930. package/docs/talks2/user-06.md +0 -88
  931. package/docs/talks2/user-07.md +0 -3
  932. package/docs/talks3/_body.txt +0 -467
  933. package/docs/talks3/_index.md +0 -10
  934. package/docs/talks3/_screenshot.png +0 -0
  935. package/docs/talks3/assistant-01.md +0 -417
  936. package/docs/talks3/assistant-02.md +0 -417
  937. package/docs/talks3/assistant-03.md +0 -29
  938. package/docs/talks3/assistant-04.md +0 -727
  939. package/docs/talks3/user-01.md +0 -88
  940. package/docs/talks3/user-02.md +0 -88
  941. package/docs/talks3/user-03.md +0 -3
  942. package/docs/talks3/user-04.md +0 -3
  943. package/docs/talks4/_body.txt +0 -14
  944. package/docs/talks4/_index.md +0 -12
  945. package/docs/talks4/_screenshot.png +0 -0
  946. package/docs/talks4/assistant-01.md +0 -5
  947. package/docs/talks4/assistant-02.md +0 -5
  948. package/docs/talks4/assistant-03.md +0 -35
  949. package/docs/talks4/assistant-04.md +0 -512
  950. package/docs/talks4/assistant-05.md +0 -599
  951. package/docs/talks4/user-01.md +0 -3
  952. package/docs/talks4/user-02.md +0 -3
  953. package/docs/talks4/user-03.md +0 -88
  954. package/docs/talks4/user-04.md +0 -88
  955. package/docs/talks4/user-05.md +0 -7
  956. package/docs/talks5/_body.txt +0 -14
  957. package/docs/talks5/_index.md +0 -13
  958. package/docs/talks5/_screenshot.png +0 -0
  959. package/docs/talks5/assistant-01.md +0 -5
  960. package/docs/talks5/assistant-02.md +0 -5
  961. package/docs/talks5/assistant-03.md +0 -690
  962. package/docs/talks5/assistant-04.md +0 -758
  963. package/docs/talks5/assistant-05.md +0 -974
  964. package/docs/talks5/user-01.md +0 -3
  965. package/docs/talks5/user-02.md +0 -3
  966. package/docs/talks5/user-03.md +0 -105
  967. package/docs/talks5/user-04.md +0 -105
  968. package/docs/talks5/user-05.md +0 -63
  969. package/docs/talks5/user-06.md +0 -105
  970. package/docs/talks6/_body.txt +0 -14
  971. package/docs/talks6/_index.md +0 -9
  972. package/docs/talks6/_screenshot.png +0 -0
  973. package/docs/talks6/assistant-01.md +0 -5
  974. package/docs/talks6/assistant-02.md +0 -5
  975. package/docs/talks6/assistant-03.md +0 -1499
  976. package/docs/talks6/user-01.md +0 -3
  977. package/docs/talks6/user-02.md +0 -3
  978. package/docs/talks6/user-03.md +0 -88
  979. package/docs/talks6/user-04.md +0 -88
  980. package/docs/talks7/_body.txt +0 -14
  981. package/docs/talks7/_index.md +0 -10
  982. package/docs/talks7/_screenshot.png +0 -0
  983. package/docs/talks7/assistant-01.md +0 -5
  984. package/docs/talks7/assistant-02.md +0 -5
  985. package/docs/talks7/assistant-03.md +0 -523
  986. package/docs/talks7/assistant-04.md +0 -617
  987. package/docs/talks7/user-01.md +0 -3
  988. package/docs/talks7/user-02.md +0 -3
  989. package/docs/talks7/user-03.md +0 -105
  990. package/docs/talks7/user-04.md +0 -67
  991. package/docs/talks8/conversa1.txt +0 -1322
  992. package/docs/talks8/conversa2.txt +0 -237
  993. package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +0 -174
  994. package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +0 -59
  995. package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +0 -91
  996. package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +0 -116
  997. package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +0 -128
  998. package/docs/talks9/README (2).md +0 -489
  999. package/docs/talks9/README.md +0 -198
  1000. package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +0 -80
  1001. package/docs/talks9/conversa.txt +0 -544
  1002. package/docs/talks9/other (2).md +0 -39
  1003. package/docs/talks9/other.md +0 -57
  1004. package/docs/talks9/outro.txt +0 -24
  1005. /package/{extension/README.md → docs/extension.md} +0 -0
@@ -1,1952 +0,0 @@
1
- # Pesquisa: Content Extraction Avançada (2026)
2
-
3
- ## Table of Contents
4
-
5
- - [Visão Geral](#visão-geral)
6
- - [JSON-LD Extraction](#json-ld-extraction)
7
- - [Microdata Extraction](#microdata-extraction)
8
- - [OpenGraph / Twitter Card](#opengraph--twitter-card)
9
- - [RSS/Atom Feeds](#rssatom-feeds)
10
- - [Breadcrumb Extraction](#breadcrumb-extraction)
11
- - [Readable Content Extraction](#readable-content-extraction)
12
- - [HTML-to-Markdown](#html-to-markdown)
13
- - [Content Detection Heuristics](#content-detection-heuristics)
14
- - [API Interception Pattern](#api-interception-pattern)
15
- - [Structured Data First Approach](#structured-data-first-approach)
16
- - [Código Completo](#código-completo)
17
-
18
- ---
19
-
20
- ## Visão Geral
21
-
22
- Content extraction é o processo de extrair dados estruturados e legíveis de HTML cru. Em 2026, a abordagem recomendada é **Structured Data First**: priorizar dados estruturados (JSON-LD, Microdata, OpenGraph) sobre extração de HTML bruto.
23
-
24
- ### Prioridade de Extração
25
-
26
- ```
27
- 1. JSON-LD → Dados estruturados mais completos e padronizados
28
- 2. Microdata → Schema.org inline (mais verboso que JSON-LD)
29
- 3. OpenGraph/Twitter → Metadados de social sharing
30
- 4. RSS/Atom → Feeds de conteúdo
31
- 5. HTML Readable → Conteúdo principal legível (Readability)
32
- 6. HTML Raw → Extração via seletores CSS
33
- ```
34
-
35
- ### Bibliotecas Principais (2026)
36
-
37
- | Biblioteca | Versão | Uso |
38
- |---|---|---|
39
- | `cheerio` | 1.2.0 | Parsing HTML (jQuery-like) |
40
- | `@mozilla/readability` | 0.6.0 | Extração de conteúdo legível |
41
- | `turndown` | 7.2.4 | HTML → Markdown |
42
- | `node-html-markdown` | 2.0.0 | HTML → Markdown (mais rápido) |
43
- | `mdream` | 0.x | HTML → Markdown (Rust, 33x mais rápido) |
44
- | `open-graph-scraper` | 6.11.0 | Extração OpenGraph |
45
- | `feedsmith` | 2.x | Parsing RSS/Atom |
46
- | `rss-parser` | 3.13.0 | Parsing RSS/Atom |
47
- | `rss-finder` | 2.1.5 | Descoberta de feeds |
48
-
49
- ---
50
-
51
- ## JSON-LD Extraction
52
-
53
- ### Conceito
54
-
55
- JSON-LD (JSON for Linked Data) é o formato preferido para dados estruturados. Google, Bing e outros motores de busca priorizam JSON-LD sobre Microdata.
56
-
57
- ### Estrutura JSON-LD
58
-
59
- ```json
60
- {
61
- "@context": "https://schema.org",
62
- "@type": "Article",
63
- "headline": "Como Criar um Web Scraper",
64
- "author": {
65
- "@type": "Person",
66
- "name": "João Silva"
67
- },
68
- "datePublished": "2026-01-15",
69
- "image": "https://example.com/image.jpg",
70
- "publisher": {
71
- "@type": "Organization",
72
- "name": "DevThink",
73
- "logo": {
74
- "@type": "ImageObject",
75
- "url": "https://example.com/logo.png"
76
- }
77
- }
78
- }
79
- ```
80
-
81
- ### Extração com Cheerio
82
-
83
- ```ts
84
- import * as cheerio from 'cheerio';
85
-
86
- interface JsonLdData {
87
- type: string;
88
- data: Record<string, unknown>;
89
- raw: string;
90
- }
91
-
92
- function extractJsonLd(html: string): JsonLdData[] {
93
- const $ = cheerio.load(html);
94
- const results: JsonLdData[] = [];
95
-
96
- $('script[type="application/ld+json"]').each((_, element) => {
97
- const raw = $(element).html();
98
- if (!raw) return;
99
-
100
- try {
101
- const data = JSON.parse(raw);
102
-
103
- // JSON-LD pode ser um objeto único ou array
104
- if (Array.isArray(data)) {
105
- for (const item of data) {
106
- results.push({
107
- type: item['@type'] ?? 'Unknown',
108
- data: item,
109
- raw: JSON.stringify(item),
110
- });
111
- }
112
- } else {
113
- results.push({
114
- type: data['@type'] ?? 'Unknown',
115
- data,
116
- raw: JSON.stringify(data),
117
- });
118
- }
119
- } catch (error) {
120
- console.error('Erro ao parsear JSON-LD:', error);
121
- }
122
- });
123
-
124
- return results;
125
- }
126
-
127
- // Usar
128
- const jsonLdItems = extractJsonLd(html);
129
- for (const item of jsonLdItems) {
130
- console.log(`Type: ${item.type}`);
131
-
132
- if (item.type === 'Article') {
133
- console.log(`Title: ${item.data.headline}`);
134
- console.log(`Author: ${(item.data.author as any)?.name}`);
135
- console.log(`Date: ${item.data.datePublished}`);
136
- }
137
-
138
- if (item.type === 'Product') {
139
- console.log(`Name: ${item.data.name}`);
140
- console.log(`Price: ${(item.data.offers as any)?.price}`);
141
- }
142
-
143
- if (item.type === 'Organization') {
144
- console.log(`Name: ${item.data.name}`);
145
- }
146
- }
147
- ```
148
-
149
- ### Extração de Tipos Comuns
150
-
151
- ```ts
152
- // Tipos JSON-LD comuns
153
- type JsonLdType =
154
- | 'Article'
155
- | 'NewsArticle'
156
- | 'BlogPosting'
157
- | 'Product'
158
- | 'Organization'
159
- | 'Person'
160
- | 'BreadcrumbList'
161
- | 'FAQPage'
162
- | 'HowTo'
163
- | 'Event'
164
- | 'LocalBusiness'
165
- | 'WebSite'
166
- | 'WebPage';
167
-
168
- function extractJsonLdByType<T = Record<string, unknown>>(
169
- html: string,
170
- type: JsonLdType,
171
- ): T[] {
172
- const items = extractJsonLd(html);
173
- return items
174
- .filter(item => item.type === type)
175
- .map(item => item.data as T);
176
- }
177
-
178
- // Extrair artigo
179
- interface ArticleData {
180
- headline: string;
181
- author: { name: string; url?: string };
182
- datePublished: string;
183
- dateModified?: string;
184
- description?: string;
185
- image?: string | string[];
186
- publisher?: { name: string };
187
- mainEntityOfPage?: string;
188
- }
189
-
190
- const articles = extractJsonLdByType<ArticleData>(html, 'Article');
191
- const article = articles[0];
192
- if (article) {
193
- console.log(`Title: ${article.headline}`);
194
- console.log(`Author: ${article.author.name}`);
195
- console.log(`Published: ${article.datePublished}`);
196
- }
197
-
198
- // Extrair produto
199
- interface ProductData {
200
- name: string;
201
- description?: string;
202
- image?: string | string[];
203
- offers?: {
204
- price: string;
205
- priceCurrency: string;
206
- availability: string;
207
- };
208
- brand?: { name: string };
209
- sku?: string;
210
- aggregateRating?: {
211
- ratingValue: string;
212
- reviewCount: string;
213
- };
214
- }
215
-
216
- const products = extractJsonLdByType<ProductData>(html, 'Product');
217
- ```
218
-
219
- ### JSON-LD Composto (Graph)
220
-
221
- ```ts
222
- // JSON-LD pode ter @graph com múltiplos tipos
223
- const graphJsonLd = {
224
- "@context": "https://schema.org",
225
- "@graph": [
226
- {
227
- "@type": "Organization",
228
- "name": "DevThink",
229
- "url": "https://example.com"
230
- },
231
- {
232
- "@type": "WebSite",
233
- "name": "DevThink Blog",
234
- "url": "https://example.com",
235
- "potentialAction": {
236
- "@type": "SearchAction",
237
- "target": "https://example.com/search?q={search_term_string}"
238
- }
239
- },
240
- {
241
- "@type": "Article",
242
- "headline": "Meu Artigo"
243
- }
244
- ]
245
- };
246
-
247
- function extractFromGraph(html: string): Record<string, unknown>[] {
248
- const $ = cheerio.load(html);
249
- const results: Record<string, unknown>[] = [];
250
-
251
- $('script[type="application/ld+json"]').each((_, element) => {
252
- const raw = $(element).html();
253
- if (!raw) return;
254
-
255
- try {
256
- const data = JSON.parse(raw);
257
-
258
- if (data['@graph']) {
259
- results.push(...data['@graph']);
260
- } else if (data['@type']) {
261
- results.push(data);
262
- }
263
- } catch {}
264
- });
265
-
266
- return results;
267
- }
268
- ```
269
-
270
- ---
271
-
272
- ## Microdata Extraction
273
-
274
- ### Conceito
275
-
276
- Microdata usa atributos HTML (`itemscope`, `itemtype`, `itemprop`) para marcar dados estruturados inline.
277
-
278
- ### Estrutura Microdata
279
-
280
- ```html
281
- <div itemscope itemtype="https://schema.org/Article">
282
- <h1 itemprop="headline">Como Criar um Web Scraper</h1>
283
- <div itemprop="author" itemscope itemtype="https://schema.org/Person">
284
- <span itemprop="name">João Silva</span>
285
- </div>
286
- <time itemprop="datePublished" datetime="2026-01-15">15 de Janeiro, 2026</time>
287
- <img itemprop="image" src="https://example.com/image.jpg" alt="">
288
- <div itemprop="articleBody">
289
- <p>Conteúdo do artigo...</p>
290
- </div>
291
- </div>
292
- ```
293
-
294
- ### Extração com Cheerio
295
-
296
- ```ts
297
- import * as cheerio from 'cheerio';
298
-
299
- interface MicrodataItem {
300
- type: string;
301
- id?: string;
302
- properties: Record<string, string | MicrodataItem[]>;
303
- }
304
-
305
- function extractMicrodata(html: string): MicrodataItem[] {
306
- const $ = cheerio.load(html);
307
- const results: MicrodataItem[] = [];
308
-
309
- $('[itemscope]').each((_, element) => {
310
- const $el = $(element);
311
- const type = $el.attr('itemtype');
312
- const id = $el.attr('itemid');
313
-
314
- if (!type) return;
315
-
316
- const properties: Record<string, string | MicrodataItem[]> = {};
317
-
318
- // Extrair propriedades simples
319
- $el.find('[itemprop]').each((_, prop) => {
320
- const $prop = $(prop);
321
- const name = $prop.attr('itemprop');
322
- if (!name) return;
323
-
324
- // Verificar se é um sub-item
325
- if ($prop.attr('itemscope')) {
326
- const subItems = extractMicrodata($.html($prop));
327
- properties[name] = subItems;
328
- } else {
329
- // Valor pode estar em href, content, src, ou texto
330
- const value = $prop.attr('content')
331
- ?? $prop.attr('href')
332
- ?? $prop.attr('src')
333
- ?? $prop.text().trim();
334
-
335
- properties[name] = value;
336
- }
337
- });
338
-
339
- results.push({ type, id, properties });
340
- });
341
-
342
- return results;
343
- }
344
-
345
- // Usar
346
- const items = extractMicrodata(html);
347
- for (const item of items) {
348
- console.log(`Type: ${item.type}`);
349
- console.log(`Properties:`, item.properties);
350
- }
351
- ```
352
-
353
- ### microdata-minimal (Alternativa)
354
-
355
- ```ts
356
- // Package: microdata-minimal
357
- import { microdata } from 'microdata-minimal';
358
-
359
- const items = microdata(html);
360
- console.log(items);
361
- // → [{ type: 'https://schema.org/Article', properties: { headline: '...' } }]
362
- ```
363
-
364
- ### Microdata vs JSON-LD
365
-
366
- | Característica | Microdata | JSON-LD |
367
- |---|---|---|
368
- | Localização | Inline no HTML | Bloco `<script>` separado |
369
- | Verbosidade | Alta (atributos em cada elemento) | Baixa (objeto JSON) |
370
- | Legibilidade | Baixa | Alta |
371
- | Google Priority | 2º | 1º |
372
- | Mantimento | Difícil (acoplado ao HTML) | Fácil (bloco separado) |
373
- | Suporte a @graph | ❌ | ✅ |
374
-
375
- ---
376
-
377
- ## OpenGraph / Twitter Card
378
-
379
- ### Conceito
380
-
381
- OpenGraph (OG) e Twitter Card são metadados usados para social sharing. Menos completos que JSON-LD, mas universalmente suportados.
382
-
383
- ### Tags OpenGraph Comuns
384
-
385
- ```html
386
- <!-- OpenGraph -->
387
- <meta property="og:title" content="Título da Página">
388
- <meta property="og:description" content="Descrição da Página">
389
- <meta property="og:image" content="https://example.com/image.jpg">
390
- <meta property="og:url" content="https://example.com/page">
391
- <meta property="og:type" content="article">
392
- <meta property="og:site_name" content="DevThink">
393
- <meta property="og:locale" content="pt_BR">
394
- <meta property="og:image:width" content="1200">
395
- <meta property="og:image:height" content="630">
396
-
397
- <!-- Twitter Card -->
398
- <meta name="twitter:card" content="summary_large_image">
399
- <meta name="twitter:site" content="@wenathlan">
400
- <meta name="twitter:creator" content="@nasblor">
401
- <meta name="twitter:title" content="Título da Página">
402
- <meta name="twitter:description" content="Descrição da Página">
403
- <meta name="twitter:image" content="https://example.com/image.jpg">
404
- ```
405
-
406
- ### Extração com Cheerio
407
-
408
- ```ts
409
- import * as cheerio from 'cheerio';
410
-
411
- interface OpenGraphData {
412
- title?: string;
413
- description?: string;
414
- image?: string;
415
- url?: string;
416
- type?: string;
417
- siteName?: string;
418
- locale?: string;
419
- imageWidth?: string;
420
- imageHeight?: string;
421
- }
422
-
423
- interface TwitterCardData {
424
- card?: string;
425
- site?: string;
426
- creator?: string;
427
- title?: string;
428
- description?: string;
429
- image?: string;
430
- }
431
-
432
- interface SocialMeta {
433
- openGraph: OpenGraphData;
434
- twitter: TwitterCardData;
435
- }
436
-
437
- function extractSocialMeta(html: string): SocialMeta {
438
- const $ = cheerio.load(html);
439
-
440
- const openGraph: OpenGraphData = {};
441
- const twitter: TwitterCardData = {};
442
-
443
- // OpenGraph
444
- $('meta[property^="og:"]').each((_, element) => {
445
- const property = $(element).attr('property')?.replace('og:', '');
446
- const content = $(element).attr('content');
447
- if (property && content) {
448
- (openGraph as any)[property] = content;
449
- }
450
- });
451
-
452
- // Twitter Card
453
- $('meta[name^="twitter:"]').each((_, element) => {
454
- const name = $(element).attr('name')?.replace('twitter:', '');
455
- const content = $(element).attr('content');
456
- if (name && content) {
457
- (twitter as any)[name] = content;
458
- }
459
- });
460
-
461
- return { openGraph, twitter };
462
- }
463
-
464
- // Usar
465
- const social = extractSocialMeta(html);
466
- console.log(social.openGraph.title);
467
- console.log(social.twitter.card);
468
- ```
469
-
470
- ### open-graph-scraper 6.11.0
471
-
472
- ```ts
473
- import og from 'open-graph-scraper';
474
-
475
- const options = {
476
- url: 'https://example.com',
477
- };
478
-
479
- const result = await og(options);
480
- if (result.success) {
481
- const { ogTitle, ogDescription, ogImage, ogUrl, ogType } = result.result;
482
- console.log(`Title: ${ogTitle}`);
483
- console.log(`Description: ${ogDescription}`);
484
- console.log(`Image: ${ogImage}`);
485
- }
486
- ```
487
-
488
- ### ogie (Mais Moderno)
489
-
490
- ```ts
491
- import ogie from 'ogie';
492
-
493
- const result = await ogie('https://example.com');
494
- console.log(result);
495
- // → { title: '...', description: '...', image: '...', ... }
496
- ```
497
-
498
- ---
499
-
500
- ## RSS/Atom Feeds
501
-
502
- ### feedsmith 2.x (Mais Rápido)
503
-
504
- `feedsmith` é o parser de feeds mais rápido em 2026. Suporta RSS 1.0, RSS 2.0, Atom, e JSON Feed.
505
-
506
- ```ts
507
- import { parseFeed } from 'feedsmith';
508
-
509
- const rssXml = `
510
- <rss version="2.0">
511
- <channel>
512
- <title>Meu Blog</title>
513
- <link>https://example.com</link>
514
- <description>Descrição do blog</description>
515
- <item>
516
- <title>Artigo 1</title>
517
- <link>https://example.com/artigo-1</link>
518
- <description>Descrição do artigo 1</description>
519
- <pubDate>Mon, 15 Jan 2026 10:00:00 GMT</pubDate>
520
- <guid>https://example.com/artigo-1</guid>
521
- </item>
522
- <item>
523
- <title>Artigo 2</title>
524
- <link>https://example.com/artigo-2</link>
525
- <description>Descrição do artigo 2</description>
526
- <pubDate>Tue, 16 Jan 2026 10:00:00 GMT</pubDate>
527
- </item>
528
- </channel>
529
- </rss>
530
- `;
531
-
532
- const feed = parseFeed(rssXml);
533
- console.log(`Feed: ${feed.title}`);
534
- console.log(`Link: ${feed.link}`);
535
- console.log(`Items: ${feed.items.length}`);
536
-
537
- for (const item of feed.items) {
538
- console.log(` - ${item.title}`);
539
- console.log(` Link: ${item.link}`);
540
- console.log(` Date: ${item.pubDate}`);
541
- }
542
- ```
543
-
544
- ### rss-parser 3.13.0
545
-
546
- ```ts
547
- import RSSParser from 'rss-parser';
548
-
549
- const parser = new RSSParser({
550
- customFields: {
551
- item: ['media:content', 'media:thumbnail'],
552
- },
553
- });
554
-
555
- const feed = await parser.parseURL('https://example.com/feed.xml');
556
- console.log(`Title: ${feed.title}`);
557
- console.log(`Items: ${feed.items.length}`);
558
-
559
- for (const item of feed.items) {
560
- console.log(` - ${item.title}`);
561
- console.log(` Link: ${item.link}`);
562
- console.log(` Date: ${item.pubDate}`);
563
- console.log(` Creator: ${item.creator}`);
564
- }
565
- ```
566
-
567
- ### rss-finder 2.1.5 (Descoberta de Feeds)
568
-
569
- `rss-finder` descobre automaticamente feeds RSS/Atom em uma página HTML.
570
-
571
- ```ts
572
- import { findRssFeeds } from 'rss-finder';
573
-
574
- const feeds = await findRssFeeds('https://example.com');
575
- console.log(feeds);
576
- // → [
577
- // { title: 'Meu Blog RSS', url: 'https://example.com/feed.xml', type: 'application/rss+xml' },
578
- // { title: 'Meu Blog Atom', url: 'https://example.com/atom.xml', type: 'application/atom+xml' },
579
- // ]
580
-
581
- // Usar com rss-parser
582
- const parser = new RSSParser();
583
- const feed = await parser.parseURL(feeds[0].url);
584
- ```
585
-
586
- ### Descoberta + Parse Combinados
587
-
588
- ```ts
589
- import { findRssFeeds } from 'rss-finder';
590
- import { parseFeed } from 'feedsmith';
591
- import { gotScraping } from 'got-scraping';
592
-
593
- async function discoverAndParseFeed(
594
- url: string,
595
- ): Promise<{ feed: any; items: any[] } | null> {
596
- // 1. Descobrir feeds
597
- const feeds = await findRssFeeds(url);
598
- if (feeds.length === 0) {
599
- console.log(`Nenhum feed encontrado em ${url}`);
600
- return null;
601
- }
602
-
603
- console.log(`Encontrados ${feeds.length} feeds`);
604
-
605
- // 2. Parsear o primeiro feed
606
- const feedUrl = feeds[0].url;
607
- const response = await gotScraping(feedUrl);
608
- const feed = parseFeed(response.body);
609
-
610
- return {
611
- feed: {
612
- title: feed.title,
613
- link: feed.link,
614
- description: feed.description,
615
- },
616
- items: feed.items.map(item => ({
617
- title: item.title,
618
- link: item.link,
619
- description: item.description,
620
- pubDate: item.pubDate,
621
- author: item.author,
622
- })),
623
- };
624
- }
625
-
626
- const result = await discoverAndParseFeed('https://example.com');
627
- if (result) {
628
- console.log(`Feed: ${result.feed.title}`);
629
- for (const item of result.items) {
630
- console.log(` - ${item.title}`);
631
- }
632
- }
633
- ```
634
-
635
- ---
636
-
637
- ## Breadcrumb Extraction
638
-
639
- ### JSON-LD BreadcrumbList
640
-
641
- ```json
642
- {
643
- "@context": "https://schema.org",
644
- "@type": "BreadcrumbList",
645
- "itemListElement": [
646
- {
647
- "@type": "ListItem",
648
- "position": 1,
649
- "name": "Home",
650
- "item": "https://example.com"
651
- },
652
- {
653
- "@type": "ListItem",
654
- "position": 2,
655
- "name": "Produtos",
656
- "item": "https://example.com/products"
657
- },
658
- {
659
- "@type": "ListItem",
660
- "position": 3,
661
- "name": "Produto X",
662
- "item": "https://example.com/products/x"
663
- }
664
- ]
665
- }
666
- ```
667
-
668
- ```ts
669
- import * as cheerio from 'cheerio';
670
-
671
- interface BreadcrumbItem {
672
- name: string;
673
- url: string;
674
- position: number;
675
- }
676
-
677
- function extractBreadcrumbs(html: string): BreadcrumbItem[] {
678
- const $ = cheerio.load(html);
679
-
680
- // 1. Tentar JSON-LD primeiro
681
- const jsonLdBreadcrumbs = extractJsonLdBreadcrumbs(html);
682
- if (jsonLdBreadcrumbs.length > 0) return jsonLdBreadcrumbs;
683
-
684
- // 2. Tentar Microdata
685
- const microdataBreadcrumbs = extractMicrodataBreadcrumbs(html);
686
- if (microdataBreadcrumbs.length > 0) return microdataBreadcrumbs;
687
-
688
- // 3. Fallback: HTML nav
689
- return extractHtmlBreadcrumbs($);
690
- }
691
-
692
- function extractJsonLdBreadcrumbs(html: string): BreadcrumbItem[] {
693
- const $ = cheerio.load(html);
694
- const breadcrumbs: BreadcrumbItem[] = [];
695
-
696
- $('script[type="application/ld+json"]').each((_, element) => {
697
- const raw = $(element).html();
698
- if (!raw) return;
699
-
700
- try {
701
- const data = JSON.parse(raw);
702
- if (data['@type'] === 'BreadcrumbList' && data.itemListElement) {
703
- for (const item of data.itemListElement) {
704
- breadcrumbs.push({
705
- name: item.name,
706
- url: item.item,
707
- position: item.position,
708
- });
709
- }
710
- }
711
- } catch {}
712
- });
713
-
714
- return breadcrumbs.sort((a, b) => a.position - b.position);
715
- }
716
-
717
- function extractMicrodataBreadcrumbs(html: string): BreadcrumbItem[] {
718
- const $ = cheerio.load(html);
719
- const breadcrumbs: BreadcrumbItem[] = [];
720
-
721
- $('[itemtype="https://schema.org/BreadcrumbList"] [itemtype="https://schema.org/ListItem"]').each((_, element) => {
722
- const $item = $(element);
723
- const name = $item.find('[itemprop="name"]').text().trim();
724
- const url = $item.find('[itemprop="item"]').attr('href') ?? '';
725
- const position = Number.parseInt($item.find('[itemprop="position"]').text() ?? '0', 10);
726
-
727
- if (name) {
728
- breadcrumbs.push({ name, url, position });
729
- }
730
- });
731
-
732
- return breadcrumbs.sort((a, b) => a.position - b.position);
733
- }
734
-
735
- function extractHtmlBreadcrumbs($: cheerio.CheerioAPI): BreadcrumbItem[] {
736
- const breadcrumbs: BreadcrumbItem[] = [];
737
-
738
- // Seletores comuns para breadcrumbs
739
- const selectors = [
740
- 'nav[aria-label="breadcrumb"] a',
741
- 'ol.breadcrumb a',
742
- '.breadcrumb a',
743
- '[itemtype="https://schema.org/BreadcrumbList"] a',
744
- ];
745
-
746
- for (const selector of selectors) {
747
- $(selector).each((index, element) => {
748
- const name = $(element).text().trim();
749
- const url = $(element).attr('href') ?? '';
750
-
751
- if (name) {
752
- breadcrumbs.push({
753
- name,
754
- url,
755
- position: index + 1,
756
- });
757
- }
758
- });
759
-
760
- if (breadcrumbs.length > 0) break;
761
- }
762
-
763
- return breadcrumbs;
764
- }
765
- ```
766
-
767
- ### Exemplo de Uso
768
-
769
- ```ts
770
- const breadcrumbs = extractBreadcrumbs(html);
771
- if (breadcrumbs.length > 0) {
772
- const path = breadcrumbs.map(b => b.name).join(' > ');
773
- console.log(`Breadcrumb: ${path}`);
774
- // → "Breadcrumb: Home > Produtos > Produto X"
775
- }
776
- ```
777
-
778
- ---
779
-
780
- ## Readable Content Extraction
781
-
782
- ### @mozilla/readability 0.6.0
783
-
784
- `@mozilla/readability` é a mesma biblioteca usada pelo Firefox Reader View. Extrai o conteúdo principal de uma página, removendo navigation, sidebars, ads, etc.
785
-
786
- ```ts
787
- import { JSDOM } from 'jsdom';
788
- import { Readability } from '@mozilla/readability';
789
-
790
- function extractReadableContent(html: string, url = ''): {
791
- title: string;
792
- content: string;
793
- textContent: string;
794
- length: number;
795
- excerpt: string;
796
- byline: string;
797
- dir: string;
798
- siteName: string;
799
- lang: string;
800
- } | null {
801
- const dom = new JSDOM(html, { url });
802
- const document = dom.window.document;
803
-
804
- const reader = new Readability(document, {
805
- charThreshold: 100, // Mínimo de caracteres
806
- keepClasses: false, // Remover classes CSS
807
- nbTopCandidates: 5, // Top 5 candidates
808
- });
809
-
810
- const article = reader.parse();
811
- if (!article) return null;
812
-
813
- return {
814
- title: article.title,
815
- content: article.content, // HTML limpo
816
- textContent: article.textContent, // Texto puro
817
- length: article.length,
818
- excerpt: article.excerpt,
819
- byline: article.byline,
820
- dir: article.dir,
821
- siteName: article.siteName,
822
- lang: article.lang,
823
- };
824
- }
825
-
826
- // Usar
827
- const readable = extractReadableContent(html, 'https://example.com/article');
828
- if (readable) {
829
- console.log(`Title: ${readable.title}`);
830
- console.log(`Author: ${readable.byline}`);
831
- console.log(`Length: ${readable.length} chars`);
832
- console.log(`Excerpt: ${readable.excerpt}`);
833
- console.log(`Content: ${readable.textContent.substring(0, 200)}...`);
834
- }
835
- ```
836
-
837
- ### defuddle (Alternativa)
838
-
839
- `defuddle` é uma alternativa ao Readability com foco em extração de conteúdo para e-readers.
840
-
841
- ```ts
842
- import { defuddle } from 'defuddle';
843
-
844
- const result = await defuddle(html, {
845
- url: 'https://example.com',
846
- });
847
-
848
- console.log(result.title);
849
- console.log(result.content); // Markdown formatado
850
- console.log(result.excerpt);
851
- console.log(result.siteName);
852
- ```
853
-
854
- ### Comparação Readability vs Defuddle
855
-
856
- | Feature | @mozilla/readability | defuddle |
857
- |---|---|---|
858
- | Output | HTML | Markdown |
859
- | Velocidade | ⭐⭐⭐⭐ | ⭐⭐⭐ |
860
- | Qualidade | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
861
- | Metadata | Básico | Completo |
862
- | Manutenção | Mozilla (ativo) | Comunidade |
863
- | Node.js | Via jsdom | Nativo |
864
-
865
- ---
866
-
867
- ## HTML-to-Markdown
868
-
869
- ### turndown 7.2.4 (Padrão)
870
-
871
- `turndown` é o conversor HTML→Markdown mais popular. Usado pelo `@wenathlan/webscrape`.
872
-
873
- ```ts
874
- import TurndownService from 'turndown';
875
-
876
- const turndown = new TurndownService({
877
- headingStyle: 'atx', # Heading
878
- hr: '---', # Horizontal rule
879
- bulletListMarker: '-', # Lista
880
- codeBlockStyle: 'fenced', # Code block
881
- fence: '```', # Fence
882
- emDelimiter: '*', # Itálico
883
- strongDelimiter: '**', # Bold
884
- linkStyle: 'inlined', # Links
885
- linkReferenceStyle: 'full', # Link references
886
- });
887
-
888
- // Customizar regras
889
- turndown.addRule('customImages', {
890
- filter: 'img',
891
- replacement(content, node) {
892
- const alt = node.getAttribute('alt') ?? '';
893
- const src = node.getAttribute('src') ?? '';
894
- return `![${alt}](${src})`;
895
- },
896
- });
897
-
898
- // Adicionar keep para preservar elementos
899
- turndown.keep(['iframe', 'video']);
900
-
901
- // Remover elementos
902
- turndown.remove(['script', 'style', 'nav', 'footer', 'aside']);
903
-
904
- const markdown = turndown.turndown(html);
905
- console.log(markdown);
906
- ```
907
-
908
- ### node-html-markdown 2.0.0 (1.57x Mais Rápido)
909
-
910
- ```ts
911
- import { NodeHtmlMarkdown } from 'node-html-markdown';
912
-
913
- const nhm = new NodeHtmlMarkdown({
914
- bulletMarker: '-',
915
- codeBlockStyle: 'fenced',
916
- useLinkReferenceDefinitions: false,
917
- });
918
-
919
- const markdown = nhm.translate(html);
920
- console.log(markdown);
921
- ```
922
-
923
- ### mdream (Rust, 33x Mais Rápido)
924
-
925
- ```ts
926
- // mdream é um conversor Rust compilado para WASM
927
- // Performance: 33x mais rápido que turndown
928
- import { convert } from 'mdream';
929
-
930
- const markdown = convert(html, {
931
- // Opções de conversão
932
- });
933
- ```
934
-
935
- ### Comparação de Performance
936
-
937
- | Biblioteca | Velocidade (1MB HTML) | Tamanho | linguagem |
938
- |---|---|---|---|
939
- | turndown | ~500ms | ~200KB | JavaScript |
940
- | node-html-markdown | ~320ms | ~150KB | JavaScript |
941
- | mdream | ~15ms | ~500KB | Rust/WASM |
942
-
943
- ### Conversão com Preservação de Estrutura
944
-
945
- ```ts
946
- import TurndownService from 'turndown';
947
-
948
- function htmlToMarkdownWithStructure(html: string): string {
949
- const turndown = new TurndownService({
950
- headingStyle: 'atx',
951
- codeBlockStyle: 'fenced',
952
- bulletListMarker: '-',
953
- });
954
-
955
- // Preservar tabelas
956
- turndown.addRule('tables', {
957
- filter: 'table',
958
- replacement(content, node) {
959
- // Implementação de tabela Markdown
960
- const rows: string[] = [];
961
- const headers: string[] = [];
962
-
963
- node.querySelectorAll('thead th, th').forEach(th => {
964
- headers.push(th.textContent?.trim() ?? '');
965
- });
966
-
967
- node.querySelectorAll('tbody tr, tr').forEach(tr => {
968
- const cells: string[] = [];
969
- tr.querySelectorAll('td').forEach(td => {
970
- cells.push(td.textContent?.trim() ?? '');
971
- });
972
- if (cells.length > 0) rows.push(cells.join(' | '));
973
- });
974
-
975
- if (headers.length === 0) return content;
976
-
977
- const headerRow = headers.join(' | ');
978
- const separator = headers.map(() => '---').join(' | ');
979
- const bodyRows = rows.join('\n');
980
-
981
- return `\n\n${headerRow}\n${separator}\n${bodyRows}\n\n`;
982
- },
983
- });
984
-
985
- // Preservar code blocks
986
- turndown.addRule('codeBlocks', {
987
- filter(node) {
988
- return (
989
- node.nodeName === 'PRE' &&
990
- node.firstChild &&
991
- node.firstChild.nodeName === 'CODE'
992
- );
993
- },
994
- replacement(content, node) {
995
- const code = node.querySelector('code');
996
- const language = code?.className?.match(/language-(\w+)/)?.[1] ?? '';
997
- const text = code?.textContent ?? node.textContent ?? '';
998
- return `\n\n\`\`\`${language}\n${text.trim()}\n\`\`\`\n\n`;
999
- },
1000
- });
1001
-
1002
- // Preservar imagens com caption
1003
- turndown.addRule('figures', {
1004
- filter: 'figure',
1005
- replacement(content, node) {
1006
- const img = node.querySelector('img');
1007
- const caption = node.querySelector('figcaption')?.textContent?.trim();
1008
-
1009
- if (!img) return content;
1010
-
1011
- const src = img.getAttribute('src') ?? '';
1012
- const alt = img.getAttribute('alt') ?? caption ?? '';
1013
-
1014
- return `\n\n![${alt}](${src})${caption ? `\n*${caption}*` : ''}\n\n`;
1015
- },
1016
- });
1017
-
1018
- return turndown.turndown(html);
1019
- }
1020
- ```
1021
-
1022
- ---
1023
-
1024
- ## Content Detection Heuristics
1025
-
1026
- ### Static vs SPA vs Hydrated
1027
-
1028
- ```ts
1029
- interface DetectionResult {
1030
- type: 'static' | 'spa' | 'hydrated' | 'api-driven';
1031
- confidence: number;
1032
- indicators: string[];
1033
- }
1034
-
1035
- function detectContentType(html: string, scripts: string[]): DetectionResult {
1036
- const indicators: string[] = [];
1037
- let spaScore = 0;
1038
- let staticScore = 0;
1039
- let hydratedScore = 0;
1040
-
1041
- // SPA indicators
1042
- if (html.includes('__NEXT_DATA__') || html.includes('_next/data')) {
1043
- spaScore += 3;
1044
- indicators.push('Next.js data');
1045
- }
1046
- if (html.includes('__NUXT__') || html.includes('_nuxt/')) {
1047
- spaScore += 3;
1048
- indicators.push('Nuxt.js data');
1049
- }
1050
- if (html.includes('window.__INITIAL_STATE__')) {
1051
- spaScore += 2;
1052
- indicators.push('Initial state');
1053
- }
1054
- if (html.includes('data-reactroot') || html.includes('data-reactroot')) {
1055
- spaScore += 2;
1056
- indicators.push('React root');
1057
- }
1058
- if (html.includes('ng-app') || html.includes('ng-controller')) {
1059
- spaScore += 3;
1060
- indicators.push('Angular');
1061
- }
1062
- if (html.includes('id="app"') && scripts.some(s => s.includes('vue'))) {
1063
- spaScore += 3;
1064
- indicators.push('Vue.js');
1065
- }
1066
-
1067
- // Static indicators
1068
- if (!scripts.some(s => s.includes('react') || s.includes('vue') || s.includes('angular'))) {
1069
- staticScore += 2;
1070
- indicators.push('No SPA framework detected');
1071
- }
1072
- if (html.match(/<article[\s>]/i)) {
1073
- staticScore += 1;
1074
- indicators.push('Article tag present');
1075
- }
1076
-
1077
- // Hydrated indicators (SPA with server-rendered content)
1078
- if (spaScore > 0 && html.match(/<article[\s>]/i)) {
1079
- hydratedScore += 2;
1080
- indicators.push('SSR with article content');
1081
- }
1082
- if (spaScore > 0 && html.includes('__NEXT_DATA__')) {
1083
- hydratedScore += 2;
1084
- indicators.push('Next.js SSR');
1085
- }
1086
-
1087
- // Determine type
1088
- if (hydratedScore > spaScore && hydratedScore > staticScore) {
1089
- return { type: 'hydrated', confidence: 0.8, indicators };
1090
- }
1091
- if (spaScore > staticScore) {
1092
- return { type: 'spa', confidence: 0.7, indicators };
1093
- }
1094
- return { type: 'static', confidence: 0.9, indicators };
1095
- }
1096
-
1097
- // Usar
1098
- const detection = detectContentType(html, scriptUrls);
1099
- console.log(`Type: ${detection.type} (confidence: ${detection.confidence})`);
1100
- console.log(`Indicators: ${detection.indicators.join(', ')}`);
1101
- ```
1102
-
1103
- ### Detecção de Framework
1104
-
1105
- ```ts
1106
- interface FrameworkDetection {
1107
- framework: string | null;
1108
- version?: string;
1109
- renderer: 'ssr' | 'csr' | 'ssg';
1110
- }
1111
-
1112
- function detectFramework(html: string): FrameworkDetection {
1113
- // Next.js
1114
- if (html.includes('__NEXT_DATA__')) {
1115
- const versionMatch = html.match(/"buildId":"([^"]+)"/);
1116
- return {
1117
- framework: 'next.js',
1118
- version: versionMatch?.[1],
1119
- renderer: 'ssr',
1120
- };
1121
- }
1122
-
1123
- // Nuxt.js
1124
- if (html.includes('__NUXT__')) {
1125
- return { framework: 'nuxt.js', renderer: 'ssr' };
1126
- }
1127
-
1128
- // Gatsby
1129
- if (html.includes('___gatsby')) {
1130
- return { framework: 'gatsby', renderer: 'ssg' };
1131
- }
1132
-
1133
- // Angular Universal
1134
- if (html.includes('ng-server-app') || html.includes('TransferState')) {
1135
- return { framework: 'angular', renderer: 'ssr' };
1136
- }
1137
-
1138
- // Remix
1139
- if (html.includes('__remixContext')) {
1140
- return { framework: 'remix', renderer: 'ssr' };
1141
- }
1142
-
1143
- // Astro
1144
- if (html.includes('astro-island')) {
1145
- return { framework: 'astro', renderer: 'ssr' };
1146
- }
1147
-
1148
- return { framework: null, renderer: 'csr' };
1149
- }
1150
- ```
1151
-
1152
- ---
1153
-
1154
- ## API Interception Pattern
1155
-
1156
- ### Pular o Browser Totalmente
1157
-
1158
- Para sites que usam APIs internas, interceptar as chamadas de rede é mais rápido e eficiente que renderizar o browser.
1159
-
1160
- ```ts
1161
- import { chromium } from 'playwright';
1162
-
1163
- interface InterceptedAPI {
1164
- url: string;
1165
- method: string;
1166
- status: number;
1167
- body: unknown;
1168
- timestamp: number;
1169
- }
1170
-
1171
- async function scrapeWithAPIInterception(
1172
- targetUrl: string,
1173
- apiPattern: RegExp,
1174
- ): Promise<{ page: any; apiData: InterceptedAPI[] }> {
1175
- const browser = await chromium.launch();
1176
- const context = await browser.newContext();
1177
- const page = await context.newPage();
1178
-
1179
- const intercepted: InterceptedAPI[] = [];
1180
-
1181
- // Interceptar requests de API
1182
- page.on('response', async (response) => {
1183
- const url = response.url();
1184
-
1185
- if (apiPattern.test(url)) {
1186
- try {
1187
- const body = await response.json();
1188
- intercepted.push({
1189
- url,
1190
- method: response.request().method(),
1191
- status: response.status(),
1192
- body,
1193
- timestamp: Date.now(),
1194
- });
1195
- console.log(`API intercepted: ${url}`);
1196
- } catch {
1197
- // Response não é JSON
1198
- }
1199
- }
1200
- });
1201
-
1202
- await page.goto(targetUrl, { waitUntil: 'networkidle' });
1203
-
1204
- return { page, apiData: intercepted };
1205
- }
1206
-
1207
- // Usar
1208
- const { page, apiData } = await scrapeWithAPIInterception(
1209
- 'https://example.com/products',
1210
- /\/api\/products/,
1211
- );
1212
-
1213
- console.log(`Interceptadas ${apiData.length} chamadas de API`);
1214
- for (const api of apiData) {
1215
- console.log(` ${api.method} ${api.url} → ${api.status}`);
1216
- console.log(` Data:`, api.body);
1217
- }
1218
- ```
1219
-
1220
- ### API Interception com Filtros
1221
-
1222
- ```ts
1223
- interface APIFilter {
1224
- method?: string[];
1225
- status?: number[];
1226
- contentType?: string[];
1227
- pattern: RegExp;
1228
- }
1229
-
1230
- async function scrapeWithFilteredAPI(
1231
- targetUrl: string,
1232
- filters: APIFilter[],
1233
- ): Promise<Map<string, unknown[]>> {
1234
- const browser = await chromium.launch();
1235
- const context = await browser.newContext();
1236
- const page = await context.newPage();
1237
-
1238
- const results = new Map<string, unknown[]>();
1239
-
1240
- page.on('response', async (response) => {
1241
- const url = response.url();
1242
- const method = response.request().method();
1243
- const status = response.status();
1244
- const contentType = response.headers()['content-type'] ?? '';
1245
-
1246
- for (const filter of filters) {
1247
- const matches =
1248
- filter.pattern.test(url) &&
1249
- (!filter.method || filter.method.includes(method)) &&
1250
- (!filter.status || filter.status.includes(status)) &&
1251
- (!filter.contentType || filter.contentType.some(ct => contentType.includes(ct)));
1252
-
1253
- if (matches) {
1254
- try {
1255
- const body = await response.json();
1256
- const key = filter.pattern.source;
1257
- if (!results.has(key)) results.set(key, []);
1258
- results.get(key)!.push(body);
1259
- } catch {}
1260
- }
1261
- }
1262
- });
1263
-
1264
- await page.goto(targetUrl, { waitUntil: 'networkidle' });
1265
- await browser.close();
1266
-
1267
- return results;
1268
- }
1269
- ```
1270
-
1271
- ### Extraindo Dados de APIs Interceptadas
1272
-
1273
- ```ts
1274
- interface Product {
1275
- id: string;
1276
- name: string;
1277
- price: number;
1278
- image: string;
1279
- }
1280
-
1281
- async function extractProductsFromAPI(
1282
- categoryUrl: string,
1283
- ): Promise<Product[]> {
1284
- const browser = await chromium.launch();
1285
- const context = await browser.newContext();
1286
- const page = await context.newPage();
1287
-
1288
- const products: Product[] = [];
1289
-
1290
- page.on('response', async (response) => {
1291
- if (response.url().includes('/api/products')) {
1292
- try {
1293
- const data = await response.json();
1294
- if (Array.isArray(data.products)) {
1295
- products.push(...data.products);
1296
- }
1297
- } catch {}
1298
- }
1299
- });
1300
-
1301
- await page.goto(categoryUrl, { waitUntil: 'networkidle' });
1302
-
1303
- // Scroll para carregar mais produtos (lazy loading)
1304
- await page.evaluate(async () => {
1305
- await new Promise((resolve) => {
1306
- let totalHeight = 0;
1307
- const distance = 500;
1308
- const timer = setInterval(() => {
1309
- window.scrollBy(0, distance);
1310
- totalHeight += distance;
1311
- if (totalHeight >= document.body.scrollHeight) {
1312
- clearInterval(timer);
1313
- resolve(undefined);
1314
- }
1315
- }, 200);
1316
- });
1317
- });
1318
-
1319
- // Aguardar requests de API
1320
- await page.waitForTimeout(2000);
1321
-
1322
- await browser.close();
1323
-
1324
- // Deduplicar por ID
1325
- const seen = new Set<string>();
1326
- return products.filter(p => {
1327
- if (seen.has(p.id)) return false;
1328
- seen.add(p.id);
1329
- return true;
1330
- });
1331
- }
1332
- ```
1333
-
1334
- ---
1335
-
1336
- ## Structured Data First Approach
1337
-
1338
- ### Estratégia de Extração em Cascata
1339
-
1340
- ```ts
1341
- import * as cheerio from 'cheerio';
1342
- import { Readability } from '@mozilla/readability';
1343
- import { JSDOM } from 'jsdom';
1344
-
1345
- interface ExtractedData {
1346
- source: 'json-ld' | 'microdata' | 'og' | 'readability' | 'html';
1347
- type: string;
1348
- title: string;
1349
- description?: string;
1350
- author?: string;
1351
- date?: string;
1352
- image?: string;
1353
- content: string;
1354
- url: string;
1355
- metadata: Record<string, unknown>;
1356
- }
1357
-
1358
- function extractWithPriority(html: string, url: string): ExtractedData | null {
1359
- // 1. Tentar JSON-LD
1360
- const jsonLdResult = extractFromJsonLd(html, url);
1361
- if (jsonLdResult) return jsonLdResult;
1362
-
1363
- // 2. Tentar Microdata
1364
- const microdataResult = extractFromMicrodata(html, url);
1365
- if (microdataResult) return microdataResult;
1366
-
1367
- // 3. Tentar OpenGraph
1368
- const ogResult = extractFromOpenGraph(html, url);
1369
- if (ogResult) return ogResult;
1370
-
1371
- // 4. Fallback: Readability
1372
- const readableResult = extractFromReadability(html, url);
1373
- if (readableResult) return readableResult;
1374
-
1375
- // 5. Último recurso: HTML cru
1376
- return extractFromHtml(html, url);
1377
- }
1378
-
1379
- function extractFromJsonLd(html: string, url: string): ExtractedData | null {
1380
- const $ = cheerio.load(html);
1381
-
1382
- const jsonLdScripts = $('script[type="application/ld+json"]');
1383
- if (jsonLdScripts.length === 0) return null;
1384
-
1385
- for (const script of jsonLdScripts.toArray()) {
1386
- const raw = $(script).html();
1387
- if (!raw) continue;
1388
-
1389
- try {
1390
- const data = JSON.parse(raw);
1391
-
1392
- // Suporte a @graph
1393
- const items = data['@graph'] ?? [data];
1394
-
1395
- for (const item of items) {
1396
- const type = item['@type'];
1397
- if (!type) continue;
1398
-
1399
- // Extrair baseado no tipo
1400
- const result = mapJsonLdToExtracted(item, type, url);
1401
- if (result) return result;
1402
- }
1403
- } catch {}
1404
- }
1405
-
1406
- return null;
1407
- }
1408
-
1409
- function mapJsonLdToExtracted(
1410
- data: Record<string, unknown>,
1411
- type: string,
1412
- url: string,
1413
- ): ExtractedData | null {
1414
- const base = {
1415
- source: 'json-ld' as const,
1416
- type,
1417
- url,
1418
- metadata: data,
1419
- };
1420
-
1421
- if (['Article', 'NewsArticle', 'BlogPosting'].includes(type)) {
1422
- return {
1423
- ...base,
1424
- title: (data.headline as string) ?? '',
1425
- description: (data.description as string) ?? '',
1426
- author: (data.author as any)?.name ?? '',
1427
- date: (data.datePublished as string) ?? '',
1428
- image: Array.isArray(data.image) ? data.image[0] as string : (data.image as string) ?? '',
1429
- content: (data.articleBody as string) ?? '',
1430
- };
1431
- }
1432
-
1433
- if (type === 'Product') {
1434
- return {
1435
- ...base,
1436
- title: (data.name as string) ?? '',
1437
- description: (data.description as string) ?? '',
1438
- image: Array.isArray(data.image) ? data.image[0] as string : (data.image as string) ?? '',
1439
- content: JSON.stringify(data.offers),
1440
- };
1441
- }
1442
-
1443
- if (type === 'WebPage') {
1444
- return {
1445
- ...base,
1446
- title: (data.name as string) ?? '',
1447
- description: (data.description as string) ?? '',
1448
- content: '',
1449
- };
1450
- }
1451
-
1452
- return null;
1453
- }
1454
-
1455
- function extractFromOpenGraph(html: string, url: string): ExtractedData | null {
1456
- const $ = cheerio.load(html);
1457
-
1458
- const title = $('meta[property="og:title"]').attr('content');
1459
- if (!title) return null;
1460
-
1461
- return {
1462
- source: 'og',
1463
- type: 'og:article',
1464
- title,
1465
- description: $('meta[property="og:description"]').attr('content'),
1466
- image: $('meta[property="og:image"]').attr('content'),
1467
- url: $('meta[property="og:url"]').attr('content') ?? url,
1468
- metadata: {
1469
- siteName: $('meta[property="og:site_name"]').attr('content'),
1470
- type: $('meta[property="og:type"]').attr('content'),
1471
- },
1472
- content: '',
1473
- };
1474
- }
1475
-
1476
- function extractFromReadability(html: string, url: string): ExtractedData | null {
1477
- const dom = new JSDOM(html, { url });
1478
- const reader = new Readability(dom.window.document);
1479
- const article = reader.parse();
1480
-
1481
- if (!article) return null;
1482
-
1483
- return {
1484
- source: 'readability',
1485
- type: 'article',
1486
- title: article.title,
1487
- author: article.byline,
1488
- content: article.textContent,
1489
- url,
1490
- metadata: {
1491
- excerpt: article.excerpt,
1492
- siteName: article.siteName,
1493
- },
1494
- };
1495
- }
1496
-
1497
- function extractFromHtml(html: string, url: string): ExtractedData {
1498
- const $ = cheerio.load(html);
1499
-
1500
- return {
1501
- source: 'html',
1502
- type: 'page',
1503
- title: $('title').text().trim() || $('h1').first().text().trim(),
1504
- description: $('meta[name="description"]').attr('content'),
1505
- author: $('meta[name="author"]').attr('content'),
1506
- url,
1507
- metadata: {},
1508
- content: $('body').text().replace(/\s+/g, ' ').trim(),
1509
- };
1510
- }
1511
-
1512
- // Usar
1513
- const data = extractWithPriority(html, 'https://example.com/article');
1514
- if (data) {
1515
- console.log(`Source: ${data.source}`);
1516
- console.log(`Type: ${data.type}`);
1517
- console.log(`Title: ${data.title}`);
1518
- }
1519
- ```
1520
-
1521
- ---
1522
-
1523
- ## Código Completo
1524
-
1525
- ### Exemplo 1: Content Extractor Completo
1526
-
1527
- ```ts
1528
- import * as cheerio from 'cheerio';
1529
- import { Readability } from '@mozilla/readability';
1530
- import { JSDOM } from 'jsdom';
1531
- import TurndownService from 'turndown';
1532
-
1533
- interface ContentExtractorOptions {
1534
- url: string;
1535
- extractJsonLd?: boolean;
1536
- extractMicrodata?: boolean;
1537
- extractOpenGraph?: boolean;
1538
- extractBreadcrumbs?: boolean;
1539
- extractFeeds?: boolean;
1540
- extractReadable?: boolean;
1541
- htmlToMarkdown?: boolean;
1542
- }
1543
-
1544
- interface ContentExtractorResult {
1545
- url: string;
1546
- title: string;
1547
- author?: string;
1548
- date?: string;
1549
- description?: string;
1550
- image?: string;
1551
- content: string;
1552
- contentMarkdown?: string;
1553
- breadcrumbs: Array<{ name: string; url: string }>;
1554
- feeds: Array<{ title: string; url: string; type: string }>;
1555
- openGraph: Record<string, string>;
1556
- jsonLd: Record<string, unknown>[];
1557
- metadata: Record<string, unknown>;
1558
- }
1559
-
1560
- class ContentExtractor {
1561
- private options: ContentExtractorOptions;
1562
-
1563
- constructor(options: ContentExtractorOptions) {
1564
- this.options = options;
1565
- }
1566
-
1567
- async extract(html: string): Promise<ContentExtractorResult> {
1568
- const $ = cheerio.load(html);
1569
- const url = this.options.url;
1570
-
1571
- const result: ContentExtractorResult = {
1572
- url,
1573
- title: $('title').text().trim(),
1574
- content: '',
1575
- breadcrumbs: [],
1576
- feeds: [],
1577
- openGraph: {},
1578
- jsonLd: [],
1579
- metadata: {},
1580
- };
1581
-
1582
- // 1. JSON-LD
1583
- if (this.options.extractJsonLd) {
1584
- result.jsonLd = this.extractJsonLd($);
1585
- const article = this.findArticleInJsonLd(result.jsonLd);
1586
- if (article) {
1587
- result.title = article.headline ?? result.title;
1588
- result.author = article.author;
1589
- result.date = article.datePublished;
1590
- result.description = article.description;
1591
- result.image = article.image;
1592
- }
1593
- }
1594
-
1595
- // 2. OpenGraph
1596
- if (this.options.extractOpenGraph) {
1597
- result.openGraph = this.extractOpenGraph($);
1598
- if (!result.description) {
1599
- result.description = result.openGraph['og:description'];
1600
- }
1601
- if (!result.image) {
1602
- result.image = result.openGraph['og:image'];
1603
- }
1604
- }
1605
-
1606
- // 3. Breadcrumbs
1607
- if (this.options.extractBreadcrumbs) {
1608
- result.breadcrumbs = this.extractBreadcrumbs($);
1609
- }
1610
-
1611
- // 4. Feeds
1612
- if (this.options.extractFeeds) {
1613
- result.feeds = this.extractFeeds($);
1614
- }
1615
-
1616
- // 5. Readable content
1617
- if (this.options.extractReadable) {
1618
- const readable = this.extractReadable(html);
1619
- if (readable) {
1620
- result.content = readable.textContent;
1621
- if (!result.title || result.title === 'Untitled') {
1622
- result.title = readable.title;
1623
- }
1624
- if (!result.author) {
1625
- result.author = readable.byline;
1626
- }
1627
- }
1628
- }
1629
-
1630
- // 6. HTML to Markdown
1631
- if (this.options.htmlToMarkdown && result.content) {
1632
- const turndown = new TurndownService({
1633
- headingStyle: 'atx',
1634
- codeBlockStyle: 'fenced',
1635
- });
1636
- result.contentMarkdown = turndown.turndown(result.content);
1637
- }
1638
-
1639
- // 7. Fallback: raw content
1640
- if (!result.content) {
1641
- result.content = $('body').text().replace(/\s+/g, ' ').trim();
1642
- }
1643
-
1644
- return result;
1645
- }
1646
-
1647
- private extractJsonLd($: cheerio.CheerioAPI): Record<string, unknown>[] {
1648
- const results: Record<string, unknown>[] = [];
1649
-
1650
- $('script[type="application/ld+json"]').each((_, element) => {
1651
- const raw = $(element).html();
1652
- if (!raw) return;
1653
-
1654
- try {
1655
- const data = JSON.parse(raw);
1656
- if (data['@graph']) {
1657
- results.push(...data['@graph']);
1658
- } else {
1659
- results.push(data);
1660
- }
1661
- } catch {}
1662
- });
1663
-
1664
- return results;
1665
- }
1666
-
1667
- private findArticleInJsonLd(jsonLd: Record<string, unknown>[]): any {
1668
- return jsonLd.find(item =>
1669
- ['Article', 'NewsArticle', 'BlogPosting'].includes(item['@type'] as string)
1670
- );
1671
- }
1672
-
1673
- private extractOpenGraph($: cheerio.CheerioAPI): Record<string, string> {
1674
- const og: Record<string, string> = {};
1675
-
1676
- $('meta[property^="og:"]').each((_, element) => {
1677
- const property = $(element).attr('property')?.replace('og:', '');
1678
- const content = $(element).attr('content');
1679
- if (property && content) {
1680
- og[property] = content;
1681
- }
1682
- });
1683
-
1684
- return og;
1685
- }
1686
-
1687
- private extractBreadcrumbs($: cheerio.CheerioAPI): Array<{ name: string; url: string }> {
1688
- const breadcrumbs: Array<{ name: string; url: string }> = [];
1689
-
1690
- $('nav[aria-label="breadcrumb"] a, .breadcrumb a').each((_, element) => {
1691
- const name = $(element).text().trim();
1692
- const url = $(element).attr('href') ?? '';
1693
- if (name) {
1694
- breadcrumbs.push({ name, url });
1695
- }
1696
- });
1697
-
1698
- return breadcrumbs;
1699
- }
1700
-
1701
- private extractFeeds($: cheerio.CheerioAPI): Array<{ title: string; url: string; type: string }> {
1702
- const feeds: Array<{ title: string; url: string; type: string }> = [];
1703
-
1704
- $('link[type="application/rss+xml"], link[type="application/atom+xml"]').each((_, element) => {
1705
- const title = $(element).attr('title') ?? '';
1706
- const url = $(element).attr('href') ?? '';
1707
- const type = $(element).attr('type') ?? '';
1708
-
1709
- if (url) {
1710
- feeds.push({ title, url, type });
1711
- }
1712
- });
1713
-
1714
- return feeds;
1715
- }
1716
-
1717
- private extractReadable(html: string): {
1718
- title: string;
1719
- content: string;
1720
- textContent: string;
1721
- byline: string;
1722
- } | null {
1723
- const dom = new JSDOM(html, { url: this.options.url });
1724
- const reader = new Readability(dom.window.document);
1725
- const article = reader.parse();
1726
-
1727
- if (!article) return null;
1728
-
1729
- return {
1730
- title: article.title,
1731
- content: article.content,
1732
- textContent: article.textContent,
1733
- byline: article.byline,
1734
- };
1735
- }
1736
- }
1737
-
1738
- // Usar
1739
- const extractor = new ContentExtractor({
1740
- url: 'https://example.com/article',
1741
- extractJsonLd: true,
1742
- extractMicrodata: true,
1743
- extractOpenGraph: true,
1744
- extractBreadcrumbs: true,
1745
- extractFeeds: true,
1746
- extractReadable: true,
1747
- htmlToMarkdown: true,
1748
- });
1749
-
1750
- const result = await extractor.extract(html);
1751
- console.log(`Title: ${result.title}`);
1752
- console.log(`Author: ${result.author}`);
1753
- console.log(`Breadcrumbs: ${result.breadcrumbs.map(b => b.name).join(' > ')}`);
1754
- console.log(`Feeds: ${result.feeds.length}`);
1755
- console.log(`JSON-LD items: ${result.jsonLd.length}`);
1756
- ```
1757
-
1758
- ### Exemplo 2: Scraper com API Interception + Content Extraction
1759
-
1760
- ```ts
1761
- import { chromium } from 'playwright';
1762
- import * as cheerio from 'cheerio';
1763
-
1764
- interface SmartScraperConfig {
1765
- url: string;
1766
- apiPatterns?: RegExp[];
1767
- waitFor?: number;
1768
- scroll?: boolean;
1769
- }
1770
-
1771
- class SmartScraper {
1772
- private config: SmartScraperConfig;
1773
-
1774
- constructor(config: SmartScraperConfig) {
1775
- this.config = config;
1776
- }
1777
-
1778
- async scrape(): Promise<{
1779
- html: string;
1780
- apiData: unknown[];
1781
- extracted: ContentExtractorResult;
1782
- }> {
1783
- const browser = await chromium.launch();
1784
- const context = await browser.newContext();
1785
- const page = await context.newPage();
1786
-
1787
- const apiData: unknown[] = [];
1788
-
1789
- // Interceptar APIs se configurado
1790
- if (this.config.apiPatterns) {
1791
- page.on('response', async (response) => {
1792
- const url = response.url();
1793
- const matches = this.config.apiPatterns!.some(p => p.test(url));
1794
-
1795
- if (matches) {
1796
- try {
1797
- const body = await response.json();
1798
- apiData.push(body);
1799
- } catch {}
1800
- }
1801
- });
1802
- }
1803
-
1804
- // Navegar
1805
- await page.goto(this.config.url, { waitUntil: 'networkidle' });
1806
-
1807
- // Scroll se configurado
1808
- if (this.config.scroll) {
1809
- await page.evaluate(async () => {
1810
- await new Promise(resolve => {
1811
- let totalHeight = 0;
1812
- const distance = 500;
1813
- const timer = setInterval(() => {
1814
- window.scrollBy(0, distance);
1815
- totalHeight += distance;
1816
- if (totalHeight >= document.body.scrollHeight) {
1817
- clearInterval(timer);
1818
- resolve(undefined);
1819
- }
1820
- }, 200);
1821
- });
1822
- });
1823
- }
1824
-
1825
- // Aguardar se configurado
1826
- if (this.config.waitFor) {
1827
- await page.waitForTimeout(this.config.waitFor);
1828
- }
1829
-
1830
- // Extrair HTML
1831
- const html = await page.content();
1832
- await browser.close();
1833
-
1834
- // Extrair conteúdo
1835
- const extractor = new ContentExtractor({
1836
- url: this.config.url,
1837
- extractJsonLd: true,
1838
- extractOpenGraph: true,
1839
- extractBreadcrumbs: true,
1840
- extractReadable: true,
1841
- htmlToMarkdown: true,
1842
- });
1843
-
1844
- const extracted = await extractor.extract(html);
1845
-
1846
- return { html, apiData, extracted };
1847
- }
1848
- }
1849
-
1850
- // Usar
1851
- const scraper = new SmartScraper({
1852
- url: 'https://example.com/products',
1853
- apiPatterns: [/\/api\/products/],
1854
- scroll: true,
1855
- waitFor: 2000,
1856
- });
1857
-
1858
- const result = await scraper.scrape();
1859
- console.log(`HTML length: ${result.html.length}`);
1860
- console.log(`API calls intercepted: ${result.apiData.length}`);
1861
- console.log(`Title: ${result.extracted.title}`);
1862
- console.log(`Content length: ${result.extracted.content.length}`);
1863
- ```
1864
-
1865
- ### Exemplo 3: Batch Extraction com Cache
1866
-
1867
- ```ts
1868
- import { LRUCache } from 'lru-cache';
1869
- import { ContentExtractor, ContentExtractorResult } from './content-extractor';
1870
-
1871
- class BatchExtractor {
1872
- private cache: LRUCache<string, ContentExtractorResult>;
1873
- private extractor: ContentExtractor;
1874
-
1875
- constructor(options: { cacheSize?: number; cacheTtl?: number } = {}) {
1876
- this.cache = new LRUCache({
1877
- max: options.cacheSize ?? 1000,
1878
- ttl: options.cacheTtl ?? 1000 * 60 * 30, // 30 min
1879
- });
1880
-
1881
- this.extractor = new ContentExtractor({
1882
- url: '',
1883
- extractJsonLd: true,
1884
- extractOpenGraph: true,
1885
- extractReadable: true,
1886
- htmlToMarkdown: true,
1887
- });
1888
- }
1889
-
1890
- async extract(url: string, html: string): Promise<ContentExtractorResult> {
1891
- const cached = this.cache.get(url);
1892
- if (cached) {
1893
- console.log(`Cache HIT: ${url}`);
1894
- return cached;
1895
- }
1896
-
1897
- console.log(`Cache MISS: ${url}`);
1898
- this.extractor = new ContentExtractor({ url, extractJsonLd: true, extractOpenGraph: true, extractReadable: true, htmlToMarkdown: true });
1899
- const result = await this.extractor.extract(html);
1900
-
1901
- this.cache.set(url, result);
1902
- return result;
1903
- }
1904
-
1905
- async extractBatch(
1906
- items: Array<{ url: string; html: string }>,
1907
- ): Promise<ContentExtractorResult[]> {
1908
- const results: ContentExtractorResult[] = [];
1909
-
1910
- for (const item of items) {
1911
- const result = await this.extract(item.url, item.html);
1912
- results.push(result);
1913
- }
1914
-
1915
- return results;
1916
- }
1917
-
1918
- stats(): { size: number } {
1919
- return { size: this.cache.size };
1920
- }
1921
- }
1922
-
1923
- // Usar
1924
- const batchExtractor = new BatchExtractor({ cacheSize: 5000 });
1925
-
1926
- const results = await batchExtractor.extractBatch([
1927
- { url: 'https://example.com/page1', html: html1 },
1928
- { url: 'https://example.com/page2', html: html2 },
1929
- { url: 'https://example.com/page1', html: html1 }, // Cache HIT
1930
- ]);
1931
-
1932
- console.log(`Cache stats:`, batchExtractor.stats());
1933
- ```
1934
-
1935
- ---
1936
-
1937
- ## Referências
1938
-
1939
- - [Schema.org](https://schema.org)
1940
- - [JSON-LD Specification](https://www.w3.org/TR/json-ld/)
1941
- - [OpenGraph Protocol](https://ogp.me/)
1942
- - [Twitter Card Documentation](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards)
1943
- - [@mozilla/readability npm](https://www.npmjs.com/package/@mozilla/readability)
1944
- - [turndown npm](https://www.npmjs.com/package/turndown)
1945
- - [node-html-markdown npm](https://www.npmjs.com/package/node-html-markdown)
1946
- - [mdream npm](https://www.npmjs.com/package/mdream)
1947
- - [open-graph-scraper npm](https://www.npmjs.com/package/open-graph-scraper)
1948
- - [feedsmith npm](https://www.npmjs.com/package/feedsmith)
1949
- - [rss-parser npm](https://www.npmjs.com/package/rss-parser)
1950
- - [rss-finder npm](https://www.npmjs.com/package/rss-finder)
1951
- - [Cheerio Documentation](https://cheerio.js.org/)
1952
- - [Playwright Network Interception](https://playwright.dev/docs/network)