jinrai 1.1.3 → 1.1.5

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 (64) hide show
  1. package/front.config.json +2 -1
  2. package/index.ts +2 -1
  3. package/lib/bin/bin.js +115 -52
  4. package/lib/index.d.ts +2 -1
  5. package/lib/index.js +2 -1
  6. package/lib/src/bin/agent/agent.d.ts +1 -0
  7. package/lib/src/bin/agent/agent.js +2 -1
  8. package/lib/src/bin/config/userConfig.d.ts +1 -0
  9. package/lib/src/bin/playwright/pageCollector.d.ts +2 -0
  10. package/lib/src/bin/playwright/pageTestCollector.d.ts +6 -0
  11. package/lib/src/bin/playwright/templates.d.ts +6 -1
  12. package/lib/src/bin/routes/Parser.d.ts +19 -1
  13. package/lib/src/bin/routes/getRoutes.d.ts +1 -0
  14. package/lib/src/front/server/useIsServer.d.ts +1 -0
  15. package/lib/src/front/server/useIsServer.js +7 -0
  16. package/lib/src/front/server-state/DataProxy.js +3 -0
  17. package/lib/src/front/server-state/SSR.d.ts +1 -0
  18. package/lib/src/front/server-state/SSR.js +3 -1
  19. package/lib/src/front/server-state/orig.d.ts +2 -0
  20. package/lib/src/front/server-state/{real.js → orig.js} +3 -2
  21. package/lib/src/front/server-state/serverStates.d.ts +1 -0
  22. package/lib/src/front/server-state/serverStates.js +6 -2
  23. package/lib/src/front/server-state/testState.d.ts +3 -0
  24. package/lib/src/front/server-state/testState.js +14 -0
  25. package/lib/src/front/server-state/useServerState.js +5 -9
  26. package/lib/src/front/translate/TranslateConfig.d.ts +21 -0
  27. package/lib/src/front/translate/TranslateConfig.js +108 -0
  28. package/lib/src/front/url/JinraiContext.d.ts +1 -0
  29. package/lib/src/front/url/JinraiContext.js +1 -0
  30. package/lib/src/front/url/adapter/def.js +1 -1
  31. package/lib/src/front/url/adapter/rrd6.js +2 -2
  32. package/lib/src/front/url/adapter/rrd7.js +2 -2
  33. package/lib/src/front/url/search/useSearch.js +3 -4
  34. package/lib/src/front/wrapper/Custom.js +5 -1
  35. package/lib/vite/plugin.js +20 -14
  36. package/package.json +6 -2
  37. package/rollup.config.mjs +2 -1
  38. package/src/bin/agent/agent.ts +1 -0
  39. package/src/bin/build/build.ts +23 -10
  40. package/src/bin/config/define.ts +1 -3
  41. package/src/bin/config/userConfig.ts +1 -0
  42. package/src/bin/playwright/pageCollector.ts +8 -4
  43. package/src/bin/playwright/pageTestCollector.ts +15 -0
  44. package/src/bin/playwright/templates.ts +14 -4
  45. package/src/bin/routes/Parser.ts +88 -27
  46. package/src/bin/routes/getRoutes.ts +5 -1
  47. package/src/front/server/useIsServer.ts +5 -0
  48. package/src/front/server-state/DataProxy.ts +4 -0
  49. package/src/front/server-state/SSR.ts +5 -1
  50. package/src/front/server-state/{real.ts → orig.ts} +3 -1
  51. package/src/front/server-state/serverStates.ts +8 -2
  52. package/src/front/server-state/testState.ts +15 -0
  53. package/src/front/server-state/useServerState.ts +6 -11
  54. package/src/front/translate/TranslateConfig.tsx +153 -0
  55. package/src/front/url/JinraiContext.tsx +2 -0
  56. package/src/front/url/adapter/def.tsx +1 -1
  57. package/src/front/url/adapter/rrd6.tsx +2 -3
  58. package/src/front/url/adapter/rrd7.tsx +2 -2
  59. package/src/front/url/search/useSearch.ts +3 -4
  60. package/src/front/wrapper/Custom.tsx +9 -1
  61. package/tests/parse/custom.test.ts +2 -1
  62. package/tsconfig.types.json +1 -0
  63. package/vite/plugin.ts +32 -20
  64. package/lib/src/front/server-state/real.d.ts +0 -1
@@ -0,0 +1,108 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { createContext, useContext, useState, useEffect } from 'react';
3
+ import { ssr } from '../server-state/SSR.js';
4
+
5
+ const TranslateContext = createContext(null);
6
+ const useTranslate = () => {
7
+ const context = useContext(TranslateContext);
8
+ if (!context)
9
+ throw new Error("not in context (<TranslateConfig>)");
10
+ return context;
11
+ };
12
+ const ONE_DAY = 1000 * 60 * 60 * 24;
13
+ const getCookie = (key) => {
14
+ const match = document.cookie.match(new RegExp(`(?:^|; )${key.replace(/([$?*|{}()[\]\\/+^])/g, "\\$1")}=([^;]*)`));
15
+ return match ? decodeURIComponent(match[1]) : null;
16
+ };
17
+ const setCookie = (key, value, days = 365) => {
18
+ const expires = new Date(Date.now() + days * 864e5).toUTCString();
19
+ document.cookie = `${key}=${encodeURIComponent(value)}; expires=${expires}; path=/`;
20
+ };
21
+ const getStorageKey = (lang) => `lang:${lang}`;
22
+ const loadFromStorage = (lang) => {
23
+ try {
24
+ const raw = localStorage.getItem(getStorageKey(lang));
25
+ if (!raw)
26
+ return null;
27
+ const parsed = JSON.parse(raw);
28
+ if (Date.now() > parsed.expires) {
29
+ localStorage.removeItem(getStorageKey(lang));
30
+ return null;
31
+ }
32
+ return parsed.data;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ };
38
+ const saveToStorage = (lang, data) => {
39
+ localStorage.setItem(getStorageKey(lang), JSON.stringify({
40
+ data,
41
+ expires: Date.now() + ONE_DAY,
42
+ }));
43
+ };
44
+ const TranslateConfig = ({ children, defaultLang, langBaseUrl, source }) => {
45
+ const [lang, setLang] = useState(defaultLang);
46
+ const [langMap, setLangMap] = useState(null);
47
+ useEffect(() => {
48
+ // @ts-ignore
49
+ window.$langDefaultConfig = {
50
+ defaultLang,
51
+ langBaseUrl,
52
+ source,
53
+ };
54
+ }, []);
55
+ // initial lang from cookie
56
+ useEffect(() => {
57
+ if (source.from === "cookie") {
58
+ const fromCookie = getCookie(source.key);
59
+ if (fromCookie)
60
+ setLang(fromCookie);
61
+ }
62
+ }, [source.from, source.key]);
63
+ // load translations on lang change
64
+ useEffect(() => {
65
+ if (lang === defaultLang) {
66
+ setLangMap(null);
67
+ return;
68
+ }
69
+ const cached = loadFromStorage(lang);
70
+ if (cached) {
71
+ setLangMap(cached);
72
+ return;
73
+ }
74
+ fetch(langBaseUrl.replace("*", lang))
75
+ .then(res => {
76
+ if (!res.ok)
77
+ throw new Error("Failed to load lang map");
78
+ return res.json();
79
+ })
80
+ .then((data) => {
81
+ saveToStorage(lang, data);
82
+ setLangMap(data);
83
+ })
84
+ .catch(() => {
85
+ setLangMap(null);
86
+ });
87
+ }, [lang, defaultLang, langBaseUrl]);
88
+ const translate = (text, context) => {
89
+ const key = context ? `${text}(context:${context})` : text;
90
+ if (ssr.current) {
91
+ return `{!${key}!}`;
92
+ }
93
+ if (!langMap)
94
+ return text;
95
+ return langMap[key] ?? langMap[text] ?? text;
96
+ };
97
+ const changeLang = (nextLang) => {
98
+ if (nextLang === lang)
99
+ return;
100
+ if (source.from === "cookie") {
101
+ setCookie(source.key, nextLang);
102
+ }
103
+ setLang(nextLang);
104
+ };
105
+ return jsx(TranslateContext.Provider, { value: { translate, changeLang, lang }, children: children });
106
+ };
107
+
108
+ export { TranslateConfig, useTranslate };
@@ -2,5 +2,6 @@ import { DependencyList, ReactNode } from "react";
2
2
  export interface JinraiProps {
3
3
  deps?: DependencyList;
4
4
  children?: ReactNode;
5
+ search: string;
5
6
  }
6
7
  export declare const JinraiContext: import("react").Context<JinraiProps>;
@@ -3,6 +3,7 @@ import { createContext } from 'react';
3
3
  const JinraiContext = createContext({
4
4
  deps: [],
5
5
  children: undefined,
6
+ search: ""
6
7
  });
7
8
 
8
9
  export { JinraiContext };
@@ -3,7 +3,7 @@ import { JinraiContext } from '../JinraiContext.js';
3
3
  import { NuqsAdapter } from 'nuqs/adapters/react';
4
4
 
5
5
  const Adapter = (props) => {
6
- return (jsx(NuqsAdapter, { children: jsx(JinraiContext.Provider, { value: { deps: props.deps ?? [] }, ...props }) }));
6
+ return (jsx(NuqsAdapter, { children: jsx(JinraiContext.Provider, { value: { deps: props.deps ?? [], search: "" }, ...props }) }));
7
7
  };
8
8
 
9
9
  export { Adapter };
@@ -7,8 +7,8 @@ const Adapter = (props) => {
7
7
  // useLocation требует, чтобы компонент был внутри RouterProvider
8
8
  // NuqsAdapter должен быть установлен на верхнем уровне, но может работать внутри роутера
9
9
  // для React Router v6 адаптера
10
- const { pathname } = useLocation();
11
- return (jsx(NuqsAdapter, { children: jsx(JinraiContext.Provider, { value: { deps: [...(props.deps ?? []), pathname] }, ...props }) }));
10
+ const { pathname, search } = useLocation();
11
+ return (jsx(NuqsAdapter, { children: jsx(JinraiContext.Provider, { value: { deps: [...(props.deps ?? []), pathname], search: search.substring(1) }, ...props }) }));
12
12
  };
13
13
 
14
14
  export { Adapter };
@@ -7,8 +7,8 @@ const Adapter = (props) => {
7
7
  // useLocation требует, чтобы компонент был внутри RouterProvider
8
8
  // NuqsAdapter должен быть установлен на верхнем уровне, но может работать внутри роутера
9
9
  // для React Router v7 адаптера
10
- const { pathname } = useLocation();
11
- return (jsx(NuqsAdapter, { children: jsx(JinraiContext.Provider, { value: { deps: [...(props.deps ?? []), pathname] }, ...props }) }));
10
+ const { pathname, search } = useLocation();
11
+ return (jsx(NuqsAdapter, { children: jsx(JinraiContext.Provider, { value: { deps: [...(props.deps ?? []), pathname], search }, ...props }) }));
12
12
  };
13
13
 
14
14
  export { Adapter };
@@ -4,11 +4,10 @@ import { ssr } from '../../server-state/SSR.js';
4
4
  import { getJinraiValue } from './useSearchValue.js';
5
5
 
6
6
  const useSearch = () => {
7
- const { deps } = useContext(JinraiContext);
8
- const value = useMemo(() => location.search.substring(1), deps ? deps : []);
7
+ const { search } = useContext(JinraiContext);
9
8
  const stableValue = useMemo(() => {
10
- return ssr.current ? value.bindSource(getJinraiValue("", "searchFull", "", "")) : value;
11
- }, [value]);
9
+ return ssr.current ? search.bindSource(getJinraiValue("", "searchFull", "", "")) : search;
10
+ }, [search]);
12
11
  return stableValue;
13
12
  };
14
13
 
@@ -2,11 +2,15 @@ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { Fragment } from 'react';
3
3
  import { ssr } from '../server-state/SSR.js';
4
4
  import { SPLIT } from '../../bin/routes/Parser.js';
5
+ import { orig } from '../server-state/orig.js';
5
6
 
6
7
  const Custom = ({ name, props, children }) => {
7
8
  if (!ssr.current)
8
9
  return jsx(Fragment, { children: children });
9
- const exampleProps = JSON.stringify({ name, props: props() });
10
+ if (typeof props != "function") {
11
+ throw new Error(`Custom props is not function (${name})`);
12
+ }
13
+ const exampleProps = JSON.stringify({ name, props: orig(props()) });
10
14
  ssr.exportToJV = true;
11
15
  const customProps = JSON.stringify({ name, props: props() });
12
16
  ssr.exportToJV = false;
@@ -2,9 +2,11 @@ import { createServer } from 'vite';
2
2
  import { AsyncLocalStorage } from 'async_hooks';
3
3
  import { chromium } from 'playwright';
4
4
 
5
- const pageCollector = async (page) => {
5
+ const ViteAgent = "____JINRAI_VITE_AGENT____";
6
+
7
+ const pageTestCollector = async (page) => {
6
8
  const state = await page.evaluate(() => {
7
- const state = Object.fromEntries(window.$exportServerStates);
9
+ const state = Object.fromEntries(window.$testStates);
8
10
  return state;
9
11
  });
10
12
  const root = await page.locator("#root").innerHTML();
@@ -12,12 +14,12 @@ const pageCollector = async (page) => {
12
14
  };
13
15
 
14
16
  const urlStorage = new AsyncLocalStorage();
17
+ const cashe = new Map();
15
18
  function hydration() {
16
19
  if (process.env.CHILD_JINRAI_DEV_SERVER) {
17
20
  return { name: "vite-jinrai-dummy" };
18
21
  }
19
22
  process.env.CHILD_JINRAI_DEV_SERVER = "true";
20
- console.log("create mirror");
21
23
  let mirrorServer = undefined;
22
24
  let context = undefined;
23
25
  let page = undefined;
@@ -30,10 +32,9 @@ function hydration() {
30
32
  mirrorServer = server;
31
33
  await mirrorServer.listen();
32
34
  debugUrl = mirrorServer.resolvedUrls?.local[0].slice(0, -1);
33
- chromium.launch({ headless: false, devtools: false, channel: "chrome" }).then(async (browser) => {
34
- console.log("create context");
35
+ chromium.launch({ headless: true, devtools: false, channel: "chrome" }).then(async (browser) => {
35
36
  context = await browser.newContext({
36
- // userAgent: JinraiAgent,
37
+ userAgent: ViteAgent,
37
38
  locale: "ru-RU",
38
39
  });
39
40
  page = await context.newPage();
@@ -54,25 +55,30 @@ function hydration() {
54
55
  async transformIndexHtml(html) {
55
56
  const currentUrl = urlStorage.getStore();
56
57
  if (currentUrl && page) {
58
+ const data = cashe.get(currentUrl);
59
+ if (data) {
60
+ return print(html, data.root, data.state);
61
+ }
57
62
  await page.goto(debugUrl + currentUrl);
58
63
  await page.waitForLoadState("networkidle");
59
- const { state } = await pageCollector(page);
60
- // const { routes } = getRoutesAndTemplates([{ id: 1, state: {}, mask: currentUrl, root }], true, false)
61
- // console.log({ routes })
62
- // writeFile("./routs.json", JSON.stringify(routes, null, 2))
63
- // html = html.replace("<!--app-html-->", root)
64
- html = html.replace("<!--app-head-->", JSON.stringify(state, null, 2));
65
- return html;
64
+ await page.waitForTimeout(2000);
65
+ const { root, state } = await pageTestCollector(page);
66
+ cashe.set(currentUrl, { root, state });
67
+ return print(html, root, state);
66
68
  }
67
69
  return html;
68
70
  },
69
71
  closeWatcher() {
70
- console.log("Stop server");
71
72
  page?.close();
72
73
  mirrorServer?.close();
73
74
  context?.close();
74
75
  },
75
76
  };
76
77
  }
78
+ const print = (html, root, state) => {
79
+ html = html.replace("<!--app-html-->", root);
80
+ html = html.replace("<!--app-head-->", `<script>window.__appc__ = ${JSON.stringify({ state })}</script>`);
81
+ return html;
82
+ };
77
83
 
78
84
  export { hydration };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinrai",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "A powerful library that analyzes your modern web application and automatically generates a perfectly rendered, static snapshot of its pages. Experience unparalleled loading speed and SEO clarity without the complexity of traditional SSR setups. Simply point Jinrai at your SPA and witness divine speed.",
5
5
  "main": "lib/index.ts",
6
6
  "scripts": {
@@ -64,12 +64,16 @@
64
64
  "import": "./lib/src/front/url/adapter/rrd7.js"
65
65
  },
66
66
  "./config": {
67
- "types": "./lib/config/config.d.ts",
67
+ "types": "./lib/config.d.ts",
68
68
  "import": "./lib/config/config.js"
69
69
  },
70
70
  "./vite": {
71
71
  "types": "./lib/vite/plugin.d.ts",
72
72
  "import": "./lib/vite/plugin.js"
73
+ },
74
+ "./translate": {
75
+ "types": "./lib/src/front/translate/TranslateConfig.d.ts",
76
+ "import": "./lib/src/front/translate/TranslateConfig.js"
73
77
  }
74
78
  }
75
79
  }
package/rollup.config.mjs CHANGED
@@ -68,7 +68,8 @@ export default defineConfig([
68
68
  index: path.resolve(__dirname, "index.ts"),
69
69
  "src/front/url/adapter/rrd6": path.resolve(__dirname, "src/front/url/adapter/rrd6.tsx"),
70
70
  "src/front/url/adapter/rrd7": path.resolve(__dirname, "src/front/url/adapter/rrd7.tsx"),
71
- "src/front/url/adapter/def": path.resolve(__dirname, "src/front/url/adapter/def.tsx")
71
+ "src/front/url/adapter/def": path.resolve(__dirname, "src/front/url/adapter/def.tsx"),
72
+ "src/front/translate/TranslateConfig": path.resolve(__dirname, "src/front/translate/TranslateConfig.tsx"),
72
73
  },
73
74
  output: {
74
75
  dir: path.resolve(__dirname, "lib"),
@@ -1 +1,2 @@
1
1
  export const JinraiAgent = "____JINRAI_AGENT____"
2
+ export const ViteAgent = "____JINRAI_VITE_AGENT____"
@@ -28,21 +28,23 @@ export const runBuild = async (options: buildArgs) => {
28
28
 
29
29
  const [serverUrl, close] = await vitePreview()
30
30
 
31
- const pages = await getRawPageData(serverUrl, config.pages, config.test, options.debug)
31
+ const { pages, lang } = await getRawPageData(serverUrl, config.pages, config.test, options.debug)
32
+
33
+ console.log({ lang })
32
34
 
33
35
  close()
34
36
 
35
37
  const outputcashe = path.join(config.dist ?? "dist", ".cached")
36
38
 
37
39
  task.do("Format")
38
- const { routes, templates } = getRoutesAndTemplates(pages)
40
+ const { routes, templates, customComponents } = getRoutesAndTemplates(pages)
39
41
 
40
42
  task.next(`Export: (${templates.length})`)
41
43
  await mkdir(outputcashe, { recursive: true })
42
44
 
43
45
  console.log("dev")
44
46
 
45
- const exportConfig = { routes, proxy: config.proxy, meta: config.meta }
47
+ const exportConfig = { routes, proxy: config.proxy, meta: config.meta, lang, cacheablePaths: config.cacheablePaths }
46
48
 
47
49
  await writeFile(path.join(outputcashe, "config.json"), JSON.stringify(exportConfig, null, 2))
48
50
  // await writeFile(
@@ -54,16 +56,27 @@ export const runBuild = async (options: buildArgs) => {
54
56
  await writeFile(path.join(outputcashe, `${name}.html`), template)
55
57
  }
56
58
 
57
- if (config.test) {
58
- task.next(`Tests`)
59
- for await (const page of pages) {
60
- if (!page.test) {
61
- continue
62
- }
59
+ if (customComponents.length) {
60
+ task.next(`Custom`)
61
+
62
+ await mkdir(path.join(outputcashe, "custom"), { recursive: true })
63
63
 
64
- await writeFile(path.join(outputcashe, `test_${page.id}.html`), normalizeHtmlWhitespace(page.test))
64
+ for await (const component of customComponents) {
65
+ await writeFile(path.join(outputcashe, "custom", `${component.name}.html`), component.html)
66
+ await writeFile(path.join(outputcashe, "custom", `${component.name}.json`), component.props)
65
67
  }
66
68
  }
67
69
 
70
+ // if (config.test) {
71
+ // task.next(`Tests`)
72
+ // for await (const page of pages) {
73
+ // if (!page.test) {
74
+ // continue
75
+ // }
76
+
77
+ // await writeFile(path.join(outputcashe, `test_${page.id}.html`), normalizeHtmlWhitespace(page.test))
78
+ // }
79
+ // }
80
+
68
81
  task.success()
69
82
  }
@@ -1,7 +1,5 @@
1
1
  import type { Config } from "./userConfig"
2
2
 
3
- export const defineConfig = (config: Config) => {
3
+ export const defineConfig = (config: Config): Config => {
4
4
  return config
5
5
  }
6
-
7
-
@@ -15,6 +15,7 @@ export interface Config {
15
15
  dist?: string
16
16
  proxy?: Record<string, string>
17
17
  meta?: string
18
+ cacheablePaths?: string[]
18
19
  }
19
20
 
20
21
  export const getUserConfig = async (configName: string): Promise<Config> => {
@@ -1,14 +1,18 @@
1
1
  import { Page } from "playwright"
2
2
  import { ServerStateMap } from "../../front/server-state/useServerState"
3
+ import { DefaultLangType } from "../../front/translate/TranslateConfig"
3
4
 
4
- export const pageCollector = async (page: Page): Promise<{ state: ServerStateMap; root: string }> => {
5
- const state = await page.evaluate(() => {
5
+ export const pageCollector = async (
6
+ page: Page,
7
+ ): Promise<{ state: ServerStateMap; root: string; lang: DefaultLangType }> => {
8
+ const [state, lang] = await page.evaluate(() => {
6
9
  const state = Object.fromEntries((window as any).$exportServerStates)
10
+ const lang = (window as any).$langDefaultConfig
7
11
 
8
- return state
12
+ return [state, lang]
9
13
  })
10
14
 
11
15
  const root = await page.locator("#root").innerHTML()
12
16
 
13
- return { root, state }
17
+ return { root, state, lang }
14
18
  }
@@ -0,0 +1,15 @@
1
+ import { Page } from "playwright";
2
+ import { ServerStateMap } from "../../front/server-state/useServerState";
3
+
4
+
5
+ export const pageTestCollector = async (page: Page): Promise<{ state: ServerStateMap; root: string }> => {
6
+ const state = await page.evaluate(() => {
7
+ const state = Object.fromEntries((window as any).$testStates)
8
+
9
+ return state
10
+ })
11
+
12
+ const root = await page.locator("#root").innerHTML()
13
+
14
+ return { root, state }
15
+ }
@@ -4,6 +4,7 @@ import { spinners } from "ora"
4
4
  import { pageCollector } from "./pageCollector"
5
5
  import { ServerValue } from "../../front/server-state/serverStates"
6
6
  import { JinraiAgent } from "../agent/agent"
7
+ import { DefaultLangType } from "../../front/translate/TranslateConfig"
7
8
 
8
9
  export interface PageData {
9
10
  id: number
@@ -13,16 +14,22 @@ export interface PageData {
13
14
  test?: string
14
15
  }
15
16
 
17
+ export interface Pages {
18
+ pages: PageData[]
19
+ lang?: DefaultLangType
20
+ }
21
+
16
22
  export const getRawPageData = async (
17
23
  url: string,
18
24
  pages: string[],
19
25
  test: boolean = false,
20
26
  debug: boolean = false,
21
- ): Promise<PageData[]> => {
27
+ ): Promise<Pages> => {
22
28
  const task = new Task()
23
29
  task.next("Router analysis", "yellow", spinners.dotsCircle)
24
30
 
25
31
  const result: PageData[] = []
32
+ let defaultLang: DefaultLangType | undefined = undefined
26
33
 
27
34
  const browser = await chromium.launch({ headless: !debug, devtools: true, channel: "chrome" })
28
35
  // const test_browser = await chromium.launch({ headless: true, channel: "chrome" })
@@ -36,7 +43,7 @@ export const getRawPageData = async (
36
43
  task.next(mask, "yellow", spinners.dotsCircle, 1)
37
44
 
38
45
  const page = await context.newPage()
39
- const path = mask.replaceAll("{", "").replaceAll("}", "")
46
+ const path = mask.replaceAll("{", "").replaceAll("}", "").replace("\/*", "")
40
47
 
41
48
  await page.goto(url + path)
42
49
 
@@ -44,7 +51,10 @@ export const getRawPageData = async (
44
51
 
45
52
  await page.waitForTimeout(1000)
46
53
 
47
- const { state, root } = await pageCollector(page)
54
+ const { state, root, lang } = await pageCollector(page)
55
+ if (defaultLang == undefined) {
56
+ defaultLang = lang
57
+ }
48
58
 
49
59
  // if (debug) console.log({ input })
50
60
 
@@ -77,5 +87,5 @@ export const getRawPageData = async (
77
87
  // await test_browser.close()
78
88
 
79
89
  task.success()
80
- return result
90
+ return { pages: result, lang: defaultLang }
81
91
  }