@crawlee/browser 3.0.0-alpha.2 → 3.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,405 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.browserCrawlerEnqueueLinks = exports.BrowserCrawler = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const timeout_1 = require("@apify/timeout");
6
+ const core_1 = require("@crawlee/core");
7
+ const basic_1 = require("@crawlee/basic");
8
+ const browser_pool_1 = require("@crawlee/browser-pool");
9
+ const ow_1 = tslib_1.__importDefault(require("ow"));
10
+ /**
11
+ * Provides a simple framework for parallel crawling of web pages
12
+ * using headless browsers with [Puppeteer](https://github.com/puppeteer/puppeteer)
13
+ * and [Playwright](https://github.com/microsoft/playwright).
14
+ * The URLs to crawl are fed either from a static list of URLs
15
+ * or from a dynamic queue of URLs enabling recursive crawling of websites.
16
+ *
17
+ * Since `BrowserCrawler` uses headless or even headfull browsers to download web pages and extract data,
18
+ * it is useful for crawling of websites that require to execute JavaScript.
19
+ * If the target website doesn't need JavaScript, consider using {@link CheerioCrawler},
20
+ * which downloads the pages using raw HTTP requests and is about 10x faster.
21
+ *
22
+ * The source URLs are represented using {@link Request} objects that are fed from
23
+ * {@link RequestList} or {@link RequestQueue} instances provided by the {@link BrowserCrawlerOptions.requestList}
24
+ * or {@link BrowserCrawlerOptions.requestQueue} constructor options, respectively.
25
+ *
26
+ * If both {@link BrowserCrawlerOptions.requestList} and {@link BrowserCrawlerOptions.requestQueue} are used,
27
+ * the instance first processes URLs from the {@link RequestList} and automatically enqueues all of them
28
+ * to {@link RequestQueue} before it starts their processing. This ensures that a single URL is not crawled multiple times.
29
+ *
30
+ * The crawler finishes when there are no more {@link Request} objects to crawl.
31
+ *
32
+ * `BrowserCrawler` opens a new browser page (i.e. tab or window) for each {@link Request} object to crawl
33
+ * and then calls the function provided by user as the {@link BrowserCrawlerOptions.handlePageFunction} option.
34
+ *
35
+ * New pages are only opened when there is enough free CPU and memory available,
36
+ * using the functionality provided by the {@link AutoscaledPool} class.
37
+ * All {@link AutoscaledPool} configuration options can be passed to the {@link BrowserCrawlerOptions.autoscaledPoolOptions}
38
+ * parameter of the `BrowserCrawler` constructor. For user convenience, the `minConcurrency` and `maxConcurrency`
39
+ * {@link AutoscaledPoolOptions} are available directly in the `BrowserCrawler` constructor.
40
+ *
41
+ * Note that the pool of browser instances is internally managed by the [BrowserPool](https://github.com/apify/browser-pool) class.
42
+ * ```js
43
+ * await crawler.run();
44
+ * ```
45
+ * @category Crawlers
46
+ */
47
+ class BrowserCrawler extends basic_1.BasicCrawler {
48
+ /**
49
+ * All `BrowserCrawler` parameters are passed via an options object.
50
+ */
51
+ constructor(options) {
52
+ (0, ow_1.default)(options, 'BrowserCrawlerOptions', ow_1.default.object.exactShape(BrowserCrawler.optionsShape));
53
+ const { navigationTimeoutSecs = 60, requestHandlerTimeoutSecs = 60, gotoFunction, // deprecated
54
+ gotoTimeoutSecs, // deprecated
55
+ persistCookiesPerSession, proxyConfiguration, browserPoolOptions, preNavigationHooks = [], postNavigationHooks = [],
56
+ // Ignored
57
+ handleRequestFunction, requestHandler: userProvidedRequestHandler, handlePageFunction, failedRequestHandler, handleFailedRequestFunction, ...basicCrawlerOptions } = options;
58
+ super({
59
+ ...basicCrawlerOptions,
60
+ requestHandler: (...args) => this._runRequestHandler(...args),
61
+ requestHandlerTimeoutSecs: navigationTimeoutSecs + requestHandlerTimeoutSecs + basic_1.BASIC_CRAWLER_TIMEOUT_BUFFER_SECS,
62
+ });
63
+ /**
64
+ * A reference to the underlying {@link ProxyConfiguration} class that manages the crawler's proxies.
65
+ * Only available if used by the crawler.
66
+ */
67
+ Object.defineProperty(this, "proxyConfiguration", {
68
+ enumerable: true,
69
+ configurable: true,
70
+ writable: true,
71
+ value: void 0
72
+ });
73
+ /**
74
+ * A reference to the underlying `BrowserPool` class that manages the crawler's browsers.
75
+ * For more information about it, see the [`browser-pool` module](https://github.com/apify/browser-pool).
76
+ * @todo the type is almost unusable with so many generic arguments, what should go there? we need inference
77
+ */
78
+ Object.defineProperty(this, "browserPool", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: void 0
83
+ });
84
+ Object.defineProperty(this, "launchContext", {
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true,
88
+ value: void 0
89
+ });
90
+ Object.defineProperty(this, "userProvidedRequestHandler", {
91
+ enumerable: true,
92
+ configurable: true,
93
+ writable: true,
94
+ value: void 0
95
+ });
96
+ Object.defineProperty(this, "navigationTimeoutMillis", {
97
+ enumerable: true,
98
+ configurable: true,
99
+ writable: true,
100
+ value: void 0
101
+ });
102
+ Object.defineProperty(this, "gotoFunction", {
103
+ enumerable: true,
104
+ configurable: true,
105
+ writable: true,
106
+ value: void 0
107
+ });
108
+ Object.defineProperty(this, "defaultGotoOptions", {
109
+ enumerable: true,
110
+ configurable: true,
111
+ writable: true,
112
+ value: void 0
113
+ });
114
+ Object.defineProperty(this, "preNavigationHooks", {
115
+ enumerable: true,
116
+ configurable: true,
117
+ writable: true,
118
+ value: void 0
119
+ });
120
+ Object.defineProperty(this, "postNavigationHooks", {
121
+ enumerable: true,
122
+ configurable: true,
123
+ writable: true,
124
+ value: void 0
125
+ });
126
+ Object.defineProperty(this, "persistCookiesPerSession", {
127
+ enumerable: true,
128
+ configurable: true,
129
+ writable: true,
130
+ value: void 0
131
+ });
132
+ this._handlePropertyNameChange({
133
+ newName: 'requestHandler',
134
+ oldName: 'handlePageFunction',
135
+ propertyKey: 'userProvidedRequestHandler',
136
+ newProperty: userProvidedRequestHandler,
137
+ oldProperty: handlePageFunction,
138
+ });
139
+ this._handlePropertyNameChange({
140
+ newName: 'failedRequestHandler',
141
+ oldName: 'handleFailedRequestFunction',
142
+ propertyKey: 'failedRequestHandler',
143
+ newProperty: failedRequestHandler,
144
+ oldProperty: handleFailedRequestFunction,
145
+ allowUndefined: true,
146
+ });
147
+ // Cookies should be persisted per session only if session pool is used
148
+ if (!this.useSessionPool && persistCookiesPerSession) {
149
+ throw new Error('You cannot use "persistCookiesPerSession" without "useSessionPool" set to true.');
150
+ }
151
+ if (gotoTimeoutSecs) {
152
+ this.log.deprecated('Option "gotoTimeoutSecs" is deprecated. Use "navigationTimeoutSecs" instead.');
153
+ }
154
+ this.navigationTimeoutMillis = (gotoTimeoutSecs || navigationTimeoutSecs) * 1000;
155
+ this.gotoFunction = gotoFunction;
156
+ this.defaultGotoOptions = {
157
+ timeout: this.navigationTimeoutMillis,
158
+ };
159
+ this.proxyConfiguration = proxyConfiguration;
160
+ this.preNavigationHooks = preNavigationHooks;
161
+ this.postNavigationHooks = postNavigationHooks;
162
+ if (this.useSessionPool) {
163
+ this.persistCookiesPerSession = persistCookiesPerSession !== undefined ? persistCookiesPerSession : true;
164
+ }
165
+ else {
166
+ this.persistCookiesPerSession = false;
167
+ }
168
+ const { preLaunchHooks = [], postLaunchHooks = [], ...rest } = browserPoolOptions;
169
+ this.browserPool = new browser_pool_1.BrowserPool({
170
+ ...rest,
171
+ preLaunchHooks: [
172
+ this._extendLaunchContext.bind(this),
173
+ ...preLaunchHooks,
174
+ ],
175
+ postLaunchHooks: [
176
+ this._maybeAddSessionRetiredListener.bind(this),
177
+ ...postLaunchHooks,
178
+ ],
179
+ });
180
+ }
181
+ /**
182
+ * Wrapper around handlePageFunction that opens and closes pages etc.
183
+ */
184
+ async _runRequestHandler(crawlingContext) {
185
+ const newPageOptions = {
186
+ id: crawlingContext.id,
187
+ };
188
+ const useIncognitoPages = this.launchContext?.useIncognitoPages;
189
+ if (this.proxyConfiguration && useIncognitoPages) {
190
+ const { session } = crawlingContext;
191
+ const proxyInfo = this.proxyConfiguration.newProxyInfo(session?.id);
192
+ crawlingContext.proxyInfo = proxyInfo;
193
+ newPageOptions.proxyUrl = proxyInfo.url;
194
+ if (this.proxyConfiguration.isManInTheMiddle) {
195
+ /**
196
+ * @see https://playwright.dev/docs/api/class-browser/#browser-new-context
197
+ * @see https://github.com/puppeteer/puppeteer/blob/main/docs/api.md
198
+ */
199
+ newPageOptions.pageOptions = {
200
+ ignoreHTTPSErrors: true,
201
+ };
202
+ }
203
+ }
204
+ const page = await this.browserPool.newPage(newPageOptions);
205
+ (0, timeout_1.tryCancel)();
206
+ this._enhanceCrawlingContextWithPageInfo(crawlingContext, page, useIncognitoPages);
207
+ // DO NOT MOVE THIS LINE ABOVE!
208
+ // `enhanceCrawlingContextWithPageInfo` gives us a valid session.
209
+ // For example, `sessionPoolOptions.sessionOptions.maxUsageCount` can be `1`.
210
+ // So we must not save the session prior to making sure it was used only once, otherwise we would use it twice.
211
+ const { request, session } = crawlingContext;
212
+ if (this.useSessionPool) {
213
+ const sessionCookies = session.getPuppeteerCookies(request.url);
214
+ if (sessionCookies.length) {
215
+ await crawlingContext.browserController.setCookies(page, sessionCookies);
216
+ (0, timeout_1.tryCancel)();
217
+ }
218
+ }
219
+ try {
220
+ await this._handleNavigation(crawlingContext);
221
+ (0, timeout_1.tryCancel)();
222
+ await this._responseHandler(crawlingContext);
223
+ (0, timeout_1.tryCancel)();
224
+ // save cookies
225
+ // TODO: Should we save the cookies also after/only the handle page?
226
+ if (this.persistCookiesPerSession) {
227
+ const cookies = await crawlingContext.browserController.getCookies(page);
228
+ (0, timeout_1.tryCancel)();
229
+ session?.setPuppeteerCookies(cookies, request.loadedUrl);
230
+ }
231
+ await (0, timeout_1.addTimeoutToPromise)(() => Promise.resolve(this.userProvidedRequestHandler(crawlingContext)), this.requestHandlerTimeoutMillis, `requestHandler timed out after ${this.requestHandlerTimeoutMillis / 1000} seconds.`);
232
+ (0, timeout_1.tryCancel)();
233
+ if (session)
234
+ session.markGood();
235
+ }
236
+ finally {
237
+ page.close().catch((error) => this.log.debug('Error while closing page', { error }));
238
+ }
239
+ }
240
+ _enhanceCrawlingContextWithPageInfo(crawlingContext, page, useIncognitoPages) {
241
+ crawlingContext.page = page;
242
+ // This switch is because the crawlingContexts are created on per request basis.
243
+ // However, we need to add the proxy info and session from browser, which is created based on the browser-pool configuration.
244
+ // We would not have to do this switch if the proxy and configuration worked as in CheerioCrawler,
245
+ // which configures proxy and session for every new request
246
+ const browserControllerInstance = this.browserPool.getBrowserControllerByPage(page);
247
+ crawlingContext.browserController = browserControllerInstance;
248
+ if (!useIncognitoPages) {
249
+ crawlingContext.session = browserControllerInstance.launchContext.session;
250
+ }
251
+ if (!crawlingContext.proxyInfo) {
252
+ crawlingContext.proxyInfo = browserControllerInstance.launchContext.proxyInfo;
253
+ }
254
+ crawlingContext.enqueueLinks = async (enqueueOptions) => {
255
+ return browserCrawlerEnqueueLinks({
256
+ options: enqueueOptions,
257
+ page,
258
+ requestQueue: await this.getRequestQueue(),
259
+ defaultBaseUrl: new URL(crawlingContext.request.loadedUrl ?? crawlingContext.request.url).origin,
260
+ });
261
+ };
262
+ }
263
+ async _handleNavigation(crawlingContext) {
264
+ const gotoOptions = { ...this.defaultGotoOptions };
265
+ await this._executeHooks(this.preNavigationHooks, crawlingContext, gotoOptions);
266
+ (0, timeout_1.tryCancel)();
267
+ try {
268
+ crawlingContext.response = await this._navigationHandler(crawlingContext, gotoOptions);
269
+ }
270
+ catch (error) {
271
+ this._handleNavigationTimeout(crawlingContext, error);
272
+ throw error;
273
+ }
274
+ (0, timeout_1.tryCancel)();
275
+ await this._executeHooks(this.postNavigationHooks, crawlingContext, gotoOptions);
276
+ }
277
+ /**
278
+ * Marks session bad in case of navigation timeout.
279
+ */
280
+ _handleNavigationTimeout(crawlingContext, error) {
281
+ const { session } = crawlingContext;
282
+ if (error && error.constructor.name === 'TimeoutError') {
283
+ (0, core_1.handleRequestTimeout)({ session, errorMessage: error.message });
284
+ }
285
+ }
286
+ async _navigationHandler(crawlingContext, gotoOptions) {
287
+ if (!this.gotoFunction) {
288
+ // @TODO: although it is optional in the validation,
289
+ // because when you make automation library specific you can override this handler.
290
+ throw new Error('BrowserCrawler: You must specify a gotoFunction!');
291
+ }
292
+ return this.gotoFunction(crawlingContext, gotoOptions);
293
+ }
294
+ /**
295
+ * Should be overridden in case of different automation library that does not support this response API.
296
+ * @todo: This can be also done as a postNavigation hook except the loadedUrl marking.
297
+ */
298
+ async _responseHandler(crawlingContext) {
299
+ const { response, session, request, page } = crawlingContext;
300
+ if (this.sessionPool && response && session) {
301
+ if (typeof response === 'object' && typeof response.status === 'function') {
302
+ (0, core_1.throwOnBlockedRequest)(session, response.status());
303
+ }
304
+ else {
305
+ this.log.debug('Got a malformed Browser response.', { request, response });
306
+ }
307
+ }
308
+ request.loadedUrl = await page.url();
309
+ }
310
+ async _extendLaunchContext(_pageId, launchContext) {
311
+ const launchContextExtends = {};
312
+ if (this.sessionPool) {
313
+ launchContextExtends.session = await this.sessionPool.getSession();
314
+ }
315
+ if (this.proxyConfiguration) {
316
+ const proxyInfo = this.proxyConfiguration.newProxyInfo(launchContextExtends.session && launchContextExtends.session.id);
317
+ launchContext.proxyUrl = proxyInfo.url;
318
+ launchContextExtends.proxyInfo = proxyInfo;
319
+ // Disable SSL verification for MITM proxies
320
+ if (this.proxyConfiguration.isManInTheMiddle) {
321
+ /**
322
+ * @see https://playwright.dev/docs/api/class-browser/#browser-new-context
323
+ * @see https://github.com/puppeteer/puppeteer/blob/main/docs/api.md
324
+ */
325
+ launchContext.launchOptions.ignoreHTTPSErrors = true;
326
+ }
327
+ }
328
+ launchContext.extend(launchContextExtends);
329
+ }
330
+ _maybeAddSessionRetiredListener(_pageId, browserController) {
331
+ if (this.sessionPool) {
332
+ const listener = (session) => {
333
+ const { launchContext } = browserController;
334
+ if (session.id === launchContext.session.id) {
335
+ this.browserPool.retireBrowserController(browserController);
336
+ }
337
+ };
338
+ this.sessionPool.on(core_1.EVENT_SESSION_RETIRED, listener);
339
+ browserController.on("browserClosed" /* BROWSER_CLOSED */, () => {
340
+ return this.sessionPool.removeListener(core_1.EVENT_SESSION_RETIRED, listener);
341
+ });
342
+ }
343
+ }
344
+ /**
345
+ * Function for cleaning up after all request are processed.
346
+ * @ignore
347
+ */
348
+ async teardown() {
349
+ await this.browserPool.destroy();
350
+ await super.teardown();
351
+ }
352
+ }
353
+ exports.BrowserCrawler = BrowserCrawler;
354
+ Object.defineProperty(BrowserCrawler, "optionsShape", {
355
+ enumerable: true,
356
+ configurable: true,
357
+ writable: true,
358
+ value: {
359
+ ...basic_1.BasicCrawler.optionsShape,
360
+ handlePageFunction: ow_1.default.optional.function,
361
+ gotoFunction: ow_1.default.optional.function,
362
+ gotoTimeoutSecs: ow_1.default.optional.number.greaterThan(0),
363
+ navigationTimeoutSecs: ow_1.default.optional.number.greaterThan(0),
364
+ preNavigationHooks: ow_1.default.optional.array,
365
+ postNavigationHooks: ow_1.default.optional.array,
366
+ browserPoolOptions: ow_1.default.object,
367
+ sessionPoolOptions: ow_1.default.optional.object,
368
+ persistCookiesPerSession: ow_1.default.optional.boolean,
369
+ useSessionPool: ow_1.default.optional.boolean,
370
+ proxyConfiguration: ow_1.default.optional.object.validate(core_1.validators.proxyConfiguration),
371
+ }
372
+ });
373
+ /** @internal */
374
+ async function browserCrawlerEnqueueLinks({ options, page, requestQueue, defaultBaseUrl }) {
375
+ const baseUrl = options?.baseUrl ?? defaultBaseUrl;
376
+ const urls = await extractUrlsFromPage(page, options?.selector ?? 'a', baseUrl);
377
+ return (0, core_1.enqueueLinks)({
378
+ // FIXME this does not make much sense, as the instance would be ignored by any crawler - the argument needs to be required
379
+ requestQueue: requestQueue ?? await core_1.RequestQueue.open(),
380
+ urls,
381
+ baseUrl,
382
+ ...options,
383
+ });
384
+ }
385
+ exports.browserCrawlerEnqueueLinks = browserCrawlerEnqueueLinks;
386
+ /**
387
+ * Extracts URLs from a given page.
388
+ * @ignore
389
+ */
390
+ // eslint-disable-next-line @typescript-eslint/ban-types
391
+ async function extractUrlsFromPage(page, selector, baseUrl) {
392
+ const urls = await page.$$eval(selector, (linkEls) => linkEls.map((link) => link.getAttribute('href')).filter((href) => !!href));
393
+ return urls.map((href) => {
394
+ // Throw a meaningful error when only a relative URL would be extracted instead of waiting for the Request to fail later.
395
+ const isHrefAbsolute = /^[a-z][a-z0-9+.-]*:/.test(href); // Grabbed this in 'is-absolute-url' package.
396
+ if (!isHrefAbsolute && !baseUrl) {
397
+ throw new Error(`An extracted URL: ${href} is relative and options.baseUrl is not set. `
398
+ + 'Use options.baseUrl in enqueueLinks() to automatically resolve relative URLs.');
399
+ }
400
+ return baseUrl
401
+ ? (new URL(href, baseUrl)).href
402
+ : href;
403
+ });
404
+ }
405
+ //# sourceMappingURL=browser-crawler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-crawler.js","sourceRoot":"","sources":["../../src/internals/browser-crawler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { Dictionary, Constructor } from '@crawlee/utils';
2
+ import { BrowserPlugin, BrowserPluginOptions } from '@crawlee/browser-pool';
3
+ export interface BrowserLaunchContext<TOptions, Launcher> extends BrowserPluginOptions<TOptions> {
4
+ /**
5
+ * If `true` and `executablePath` is not set,
6
+ * the launcher will launch full Google Chrome browser available on the machine
7
+ * rather than the bundled Chromium. The path to Chrome executable
8
+ * is taken from the `APIFY_CHROME_EXECUTABLE_PATH` environment variable if provided,
9
+ * or defaults to the typical Google Chrome executable location specific for the operating system.
10
+ * By default, this option is `false`.
11
+ * @default false
12
+ */
13
+ useChrome?: boolean;
14
+ launcher?: Launcher;
15
+ }
16
+ /**
17
+ * Abstract class for creating browser launchers, such as `PlaywrightLauncher` and `PuppeteerLauncher`.
18
+ * @ignore
19
+ */
20
+ export declare abstract class BrowserLauncher<Plugin extends BrowserPlugin, Launcher = Plugin['library'], T extends Constructor<Plugin> = Constructor<Plugin>, LaunchOptions = Partial<Parameters<Plugin['launch']>[0]>, LaunchResult extends ReturnType<Plugin['launch']> = ReturnType<Plugin['launch']>> {
21
+ launcher: Launcher;
22
+ proxyUrl?: string;
23
+ useChrome?: boolean;
24
+ launchOptions: Dictionary;
25
+ otherLaunchContextProps: Dictionary;
26
+ Plugin: T;
27
+ userAgent?: string;
28
+ protected static optionsShape: {
29
+ proxyUrl: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
30
+ useChrome: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
31
+ useIncognitoPages: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
32
+ userDataDir: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
33
+ launchOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
34
+ };
35
+ static requireLauncherOrThrow<T>(launcher: string, apifyImageName: string): T;
36
+ /**
37
+ * All `BrowserLauncher` parameters are passed via an launchContext object.
38
+ */
39
+ constructor(launchContext: BrowserLaunchContext<LaunchOptions, Launcher>);
40
+ /**
41
+ * @ignore
42
+ */
43
+ createBrowserPlugin(): Plugin;
44
+ /**
45
+ * Launches a browser instance based on the plugin.
46
+ * @returns Browser instance.
47
+ */
48
+ launch(): LaunchResult;
49
+ createLaunchOptions(): {
50
+ args?: string[];
51
+ } & Dictionary;
52
+ protected _getDefaultHeadlessOption(): boolean;
53
+ protected _getChromeExecutablePath(): string;
54
+ /**
55
+ * Gets a typical path to Chrome executable, depending on the current operating system.
56
+ */
57
+ protected _getTypicalChromeExecutablePath(): string;
58
+ protected _validateProxyUrlProtocol(proxyUrl?: string): void;
59
+ }
60
+ //# sourceMappingURL=browser-launcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-launcher.d.ts","sourceRoot":"","sources":["../../src/internals/browser-launcher.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,UAAU,EACV,WAAW,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACH,aAAa,EACb,oBAAoB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAE,SAAQ,oBAAoB,CAAC,QAAQ,CAAC;IAC5F;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED;;;GAGG;AACH,8BAAsB,eAAe,CACjC,MAAM,SAAS,aAAa,EAC5B,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,EAC5B,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,EACnD,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACxD,YAAY,SAAS,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEhF,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,UAAU,CAAC;IAC1B,uBAAuB,EAAE,UAAU,CAAC;IAEpC,MAAM,EAAG,CAAC,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,MAAM,CAAC,YAAY;;;;;;MAM3B;IAEF,MAAM,CAAC,sBAAsB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,CAAC;IAuB7E;;OAEG;gBACS,aAAa,EAAE,oBAAoB,CAAC,aAAa,EAAE,QAAQ,CAAC;IAmBxE;;OAEG;IACH,mBAAmB,IAAI,MAAM;IAQ7B;;;OAGG;IACH,MAAM,IAAI,YAAY;IAOtB,mBAAmB,IAAI;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,UAAU;IAgBvD,SAAS,CAAC,yBAAyB,IAAI,OAAO;IAI9C,SAAS,CAAC,wBAAwB,IAAI,MAAM;IAI5C;;OAEG;IACH,SAAS,CAAC,+BAA+B,IAAI,MAAM;IA8BnD,SAAS,CAAC,yBAAyB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAe/D"}