googlemaps-kit 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/README.md +54 -2
  2. package/dist/books.d.ts +30 -0
  3. package/dist/books.d.ts.map +1 -0
  4. package/dist/books.js +77 -0
  5. package/dist/books.js.map +1 -0
  6. package/dist/client/http-client.d.ts +3 -1
  7. package/dist/client/http-client.d.ts.map +1 -1
  8. package/dist/client/http-client.js +14 -3
  9. package/dist/client/http-client.js.map +1 -1
  10. package/dist/client/namespaces.d.ts +1 -4
  11. package/dist/client/namespaces.d.ts.map +1 -1
  12. package/dist/client/namespaces.js +1 -5
  13. package/dist/client/namespaces.js.map +1 -1
  14. package/dist/finance/client.d.ts +19 -0
  15. package/dist/finance/client.d.ts.map +1 -0
  16. package/dist/finance/client.js +75 -0
  17. package/dist/finance/client.js.map +1 -0
  18. package/dist/finance/parsers.d.ts +13 -0
  19. package/dist/finance/parsers.d.ts.map +1 -0
  20. package/dist/finance/parsers.js +146 -0
  21. package/dist/finance/parsers.js.map +1 -0
  22. package/dist/finance/types.d.ts +76 -0
  23. package/dist/finance/types.d.ts.map +1 -0
  24. package/dist/finance/types.js +2 -0
  25. package/dist/finance/types.js.map +1 -0
  26. package/dist/finance.d.ts +5 -0
  27. package/dist/finance.d.ts.map +1 -0
  28. package/dist/finance.js +4 -0
  29. package/dist/finance.js.map +1 -0
  30. package/dist/flights/client.d.ts +9 -0
  31. package/dist/flights/client.d.ts.map +1 -0
  32. package/dist/flights/client.js +14 -0
  33. package/dist/flights/client.js.map +1 -0
  34. package/dist/flights/parsers.d.ts +11 -0
  35. package/dist/flights/parsers.d.ts.map +1 -0
  36. package/dist/flights/parsers.js +64 -0
  37. package/dist/flights/parsers.js.map +1 -0
  38. package/dist/flights/types.d.ts +52 -0
  39. package/dist/flights/types.d.ts.map +1 -0
  40. package/dist/flights/types.js +2 -0
  41. package/dist/flights/types.js.map +1 -0
  42. package/dist/flights.d.ts +5 -0
  43. package/dist/flights.d.ts.map +1 -0
  44. package/dist/flights.js +4 -0
  45. package/dist/flights.js.map +1 -0
  46. package/dist/gemini-web/client.d.ts +16 -0
  47. package/dist/gemini-web/client.d.ts.map +1 -0
  48. package/dist/gemini-web/client.js +110 -0
  49. package/dist/gemini-web/client.js.map +1 -0
  50. package/dist/gemini-web/parsers.d.ts +5 -0
  51. package/dist/gemini-web/parsers.d.ts.map +1 -0
  52. package/dist/gemini-web/parsers.js +62 -0
  53. package/dist/gemini-web/parsers.js.map +1 -0
  54. package/dist/gemini-web/types.d.ts +47 -0
  55. package/dist/gemini-web/types.d.ts.map +1 -0
  56. package/dist/gemini-web/types.js +2 -0
  57. package/dist/gemini-web/types.js.map +1 -0
  58. package/dist/gemini-web.d.ts +5 -0
  59. package/dist/gemini-web.d.ts.map +1 -0
  60. package/dist/gemini-web.js +4 -0
  61. package/dist/gemini-web.js.map +1 -0
  62. package/dist/google-search/client.d.ts +16 -0
  63. package/dist/google-search/client.d.ts.map +1 -0
  64. package/dist/google-search/client.js +117 -0
  65. package/dist/google-search/client.js.map +1 -0
  66. package/dist/google-search/errors.d.ts +8 -0
  67. package/dist/google-search/errors.d.ts.map +1 -0
  68. package/dist/google-search/errors.js +13 -0
  69. package/dist/google-search/errors.js.map +1 -0
  70. package/dist/google-search/html.d.ts +12 -0
  71. package/dist/google-search/html.d.ts.map +1 -0
  72. package/dist/google-search/html.js +135 -0
  73. package/dist/google-search/html.js.map +1 -0
  74. package/dist/google-search/parsers.d.ts +6 -0
  75. package/dist/google-search/parsers.d.ts.map +1 -0
  76. package/dist/google-search/parsers.js +177 -0
  77. package/dist/google-search/parsers.js.map +1 -0
  78. package/dist/google-search/types.d.ts +66 -0
  79. package/dist/google-search/types.d.ts.map +1 -0
  80. package/dist/google-search/types.js +2 -0
  81. package/dist/google-search/types.js.map +1 -0
  82. package/dist/google-search.d.ts +6 -0
  83. package/dist/google-search.d.ts.map +1 -0
  84. package/dist/google-search.js +4 -0
  85. package/dist/google-search.js.map +1 -0
  86. package/dist/hotels/client.d.ts +9 -0
  87. package/dist/hotels/client.d.ts.map +1 -0
  88. package/dist/hotels/client.js +14 -0
  89. package/dist/hotels/client.js.map +1 -0
  90. package/dist/hotels/parsers.d.ts +7 -0
  91. package/dist/hotels/parsers.d.ts.map +1 -0
  92. package/dist/hotels/parsers.js +74 -0
  93. package/dist/hotels/parsers.js.map +1 -0
  94. package/dist/hotels/types.d.ts +55 -0
  95. package/dist/hotels/types.d.ts.map +1 -0
  96. package/dist/hotels/types.js +2 -0
  97. package/dist/hotels/types.js.map +1 -0
  98. package/dist/hotels.d.ts +4 -0
  99. package/dist/hotels.d.ts.map +1 -0
  100. package/dist/hotels.js +3 -0
  101. package/dist/hotels.js.map +1 -0
  102. package/dist/index.d.ts +0 -1
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js.map +1 -1
  105. package/dist/known-surfaces.d.ts +0 -6
  106. package/dist/known-surfaces.d.ts.map +1 -1
  107. package/dist/known-surfaces.js +0 -6
  108. package/dist/known-surfaces.js.map +1 -1
  109. package/dist/lens/client.d.ts +14 -0
  110. package/dist/lens/client.d.ts.map +1 -0
  111. package/dist/lens/client.js +116 -0
  112. package/dist/lens/client.js.map +1 -0
  113. package/dist/lens/errors.d.ts +8 -0
  114. package/dist/lens/errors.d.ts.map +1 -0
  115. package/dist/lens/errors.js +13 -0
  116. package/dist/lens/errors.js.map +1 -0
  117. package/dist/lens/types.d.ts +27 -0
  118. package/dist/lens/types.d.ts.map +1 -0
  119. package/dist/lens/types.js +2 -0
  120. package/dist/lens/types.js.map +1 -0
  121. package/dist/lens.d.ts +8 -0
  122. package/dist/lens.d.ts.map +1 -0
  123. package/dist/lens.js +5 -0
  124. package/dist/lens.js.map +1 -0
  125. package/dist/news.d.ts +46 -0
  126. package/dist/news.d.ts.map +1 -0
  127. package/dist/news.js +202 -0
  128. package/dist/news.js.map +1 -0
  129. package/dist/pagespeed/client.d.ts +28 -0
  130. package/dist/pagespeed/client.d.ts.map +1 -0
  131. package/dist/pagespeed/client.js +222 -0
  132. package/dist/pagespeed/client.js.map +1 -0
  133. package/dist/pagespeed/errors.d.ts +9 -0
  134. package/dist/pagespeed/errors.d.ts.map +1 -0
  135. package/dist/pagespeed/errors.js +15 -0
  136. package/dist/pagespeed/errors.js.map +1 -0
  137. package/dist/pagespeed/parsers.d.ts +7 -0
  138. package/dist/pagespeed/parsers.d.ts.map +1 -0
  139. package/dist/pagespeed/parsers.js +236 -0
  140. package/dist/pagespeed/parsers.js.map +1 -0
  141. package/dist/pagespeed/types.d.ts +156 -0
  142. package/dist/pagespeed/types.d.ts.map +1 -0
  143. package/dist/pagespeed/types.js +2 -0
  144. package/dist/pagespeed/types.js.map +1 -0
  145. package/dist/pagespeed/wire.d.ts +10 -0
  146. package/dist/pagespeed/wire.d.ts.map +1 -0
  147. package/dist/pagespeed/wire.js +96 -0
  148. package/dist/pagespeed/wire.js.map +1 -0
  149. package/dist/pagespeed.d.ts +6 -0
  150. package/dist/pagespeed.d.ts.map +1 -0
  151. package/dist/pagespeed.js +4 -0
  152. package/dist/pagespeed.js.map +1 -0
  153. package/dist/platform/catalog.d.ts.map +1 -1
  154. package/dist/platform/catalog.js +0 -9
  155. package/dist/platform/catalog.js.map +1 -1
  156. package/dist/services/environment/air-quality.d.ts.map +1 -1
  157. package/dist/services/environment/air-quality.js +3 -7
  158. package/dist/services/environment/air-quality.js.map +1 -1
  159. package/dist/services/environment/weather.d.ts +4 -1
  160. package/dist/services/environment/weather.d.ts.map +1 -1
  161. package/dist/services/environment/weather.js +12 -3
  162. package/dist/services/environment/weather.js.map +1 -1
  163. package/dist/services/reviews.d.ts.map +1 -1
  164. package/dist/services/reviews.js +4 -1
  165. package/dist/services/reviews.js.map +1 -1
  166. package/dist/translate.d.ts +75 -0
  167. package/dist/translate.d.ts.map +1 -0
  168. package/dist/translate.js +126 -0
  169. package/dist/translate.js.map +1 -0
  170. package/dist/travel-google/common.d.ts +24 -0
  171. package/dist/travel-google/common.d.ts.map +1 -0
  172. package/dist/travel-google/common.js +72 -0
  173. package/dist/travel-google/common.js.map +1 -0
  174. package/dist/trends/client.d.ts +17 -0
  175. package/dist/trends/client.d.ts.map +1 -0
  176. package/dist/trends/client.js +86 -0
  177. package/dist/trends/client.js.map +1 -0
  178. package/dist/trends/errors.d.ts +8 -0
  179. package/dist/trends/errors.d.ts.map +1 -0
  180. package/dist/trends/errors.js +13 -0
  181. package/dist/trends/errors.js.map +1 -0
  182. package/dist/trends/links.d.ts +8 -0
  183. package/dist/trends/links.d.ts.map +1 -0
  184. package/dist/trends/links.js +71 -0
  185. package/dist/trends/links.js.map +1 -0
  186. package/dist/trends/parsers.d.ts +5 -0
  187. package/dist/trends/parsers.d.ts.map +1 -0
  188. package/dist/trends/parsers.js +126 -0
  189. package/dist/trends/parsers.js.map +1 -0
  190. package/dist/trends/types.d.ts +71 -0
  191. package/dist/trends/types.d.ts.map +1 -0
  192. package/dist/trends/types.js +2 -0
  193. package/dist/trends/types.js.map +1 -0
  194. package/dist/trends.d.ts +9 -0
  195. package/dist/trends.d.ts.map +1 -0
  196. package/dist/trends.js +8 -0
  197. package/dist/trends.js.map +1 -0
  198. package/dist/types/common.d.ts +0 -2
  199. package/dist/types/common.d.ts.map +1 -1
  200. package/dist/types/common.js.map +1 -1
  201. package/dist/utils/google-web.d.ts +24 -0
  202. package/dist/utils/google-web.d.ts.map +1 -0
  203. package/dist/utils/google-web.js +150 -0
  204. package/dist/utils/google-web.js.map +1 -0
  205. package/dist/youtube/client.d.ts +19 -0
  206. package/dist/youtube/client.d.ts.map +1 -0
  207. package/dist/youtube/client.js +115 -0
  208. package/dist/youtube/client.js.map +1 -0
  209. package/dist/youtube/errors.d.ts +8 -0
  210. package/dist/youtube/errors.d.ts.map +1 -0
  211. package/dist/youtube/errors.js +13 -0
  212. package/dist/youtube/errors.js.map +1 -0
  213. package/dist/youtube/parsers.d.ts +9 -0
  214. package/dist/youtube/parsers.d.ts.map +1 -0
  215. package/dist/youtube/parsers.js +213 -0
  216. package/dist/youtube/parsers.js.map +1 -0
  217. package/dist/youtube/types.d.ts +90 -0
  218. package/dist/youtube/types.d.ts.map +1 -0
  219. package/dist/youtube/types.js +2 -0
  220. package/dist/youtube/types.js.map +1 -0
  221. package/dist/youtube.d.ts +9 -0
  222. package/dist/youtube.d.ts.map +1 -0
  223. package/dist/youtube.js +6 -0
  224. package/dist/youtube.js.map +1 -0
  225. package/docs/books.md +18 -0
  226. package/docs/environment-research.md +65 -0
  227. package/docs/finance-research.md +153 -0
  228. package/docs/finance.md +43 -0
  229. package/docs/gemini-web.md +36 -0
  230. package/docs/google-ai-books-research.md +53 -0
  231. package/docs/google-media-research.md +105 -0
  232. package/docs/google-search-research.md +36 -0
  233. package/docs/google-search.md +53 -0
  234. package/docs/google-services-research.md +135 -0
  235. package/docs/google-travel-research.md +86 -0
  236. package/docs/internal/reverse-engineering.md +85 -0
  237. package/docs/lens.md +54 -0
  238. package/docs/maps-revalidation.md +31 -0
  239. package/docs/news.md +35 -0
  240. package/docs/pagespeed-research.md +153 -0
  241. package/docs/pagespeed.md +135 -0
  242. package/docs/reviews-research.md +33 -0
  243. package/docs/translate.md +78 -0
  244. package/docs/trends-research.md +82 -0
  245. package/docs/trends.md +75 -0
  246. package/docs/youtube.md +72 -0
  247. package/package.json +77 -2
  248. package/dist/services/aerial-view.d.ts +0 -22
  249. package/dist/services/aerial-view.d.ts.map +0 -1
  250. package/dist/services/aerial-view.js +0 -107
  251. package/dist/services/aerial-view.js.map +0 -1
  252. package/dist/types/aerial-view.d.ts +0 -39
  253. package/dist/types/aerial-view.d.ts.map +0 -1
  254. package/dist/types/aerial-view.js +0 -2
  255. package/dist/types/aerial-view.js.map +0 -1
@@ -0,0 +1,110 @@
1
+ import { googleWebText, GoogleWebError, positiveTimeout } from '../utils/google-web.js';
2
+ import { parseGeminiWebBootstrap, parseGeminiWebConversationHtml } from './parsers.js';
3
+ function checkAbort(signal) { if (signal.aborted)
4
+ throw signal.reason; }
5
+ async function interruptible(promise, signal) {
6
+ checkAbort(signal);
7
+ let abort = () => { };
8
+ const interrupted = new Promise((_resolve, reject) => { abort = () => reject(signal.reason); signal.addEventListener('abort', abort, { once: true }); });
9
+ try {
10
+ return await Promise.race([promise, interrupted]);
11
+ }
12
+ finally {
13
+ signal.removeEventListener('abort', abort);
14
+ }
15
+ }
16
+ async function delay(ms, signal) {
17
+ checkAbort(signal);
18
+ let timer;
19
+ const waiting = new Promise(resolve => { timer = setTimeout(resolve, ms); });
20
+ try {
21
+ await interruptible(waiting, signal);
22
+ }
23
+ finally {
24
+ clearTimeout(timer);
25
+ }
26
+ }
27
+ /** Uses the caller's browser for actual generation; static HTTP bootstrap is inspection only. */
28
+ export class GeminiWebClient {
29
+ config;
30
+ fetcher;
31
+ timeoutMs;
32
+ intervalMs;
33
+ generating = false;
34
+ constructor(config = {}) {
35
+ this.config = config;
36
+ this.fetcher = config.fetch ?? globalThis.fetch;
37
+ this.timeoutMs = positiveTimeout(config.timeoutMs ?? 90_000);
38
+ this.intervalMs = positiveTimeout(config.pollIntervalMs ?? 500);
39
+ }
40
+ async inspect(options = {}) {
41
+ return parseGeminiWebBootstrap(await googleWebText(this.fetcher, new URL('https://gemini.google.com/app?hl=en'), { method: 'GET' }, this.timeoutMs, options.signal));
42
+ }
43
+ /** Submits to the existing browser conversation and waits for a new completed model response. */
44
+ async generate(prompt, options = {}) {
45
+ if (typeof prompt !== 'string' || !prompt.trim())
46
+ throw new TypeError('Gemini prompt must not be empty');
47
+ const page = this.config.page;
48
+ if (!page)
49
+ throw new TypeError('Gemini generation requires a caller-owned browser Page; HTTP bootstrap alone cannot generate an answer');
50
+ if (this.generating)
51
+ throw new TypeError('This Gemini browser conversation already has a generation in progress');
52
+ const timeoutMs = positiveTimeout(options.timeoutMs ?? this.timeoutMs);
53
+ if (options.signal?.aborted)
54
+ throw options.signal.reason;
55
+ const controller = new AbortController();
56
+ const abort = () => controller.abort(options.signal?.reason);
57
+ options.signal?.addEventListener('abort', abort, { once: true });
58
+ const timer = setTimeout(() => controller.abort(new GoogleWebError('Gemini browser generation timed out', 'timeout')), timeoutMs);
59
+ const expiresAt = Date.now() + timeoutMs;
60
+ this.generating = true;
61
+ try {
62
+ if (!/^https:\/\/gemini\.google\.com\/app(?:[/?#]|$)/.test(page.url())) {
63
+ await interruptible(page.goto('https://gemini.google.com/app?hl=en', { waitUntil: 'domcontentloaded', timeout: timeoutMs }), controller.signal);
64
+ }
65
+ let composer;
66
+ while (!composer) {
67
+ checkAbort(controller.signal);
68
+ if (/^https:\/\/(?:accounts|consent)\.google\.com\//.test(page.url()) || /^https:\/\/gemini\.google\.com\/sorry\//.test(page.url()))
69
+ throw new GoogleWebError('Gemini browser requires sign-in, consent or an access challenge', 'blocked');
70
+ const candidates = page.locator('[contenteditable="true"][role="textbox"]');
71
+ const count = await interruptible(candidates.count(), controller.signal);
72
+ for (let index = 0; index < count; index++) {
73
+ const candidate = candidates.nth(index);
74
+ if (await interruptible(candidate.isVisible(), controller.signal)) {
75
+ composer = candidate;
76
+ break;
77
+ }
78
+ }
79
+ if (!composer)
80
+ await delay(this.intervalMs, controller.signal);
81
+ }
82
+ const before = parseGeminiWebConversationHtml(await interruptible(page.content(), controller.signal));
83
+ const priorModels = before.filter(message => message.role === 'model').length;
84
+ checkAbort(controller.signal);
85
+ await interruptible(composer.fill(prompt, { timeout: Math.max(1, expiresAt - Date.now()) }), controller.signal);
86
+ checkAbort(controller.signal);
87
+ await interruptible(composer.press('Enter', { timeout: Math.max(1, expiresAt - Date.now()) }), controller.signal);
88
+ while (true) {
89
+ checkAbort(controller.signal);
90
+ const messages = parseGeminiWebConversationHtml(await interruptible(page.content(), controller.signal));
91
+ const models = messages.filter(message => message.role === 'model');
92
+ let latestUser = messages.length - 1;
93
+ while (latestUser >= 0 && messages[latestUser].role !== 'user')
94
+ latestUser--;
95
+ const answer = messages[messages.length - 1];
96
+ if (models.length > priorModels && latestUser >= 0 && messages[latestUser].text.replace(/\s+/g, ' ').trim() === prompt.replace(/\s+/g, ' ').trim() && answer?.role === 'model' && answer.complete) {
97
+ return { text: answer.text, responseId: answer.id, conversationUrl: page.url() };
98
+ }
99
+ await delay(this.intervalMs, controller.signal);
100
+ }
101
+ }
102
+ finally {
103
+ this.generating = false;
104
+ clearTimeout(timer);
105
+ options.signal?.removeEventListener('abort', abort);
106
+ }
107
+ }
108
+ }
109
+ export function geminiWeb(config = {}) { return new GeminiWebClient(config); }
110
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/gemini-web/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { GeminiWebBootstrap, GeminiWebMessage } from './types.js';
2
+ export declare function parseGeminiWebBootstrap(html: string): GeminiWebBootstrap;
3
+ /** Extracts observed user/model containers; busy or unfinished responses are never marked complete. */
4
+ export declare function parseGeminiWebConversationHtml(html: string): GeminiWebMessage[];
5
+ //# sourceMappingURL=parsers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.d.ts","sourceRoot":"","sources":["../../src/gemini-web/parsers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAOxE;AAgBD,uGAAuG;AACvG,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAqB/E"}
@@ -0,0 +1,62 @@
1
+ import { decodeEntities, descendants, parseHtml, visibleText } from '../google-search/html.js';
2
+ import { googleBootstrap, GoogleWebError } from '../utils/google-web.js';
3
+ export function parseGeminiWebBootstrap(html) {
4
+ const data = googleBootstrap(html);
5
+ if (typeof data.cfb2h !== 'string')
6
+ throw new GoogleWebError('Gemini bootstrap has no build', 'parse');
7
+ return {
8
+ build: data.cfb2h, hasSession: typeof data.FdrFJe === 'string',
9
+ hasPromptToken: typeof data.SNlM0e === 'string' && data.SNlM0e.length > 0, generation: 'unverified',
10
+ };
11
+ }
12
+ function responseText(node) {
13
+ const chunks = [];
14
+ const stack = [node];
15
+ while (stack.length > 0) {
16
+ const value = stack.pop();
17
+ if (typeof value === 'string') {
18
+ chunks.push(value);
19
+ continue;
20
+ }
21
+ if (/^(?:script|style|template|noscript)$/.test(value.tag) || value.attrs.hidden !== undefined || value.attrs['aria-hidden'] === 'true' || /display\s*:\s*none|visibility\s*:\s*hidden/i.test(value.attrs.style ?? ''))
22
+ continue;
23
+ const block = /^(?:p|div|br|li|pre|h[1-6])$/.test(value.tag);
24
+ if (block) {
25
+ chunks.push('\n');
26
+ stack.push('\n');
27
+ }
28
+ for (let i = value.children.length - 1; i >= 0; i--)
29
+ stack.push(value.children[i]);
30
+ }
31
+ return decodeEntities(chunks.join('')).replace(/[\t\f\v ]+/g, ' ').replace(/ *\n */g, '\n').replace(/\n{3,}/g, '\n\n').trim();
32
+ }
33
+ /** Extracts observed user/model containers; busy or unfinished responses are never marked complete. */
34
+ export function parseGeminiWebConversationHtml(html) {
35
+ if (typeof html !== 'string' || html.length > 10_000_000)
36
+ throw new GoogleWebError('Unsupported Gemini HTML size', 'parse');
37
+ const nodes = descendants(parseHtml(html));
38
+ const messages = [];
39
+ for (const node of nodes) {
40
+ if (node.tag === 'user-query') {
41
+ const lines = descendants(node).filter(child => /(?:^|\s)query-text-line(?:\s|$)/.test(child.attrs.class ?? ''));
42
+ const text = lines.map(visibleText).join('\n');
43
+ if (text)
44
+ messages.push({ role: 'user', text });
45
+ }
46
+ else if (node.tag === 'model-response') {
47
+ const children = descendants(node);
48
+ const content = children.find(child => child.tag === 'message-content');
49
+ if (!content)
50
+ continue;
51
+ const markdown = descendants(content).find(child => /(?:^|\s)markdown(?:\s|$)/.test(child.attrs.class ?? ''));
52
+ if (!markdown)
53
+ continue;
54
+ const text = responseText(markdown);
55
+ const finished = children.some(child => /(?:^|\s)response-footer(?:\s|$)/.test(child.attrs.class ?? '') && /(?:^|\s)complete(?:\s|$)/.test(child.attrs.class ?? ''));
56
+ if (text)
57
+ messages.push({ role: 'model', text, complete: markdown.attrs['aria-busy'] === 'false' && finished, id: content.attrs.id });
58
+ }
59
+ }
60
+ return messages;
61
+ }
62
+ //# sourceMappingURL=parsers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/gemini-web/parsers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { GoogleWebConfig, GoogleWebRequestOptions } from '../utils/google-web.js';
2
+ export interface GeminiBrowserLocator {
3
+ count(): Promise<number>;
4
+ nth(index: number): GeminiBrowserLocator;
5
+ isVisible(): Promise<boolean>;
6
+ fill(value: string, options?: {
7
+ timeout?: number;
8
+ }): Promise<void>;
9
+ press(key: string, options?: {
10
+ timeout?: number;
11
+ }): Promise<void>;
12
+ }
13
+ /** The subset of a browser Page needed to use the observed anonymous Gemini composer. */
14
+ export interface GeminiBrowserPage {
15
+ url(): string;
16
+ goto(url: string, options?: {
17
+ waitUntil?: 'domcontentloaded';
18
+ timeout?: number;
19
+ }): Promise<unknown>;
20
+ content(): Promise<string>;
21
+ locator(selector: string): GeminiBrowserLocator;
22
+ }
23
+ export interface GeminiWebConfig extends GoogleWebConfig {
24
+ page?: GeminiBrowserPage;
25
+ pollIntervalMs?: number;
26
+ }
27
+ export interface GeminiWebBootstrap {
28
+ build: string;
29
+ hasSession: boolean;
30
+ hasPromptToken: boolean;
31
+ generation: 'unverified';
32
+ }
33
+ export interface GeminiWebMessage {
34
+ role: 'user' | 'model';
35
+ text: string;
36
+ complete?: boolean;
37
+ id?: string;
38
+ }
39
+ export interface GeminiWebGenerationOptions extends GoogleWebRequestOptions {
40
+ timeoutMs?: number;
41
+ }
42
+ export interface GeminiWebGeneration {
43
+ text: string;
44
+ responseId?: string;
45
+ conversationUrl: string;
46
+ }
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gemini-web/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEvF,MAAM,WAAW,oBAAoB;IACnC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAAC;IACzC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE;AAED,yFAAyF;AACzF,MAAM,WAAW,iBAAiB;IAChC,GAAG,IAAI,MAAM,CAAC;IACd,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CAAC;CACjD;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,YAAY,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,0BAA2B,SAAQ,uBAAuB;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/gemini-web/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export { GeminiWebClient, geminiWeb } from './gemini-web/client.js';
2
+ export { parseGeminiWebBootstrap, parseGeminiWebConversationHtml } from './gemini-web/parsers.js';
3
+ export { GoogleWebError } from './utils/google-web.js';
4
+ export type * from './gemini-web/types.js';
5
+ //# sourceMappingURL=gemini-web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-web.d.ts","sourceRoot":"","sources":["../src/gemini-web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,mBAAmB,uBAAuB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { GeminiWebClient, geminiWeb } from './gemini-web/client.js';
2
+ export { parseGeminiWebBootstrap, parseGeminiWebConversationHtml } from './gemini-web/parsers.js';
3
+ export { GoogleWebError } from './utils/google-web.js';
4
+ //# sourceMappingURL=gemini-web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-web.js","sourceRoot":"","sources":["../src/gemini-web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { GoogleAutocompleteResponse, GoogleSearchConfig, GoogleSearchOptions, GoogleSearchResponse, GoogleSuggestOptions } from './types.js';
2
+ /** Anonymous public Search and autocomplete requests; access challenges are returned explicitly. */
3
+ export declare class GoogleSearchClient {
4
+ private readonly fetcher;
5
+ private readonly language;
6
+ private readonly country;
7
+ private readonly timeoutMs;
8
+ constructor(config?: GoogleSearchConfig);
9
+ /** Requests Search HTML; JavaScript challenges and unsupported markup are not treated as empty results. */
10
+ search(query: string, options?: GoogleSearchOptions): Promise<GoogleSearchResponse>;
11
+ /** Fetches Google's anonymous public autocomplete suggestions without a Search page or API key. */
12
+ suggest(query: string, options?: GoogleSuggestOptions): Promise<GoogleAutocompleteResponse>;
13
+ private request;
14
+ }
15
+ export declare function googleSearch(config?: GoogleSearchConfig): GoogleSearchClient;
16
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/google-search/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAmBlJ,oGAAoG;AACpG,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,MAAM,GAAE,kBAAuB;IAO3C,2GAA2G;IACrG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAsB7F,mGAAmG;IAC7F,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,0BAA0B,CAAC;YAcvF,OAAO;CAiCtB;AAED,wBAAgB,YAAY,CAAC,MAAM,GAAE,kBAAuB,GAAG,kBAAkB,CAEhF"}
@@ -0,0 +1,117 @@
1
+ import { GoogleSearchError } from './errors.js';
2
+ import { parseGoogleAutocomplete, parseGoogleSearchHtml } from './parsers.js';
3
+ function positive(value) {
4
+ if (!Number.isFinite(value) || value <= 0 || value > 2_147_483_647)
5
+ throw new RangeError('timeoutMs must be positive and no greater than 2147483647');
6
+ return value;
7
+ }
8
+ function queryValue(query) {
9
+ if (typeof query !== 'string' || !query.trim())
10
+ throw new TypeError('A nonempty search query is required');
11
+ return query;
12
+ }
13
+ function retryAfter(value) {
14
+ if (!value)
15
+ return undefined;
16
+ if (/^\d+(?:\.\d+)?$/.test(value))
17
+ return Number(value) * 1000;
18
+ const timestamp = Date.parse(value);
19
+ return Number.isFinite(timestamp) ? Math.max(0, timestamp - Date.now()) : undefined;
20
+ }
21
+ /** Anonymous public Search and autocomplete requests; access challenges are returned explicitly. */
22
+ export class GoogleSearchClient {
23
+ fetcher;
24
+ language;
25
+ country;
26
+ timeoutMs;
27
+ constructor(config = {}) {
28
+ this.fetcher = config.fetch ?? globalThis.fetch;
29
+ this.language = config.language ?? 'en';
30
+ this.country = config.country ?? 'us';
31
+ this.timeoutMs = positive(config.timeoutMs ?? 20_000);
32
+ }
33
+ /** Requests Search HTML; JavaScript challenges and unsupported markup are not treated as empty results. */
34
+ async search(query, options = {}) {
35
+ const endpoint = new URL('https://www.google.com/search');
36
+ endpoint.searchParams.set('q', queryValue(query));
37
+ endpoint.searchParams.set('hl', options.language ?? this.language);
38
+ endpoint.searchParams.set('gl', options.country ?? this.country);
39
+ if (options.start !== undefined) {
40
+ if (!Number.isSafeInteger(options.start) || options.start < 0)
41
+ throw new RangeError('start must be a nonnegative safe integer');
42
+ endpoint.searchParams.set('start', String(options.start));
43
+ }
44
+ if (options.safe !== undefined) {
45
+ if (options.safe !== 'active' && options.safe !== 'off')
46
+ throw new TypeError('safe must be active or off');
47
+ endpoint.searchParams.set('safe', options.safe);
48
+ }
49
+ const { response, body } = await this.request(endpoint, options.signal, true);
50
+ const report = parseGoogleSearchHtml(body, {
51
+ sourceUrl: response.url || endpoint.toString(), query, httpStatus: response.status, includeRawHtml: options.includeRawHtml,
52
+ });
53
+ const delay = retryAfter(response.headers.get('Retry-After'));
54
+ if (delay !== undefined)
55
+ report.retryAfterMs = delay;
56
+ return report;
57
+ }
58
+ /** Fetches Google's anonymous public autocomplete suggestions without a Search page or API key. */
59
+ async suggest(query, options = {}) {
60
+ const endpoint = new URL('https://suggestqueries.google.com/complete/search');
61
+ endpoint.searchParams.set('client', 'firefox');
62
+ endpoint.searchParams.set('q', queryValue(query));
63
+ endpoint.searchParams.set('hl', options.language ?? this.language);
64
+ endpoint.searchParams.set('gl', options.country ?? this.country);
65
+ const { body } = await this.request(endpoint, options.signal);
66
+ let raw;
67
+ try {
68
+ raw = JSON.parse(body);
69
+ }
70
+ catch (cause) {
71
+ throw new GoogleSearchError('Invalid autocomplete JSON', 'parse', undefined, undefined, { cause });
72
+ }
73
+ return parseGoogleAutocomplete(raw);
74
+ }
75
+ async request(url, signal, allowBlocked = false) {
76
+ if (signal?.aborted)
77
+ throw signal.reason;
78
+ const controller = new AbortController();
79
+ const abort = () => controller.abort(signal?.reason);
80
+ signal?.addEventListener('abort', abort, { once: true });
81
+ const timer = setTimeout(() => controller.abort(new GoogleSearchError('Google Search request timed out', 'timeout')), this.timeoutMs);
82
+ timer.unref?.();
83
+ let rejectAbort;
84
+ const interrupted = new Promise((_resolve, reject) => { rejectAbort = reject; });
85
+ const abortRequest = () => rejectAbort?.(controller.signal.reason);
86
+ controller.signal.addEventListener('abort', abortRequest, { once: true });
87
+ try {
88
+ const { response, body } = await Promise.race([
89
+ (async () => {
90
+ const response = await this.fetcher(url.toString(), { method: 'GET', signal: controller.signal });
91
+ return { response, body: await response.text() };
92
+ })(),
93
+ interrupted,
94
+ ]);
95
+ if (!response.ok && !(allowBlocked && [403, 429].includes(response.status))) {
96
+ throw new GoogleSearchError(`Google Search HTTP ${response.status}`, 'http', response.status, retryAfter(response.headers.get('Retry-After')));
97
+ }
98
+ return { response, body };
99
+ }
100
+ catch (cause) {
101
+ if (controller.signal.aborted)
102
+ throw controller.signal.reason;
103
+ if (cause instanceof GoogleSearchError)
104
+ throw cause;
105
+ throw new GoogleSearchError('Google Search network request failed', 'network', undefined, undefined, { cause });
106
+ }
107
+ finally {
108
+ clearTimeout(timer);
109
+ signal?.removeEventListener('abort', abort);
110
+ controller.signal.removeEventListener('abort', abortRequest);
111
+ }
112
+ }
113
+ }
114
+ export function googleSearch(config = {}) {
115
+ return new GoogleSearchClient(config);
116
+ }
117
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/google-search/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type GoogleSearchErrorKind = 'http' | 'network' | 'parse' | 'timeout';
2
+ export declare class GoogleSearchError extends Error {
3
+ readonly kind: GoogleSearchErrorKind;
4
+ readonly status?: number | undefined;
5
+ readonly retryAfterMs?: number | undefined;
6
+ constructor(message: string, kind: GoogleSearchErrorKind, status?: number | undefined, retryAfterMs?: number | undefined, options?: ErrorOptions);
7
+ }
8
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/google-search/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7E,qBAAa,iBAAkB,SAAQ,KAAK;IAGxC,QAAQ,CAAC,IAAI,EAAE,qBAAqB;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM;gBAH9B,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,qBAAqB,EAC3B,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,YAAY,CAAC,EAAE,MAAM,YAAA,EAC9B,OAAO,CAAC,EAAE,YAAY;CAKzB"}
@@ -0,0 +1,13 @@
1
+ export class GoogleSearchError extends Error {
2
+ kind;
3
+ status;
4
+ retryAfterMs;
5
+ constructor(message, kind, status, retryAfterMs, options) {
6
+ super(message, options);
7
+ this.kind = kind;
8
+ this.status = status;
9
+ this.retryAfterMs = retryAfterMs;
10
+ this.name = 'GoogleSearchError';
11
+ }
12
+ }
13
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/google-search/errors.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAG/B;IACA;IACA;IAJX,YACE,OAAe,EACN,IAA2B,EAC3B,MAAe,EACf,YAAqB,EAC9B,OAAsB;QAEtB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QALf,SAAI,GAAJ,IAAI,CAAuB;QAC3B,WAAM,GAAN,MAAM,CAAS;QACf,iBAAY,GAAZ,YAAY,CAAS;QAI9B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ export interface HtmlNode {
2
+ tag: string;
3
+ attrs: Record<string, string>;
4
+ parent?: HtmlNode;
5
+ children: Array<HtmlNode | string>;
6
+ }
7
+ export declare function decodeEntities(value: string): string;
8
+ export declare function parseHtml(html: string): HtmlNode;
9
+ export declare function descendants(node: HtmlNode): HtmlNode[];
10
+ export declare function visibleText(node: HtmlNode): string;
11
+ export declare function ancestor(node: HtmlNode, predicate: (candidate: HtmlNode) => boolean, boundary?: HtmlNode): HtmlNode | undefined;
12
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/google-search/html.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC;CACpC;AAWD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpD;AAaD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CA+ChD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAUtD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAWlD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,SAAS,EAAE,QAAQ,KAAK,OAAO,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAO/H"}
@@ -0,0 +1,135 @@
1
+ const entities = {
2
+ amp: '&', lt: '<', gt: '>', quot: '"', apos: "'", nbsp: ' ',
3
+ hellip: '…', ndash: '–', mdash: '—', rsquo: '’', lsquo: '‘',
4
+ rdquo: '”', ldquo: '“', bull: '•', middot: '·', copy: '©', reg: '®',
5
+ };
6
+ const voidTags = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
7
+ const ignoredTags = new Set(['script', 'style', 'template', 'noscript']);
8
+ export function decodeEntities(value) {
9
+ return value.replace(/&(#x[\da-f]+|#\d+|[a-z]+);/gi, (match, entity) => {
10
+ if (!entity.startsWith('#'))
11
+ return entities[entity] ?? match;
12
+ const code = entity[1]?.toLowerCase() === 'x' ? Number.parseInt(entity.slice(2), 16) : Number(entity.slice(1));
13
+ return code > 0 && code <= 0x10ffff && !(code >= 0xd800 && code <= 0xdfff) ? String.fromCodePoint(code) : '�';
14
+ });
15
+ }
16
+ function tagEnd(html, start) {
17
+ let quote;
18
+ for (let i = start; i < html.length; i++) {
19
+ const character = html[i];
20
+ if (quote) {
21
+ if (character === quote)
22
+ quote = undefined;
23
+ }
24
+ else if (character === '"' || character === "'")
25
+ quote = character;
26
+ else if (character === '>')
27
+ return i;
28
+ }
29
+ return -1;
30
+ }
31
+ export function parseHtml(html) {
32
+ const root = { tag: '#document', attrs: {}, children: [] };
33
+ const stack = [root];
34
+ const lower = html.toLowerCase();
35
+ let cursor = 0;
36
+ while (cursor < html.length) {
37
+ const open = html.indexOf('<', cursor);
38
+ const parent = stack[stack.length - 1];
39
+ if (open === -1) {
40
+ parent.children.push(html.slice(cursor));
41
+ break;
42
+ }
43
+ if (open > cursor)
44
+ parent.children.push(html.slice(cursor, open));
45
+ if (html.startsWith('<!--', open)) {
46
+ const end = html.indexOf('-->', open + 4);
47
+ cursor = end === -1 ? html.length : end + 3;
48
+ continue;
49
+ }
50
+ const end = tagEnd(html, open + 1);
51
+ if (end === -1) {
52
+ parent.children.push(html.slice(open));
53
+ break;
54
+ }
55
+ const token = html.slice(open + 1, end);
56
+ const match = /^(\/?)\s*([a-z][a-z\d:-]*)\b/i.exec(token);
57
+ cursor = end + 1;
58
+ if (!match)
59
+ continue;
60
+ const tag = match[2].toLowerCase();
61
+ if (match[1]) {
62
+ for (let i = stack.length - 1; i > 0; i--) {
63
+ if (stack[i].tag === tag) {
64
+ stack.length = i;
65
+ break;
66
+ }
67
+ }
68
+ continue;
69
+ }
70
+ const attrs = Object.create(null);
71
+ const pattern = /([^\s=/>]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
72
+ pattern.lastIndex = match[0].length;
73
+ let attribute;
74
+ while ((attribute = pattern.exec(token))) {
75
+ const name = attribute[1].toLowerCase();
76
+ if (!(name in attrs))
77
+ attrs[name] = decodeEntities(attribute[2] ?? attribute[3] ?? attribute[4] ?? '');
78
+ }
79
+ const node = { tag, attrs, children: [], parent };
80
+ parent.children.push(node);
81
+ if (ignoredTags.has(tag)) {
82
+ const close = lower.indexOf(`</${tag}`, cursor);
83
+ if (close !== -1) {
84
+ const closeEnd = tagEnd(html, close + 2);
85
+ cursor = closeEnd === -1 ? html.length : closeEnd + 1;
86
+ }
87
+ else
88
+ cursor = html.length;
89
+ }
90
+ else if (!voidTags.has(tag) && !token.endsWith('/'))
91
+ stack.push(node);
92
+ }
93
+ return root;
94
+ }
95
+ export function descendants(node) {
96
+ const found = [];
97
+ const stack = [...node.children].reverse();
98
+ while (stack.length > 0) {
99
+ const value = stack.pop();
100
+ if (typeof value !== 'object' || ignoredTags.has(value.tag) || value.attrs.hidden !== undefined || value.attrs['aria-hidden'] === 'true' || /display\s*:\s*none|visibility\s*:\s*hidden/i.test(value.attrs.style ?? ''))
101
+ continue;
102
+ found.push(value);
103
+ for (let i = value.children.length - 1; i >= 0; i--)
104
+ stack.push(value.children[i]);
105
+ }
106
+ return found;
107
+ }
108
+ export function visibleText(node) {
109
+ const text = [];
110
+ const stack = [node];
111
+ while (stack.length > 0) {
112
+ const value = stack.pop();
113
+ if (typeof value === 'string') {
114
+ text.push(value);
115
+ continue;
116
+ }
117
+ if (ignoredTags.has(value.tag) || value.attrs.hidden !== undefined || value.attrs['aria-hidden'] === 'true' || /display\s*:\s*none|visibility\s*:\s*hidden/i.test(value.attrs.style ?? ''))
118
+ continue;
119
+ if (/^(?:br|div|p|li|section|h[1-6])$/.test(value.tag))
120
+ text.push(' ');
121
+ for (let i = value.children.length - 1; i >= 0; i--)
122
+ stack.push(value.children[i]);
123
+ }
124
+ return decodeEntities(text.join('')).replace(/\s+/g, ' ').trim();
125
+ }
126
+ export function ancestor(node, predicate, boundary) {
127
+ let current = node;
128
+ while (current && current !== boundary) {
129
+ if (predicate(current))
130
+ return current;
131
+ current = current.parent;
132
+ }
133
+ return undefined;
134
+ }
135
+ //# sourceMappingURL=html.js.map