nuxt-i18n-micro 1.23.1 → 1.24.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.
@@ -1,12 +1,12 @@
1
1
  <!DOCTYPE html><html data-capo=""><head><meta charset="utf-8">
2
2
  <meta name="viewport" content="width=device-width, initial-scale=1">
3
- <link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.DjxsrOxm.css">
4
- <link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/C1B-o0oj.js">
3
+ <link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.BqOlM4b6.css">
4
+ <link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/mVL4Ag1z.js">
5
5
  <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/B6E6ObS_.js">
6
6
  <link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.C_4C5G96.css">
7
- <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/OEHygY_C.js">
8
- <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CENn-FX6.js">
7
+ <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/B3qz2zap.js">
8
+ <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CtNJ_juG.js">
9
9
  <link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.CBAEdpZV.css">
10
- <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Chs_ma_0.js">
11
- <script type="module" src="/__nuxt-i18n-micro/_nuxt/C1B-o0oj.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1729016909602,false]</script>
12
- <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"4e09a245-62b6-4516-8bb3-f4f43b22dd1b",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
10
+ <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CKE-slgQ.js">
11
+ <script type="module" src="/__nuxt-i18n-micro/_nuxt/mVL4Ag1z.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1729146164615,false]</script>
12
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"6babd624-967d-4b7f-b3a3-4cea27f30fdf",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
package/dist/module.d.mts CHANGED
@@ -7,6 +7,7 @@ interface Locale {
7
7
  disabled?: boolean;
8
8
  iso?: string;
9
9
  dir?: 'ltr' | 'rtl' | 'auto';
10
+ displayName?: string;
10
11
  }
11
12
  type Getter = (key: string, params?: Record<string, string | number | boolean>, defaultValue?: string) => unknown;
12
13
  type PluralFunc = (key: string, count: number, locale: string, getter: Getter) => string | null;
@@ -29,6 +30,7 @@ interface ModuleOptions {
29
30
  fallbackLocale?: string;
30
31
  localeCookie?: string;
31
32
  globalLocaleRoutes?: GlobalLocaleRoutes;
33
+ customRegexMatcher?: string | RegExp;
32
34
  }
33
35
  interface ModuleOptionsExtend extends ModuleOptions {
34
36
  plural: string;
package/dist/module.d.ts CHANGED
@@ -7,6 +7,7 @@ interface Locale {
7
7
  disabled?: boolean;
8
8
  iso?: string;
9
9
  dir?: 'ltr' | 'rtl' | 'auto';
10
+ displayName?: string;
10
11
  }
11
12
  type Getter = (key: string, params?: Record<string, string | number | boolean>, defaultValue?: string) => unknown;
12
13
  type PluralFunc = (key: string, count: number, locale: string, getter: Getter) => string | null;
@@ -29,6 +30,7 @@ interface ModuleOptions {
29
30
  fallbackLocale?: string;
30
31
  localeCookie?: string;
31
32
  globalLocaleRoutes?: GlobalLocaleRoutes;
33
+ customRegexMatcher?: string | RegExp;
32
34
  }
33
35
  interface ModuleOptionsExtend extends ModuleOptions {
34
36
  plural: string;
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
3
  "configKey": "i18n",
4
- "version": "1.23.1",
4
+ "version": "1.24.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.4",
7
7
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -128,10 +128,16 @@ const isLocaleDefault = (locale, defaultLocale, includeDefaultLocaleRoute) => {
128
128
  const localeCode = typeof locale === "string" ? locale : locale.code;
129
129
  return localeCode === defaultLocale.code && !includeDefaultLocaleRoute;
130
130
  };
131
- const buildFullPath = (locale, basePath) => {
132
- const localeParam = Array.isArray(locale) ? locale.join("|") : locale;
131
+ const buildFullPath = (locale, basePath, customRegex) => {
132
+ const regexString = normalizeRegex(customRegex?.toString());
133
+ const localeParam = Array.isArray(locale) ? regexString ? regexString : locale.join("|") : locale;
133
134
  return normalizePath(path.posix.join("/", `:locale(${localeParam})`, basePath));
134
135
  };
136
+ const normalizeRegex = (toNorm) => {
137
+ if (typeof toNorm === "undefined")
138
+ return void 0;
139
+ return toNorm.startsWith("/") && toNorm.endsWith("/") ? toNorm?.slice(1, -1) : toNorm;
140
+ };
135
141
 
136
142
  class PageManager {
137
143
  locales;
@@ -153,7 +159,7 @@ class PageManager {
153
159
  computeActiveLocaleCodes() {
154
160
  return this.locales.filter((locale) => locale.code !== this.defaultLocale.code || this.includeDefaultLocaleRoute).map((locale) => locale.code);
155
161
  }
156
- extendPages(pages, rootDir) {
162
+ extendPages(pages, rootDir, customRegex) {
157
163
  this.localizedPaths = this.extractLocalizedPaths(pages, rootDir);
158
164
  const additionalRoutes = [];
159
165
  pages.forEach((page) => {
@@ -162,9 +168,9 @@ class PageManager {
162
168
  return;
163
169
  }
164
170
  if (customRoute && typeof customRoute === "object") {
165
- this.addCustomGlobalLocalizedRoutes(page, customRoute, additionalRoutes);
171
+ this.addCustomGlobalLocalizedRoutes(page, customRoute, additionalRoutes, customRegex);
166
172
  } else {
167
- this.localizePage(page, additionalRoutes);
173
+ this.localizePage(page, additionalRoutes, customRegex);
168
174
  }
169
175
  });
170
176
  pages.push(...additionalRoutes);
@@ -195,7 +201,7 @@ class PageManager {
195
201
  });
196
202
  return localizedPaths;
197
203
  }
198
- addCustomGlobalLocalizedRoutes(page, customRoutePaths, additionalRoutes) {
204
+ addCustomGlobalLocalizedRoutes(page, customRoutePaths, additionalRoutes, customRegex) {
199
205
  this.locales.forEach((locale) => {
200
206
  const customPath = customRoutePaths[locale.code];
201
207
  if (!customPath)
@@ -204,18 +210,18 @@ class PageManager {
204
210
  if (isDefaultLocale) {
205
211
  page.path = normalizePath(customPath);
206
212
  } else {
207
- additionalRoutes.push(this.createLocalizedRoute(page, [locale.code], page.children ?? [], true, customPath));
213
+ additionalRoutes.push(this.createLocalizedRoute(page, [locale.code], page.children ?? [], true, customPath, customRegex));
208
214
  }
209
215
  });
210
216
  }
211
- localizePage(page, additionalRoutes) {
217
+ localizePage(page, additionalRoutes, customRegex) {
212
218
  if (isPageRedirectOnly(page))
213
219
  return;
214
220
  const originalChildren = cloneArray(page.children ?? []);
215
221
  const normalizedFullPath = normalizePath(page.path);
216
222
  const localeCodesWithoutCustomPaths = this.filterLocaleCodesWithoutCustomPaths(normalizedFullPath);
217
223
  if (localeCodesWithoutCustomPaths.length) {
218
- additionalRoutes.push(this.createLocalizedRoute(page, localeCodesWithoutCustomPaths, originalChildren, false));
224
+ additionalRoutes.push(this.createLocalizedRoute(page, localeCodesWithoutCustomPaths, originalChildren, false, "", customRegex));
219
225
  }
220
226
  this.addCustomLocalizedRoutes(page, normalizedFullPath, originalChildren, additionalRoutes);
221
227
  this.adjustRouteForDefaultLocale(page, originalChildren);
@@ -250,7 +256,7 @@ class PageManager {
250
256
  const localizedChildren = this.createLocalizedChildren(originalChildren, parentPath, localeCodes, false);
251
257
  return [...originalChildren, ...localizedChildren];
252
258
  }
253
- addCustomLocalizedRoutes(page, fullPath, originalChildren, additionalRoutes) {
259
+ addCustomLocalizedRoutes(page, fullPath, originalChildren, additionalRoutes, customRegex) {
254
260
  this.locales.forEach((locale) => {
255
261
  const customPath = this.localizedPaths[fullPath]?.[locale.code];
256
262
  if (!customPath)
@@ -259,7 +265,7 @@ class PageManager {
259
265
  if (isDefaultLocale) {
260
266
  page.children = this.createLocalizedChildren(originalChildren, "", [locale.code], false);
261
267
  } else {
262
- additionalRoutes.push(this.createLocalizedRoute(page, [locale.code], originalChildren, true, customPath));
268
+ additionalRoutes.push(this.createLocalizedRoute(page, [locale.code], originalChildren, true, customPath, customRegex));
263
269
  }
264
270
  });
265
271
  }
@@ -273,8 +279,8 @@ class PageManager {
273
279
  const localizedChildren = this.createLocalizedChildren(route.children ?? [], fullPath, localeCodes, modifyName);
274
280
  return localeCodes.map((locale) => this.createLocalizedChildRoute(route, routePath, locale, customLocalePaths, localizedChildren, modifyName, addLocalePrefix));
275
281
  }
276
- createLocalizedRoute(page, localeCodes, originalChildren, isCustom, customPath = "") {
277
- const routePath = this.buildRoutePath(localeCodes, page.path, customPath, isCustom);
282
+ createLocalizedRoute(page, localeCodes, originalChildren, isCustom, customPath = "", customRegex) {
283
+ const routePath = this.buildRoutePath(localeCodes, page.path, customPath, isCustom, customRegex);
278
284
  const routeName = buildRouteName(page.name ?? "", localeCodes[0], isCustom);
279
285
  return {
280
286
  ...page,
@@ -301,11 +307,11 @@ class PageManager {
301
307
  buildLocalizedRouteName(baseName, locale, modifyName) {
302
308
  return modifyName && !isLocaleDefault(locale, this.defaultLocale, this.includeDefaultLocaleRoute) ? `localized-${baseName}-${locale}` : baseName;
303
309
  }
304
- buildRoutePath(localeCodes, originalPath, customPath, isCustom) {
310
+ buildRoutePath(localeCodes, originalPath, customPath, isCustom, customRegex) {
305
311
  if (isCustom) {
306
- return this.includeDefaultLocaleRoute || !localeCodes.includes(this.defaultLocale.code) ? buildFullPath(localeCodes, customPath) : normalizePath(customPath);
312
+ return this.includeDefaultLocaleRoute || !localeCodes.includes(this.defaultLocale.code) ? buildFullPath(localeCodes, customPath, customRegex) : normalizePath(customPath);
307
313
  }
308
- return buildFullPath(localeCodes, originalPath);
314
+ return buildFullPath(localeCodes, originalPath, customRegex);
309
315
  }
310
316
  }
311
317
 
@@ -389,7 +395,8 @@ const module = defineNuxtModule({
389
395
  return forms[1].trim();
390
396
  }
391
397
  return (forms.length > 2 ? forms[2].trim() : forms[forms.length - 1].trim()).replace("{count}", count.toString());
392
- }
398
+ },
399
+ customRegexMatcher: void 0
393
400
  },
394
401
  async setup(options, nuxt) {
395
402
  const isCloudflarePages = nuxt.options.nitro.preset === "cloudflare_pages" || process.env.NITRO_PRESET === "cloudflare-pages";
@@ -421,8 +428,15 @@ const module = defineNuxtModule({
421
428
  baseURL: nuxt.options.app.baseURL,
422
429
  hashMode: nuxt.options?.router?.options?.hashMode ?? false,
423
430
  globalLocaleRoutes: void 0,
424
- apiBaseUrl
431
+ apiBaseUrl,
432
+ customRegexMatcher: options.customRegexMatcher
425
433
  };
434
+ if (typeof options.customRegexMatcher !== "undefined") {
435
+ const localeCodes = localeManager.locales.map((l) => l.code);
436
+ if (!localeCodes.every((code) => code.match(options.customRegexMatcher))) {
437
+ throw new Error("Nuxt-18n-micro: Some locale codes does not match customRegexMatcher");
438
+ }
439
+ }
426
440
  nuxt.options.runtimeConfig.i18nConfig = {
427
441
  rootDir: nuxt.options.rootDir,
428
442
  rootDirs
@@ -465,7 +479,7 @@ const module = defineNuxtModule({
465
479
  if (!options.disableWatcher) {
466
480
  localeManager.ensureTranslationFilesExist(pagesNames, options.translationDir, nuxt.options.rootDir);
467
481
  }
468
- pageManager.extendPages(pages, nuxt.options.rootDir);
482
+ pageManager.extendPages(pages, nuxt.options.rootDir, options.customRegexMatcher);
469
483
  nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
470
484
  const prerenderRoutes = [];
471
485
  localeManager.locales.forEach((locale) => {
@@ -1,7 +1,7 @@
1
1
  import { resolve } from "node:path";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { defineEventHandler } from "h3";
4
- import { useRuntimeConfig } from "#imports";
4
+ import { useRuntimeConfig, createError } from "#imports";
5
5
  function deepMerge(target, source) {
6
6
  for (const key of Object.keys(source)) {
7
7
  if (key === "__proto__" || key === "constructor") {
@@ -25,7 +25,12 @@ export default defineEventHandler(async (event) => {
25
25
  const { page, locale } = event.context.params;
26
26
  const config = useRuntimeConfig();
27
27
  const { rootDirs } = config.i18nConfig;
28
- const { translationDir, fallbackLocale } = config.public.i18nConfig;
28
+ const { translationDir, fallbackLocale, customRegexMatcher, locales } = config.public.i18nConfig;
29
+ if (customRegexMatcher && locales && !locales.map((l) => l.code).includes(locale)) {
30
+ throw createError({
31
+ statusCode: 404
32
+ });
33
+ }
29
34
  const getTranslationPath = (locale2, page2) => {
30
35
  return page2 === "general" ? `${locale2}.json` : `pages/${page2}/${locale2}.json`;
31
36
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
- "version": "1.23.1",
3
+ "version": "1.24.0",
4
4
  "description": "Nuxt I18n Micro is a lightweight, high-performance internationalization module for Nuxt, designed to handle multi-language support with minimal overhead, fast build times, and efficient runtime performance.",
5
5
  "repository": "s00d/nuxt-i18n-micro",
6
6
  "license": "MIT",
@@ -89,7 +89,6 @@
89
89
  },
90
90
  "workspaces": [
91
91
  "client",
92
- "playground",
93
92
  "test/fixtures/**/*"
94
93
  ],
95
94
  "packageManager": "yarn@3.7.0+sha256.7bf0c78a106332886ea4e59641fd819b1af953edcd72c4d93a32b1c71000ee67"
@@ -1 +0,0 @@
1
- {"id":"4e09a245-62b6-4516-8bb3-f4f43b22dd1b","timestamp":1729016892566,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
@@ -1 +0,0 @@
1
- :root{--nui-c-context:125,125,125}html{background-color:#fff}html.dark{background-color:#151515;color:#fff;color-scheme:dark}::-moz-selection{background:#8884}::selection{background:#8884}.shiki .line{display:inline-block;position:relative;width:100%}.shiki.diff .line>span{filter:saturate(.75);opacity:.75}.shiki.diff .line-added,.shiki.diff .line-removed{scroll-margin:5em}.shiki.diff .line-added>span,.shiki.diff .line-removed>span{opacity:1!important;position:inherit;scroll-margin:20px;z-index:100}.shiki.diff .line-added>span{color:#218c3b!important}.shiki.diff .line-removed>span{color:#d15547!important}.shiki .line-added:after{background-color:#43885420}.shiki .line-added:after,.shiki .line-removed:after{bottom:0;content:"";display:block;left:0;position:absolute;right:0;top:0}.shiki .line-removed:after{background-color:#8f4c3926}::view-transition-new(root),::view-transition-old(root){animation:none;mix-blend-mode:normal}::view-transition-old(root){z-index:1}::view-transition-new(root){z-index:2147483646}.dark::view-transition-old(root){z-index:2147483646}.dark::view-transition-new(root){z-index:1}*,:after,:before{border-color:var(--un-default-border-color,#e5e7eb);border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--un-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-feature-settings:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }@font-face{font-display:swap;font-family:DM Mono;font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/dmmono/v14/aFTU7PB1QTsUX8KYthSQBLyM.woff2) format("woff2");unicode-range:u+0100-02af,u+0304,u+0308,u+0329,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-display:swap;font-family:DM Mono;font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/dmmono/v14/aFTU7PB1QTsUX8KYthqQBA.woff2) format("woff2");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+2074,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}@font-face{font-display:swap;font-family:DM Sans;font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/dmsans/v15/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxRR232VGM.woff2) format("woff2");unicode-range:u+0100-02af,u+0304,u+0308,u+0329,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-display:swap;font-family:DM Sans;font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/dmsans/v15/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxRSW32.woff2) format("woff2");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+2074,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}.carbon-search{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' display='inline-block' vertical-align='middle' width='1.2em' height='1.2em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m29 27.586l-7.552-7.552a11.018 11.018 0 1 0-1.414 1.414L27.586 29ZM4 13a9 9 0 1 1 9 9a9.01 9.01 0 0 1-9-9'/%3E%3C/svg%3E")}.carbon-search,.i-carbon-circle-dash{background-color:currentColor;color:inherit;display:inline-block;height:1.2em;-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;vertical-align:middle;width:1.2em}.i-carbon-circle-dash{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' display='inline-block' vertical-align='middle' width='1.2em' height='1.2em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7.7 4.7a14.7 14.7 0 0 0-3 3.1L6.3 9a13.3 13.3 0 0 1 2.6-2.7zm-3.1 7.6l-1.9-.6A12.5 12.5 0 0 0 2 16h2a11.5 11.5 0 0 1 .6-3.7m-1.9 8.1a14.4 14.4 0 0 0 2 3.9l1.6-1.2a12.9 12.9 0 0 1-1.7-3.3zm5.1 6.9a14.4 14.4 0 0 0 3.9 2l.6-1.9A12.9 12.9 0 0 1 9 25.7zm3.9-24.6l.6 1.9A11.5 11.5 0 0 1 16 4V2a12.5 12.5 0 0 0-4.3.7m12.5 24.6a15.2 15.2 0 0 0 3.1-3.1L25.7 23a11.5 11.5 0 0 1-2.7 2.7zm3.2-7.6l1.9.6A15.5 15.5 0 0 0 30 16h-2a11.5 11.5 0 0 1-.6 3.7m1.8-8.1a14.4 14.4 0 0 0-2-3.9l-1.6 1.2a12.9 12.9 0 0 1 1.7 3.3zm-5.1-7a14.4 14.4 0 0 0-3.9-2l-.6 1.9a12.9 12.9 0 0 1 3.3 1.7zm-3.8 24.7l-.6-1.9a11.5 11.5 0 0 1-3.7.6v2a21.4 21.4 0 0 0 4.3-.7'/%3E%3C/svg%3E")}.i-carbon\:arrow-up-right,[i-carbon\:arrow-up-right=""]{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' display='inline-block' vertical-align='middle' width='1.2em' height='1.2em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M10 6v2h12.59L6 24.59L7.41 26L24 9.41V22h2V6z'/%3E%3C/svg%3E");background-color:currentColor;color:inherit;display:inline-block;height:1.2em;-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;vertical-align:middle;width:1.2em}.n-button-icon{font-size:1.1em;margin-left:-.2em;margin-right:.2em}.n-icon-button{align-items:center;aspect-ratio:1/1;border-radius:.25rem;display:flex;height:1.6em;justify-content:center;opacity:.5;width:1.6em}.n-loading{width:100%}.n-loading,.n-panel-grids-center{align-items:center;display:flex;height:100%;justify-content:center}.n-panel-grids-center{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' transform='scale(3)'%3E%3Crect width='100%25' height='100%25' fill='%23fff'/%3E%3Cpath fill='none' stroke='hsla(0, 0%25, 98%25, 1)' stroke-width='.2' d='M10 0v20ZM0 10h20Z'/%3E%3C/svg%3E");background-size:40px 40px;flex-direction:column;gap:.5rem}.n-button-base{align-items:center;border-color:#9ca3af33;border-radius:.25rem;border-width:1px;display:inline-flex;gap:.25rem;opacity:.8;padding:.25em 1em;touch-action:manipulation;--un-shadow:var(--un-shadow-inset) 0 1px 2px 0 var(--un-shadow-color,rgba(0,0,0,.05));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow);outline:2px solid transparent!important;outline-offset:2px!important}.n-icon{flex:none}.n-card-base{border-color:#9ca3af33;border-radius:.25rem;border-width:1px;--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity));--un-shadow:var(--un-shadow-inset) 0 1px 2px 0 var(--un-shadow-color,rgba(0,0,0,.05));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.n-border-base{border-color:#9ca3af33}.hover\:n-button-hover:hover{--un-border-opacity:1!important;border-color:rgba(var(--nui-c-context),var(--un-border-opacity))!important;--un-text-opacity:1;color:rgba(var(--nui-c-context),var(--un-text-opacity));opacity:1}.n-bg-active{background-color:#9ca3af0d}.dark .n-bg-base,.dark .n-card-base{--un-bg-opacity:1;background-color:rgb(21 21 21/var(--un-bg-opacity))}.n-bg-base{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.hover\:n-bg-hover:hover{background-color:#9ca3af08}.n-icon-button:hover{background-color:#9ca3af0d;opacity:1}.active\:n-button-active:active{background-color:rgba(var(--nui-c-context),.05);--un-ring-width:3px;--un-ring-offset-shadow:var(--un-ring-inset) 0 0 0 var(--un-ring-offset-width) var(--un-ring-offset-color);--un-ring-shadow:var(--un-ring-inset) 0 0 0 calc(var(--un-ring-width) + var(--un-ring-offset-width)) var(--un-ring-color);box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow);--un-ring-color:rgba(var(--nui-c-context),.1)}.hover\:n-link-hover:hover{--un-text-opacity:1;color:rgba(var(--nui-c-context),var(--un-text-opacity));-webkit-text-decoration-color:rgba(var(--nui-c-context),var(--un-line-opacity))!important;--un-line-opacity:1!important;opacity:1!important;text-decoration-color:rgba(var(--nui-c-context),var(--un-line-opacity))!important;text-decoration-style:dotted}.n-link-base{text-decoration-color:#0003;text-decoration-line:underline;text-underline-offset:2px}.dark .n-link-base{text-decoration-color:#fff6}.focus-within\:n-focus-base:focus-within{--un-ring-width:2px;--un-ring-offset-shadow:var(--un-ring-inset) 0 0 0 var(--un-ring-offset-width) var(--un-ring-offset-color);--un-ring-shadow:var(--un-ring-inset) 0 0 0 calc(var(--un-ring-width) + var(--un-ring-offset-width)) var(--un-ring-color);box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow);--un-ring-color:rgba(var(--nui-c-context),.5)}.focus-visible\:n-focus-base:focus-visible{--un-ring-width:2px;--un-ring-offset-shadow:var(--un-ring-inset) 0 0 0 var(--un-ring-offset-width) var(--un-ring-offset-color);--un-ring-shadow:var(--un-ring-inset) 0 0 0 calc(var(--un-ring-width) + var(--un-ring-offset-width)) var(--un-ring-color);box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow);--un-ring-color:rgba(var(--nui-c-context),.5)}.n-transition{transition-duration:.15s;transition-duration:.2s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dark .n-panel-grids-center{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' transform='scale(3)'%3E%3Crect width='100%25' height='100%25' fill='hsl(0, 0%25, 8.5%25)'/%3E%3Cpath fill='none' stroke='hsl(0, 0%25, 11.0%25)' stroke-width='.2' d='M10 0v20ZM0 10h20Z'/%3E%3C/svg%3E");background-size:40px 40px}.fixed{position:fixed}.relative,[relative=""]{position:relative}.-bottom-1\/2{bottom:-50%}.left-0{left:0}.right-0{right:0}.z-10{z-index:10}.z-20{z-index:20}.grid{display:grid}.mb-16{margin-bottom:4rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-0\.3em{margin-left:.3em}.ml-0\.4em{margin-left:.4em}.mr-0\.1em{margin-right:.1em}.block,[block=""]{display:block}.h-1\/2{height:50%}.h-auto{height:auto}.h-full,[h-full=""]{height:100%}.h-screen{height:100vh}.h1{height:.25rem}.max-w-520px{max-width:520px}.min-h-screen{min-height:100vh}.w-full,[w-full=""]{width:100%}.flex,[flex~="~"]{display:flex}.flex-1{flex:1 1 0%}.flex-auto{flex:1 1 auto}.flex-col,[flex~=col]{flex-direction:column}.translate-y--1,[translate-y--1=""]{--un-translate-y:-.25rem;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.place-content-center{place-content:center}.items-center{align-items:center}.justify-center{justify-content:center}.of-auto\!{overflow:auto!important}.of-hidden,.overflow-hidden,[of-hidden=""]{overflow:hidden}.overflow-auto{overflow:auto}.overflow-y-auto{overflow-y:auto}.truncate,[truncate=""]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.border,[border=""]{border-width:1px}.focus-within\:border-context:focus-within{--un-border-opacity:1;border-color:rgba(var(--nui-c-context),var(--un-border-opacity))}.rounded{border-radius:.25rem}.rounded-t-md{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.bg-black\/5{background-color:#0000000d}.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.dark .dark\:bg-black{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark .dark\:bg-white\/10{background-color:#ffffff1a}.p-8{padding:2rem}.px-10{padding-left:2.5rem;padding-right:2.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.px2,[px2=""]{padding-left:.5rem;padding-right:.5rem}.px6,[px6=""]{padding-left:1.5rem;padding-right:1.5rem}.py-1,.py1,[py1=""]{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py4,[py4=""]{padding-bottom:1rem;padding-top:1rem}.pl-1{padding-left:.25rem}.pr-2{padding-right:.5rem}.pt-14{padding-top:3.5rem}.text-center{text-align:center}.text-start,[text-start=""]{text-align:start}.text-1\.1em{font-size:1.1em}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-6xl{font-size:3.75rem;line-height:1}.text-8xl{font-size:6rem;line-height:1}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm,[text-sm=""]{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs,[text-xs=""]{font-size:.75rem;line-height:1rem}.dark .dark\:text-white{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}.text-black{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.text-primary{--un-text-opacity:1;color:rgb(9 158 97/var(--un-text-opacity))}.font-light{font-weight:300}.font-medium{font-weight:500}.leading-tight{line-height:1.25}.font-mono,[font-mono=""]{font-family:DM Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:DM Sans,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.underline,[underline=""]{text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.op50,[op50=""]{opacity:.5}.\!outline-none{outline:2px solid transparent!important;outline-offset:2px!important}.ease,.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}[n~=orange]{--nui-c-context:251,146,60}.n-disabled\:n-disabled[disabled],[disabled] .n-disabled\:n-disabled{filter:saturate(0);opacity:.6;pointer-events:none}@media (min-width:640px){.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-3{padding-bottom:.75rem;padding-top:.75rem}.sm\:text-2xl{font-size:1.5rem;line-height:2rem}.sm\:text-4xl{font-size:2.25rem;line-height:2.5rem}.sm\:text-8xl{font-size:6rem;line-height:1}.sm\:text-xl{font-size:1.25rem;line-height:1.75rem}}.splitpanes{display:flex;height:100%;width:100%}.splitpanes--vertical{flex-direction:row}.splitpanes--horizontal{flex-direction:column}.splitpanes--dragging *{-webkit-user-select:none;-moz-user-select:none;user-select:none}.splitpanes__pane{height:100%;overflow:hidden;width:100%}.splitpanes--vertical .splitpanes__pane{transition:width .2s ease-out}.splitpanes--horizontal .splitpanes__pane{transition:height .2s ease-out}.splitpanes--dragging .splitpanes__pane{transition:none}.splitpanes__splitter{touch-action:none}.splitpanes--vertical>.splitpanes__splitter{cursor:col-resize;min-width:1px}.splitpanes--horizontal>.splitpanes__splitter{cursor:row-resize;min-height:1px}.splitpanes.default-theme .splitpanes__pane{background-color:#f2f2f2}.splitpanes.default-theme .splitpanes__splitter{background-color:#fff;box-sizing:border-box;flex-shrink:0;position:relative}.splitpanes.default-theme .splitpanes__splitter:after,.splitpanes.default-theme .splitpanes__splitter:before{background-color:#00000026;content:"";left:50%;position:absolute;top:50%;transition:background-color .3s}.splitpanes.default-theme .splitpanes__splitter:hover:after,.splitpanes.default-theme .splitpanes__splitter:hover:before{background-color:#00000040}.splitpanes.default-theme .splitpanes__splitter:first-child{cursor:auto}.default-theme.splitpanes .splitpanes .splitpanes__splitter{z-index:1}.default-theme .splitpanes--vertical>.splitpanes__splitter,.default-theme.splitpanes--vertical>.splitpanes__splitter{border-left:1px solid #eee;margin-left:-1px;width:7px}.default-theme .splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:before,.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme.splitpanes--vertical>.splitpanes__splitter:before{height:30px;transform:translateY(-50%);width:1px}.default-theme .splitpanes--vertical>.splitpanes__splitter:before,.default-theme.splitpanes--vertical>.splitpanes__splitter:before{margin-left:-2px}.default-theme .splitpanes--vertical>.splitpanes__splitter:after,.default-theme.splitpanes--vertical>.splitpanes__splitter:after{margin-left:1px}.default-theme .splitpanes--horizontal>.splitpanes__splitter,.default-theme.splitpanes--horizontal>.splitpanes__splitter{border-top:1px solid #eee;height:7px;margin-top:-1px}.default-theme .splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before,.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme.splitpanes--horizontal>.splitpanes__splitter:before{height:1px;transform:translate(-50%);width:30px}.default-theme .splitpanes--horizontal>.splitpanes__splitter:before,.default-theme.splitpanes--horizontal>.splitpanes__splitter:before{margin-top:-2px}.default-theme .splitpanes--horizontal>.splitpanes__splitter:after,.default-theme.splitpanes--horizontal>.splitpanes__splitter:after{margin-top:1px}.splitpanes__splitter{position:relative}.splitpanes__splitter:before{content:"";left:0;position:absolute;top:0;transition:.2s ease;transition:opacity .4s;z-index:1}.splitpanes__splitter:hover:before{background:#8881;opacity:1}.splitpanes--vertical>.splitpanes__splitter{min-width:0!important;width:0!important;border-right-width:1px}.splitpanes--horizontal>.splitpanes__splitter{height:0!important;min-height:0!important;border-top-width:1px}.splitpanes--vertical>.splitpanes__splitter:before{height:100%;left:-5px;right:-4px}.splitpanes--horizontal>.splitpanes__splitter:before{bottom:-4px;top:-5px;width:100%}