@pyscript/core 0.7.14 → 0.7.15

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 (38) hide show
  1. package/dist/{codemirror-lkW_eC9r.js → codemirror-BIjK0FyF.js} +2 -2
  2. package/dist/{codemirror-lkW_eC9r.js.map → codemirror-BIjK0FyF.js.map} +1 -1
  3. package/dist/{codemirror_commands-DL2aL4qa.js → codemirror_commands-Ot159sys.js} +2 -2
  4. package/dist/{codemirror_commands-DL2aL4qa.js.map → codemirror_commands-Ot159sys.js.map} +1 -1
  5. package/dist/{codemirror_lang-python-DD5EtV36.js → codemirror_lang-python-BrxzY-1G.js} +2 -2
  6. package/dist/{codemirror_lang-python-DD5EtV36.js.map → codemirror_lang-python-BrxzY-1G.js.map} +1 -1
  7. package/dist/{codemirror_language-DRHeqAwG.js → codemirror_language-CGuBIifm.js} +2 -2
  8. package/dist/{codemirror_language-DRHeqAwG.js.map → codemirror_language-CGuBIifm.js.map} +1 -1
  9. package/dist/{codemirror_view-FN7LalDk.js → codemirror_view-C_m1bYT7.js} +2 -2
  10. package/dist/{codemirror_view-FN7LalDk.js.map → codemirror_view-C_m1bYT7.js.map} +1 -1
  11. package/dist/{core-CxWc2b7k.js → core-uXjUCyYJ.js} +3 -3
  12. package/dist/{core-CxWc2b7k.js.map → core-uXjUCyYJ.js.map} +1 -1
  13. package/dist/core.js +1 -1
  14. package/dist/{deprecations-manager-C3dm_nFe.js → deprecations-manager-9ZyrTvDd.js} +2 -2
  15. package/dist/{deprecations-manager-C3dm_nFe.js.map → deprecations-manager-9ZyrTvDd.js.map} +1 -1
  16. package/dist/{donkey-BEomLEVJ.js → donkey-BT724r9p.js} +2 -2
  17. package/dist/{donkey-BEomLEVJ.js.map → donkey-BT724r9p.js.map} +1 -1
  18. package/dist/{error-BxgMGRHm.js → error-M0noMyk4.js} +2 -2
  19. package/dist/{error-BxgMGRHm.js.map → error-M0noMyk4.js.map} +1 -1
  20. package/dist/{index-C-U2wRvV.js → index-DM-nsZEM.js} +2 -2
  21. package/dist/{index-C-U2wRvV.js.map → index-DM-nsZEM.js.map} +1 -1
  22. package/dist/{mpy-vg214mJz.js → mpy-C-mFwLd4.js} +2 -2
  23. package/dist/{mpy-vg214mJz.js.map → mpy-C-mFwLd4.js.map} +1 -1
  24. package/dist/{py-D41YGorm.js → py-CCtvrzWS.js} +2 -2
  25. package/dist/{py-D41YGorm.js.map → py-CCtvrzWS.js.map} +1 -1
  26. package/dist/{py-editor-CYTrIYru.js → py-editor-DiFcvRlU.js} +2 -2
  27. package/dist/{py-editor-CYTrIYru.js.map → py-editor-DiFcvRlU.js.map} +1 -1
  28. package/dist/{py-game-sxceV63x.js → py-game-2v7HaC-d.js} +2 -2
  29. package/dist/{py-game-sxceV63x.js.map → py-game-2v7HaC-d.js.map} +1 -1
  30. package/dist/{py-terminal-DjW3NiNp.js → py-terminal-C8V2KXpf.js} +2 -2
  31. package/dist/{py-terminal-DjW3NiNp.js.map → py-terminal-C8V2KXpf.js.map} +1 -1
  32. package/dist/toml-DCqPSmRg.js +3 -0
  33. package/dist/toml-DCqPSmRg.js.map +1 -0
  34. package/dist/zip-CgZGjqjF.js.map +1 -1
  35. package/package.json +3 -3
  36. package/src/core.js +174 -186
  37. package/dist/toml-BK2RWy-G.js +0 -3
  38. package/dist/toml-BK2RWy-G.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyscript/core",
3
- "version": "0.7.14",
3
+ "version": "0.7.15",
4
4
  "type": "module",
5
5
  "description": "PyScript",
6
6
  "module": "./index.js",
@@ -71,7 +71,7 @@
71
71
  "@webreflection/utils": "^0.1.1",
72
72
  "add-promise-listener": "^0.1.3",
73
73
  "basic-devtools": "^0.1.6",
74
- "polyscript": "^0.20.5",
74
+ "polyscript": "^0.20.6",
75
75
  "sticky-module": "^0.1.1",
76
76
  "to-json-callback": "^0.1.1",
77
77
  "type-checked-collections": "^0.1.7"
@@ -96,7 +96,7 @@
96
96
  "codemirror": "^6.0.2",
97
97
  "eslint": "^9.39.2",
98
98
  "flatted": "^3.3.3",
99
- "rollup": "^4.55.3",
99
+ "rollup": "^4.56.0",
100
100
  "rollup-plugin-postcss": "^4.0.2",
101
101
  "rollup-plugin-string": "^3.0.0",
102
102
  "static-handler": "^0.5.3",
package/src/core.js CHANGED
@@ -180,201 +180,189 @@ for (const [TYPE, interpreter] of TYPES) {
180
180
  });
181
181
  };
182
182
 
183
- // define the module as both `<script type="py">` and `<py-script>`
184
- // but only if the config didn't throw an error
185
- if (!error) {
186
- // ensure plugins are bootstrapped already before custom type definition
187
- // NOTE: we cannot top-level await in here as plugins import other utilities
188
- // from core.js itself so that custom definition should not be blocking.
189
- plugins().then(() => {
190
- // possible early errors sent by polyscript
191
- const errors = new Map();
192
-
193
- // specific main and worker hooks
194
- const hooks = {
195
- main: {
196
- ...codeFor(main, TYPE),
197
- async onReady(wrap, element) {
198
- registerModule(wrap);
199
-
200
- // allows plugins to do whatever they want with the element
201
- // before regular stuff happens in here
202
- for (const callback of main("onReady"))
203
- await callback(wrap, element);
204
-
205
- // now that all possible plugins are configured,
206
- // bail out if polyscript encountered an error
207
- if (errors.has(element)) {
208
- let { message } = errors.get(element);
209
- errors.delete(element);
210
- const clone = message === INVALID_CONTENT;
211
- message = `(${ErrorCode.CONFLICTING_CODE}) ${message} for `;
212
- message += element.cloneNode(clone).outerHTML;
213
- wrap.io.stderr(message);
214
- return;
215
- }
183
+ // ensure plugins are bootstrapped already before custom type definition
184
+ // NOTE: we cannot top-level await in here as plugins import other utilities
185
+ // from core.js itself so that custom definition should not be blocking.
186
+ plugins().then(() => {
187
+ // let plugins logic decide how to show the error but stop here if any
188
+ if (error) return;
189
+
190
+ // possible early errors sent by polyscript
191
+ const errors = new Map();
192
+
193
+ // specific main and worker hooks
194
+ const hooks = {
195
+ main: {
196
+ ...codeFor(main, TYPE),
197
+ async onReady(wrap, element) {
198
+ registerModule(wrap);
199
+
200
+ // allows plugins to do whatever they want with the element
201
+ // before regular stuff happens in here
202
+ for (const callback of main("onReady"))
203
+ await callback(wrap, element);
204
+
205
+ // now that all possible plugins are configured,
206
+ // bail out if polyscript encountered an error
207
+ if (errors.has(element)) {
208
+ let { message } = errors.get(element);
209
+ errors.delete(element);
210
+ const clone = message === INVALID_CONTENT;
211
+ message = `(${ErrorCode.CONFLICTING_CODE}) ${message} for `;
212
+ message += element.cloneNode(clone).outerHTML;
213
+ wrap.io.stderr(message);
214
+ return;
215
+ }
216
216
 
217
- if (isScript(element)) {
218
- const isAsync = !isSync(element);
219
- const target = element.getAttribute("target");
220
- const show = target
221
- ? queryTarget(element, target)
222
- : document.createElement("script-py");
223
-
224
- if (!target) {
225
- const { head, body } = document;
226
- if (head.contains(element)) body.append(show);
227
- else element.after(show);
228
- }
229
- if (!show.id) show.id = getID();
230
-
231
- // allows the code to retrieve the target element via
232
- // document.currentScript.target if needed
233
- defineProperty(element, "target", { value: show });
234
-
235
- // notify before the code runs
236
- dispatch(element, TYPE, "ready");
237
- dispatchDone(
238
- element,
239
- isAsync,
240
- wrap[`run${isAsync ? "Async" : ""}`](
241
- await fetchSource(element, wrap.io, true),
242
- ),
243
- );
244
- } else {
245
- // resolve PyScriptElement to allow connectedCallback
246
- element._wrap.resolve(wrap);
217
+ if (isScript(element)) {
218
+ const isAsync = !isSync(element);
219
+ const target = element.getAttribute("target");
220
+ const show = target
221
+ ? queryTarget(element, target)
222
+ : document.createElement("script-py");
223
+
224
+ if (!target) {
225
+ const { head, body } = document;
226
+ if (head.contains(element)) body.append(show);
227
+ else element.after(show);
247
228
  }
248
- console.debug("[pyscript/main] PyScript Ready");
249
- },
250
- onWorker(_, xworker) {
251
- assign(xworker.sync, sync);
252
- for (const callback of main("onWorker"))
253
- callback(_, xworker);
254
- },
255
- onBeforeRun(wrap, element) {
256
- currentElement = element;
257
- bootstrapNodeAndPlugins(
258
- main,
259
- wrap,
260
- element,
261
- "onBeforeRun",
262
- );
263
- },
264
- onBeforeRunAsync(wrap, element) {
265
- currentElement = element;
266
- return bootstrapNodeAndPlugins(
267
- main,
268
- wrap,
269
- element,
270
- "onBeforeRunAsync",
271
- );
272
- },
273
- onAfterRun(wrap, element) {
274
- bootstrapNodeAndPlugins(
275
- main,
276
- wrap,
277
- element,
278
- "onAfterRun",
279
- );
280
- },
281
- onAfterRunAsync(wrap, element) {
282
- return bootstrapNodeAndPlugins(
283
- main,
284
- wrap,
229
+ if (!show.id) show.id = getID();
230
+
231
+ // allows the code to retrieve the target element via
232
+ // document.currentScript.target if needed
233
+ defineProperty(element, "target", { value: show });
234
+
235
+ // notify before the code runs
236
+ dispatch(element, TYPE, "ready");
237
+ dispatchDone(
285
238
  element,
286
- "onAfterRunAsync",
239
+ isAsync,
240
+ wrap[`run${isAsync ? "Async" : ""}`](
241
+ await fetchSource(element, wrap.io, true),
242
+ ),
287
243
  );
288
- },
244
+ } else {
245
+ // resolve PyScriptElement to allow connectedCallback
246
+ element._wrap.resolve(wrap);
247
+ }
248
+ console.debug("[pyscript/main] PyScript Ready");
289
249
  },
290
- worker: {
291
- ...codeFor(worker, TYPE),
292
- // these are lazy getters that returns a composition
293
- // of the current hooks or undefined, if no hook is present
294
- get onReady() {
295
- return createFunction(this, "onReady", true);
296
- },
297
- get onBeforeRun() {
298
- return createFunction(this, "onBeforeRun", false);
299
- },
300
- get onBeforeRunAsync() {
301
- return createFunction(this, "onBeforeRunAsync", true);
302
- },
303
- get onAfterRun() {
304
- return createFunction(this, "onAfterRun", false);
305
- },
306
- get onAfterRunAsync() {
307
- return createFunction(this, "onAfterRunAsync", true);
308
- },
250
+ onWorker(_, xworker) {
251
+ assign(xworker.sync, sync);
252
+ for (const callback of main("onWorker"))
253
+ callback(_, xworker);
309
254
  },
310
- };
311
-
312
- hooked.set(TYPE, hooks);
313
-
314
- // allow offline interpreter detection via [offline] attribute
315
- let version = offline_interpreter(config);
316
- if (!version) {
317
- const css = "script[type='module'][offline]";
318
- const s = document.querySelector(css)?.src;
319
- if (s && import.meta.url.startsWith(s.replace(/\.js$/, ""))) {
320
- version = `./pyscript/${interpreter}/${interpreter}.mjs`;
321
- version = offline_interpreter({ interpreter: version });
322
- }
323
- }
324
-
325
- define(TYPE, {
326
- config,
327
- configURL,
328
- interpreter,
329
- hooks,
330
- version,
331
- env: `${TYPE}-script`,
332
- onerror(error, element) {
333
- errors.set(element, error);
255
+ onBeforeRun(wrap, element) {
256
+ currentElement = element;
257
+ bootstrapNodeAndPlugins(main, wrap, element, "onBeforeRun");
334
258
  },
335
- });
336
-
337
- customElements.define(
338
- `${TYPE}-script`,
339
- class extends HTMLElement {
340
- constructor() {
341
- assign(super(), {
342
- _wrap: withResolvers(),
343
- srcCode: "",
344
- executed: false,
345
- });
346
- }
347
- get id() {
348
- return super.id || (super.id = getID());
349
- }
350
- set id(value) {
351
- super.id = value;
352
- }
353
- async connectedCallback() {
354
- if (!this.executed) {
355
- this.executed = true;
356
- const isAsync = !isSync(this);
357
- const { io, run, runAsync } = await this._wrap
358
- .promise;
359
- this.srcCode = await fetchSource(
360
- this,
361
- io,
362
- !this.childElementCount,
363
- );
364
- this.replaceChildren();
365
- this.style.display = "block";
366
- dispatch(this, TYPE, "ready");
367
- dispatchDone(
368
- this,
369
- isAsync,
370
- (isAsync ? runAsync : run)(this.srcCode),
371
- );
372
- }
373
- }
259
+ onBeforeRunAsync(wrap, element) {
260
+ currentElement = element;
261
+ return bootstrapNodeAndPlugins(
262
+ main,
263
+ wrap,
264
+ element,
265
+ "onBeforeRunAsync",
266
+ );
374
267
  },
375
- );
268
+ onAfterRun(wrap, element) {
269
+ bootstrapNodeAndPlugins(main, wrap, element, "onAfterRun");
270
+ },
271
+ onAfterRunAsync(wrap, element) {
272
+ return bootstrapNodeAndPlugins(
273
+ main,
274
+ wrap,
275
+ element,
276
+ "onAfterRunAsync",
277
+ );
278
+ },
279
+ },
280
+ worker: {
281
+ ...codeFor(worker, TYPE),
282
+ // these are lazy getters that returns a composition
283
+ // of the current hooks or undefined, if no hook is present
284
+ get onReady() {
285
+ return createFunction(this, "onReady", true);
286
+ },
287
+ get onBeforeRun() {
288
+ return createFunction(this, "onBeforeRun", false);
289
+ },
290
+ get onBeforeRunAsync() {
291
+ return createFunction(this, "onBeforeRunAsync", true);
292
+ },
293
+ get onAfterRun() {
294
+ return createFunction(this, "onAfterRun", false);
295
+ },
296
+ get onAfterRunAsync() {
297
+ return createFunction(this, "onAfterRunAsync", true);
298
+ },
299
+ },
300
+ };
301
+
302
+ hooked.set(TYPE, hooks);
303
+
304
+ // allow offline interpreter detection via [offline] attribute
305
+ let version = offline_interpreter(config);
306
+ if (!version) {
307
+ const css = "script[type='module'][offline]";
308
+ const s = document.querySelector(css)?.src;
309
+ if (s && import.meta.url.startsWith(s.replace(/\.js$/, ""))) {
310
+ version = `./pyscript/${interpreter}/${interpreter}.mjs`;
311
+ version = offline_interpreter({ interpreter: version });
312
+ }
313
+ }
314
+
315
+ define(TYPE, {
316
+ config,
317
+ configURL,
318
+ interpreter,
319
+ hooks,
320
+ version,
321
+ env: `${TYPE}-script`,
322
+ onerror(error, element) {
323
+ errors.set(element, error);
324
+ },
376
325
  });
377
- }
326
+
327
+ customElements.define(
328
+ `${TYPE}-script`,
329
+ class extends HTMLElement {
330
+ constructor() {
331
+ assign(super(), {
332
+ _wrap: withResolvers(),
333
+ srcCode: "",
334
+ executed: false,
335
+ });
336
+ }
337
+ get id() {
338
+ return super.id || (super.id = getID());
339
+ }
340
+ set id(value) {
341
+ super.id = value;
342
+ }
343
+ async connectedCallback() {
344
+ if (!this.executed) {
345
+ this.executed = true;
346
+ const isAsync = !isSync(this);
347
+ const { io, run, runAsync } = await this._wrap.promise;
348
+ this.srcCode = await fetchSource(
349
+ this,
350
+ io,
351
+ !this.childElementCount,
352
+ );
353
+ this.replaceChildren();
354
+ this.style.display = "block";
355
+ dispatch(this, TYPE, "ready");
356
+ dispatchDone(
357
+ this,
358
+ isAsync,
359
+ (isAsync ? runAsync : run)(this.srcCode),
360
+ );
361
+ }
362
+ }
363
+ },
364
+ );
365
+ });
378
366
 
379
367
  // export the used config without allowing leaks through it
380
368
  exportedConfig[TYPE] = structuredClone(config);
@@ -1,3 +0,0 @@
1
- /*! (c) Andrea Giammarchi - ISC */
2
- const{isArray:e}=Array,{parse:r}=JSON,s=(e,{s:r})=>e.replace(/"s(\d+)"/g,(e,s)=>r[s]),t=(e,s)=>r(e.replace(/(\S+?)\s*=/g,'"$1":'),(e,r)=>"string"==typeof r?s[r[0]][r.slice(1)]:r),p=(r,t,p,l)=>{for(let n=0,{length:a}=r,c=a-1;n<a;n++){const a=s(r[n],t);p=p[a]||(p[a]=l&&n===c?[]:{}),e(p)&&(n!==c&&p.length||p.push({}),p=p.at(-1))}return p},l=e=>{const[r,l]=((e,r,s)=>[e.replace(/(["'])(?:(?=(\\?))\2.)*?\1/g,e=>`"s${r.push(e.slice(1,-1))-1}"`).replace(/\d{2,}([:-]\d{2}){2}([ T:-][\dZ:-]+)?/g,e=>`"d${s.push(new Date(e))-1}"`).replace(/,\s*[\r\n]+/g,", ").replace(/\[\s*[\r\n]+/g,"[").replace(/[\r\n]+\s*]/g,"]"),{s:r,d:s}])(e,[],[]),n={};let a=n;for(let e of r.split(/[\r\n]+/))if((e=e.trim())&&!e.startsWith("#"))if(/^(\[+)(.*?)\]+/.test(e))a=p(RegExp.$2.trim().split("."),l,n,"["!==RegExp.$1);else if(/^(\S+?)\s*=([^#]+)/.test(e)){const{$1:e,$2:r}=RegExp;a[s(e,l)]=t(r.trim(),l)}return n};export{l as parse};
3
- //# sourceMappingURL=toml-BK2RWy-G.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toml-BK2RWy-G.js","sources":["../node_modules/polyscript/esm/3rd-party/toml.js"],"sourcesContent":["/* c8 ignore start */\n/*! (c) Andrea Giammarchi - ISC */\n\nconst {isArray} = Array;\nconst {parse: jsonParse} = JSON;\n\n/** @typedef {{s: string[], d: Date[]}} Foreign foreign strings and dates */\n\n/**\n * Transform quoted keys into regular keys.\n * @param {string} str the key to eventually normalize\n * @param {Foreign} foreign foreign strings and dates\n * @returns \n */\nconst getKey = (str, {s}) => str.replace(/\"s(\\d+)\"/g, (_, $1) => s[$1]);\n\n/**\n * Given a `'string'` or a `\"string\"` returns a JSON compatible string.\n * @param {string} str a TOML entry to parse\n * @param {Foreign} foreign foreign strings and dates\n * @returns {string}\n */\nconst getValue = (str, foreign) => jsonParse(\n str.replace(/(\\S+?)\\s*=/g, '\"$1\":'),\n (_, value) => typeof value === 'string' ?\n foreign[value[0]][value.slice(1)] :\n value\n);\n\n/**\n * Crawl the `json` object via the given array of keys and handle array entries.\n * @param {string[]} keys a path with all keys to reach the entry\n * @param {Foreign} foreign foreign strings and dates\n * @param {object} entry the root entry of the TOML\n * @param {boolean} asArray handle array entries\n * @returns {object} the current entry to handle\n */\nconst getPath = (keys, foreign, entry, asArray) => {\n for (let i = 0, {length} = keys, last = length - 1; i < length; i++) {\n const key = getKey(keys[i], foreign);\n entry = entry[key] || (entry[key] = (asArray && (i === last) ? [] : {}));\n if (isArray(entry)) {\n if ((i === last) || !entry.length)\n entry.push({});\n entry = entry.at(-1);\n }\n }\n return entry;\n};\n\n/**\n * Given a TOML text, removes stirngs and dates for easier parsing +\n * remove multi-line arrays to not need evaluation.\n * @param {string} toml the TOML text to map\n * @param {string[]} strings mapped strings\n * @param {Date[]} dates mapped Dates\n * @returns {[string, Foreign]}\n */\nconst mapForeign = (toml, strings, dates) => [\n toml\n // map strings in the TOML\n .replace(\n /([\"'])(?:(?=(\\\\?))\\2.)*?\\1/g,\n value => `\"s${strings.push(value.slice(1, -1)) - 1}\"`\n )\n // map dates in the TOML\n .replace(\n /\\d{2,}([:-]\\d{2}){2}([ T:-][\\dZ:-]+)?/g,\n value => `\"d${dates.push(new Date(value)) - 1}\"`\n )\n // avoid multi-line array entries\n .replace(/,\\s*[\\r\\n]+/g, ', ')\n .replace(/\\[\\s*[\\r\\n]+/g, '[')\n .replace(/[\\r\\n]+\\s*]/g, ']'),\n {s: strings, d: dates}\n];\n\n/**\n * Given a simple subset of a TOML file, returns its JS equivalent.\n * @param {string} toml the TOML text to parse\n * @returns {object} the TOML equivalent as JSON serializable\n */\nconst parse = toml => {\n const [text, foreign] = mapForeign(toml, [], []);\n const json = {};\n let entry = json;\n for (let line of text.split(/[\\r\\n]+/)) {\n if ((line = line.trim()) && !line.startsWith('#')) {\n if (/^(\\[+)(.*?)\\]+/.test(line))\n entry = getPath(RegExp.$2.trim().split('.'), foreign, json, RegExp.$1 !== '[');\n else if (/^(\\S+?)\\s*=([^#]+)/.test(line)) {\n const {$1: key, $2: value} = RegExp;\n entry[getKey(key, foreign)] = getValue(value.trim(), foreign);\n }\n }\n }\n return json;\n};\n\nexport { parse };\n\n/* c8 ignore stop */\n"],"names":["isArray","Array","parse","jsonParse","JSON","getKey","str","s","replace","_","$1","getValue","foreign","value","slice","getPath","keys","entry","asArray","i","length","last","key","push","at","toml","text","strings","dates","Date","d","mapForeign","json","line","split","trim","startsWith","test","RegExp","$2"],"mappings":";AAGA,MAAMA,QAACA,GAAWC,OACXC,MAAOC,GAAaC,KAUrBC,EAAS,CAACC,GAAMC,OAAOD,EAAIE,QAAQ,YAAa,CAACC,EAAGC,IAAOH,EAAEG,IAQ7DC,EAAW,CAACL,EAAKM,IAAYT,EACjCG,EAAIE,QAAQ,cAAe,SAC3B,CAACC,EAAGI,IAA2B,iBAAVA,EACnBD,EAAQC,EAAM,IAAIA,EAAMC,MAAM,IAC9BD,GAWEE,EAAU,CAACC,EAAMJ,EAASK,EAAOC,KACrC,IAAK,IAAIC,EAAI,GAAGC,OAACA,GAAUJ,EAAMK,EAAOD,EAAS,EAAGD,EAAIC,EAAQD,IAAK,CACnE,MAAMG,EAAMjB,EAAOW,EAAKG,GAAIP,GAC5BK,EAAQA,EAAMK,KAASL,EAAMK,GAAQJ,GAAYC,IAAME,EAAQ,GAAK,CAAA,GAChErB,EAAQiB,KACLE,IAAME,GAAUJ,EAAMG,QACzBH,EAAMM,KAAK,IACbN,EAAQA,EAAMO,OAElB,CACA,OAAOP,GAmCHf,EAAQuB,IACZ,MAAOC,EAAMd,GAzBI,EAACa,EAAME,EAASC,IAAU,CAC3CH,EAEGjB,QACC,8BACAK,GAAS,KAAKc,EAAQJ,KAAKV,EAAMC,MAAM,GAAG,IAAO,MAGlDN,QACC,yCACAK,GAAS,KAAKe,EAAML,KAAK,IAAIM,KAAKhB,IAAU,MAG7CL,QAAQ,eAAgB,MACxBA,QAAQ,gBAAiB,KACzBA,QAAQ,eAAgB,KAC3B,CAACD,EAAGoB,EAASG,EAAGF,IASQG,CAAWN,EAAM,GAAI,IACvCO,EAAO,CAAA,EACb,IAAIf,EAAQe,EACZ,IAAK,IAAIC,KAAQP,EAAKQ,MAAM,WAC1B,IAAKD,EAAOA,EAAKE,UAAYF,EAAKG,WAAW,KAC3C,GAAI,iBAAiBC,KAAKJ,GACxBhB,EAAQF,EAAQuB,OAAOC,GAAGJ,OAAOD,MAAM,KAAMtB,EAASoB,EAAoB,MAAdM,OAAO5B,SAChE,GAAI,qBAAqB2B,KAAKJ,GAAO,CACxC,MAAOvB,GAAIY,EAAKiB,GAAI1B,GAASyB,OAC7BrB,EAAMZ,EAAOiB,EAAKV,IAAYD,EAASE,EAAMsB,OAAQvB,EACvD,CAGJ,OAAOoB","x_google_ignoreList":[0]}