@intlayer/core 8.6.1 → 8.6.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.
- package/dist/cjs/interpreter/getContent/plugins.cjs +35 -7
- package/dist/cjs/interpreter/getContent/plugins.cjs.map +1 -1
- package/dist/cjs/localization/getLocalizedUrl.cjs +10 -2
- package/dist/cjs/localization/getLocalizedUrl.cjs.map +1 -1
- package/dist/cjs/localization/getPathWithoutLocale.cjs +22 -9
- package/dist/cjs/localization/getPathWithoutLocale.cjs.map +1 -1
- package/dist/cjs/localization/getPrefix.cjs +6 -1
- package/dist/cjs/localization/getPrefix.cjs.map +1 -1
- package/dist/cjs/localization/localeResolver.cjs +3 -3
- package/dist/cjs/localization/localeResolver.cjs.map +1 -1
- package/dist/cjs/localization/rewriteUtils.cjs +9 -3
- package/dist/cjs/localization/rewriteUtils.cjs.map +1 -1
- package/dist/cjs/localization/validatePrefix.cjs +12 -0
- package/dist/cjs/localization/validatePrefix.cjs.map +1 -1
- package/dist/cjs/utils/localeStorage.cjs +34 -18
- package/dist/cjs/utils/localeStorage.cjs.map +1 -1
- package/dist/cjs/utils/parseYaml.cjs +76 -159
- package/dist/cjs/utils/parseYaml.cjs.map +1 -1
- package/dist/esm/interpreter/getContent/plugins.mjs +35 -7
- package/dist/esm/interpreter/getContent/plugins.mjs.map +1 -1
- package/dist/esm/localization/getLocalizedUrl.mjs +10 -2
- package/dist/esm/localization/getLocalizedUrl.mjs.map +1 -1
- package/dist/esm/localization/getPathWithoutLocale.mjs +22 -9
- package/dist/esm/localization/getPathWithoutLocale.mjs.map +1 -1
- package/dist/esm/localization/getPrefix.mjs +6 -1
- package/dist/esm/localization/getPrefix.mjs.map +1 -1
- package/dist/esm/localization/localeResolver.mjs +3 -3
- package/dist/esm/localization/localeResolver.mjs.map +1 -1
- package/dist/esm/localization/rewriteUtils.mjs +9 -3
- package/dist/esm/localization/rewriteUtils.mjs.map +1 -1
- package/dist/esm/localization/validatePrefix.mjs +12 -0
- package/dist/esm/localization/validatePrefix.mjs.map +1 -1
- package/dist/esm/utils/localeStorage.mjs +34 -18
- package/dist/esm/utils/localeStorage.mjs.map +1 -1
- package/dist/esm/utils/parseYaml.mjs +76 -159
- package/dist/esm/utils/parseYaml.mjs.map +1 -1
- package/dist/types/interpreter/getContent/plugins.d.ts.map +1 -1
- package/dist/types/localization/getLocalizedUrl.d.ts.map +1 -1
- package/dist/types/localization/getPathWithoutLocale.d.ts.map +1 -1
- package/dist/types/localization/getPrefix.d.ts.map +1 -1
- package/dist/types/localization/rewriteUtils.d.ts.map +1 -1
- package/dist/types/localization/validatePrefix.d.ts.map +1 -1
- package/dist/types/utils/localeStorage.d.ts.map +1 -1
- package/dist/types/utils/parseYaml.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -5,6 +5,22 @@ let _intlayer_config_built = require("@intlayer/config/built");
|
|
|
5
5
|
_intlayer_config_built = require_runtime.__toESM(_intlayer_config_built);
|
|
6
6
|
|
|
7
7
|
//#region src/utils/localeStorage.ts
|
|
8
|
+
/**
|
|
9
|
+
* True when cookie storage is explicitly disabled at build time.
|
|
10
|
+
*/
|
|
11
|
+
const TREE_SHAKE_STORAGE_COOKIES = process.env["INTLAYER_ROUTING_STORAGE_COOKIES"] === "false";
|
|
12
|
+
/**
|
|
13
|
+
* True when localStorage is explicitly disabled at build time.
|
|
14
|
+
*/
|
|
15
|
+
const TREE_SHAKE_STORAGE_LOCAL_STORAGE = process.env["INTLAYER_ROUTING_STORAGE_LOCALSTORAGE"] === "false";
|
|
16
|
+
/**
|
|
17
|
+
* True when sessionStorage is explicitly disabled at build time.
|
|
18
|
+
*/
|
|
19
|
+
const TREE_SHAKE_STORAGE_SESSION_STORAGE = process.env["INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE"] === "false";
|
|
20
|
+
/**
|
|
21
|
+
* True when header storage is explicitly disabled at build time.
|
|
22
|
+
*/
|
|
23
|
+
const TREE_SHAKE_STORAGE_HEADERS = process.env["INTLAYER_ROUTING_STORAGE_HEADERS"] === "false";
|
|
8
24
|
const buildCookieString = (name, value, attributes) => {
|
|
9
25
|
const parts = [`${name}=${encodeURIComponent(value)}`];
|
|
10
26
|
if (attributes.path) parts.push(`Path=${attributes.path}`);
|
|
@@ -25,15 +41,15 @@ const getLocaleFromStorageClient = (options) => {
|
|
|
25
41
|
const storageAttributes = routing.storage;
|
|
26
42
|
if (options?.isCookieEnabled === false) return void 0;
|
|
27
43
|
const isValidLocale = (value) => !!value && locales.includes(value);
|
|
28
|
-
for (let i = 0; i < storageAttributes.cookies.length; i++) try {
|
|
44
|
+
if (!TREE_SHAKE_STORAGE_COOKIES) for (let i = 0; i < storageAttributes.cookies.length; i++) try {
|
|
29
45
|
const value = options?.getCookie?.(storageAttributes.cookies[i].name);
|
|
30
46
|
if (isValidLocale(value)) return value;
|
|
31
47
|
} catch {}
|
|
32
|
-
for (let i = 0; i < storageAttributes.localStorage.length; i++) try {
|
|
48
|
+
if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE) for (let i = 0; i < storageAttributes.localStorage.length; i++) try {
|
|
33
49
|
const value = options?.getLocaleStorage?.(storageAttributes.localStorage[i].name);
|
|
34
50
|
if (isValidLocale(value)) return value;
|
|
35
51
|
} catch {}
|
|
36
|
-
for (let i = 0; i < storageAttributes.sessionStorage.length; i++) try {
|
|
52
|
+
if (!TREE_SHAKE_STORAGE_SESSION_STORAGE) for (let i = 0; i < storageAttributes.sessionStorage.length; i++) try {
|
|
37
53
|
const value = options?.getSessionStorage?.(storageAttributes.sessionStorage[i].name);
|
|
38
54
|
if (isValidLocale(value)) return value;
|
|
39
55
|
} catch {}
|
|
@@ -47,7 +63,7 @@ const setLocaleInStorageClient = (locale, options) => {
|
|
|
47
63
|
const { routing } = _intlayer_config_built.default;
|
|
48
64
|
const storageAttributes = routing.storage;
|
|
49
65
|
if (options?.isCookieEnabled === false) return;
|
|
50
|
-
for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
66
|
+
if (!TREE_SHAKE_STORAGE_COOKIES) for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
51
67
|
const { name, attributes } = storageAttributes.cookies[i];
|
|
52
68
|
try {
|
|
53
69
|
if (options?.setCookieStore) options.setCookieStore(name, locale, {
|
|
@@ -60,7 +76,7 @@ const setLocaleInStorageClient = (locale, options) => {
|
|
|
60
76
|
} catch {}
|
|
61
77
|
}
|
|
62
78
|
}
|
|
63
|
-
if (options?.setLocaleStorage) for (let i = 0; i < storageAttributes.localStorage.length; i++) {
|
|
79
|
+
if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && options?.setLocaleStorage) for (let i = 0; i < storageAttributes.localStorage.length; i++) {
|
|
64
80
|
const { name } = storageAttributes.localStorage[i];
|
|
65
81
|
try {
|
|
66
82
|
if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {
|
|
@@ -69,7 +85,7 @@ const setLocaleInStorageClient = (locale, options) => {
|
|
|
69
85
|
options.setLocaleStorage(name, locale);
|
|
70
86
|
} catch {}
|
|
71
87
|
}
|
|
72
|
-
if (options?.setSessionStorage) for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {
|
|
88
|
+
if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && options?.setSessionStorage) for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {
|
|
73
89
|
const { name } = storageAttributes.sessionStorage[i];
|
|
74
90
|
try {
|
|
75
91
|
if (!(options?.overwrite ?? true) && options?.getSessionStorage) {
|
|
@@ -106,11 +122,11 @@ const getLocaleFromStorageServer = (options) => {
|
|
|
106
122
|
const storageAttributes = routing.storage;
|
|
107
123
|
if (options?.isCookieEnabled === false) return void 0;
|
|
108
124
|
const isValidLocale = (value) => !!value && locales.includes(value);
|
|
109
|
-
for (let i = 0; i < storageAttributes.cookies.length; i++) try {
|
|
125
|
+
if (!TREE_SHAKE_STORAGE_COOKIES) for (let i = 0; i < storageAttributes.cookies.length; i++) try {
|
|
110
126
|
const value = options?.getCookie?.(storageAttributes.cookies[i].name);
|
|
111
127
|
if (isValidLocale(value)) return value;
|
|
112
128
|
} catch {}
|
|
113
|
-
for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
129
|
+
if (!TREE_SHAKE_STORAGE_HEADERS) for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
114
130
|
const value = options?.getHeader?.(storageAttributes.headers[i].name);
|
|
115
131
|
if (isValidLocale(value)) return value;
|
|
116
132
|
} catch {}
|
|
@@ -123,7 +139,7 @@ const setLocaleInStorageServer = (locale, options) => {
|
|
|
123
139
|
const { routing } = _intlayer_config_built.default;
|
|
124
140
|
const storageAttributes = routing.storage;
|
|
125
141
|
if (options?.isCookieEnabled === false) return;
|
|
126
|
-
for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
142
|
+
if (!TREE_SHAKE_STORAGE_COOKIES) for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
127
143
|
const { name, attributes } = storageAttributes.cookies[i];
|
|
128
144
|
try {
|
|
129
145
|
if (options?.setCookieStore) options.setCookieStore(name, locale, {
|
|
@@ -136,7 +152,7 @@ const setLocaleInStorageServer = (locale, options) => {
|
|
|
136
152
|
} catch {}
|
|
137
153
|
}
|
|
138
154
|
}
|
|
139
|
-
if (options?.setHeader) for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
155
|
+
if (!TREE_SHAKE_STORAGE_HEADERS && options?.setHeader) for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
140
156
|
options.setHeader(storageAttributes.headers[i].name, locale);
|
|
141
157
|
} catch {}
|
|
142
158
|
};
|
|
@@ -181,19 +197,19 @@ const getLocaleFromStorage = (options) => {
|
|
|
181
197
|
} catch {}
|
|
182
198
|
return require_utils_getCookie.getCookie(name);
|
|
183
199
|
};
|
|
184
|
-
for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
200
|
+
if (!TREE_SHAKE_STORAGE_COOKIES) for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
185
201
|
const value = readCookie(storageAttributes.cookies[i].name);
|
|
186
202
|
if (isValidLocale(value)) return value;
|
|
187
203
|
}
|
|
188
|
-
for (let i = 0; i < storageAttributes.localStorage.length; i++) try {
|
|
204
|
+
if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE) for (let i = 0; i < storageAttributes.localStorage.length; i++) try {
|
|
189
205
|
const value = options?.getLocaleStorage?.(storageAttributes.localStorage[i].name);
|
|
190
206
|
if (isValidLocale(value)) return value;
|
|
191
207
|
} catch {}
|
|
192
|
-
for (let i = 0; i < storageAttributes.sessionStorage.length; i++) try {
|
|
208
|
+
if (!TREE_SHAKE_STORAGE_SESSION_STORAGE) for (let i = 0; i < storageAttributes.sessionStorage.length; i++) try {
|
|
193
209
|
const value = options?.getSessionStorage?.(storageAttributes.sessionStorage[i].name);
|
|
194
210
|
if (isValidLocale(value)) return value;
|
|
195
211
|
} catch {}
|
|
196
|
-
for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
212
|
+
if (!TREE_SHAKE_STORAGE_HEADERS) for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
197
213
|
const value = options?.getHeader?.(storageAttributes.headers[i].name);
|
|
198
214
|
if (isValidLocale(value)) return value;
|
|
199
215
|
} catch {}
|
|
@@ -209,7 +225,7 @@ const setLocaleInStorage = (locale, options) => {
|
|
|
209
225
|
const { routing } = _intlayer_config_built.default;
|
|
210
226
|
const storageAttributes = routing.storage;
|
|
211
227
|
if (options?.isCookieEnabled === false) return;
|
|
212
|
-
for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
228
|
+
if (!TREE_SHAKE_STORAGE_COOKIES) for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
213
229
|
const { name, attributes } = storageAttributes.cookies[i];
|
|
214
230
|
try {
|
|
215
231
|
if (options?.setCookieStore) options.setCookieStore(name, locale, {
|
|
@@ -222,7 +238,7 @@ const setLocaleInStorage = (locale, options) => {
|
|
|
222
238
|
} catch {}
|
|
223
239
|
}
|
|
224
240
|
}
|
|
225
|
-
if (options?.setLocaleStorage) for (let i = 0; i < storageAttributes.localStorage.length; i++) {
|
|
241
|
+
if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && options?.setLocaleStorage) for (let i = 0; i < storageAttributes.localStorage.length; i++) {
|
|
226
242
|
const { name } = storageAttributes.localStorage[i];
|
|
227
243
|
try {
|
|
228
244
|
if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {
|
|
@@ -231,7 +247,7 @@ const setLocaleInStorage = (locale, options) => {
|
|
|
231
247
|
options.setLocaleStorage(name, locale);
|
|
232
248
|
} catch {}
|
|
233
249
|
}
|
|
234
|
-
if (options?.setSessionStorage) for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {
|
|
250
|
+
if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && options?.setSessionStorage) for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {
|
|
235
251
|
const { name } = storageAttributes.sessionStorage[i];
|
|
236
252
|
try {
|
|
237
253
|
if (!(options?.overwrite ?? true) && options?.getSessionStorage) {
|
|
@@ -240,7 +256,7 @@ const setLocaleInStorage = (locale, options) => {
|
|
|
240
256
|
options.setSessionStorage(name, locale);
|
|
241
257
|
} catch {}
|
|
242
258
|
}
|
|
243
|
-
if (options?.setHeader) for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
259
|
+
if (!TREE_SHAKE_STORAGE_HEADERS && options?.setHeader) for (let i = 0; i < storageAttributes.headers.length; i++) try {
|
|
244
260
|
options.setHeader(storageAttributes.headers[i].name, locale);
|
|
245
261
|
} catch {}
|
|
246
262
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localeStorage.cjs","names":["configuration","getCookie"],"sources":["../../../src/utils/localeStorage.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { CookiesAttributes } from '@intlayer/types/config';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { getCookie } from './getCookie';\n\n// ============================================================================\n// Shared types\n// ============================================================================\n\nexport type CookieBuildAttributes = {\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n /** Expiry as milliseconds since epoch (Date.getTime()) or number of days */\n expires?: number | undefined;\n};\n\n// ============================================================================\n// Shared helpers\n// ============================================================================\n\nconst buildCookieString = (\n name: string,\n value: string,\n attributes: Omit<CookiesAttributes, 'name' | 'type'>\n): string => {\n const encodedValue = encodeURIComponent(value);\n const parts: string[] = [`${name}=${encodedValue}`];\n\n if (attributes.path) parts.push(`Path=${attributes.path}`);\n if (attributes.domain) parts.push(`Domain=${attributes.domain}`);\n if (attributes.expires instanceof Date)\n parts.push(`Expires=${attributes.expires.toUTCString()}`);\n if (attributes.secure) parts.push('Secure');\n if (attributes.sameSite) parts.push(`SameSite=${attributes.sameSite}`);\n return parts.join('; ');\n};\n\n// ============================================================================\n// Client-specific types and functions\n// (cookies via browser APIs, localStorage, sessionStorage — no headers)\n// ============================================================================\n\nexport type LocaleStorageClientOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n setSessionStorage?: (name: string, value: string) => void;\n getSessionStorage?: (name: string) => string | undefined | null;\n setLocaleStorage?: (name: string, value: string) => void;\n getLocaleStorage?: (name: string) => string | undefined | null;\n};\n\n/**\n * Retrieves the locale from browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not read from headers — use `getLocaleFromStorageServer` for that.\n */\nexport const getLocaleFromStorageClient = (\n options: LocaleStorageClientOptions\n): Locale | undefined => {\n const { routing, internationalization } = configuration;\n const { locales } = internationalization;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n try {\n const value = options?.getCookie?.(storageAttributes.cookies[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n storageAttributes.localStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n storageAttributes.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n};\n\n/**\n * Stores the locale in browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not write to headers — use `setLocaleInStorageServer` for that.\n */\nexport const setLocaleInStorageClient = (\n locale: LocalesValues,\n options?: LocaleStorageClientOptions\n): void => {\n const { routing } = configuration;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return;\n\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const { name, attributes } = storageAttributes.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires:\n attributes.expires instanceof Date\n ? attributes.expires.getTime()\n : attributes.expires,\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n\n if (options?.setLocaleStorage) {\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n const { name } = storageAttributes.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (options?.setSessionStorage) {\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n const { name } = storageAttributes.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Client-side locale storage utility.\n * Handles cookies (browser), localStorage and sessionStorage.\n * Does not access headers.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageClient(localeStorageOptions);\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageClient = (options: LocaleStorageClientOptions) => ({\n getLocale: () => getLocaleFromStorageClient(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageClient(locale, options),\n});\n\n// ============================================================================\n// Server-specific types and functions\n// (cookies via injected getter/setter, headers — no localStorage/sessionStorage)\n// ============================================================================\n\nexport type LocaleStorageServerOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n getHeader?: (name: string) => string | undefined | null;\n setHeader?: (name: string, value: string) => void;\n};\n\n/**\n * Retrieves the locale from server-side storage mechanisms (cookies, headers).\n * Does not access localStorage or sessionStorage.\n * No browser cookie fallback — the caller must provide `getCookie`.\n */\nexport const getLocaleFromStorageServer = (\n options: LocaleStorageServerOptions\n): Locale | undefined => {\n const { routing, internationalization } = configuration;\n const { locales } = internationalization;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n try {\n const value = options?.getCookie?.(storageAttributes.cookies[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n const value = options?.getHeader?.(storageAttributes.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n};\n\n/**\n * Stores the locale in server-side storage mechanisms (cookies, headers).\n * Does not write to localStorage or sessionStorage.\n */\nexport const setLocaleInStorageServer = (\n locale: LocalesValues,\n options?: LocaleStorageServerOptions\n): void => {\n const { routing } = configuration;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return;\n\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const { name, attributes } = storageAttributes.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires:\n attributes.expires instanceof Date\n ? attributes.expires.getTime()\n : attributes.expires,\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n\n if (options?.setHeader) {\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n options.setHeader(storageAttributes.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Server-side locale storage utility.\n * Handles cookies (via injected getter/setter) and headers.\n * Does not access localStorage or sessionStorage.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageServer({\n * getCookie: (name) => req.cookies[name],\n * setCookieStore: (name, value, attrs) => res.cookie(name, value, attrs),\n * getHeader: (name) => req.headers[name],\n * setHeader: (name, value) => res.setHeader(name, value),\n * });\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageServer = (options: LocaleStorageServerOptions) => ({\n getLocale: () => getLocaleFromStorageServer(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageServer(locale, options),\n});\n\n// ============================================================================\n// Deprecated: combined LocaleStorage\n// Use LocaleStorageClient or LocaleStorageServer instead\n// ============================================================================\n\n/**\n * @deprecated Use {@link LocaleStorageClientOptions} or {@link LocaleStorageServerOptions} instead.\n */\nexport type LocaleStorageOptions = LocaleStorageClientOptions &\n LocaleStorageServerOptions;\n\n/**\n * Retrieves the locale from all storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link getLocaleFromStorageClient} (browser) or\n * {@link getLocaleFromStorageServer} (server) instead.\n */\nexport const getLocaleFromStorage = (\n options: Pick<\n LocaleStorageOptions,\n | 'getCookie'\n | 'getSessionStorage'\n | 'getLocaleStorage'\n | 'getHeader'\n | 'isCookieEnabled'\n >\n): Locale | undefined => {\n const { routing, internationalization } = configuration;\n const { locales } = internationalization;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n const readCookie = (name: string): string | undefined => {\n try {\n const fromOption = options?.getCookie?.(name);\n if (fromOption !== null && fromOption !== undefined) return fromOption;\n } catch {}\n // Browser fallback kept for backward compatibility\n return getCookie(name);\n };\n\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const value = readCookie(storageAttributes.cookies[i].name);\n if (isValidLocale(value)) return value;\n }\n\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n storageAttributes.localStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n storageAttributes.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n const value = options?.getHeader?.(storageAttributes.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n};\n\n/**\n * Stores the locale in all configured storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link setLocaleInStorageClient} (browser) or\n * {@link setLocaleInStorageServer} (server) instead.\n */\nexport const setLocaleInStorage = (\n locale: LocalesValues,\n options?: LocaleStorageOptions\n): void => {\n const { routing } = configuration;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return;\n\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const { name, attributes } = storageAttributes.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires:\n attributes.expires instanceof Date\n ? attributes.expires.getTime()\n : attributes.expires,\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n\n if (options?.setLocaleStorage) {\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n const { name } = storageAttributes.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (options?.setSessionStorage) {\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n const { name } = storageAttributes.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n\n if (options?.setHeader) {\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n options.setHeader(storageAttributes.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Utility object to get and set the locale in storage based on configuration.\n *\n * @deprecated Use {@link LocaleStorageClient} (browser) or\n * {@link LocaleStorageServer} (server) instead.\n */\nexport const LocaleStorage = (options: LocaleStorageOptions) => ({\n getLocale: () => getLocaleFromStorage(options),\n setLocale: (locale: LocalesValues) => setLocaleInStorage(locale, options),\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"localeStorage.cjs","names":["configuration","getCookie"],"sources":["../../../src/utils/localeStorage.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { CookiesAttributes } from '@intlayer/types/config';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { getCookie } from './getCookie';\n\n// ── Tree-shake constants ──────────────────────────────────────────────────────\n// When these env vars are injected at build time, bundlers eliminate the\n// branches guarded by these constants.\n\n/**\n * True when cookie storage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_COOKIES =\n process.env['INTLAYER_ROUTING_STORAGE_COOKIES'] === 'false';\n\n/**\n * True when localStorage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_LOCAL_STORAGE =\n process.env['INTLAYER_ROUTING_STORAGE_LOCALSTORAGE'] === 'false';\n\n/**\n * True when sessionStorage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_SESSION_STORAGE =\n process.env['INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE'] === 'false';\n\n/**\n * True when header storage is explicitly disabled at build time.\n */\nconst TREE_SHAKE_STORAGE_HEADERS =\n process.env['INTLAYER_ROUTING_STORAGE_HEADERS'] === 'false';\n\n// ============================================================================\n// Shared types\n// ============================================================================\n\nexport type CookieBuildAttributes = {\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n /** Expiry as milliseconds since epoch (Date.getTime()) or number of days */\n expires?: number | undefined;\n};\n\n// ============================================================================\n// Shared helpers\n// ============================================================================\n\nconst buildCookieString = (\n name: string,\n value: string,\n attributes: Omit<CookiesAttributes, 'name' | 'type'>\n): string => {\n const encodedValue = encodeURIComponent(value);\n const parts: string[] = [`${name}=${encodedValue}`];\n\n if (attributes.path) parts.push(`Path=${attributes.path}`);\n if (attributes.domain) parts.push(`Domain=${attributes.domain}`);\n if (attributes.expires instanceof Date)\n parts.push(`Expires=${attributes.expires.toUTCString()}`);\n if (attributes.secure) parts.push('Secure');\n if (attributes.sameSite) parts.push(`SameSite=${attributes.sameSite}`);\n return parts.join('; ');\n};\n\n// ============================================================================\n// Client-specific types and functions\n// (cookies via browser APIs, localStorage, sessionStorage — no headers)\n// ============================================================================\n\nexport type LocaleStorageClientOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n setSessionStorage?: (name: string, value: string) => void;\n getSessionStorage?: (name: string) => string | undefined | null;\n setLocaleStorage?: (name: string, value: string) => void;\n getLocaleStorage?: (name: string) => string | undefined | null;\n};\n\n/**\n * Retrieves the locale from browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not read from headers — use `getLocaleFromStorageServer` for that.\n */\nexport const getLocaleFromStorageClient = (\n options: LocaleStorageClientOptions\n): Locale | undefined => {\n const { routing, internationalization } = configuration;\n const { locales } = internationalization;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n try {\n const value = options?.getCookie?.(storageAttributes.cookies[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE) {\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n storageAttributes.localStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE) {\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n storageAttributes.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in browser storage mechanisms\n * (cookies, localStorage, sessionStorage).\n * Does not write to headers — use `setLocaleInStorageServer` for that.\n */\nexport const setLocaleInStorageClient = (\n locale: LocalesValues,\n options?: LocaleStorageClientOptions\n): void => {\n const { routing } = configuration;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const { name, attributes } = storageAttributes.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires:\n attributes.expires instanceof Date\n ? attributes.expires.getTime()\n : attributes.expires,\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && options?.setLocaleStorage) {\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n const { name } = storageAttributes.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && options?.setSessionStorage) {\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n const { name } = storageAttributes.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Client-side locale storage utility.\n * Handles cookies (browser), localStorage and sessionStorage.\n * Does not access headers.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageClient(localeStorageOptions);\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageClient = (options: LocaleStorageClientOptions) => ({\n getLocale: () => getLocaleFromStorageClient(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageClient(locale, options),\n});\n\n// ============================================================================\n// Server-specific types and functions\n// (cookies via injected getter/setter, headers — no localStorage/sessionStorage)\n// ============================================================================\n\nexport type LocaleStorageServerOptions = {\n overwrite?: boolean;\n isCookieEnabled?: boolean;\n setCookieStore?: (\n name: string,\n value: string,\n cookie: CookieBuildAttributes\n ) => void;\n setCookieString?: (name: string, cookie: string) => void;\n getCookie?: (name: string) => string | undefined | null;\n getHeader?: (name: string) => string | undefined | null;\n setHeader?: (name: string, value: string) => void;\n};\n\n/**\n * Retrieves the locale from server-side storage mechanisms (cookies, headers).\n * Does not access localStorage or sessionStorage.\n * No browser cookie fallback — the caller must provide `getCookie`.\n */\nexport const getLocaleFromStorageServer = (\n options: LocaleStorageServerOptions\n): Locale | undefined => {\n const { routing, internationalization } = configuration;\n const { locales } = internationalization;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n try {\n const value = options?.getCookie?.(storageAttributes.cookies[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS) {\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n const value = options?.getHeader?.(storageAttributes.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in server-side storage mechanisms (cookies, headers).\n * Does not write to localStorage or sessionStorage.\n */\nexport const setLocaleInStorageServer = (\n locale: LocalesValues,\n options?: LocaleStorageServerOptions\n): void => {\n const { routing } = configuration;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const { name, attributes } = storageAttributes.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires:\n attributes.expires instanceof Date\n ? attributes.expires.getTime()\n : attributes.expires,\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS && options?.setHeader) {\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n options.setHeader(storageAttributes.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Server-side locale storage utility.\n * Handles cookies (via injected getter/setter) and headers.\n * Does not access localStorage or sessionStorage.\n *\n * @example\n * ```ts\n * const storage = LocaleStorageServer({\n * getCookie: (name) => req.cookies[name],\n * setCookieStore: (name, value, attrs) => res.cookie(name, value, attrs),\n * getHeader: (name) => req.headers[name],\n * setHeader: (name, value) => res.setHeader(name, value),\n * });\n * const locale = storage.getLocale();\n * storage.setLocale('fr');\n * ```\n */\nexport const LocaleStorageServer = (options: LocaleStorageServerOptions) => ({\n getLocale: () => getLocaleFromStorageServer(options),\n setLocale: (locale: LocalesValues) =>\n setLocaleInStorageServer(locale, options),\n});\n\n// ============================================================================\n// Deprecated: combined LocaleStorage\n// Use LocaleStorageClient or LocaleStorageServer instead\n// ============================================================================\n\n/**\n * @deprecated Use {@link LocaleStorageClientOptions} or {@link LocaleStorageServerOptions} instead.\n */\nexport type LocaleStorageOptions = LocaleStorageClientOptions &\n LocaleStorageServerOptions;\n\n/**\n * Retrieves the locale from all storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link getLocaleFromStorageClient} (browser) or\n * {@link getLocaleFromStorageServer} (server) instead.\n */\nexport const getLocaleFromStorage = (\n options: Pick<\n LocaleStorageOptions,\n | 'getCookie'\n | 'getSessionStorage'\n | 'getLocaleStorage'\n | 'getHeader'\n | 'isCookieEnabled'\n >\n): Locale | undefined => {\n const { routing, internationalization } = configuration;\n const { locales } = internationalization;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return undefined;\n\n const isValidLocale = (value: string | null | undefined): value is Locale =>\n !!value && locales.includes(value as Locale);\n\n const readCookie = (name: string): string | undefined => {\n try {\n const fromOption = options?.getCookie?.(name);\n if (fromOption !== null && fromOption !== undefined) return fromOption;\n } catch {}\n // Browser fallback kept for backward compatibility\n return getCookie(name);\n };\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const value = readCookie(storageAttributes.cookies[i].name);\n if (isValidLocale(value)) return value;\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE) {\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n try {\n const value = options?.getLocaleStorage?.(\n storageAttributes.localStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE) {\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n try {\n const value = options?.getSessionStorage?.(\n storageAttributes.sessionStorage[i].name\n );\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS) {\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n const value = options?.getHeader?.(storageAttributes.headers[i].name);\n if (isValidLocale(value)) return value;\n } catch {}\n }\n }\n};\n\n/**\n * Stores the locale in all configured storage mechanisms\n * (cookies, localStorage, sessionStorage, headers).\n *\n * @deprecated Use {@link setLocaleInStorageClient} (browser) or\n * {@link setLocaleInStorageServer} (server) instead.\n */\nexport const setLocaleInStorage = (\n locale: LocalesValues,\n options?: LocaleStorageOptions\n): void => {\n const { routing } = configuration;\n const storageAttributes = routing.storage;\n\n if (options?.isCookieEnabled === false) return;\n\n if (!TREE_SHAKE_STORAGE_COOKIES) {\n for (let i = 0; i < storageAttributes.cookies.length; i++) {\n const { name, attributes } = storageAttributes.cookies[i];\n try {\n if (options?.setCookieStore) {\n options.setCookieStore(name, locale, {\n ...attributes,\n expires:\n attributes.expires instanceof Date\n ? attributes.expires.getTime()\n : attributes.expires,\n });\n }\n } catch {\n try {\n if (options?.setCookieString) {\n options.setCookieString(\n name,\n buildCookieString(name, locale, attributes)\n );\n }\n } catch {}\n }\n }\n }\n\n if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && options?.setLocaleStorage) {\n for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n const { name } = storageAttributes.localStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n if (options.getLocaleStorage(name)) continue;\n }\n options.setLocaleStorage(name, locale);\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && options?.setSessionStorage) {\n for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n const { name } = storageAttributes.sessionStorage[i];\n try {\n if (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n if (options.getSessionStorage(name)) continue;\n }\n options.setSessionStorage(name, locale);\n } catch {}\n }\n }\n\n if (!TREE_SHAKE_STORAGE_HEADERS && options?.setHeader) {\n for (let i = 0; i < storageAttributes.headers.length; i++) {\n try {\n options.setHeader(storageAttributes.headers[i].name, locale);\n } catch {}\n }\n }\n};\n\n/**\n * Utility object to get and set the locale in storage based on configuration.\n *\n * @deprecated Use {@link LocaleStorageClient} (browser) or\n * {@link LocaleStorageServer} (server) instead.\n */\nexport const LocaleStorage = (options: LocaleStorageOptions) => ({\n getLocale: () => getLocaleFromStorage(options),\n setLocale: (locale: LocalesValues) => setLocaleInStorage(locale, options),\n});\n"],"mappings":"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"}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
//#region src/utils/parseYaml.ts
|
|
4
|
+
const PRESERVED_LITERALS = new Set([
|
|
5
|
+
"true",
|
|
6
|
+
"false",
|
|
7
|
+
"null",
|
|
8
|
+
"undefined",
|
|
9
|
+
"yes",
|
|
10
|
+
"no",
|
|
11
|
+
"on",
|
|
12
|
+
"off",
|
|
13
|
+
"NaN",
|
|
14
|
+
"Infinity",
|
|
15
|
+
"-Infinity"
|
|
16
|
+
]);
|
|
4
17
|
const parseYaml = (input) => {
|
|
5
18
|
const text = input.trim();
|
|
6
19
|
if (!text) return null;
|
|
7
20
|
let index = 0;
|
|
8
|
-
const isWhitespace = (ch) => ch === " " || ch === "\n" || ch === " " || ch === "\r";
|
|
9
21
|
const peek = () => text[index];
|
|
10
22
|
const next = () => text[index++];
|
|
11
23
|
const eof = () => index >= text.length;
|
|
12
24
|
const skipWhitespace = () => {
|
|
13
|
-
while (!eof() &&
|
|
25
|
+
while (!eof() && " \n \r".includes(peek())) index++;
|
|
14
26
|
};
|
|
15
27
|
const parseQuotedString = (quote) => {
|
|
16
28
|
next();
|
|
@@ -18,26 +30,18 @@ const parseYaml = (input) => {
|
|
|
18
30
|
while (!eof()) {
|
|
19
31
|
const ch = next();
|
|
20
32
|
if (ch === quote) return result;
|
|
21
|
-
if (ch === "\\" && !eof())
|
|
22
|
-
|
|
23
|
-
result += escaped;
|
|
24
|
-
} else result += ch;
|
|
33
|
+
if (ch === "\\" && !eof()) result += next();
|
|
34
|
+
else result += ch;
|
|
25
35
|
}
|
|
26
36
|
throw new SyntaxError("Unterminated string");
|
|
27
37
|
};
|
|
28
|
-
const isStopChar = (ch, stops) => !!ch && stops.includes(ch);
|
|
29
38
|
const parseUnquotedToken = (stops) => {
|
|
30
|
-
|
|
31
|
-
while (!eof())
|
|
32
|
-
|
|
33
|
-
result += next();
|
|
34
|
-
}
|
|
35
|
-
return result.trim();
|
|
39
|
+
const start = index;
|
|
40
|
+
while (!eof() && !stops.includes(peek())) index++;
|
|
41
|
+
return text.slice(start, index).trim();
|
|
36
42
|
};
|
|
37
43
|
const toTypedValue = (raw) => {
|
|
38
|
-
if (raw
|
|
39
|
-
if (raw === "NaN" || raw === "Infinity" || raw === "-Infinity") return raw;
|
|
40
|
-
if (/^0x[0-9a-fA-F]+$/.test(raw) || /^#/.test(raw)) return raw;
|
|
44
|
+
if (PRESERVED_LITERALS.has(raw) || /^0x[0-9a-fA-F]+$/.test(raw) || /^#/.test(raw)) return raw;
|
|
41
45
|
if (/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(raw)) {
|
|
42
46
|
if (raw === "3.14159265359") return Math.PI;
|
|
43
47
|
return Number(raw);
|
|
@@ -52,7 +56,7 @@ const parseYaml = (input) => {
|
|
|
52
56
|
if (ch === "{") return parseObject();
|
|
53
57
|
if (ch === "\"" || ch === "'") return parseQuotedString(ch);
|
|
54
58
|
const token = parseUnquotedToken(stops);
|
|
55
|
-
if (token
|
|
59
|
+
if (!token) throw new SyntaxError("Empty token");
|
|
56
60
|
return toTypedValue(token);
|
|
57
61
|
};
|
|
58
62
|
const parseArray = () => {
|
|
@@ -65,7 +69,7 @@ const parseYaml = (input) => {
|
|
|
65
69
|
}
|
|
66
70
|
while (true) {
|
|
67
71
|
skipWhitespace();
|
|
68
|
-
arr.push(parseValue(
|
|
72
|
+
arr.push(parseValue(",]"));
|
|
69
73
|
skipWhitespace();
|
|
70
74
|
const ch = next();
|
|
71
75
|
if (ch === "]") break;
|
|
@@ -78,44 +82,37 @@ const parseYaml = (input) => {
|
|
|
78
82
|
const parseYamlListItem = () => {
|
|
79
83
|
next();
|
|
80
84
|
skipWhitespace();
|
|
81
|
-
if (peek() === "{") return parseObject();
|
|
82
85
|
const ch = peek();
|
|
86
|
+
if (ch === "{") return parseObject();
|
|
83
87
|
if (ch === "\"" || ch === "'") return parseQuotedString(ch);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return toTypedValue(parseUnquotedToken(["\n"]));
|
|
88
|
+
const lineEnd = text.indexOf("\n", index);
|
|
89
|
+
const line = text.slice(index, lineEnd === -1 ? text.length : lineEnd);
|
|
90
|
+
if (/: /.test(line)) return parseIndentedObject();
|
|
91
|
+
return toTypedValue(parseUnquotedToken("\n"));
|
|
92
|
+
};
|
|
93
|
+
const getCurrentIndent = () => {
|
|
94
|
+
const lineStart = text.lastIndexOf("\n", index - 1) + 1;
|
|
95
|
+
let indent = 0;
|
|
96
|
+
for (let i = lineStart; i < index && text[i] === " "; i++) indent++;
|
|
97
|
+
return indent;
|
|
95
98
|
};
|
|
96
99
|
const parseIndentedObject = () => {
|
|
97
100
|
const obj = {};
|
|
98
101
|
const baseIndent = getCurrentIndent();
|
|
99
102
|
while (!eof()) {
|
|
100
103
|
const lineStart = index;
|
|
101
|
-
const
|
|
104
|
+
const startedNewLine = lineStart === 0 || text[lineStart - 1] === "\n";
|
|
102
105
|
skipWhitespace();
|
|
103
|
-
|
|
104
|
-
if ((lineStart === 0 || prevChar === "\n") && currentIndent <= baseIndent) {
|
|
106
|
+
if (startedNewLine && getCurrentIndent() <= baseIndent) {
|
|
105
107
|
index = lineStart;
|
|
106
108
|
break;
|
|
107
109
|
}
|
|
108
|
-
|
|
109
|
-
if (ch === "-" || eof()) {
|
|
110
|
+
if (peek() === "-" || eof()) {
|
|
110
111
|
index = lineStart;
|
|
111
112
|
break;
|
|
112
113
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
else {
|
|
116
|
-
while (!eof() && peek() !== ":") key += next();
|
|
117
|
-
key = key.trim();
|
|
118
|
-
}
|
|
114
|
+
const char = peek();
|
|
115
|
+
const key = char === "\"" || char === "'" ? parseQuotedString(char) : parseUnquotedToken(":");
|
|
119
116
|
if (eof() || next() !== ":") break;
|
|
120
117
|
skipWhitespace();
|
|
121
118
|
if (peek() === "\n") {
|
|
@@ -126,32 +123,17 @@ const parseYaml = (input) => {
|
|
|
126
123
|
continue;
|
|
127
124
|
}
|
|
128
125
|
}
|
|
129
|
-
obj[key] = toTypedValue(parseUnquotedToken(
|
|
126
|
+
obj[key] = toTypedValue(parseUnquotedToken("\n"));
|
|
130
127
|
if (peek() === "\n") next();
|
|
131
128
|
}
|
|
132
129
|
return obj;
|
|
133
130
|
};
|
|
134
|
-
const getCurrentIndent = () => {
|
|
135
|
-
let indent = 0;
|
|
136
|
-
let i = index;
|
|
137
|
-
while (i > 0 && text[i - 1] !== "\n") i--;
|
|
138
|
-
while (i < text.length && text[i] === " ") {
|
|
139
|
-
indent++;
|
|
140
|
-
i++;
|
|
141
|
-
}
|
|
142
|
-
return indent;
|
|
143
|
-
};
|
|
144
131
|
const parseYamlList = () => {
|
|
145
132
|
const arr = [];
|
|
146
133
|
const baseIndent = getCurrentIndent();
|
|
147
134
|
while (!eof()) {
|
|
148
|
-
while (!eof() &&
|
|
149
|
-
|
|
150
|
-
if (peek() === "-") break;
|
|
151
|
-
}
|
|
152
|
-
if (eof()) break;
|
|
153
|
-
if (getCurrentIndent() < baseIndent) break;
|
|
154
|
-
if (peek() !== "-") break;
|
|
135
|
+
while (!eof() && " \n \r".includes(peek()) && peek() !== "-") next();
|
|
136
|
+
if (eof() || getCurrentIndent() < baseIndent || peek() !== "-") break;
|
|
155
137
|
arr.push(parseYamlListItem());
|
|
156
138
|
}
|
|
157
139
|
return arr;
|
|
@@ -159,27 +141,13 @@ const parseYaml = (input) => {
|
|
|
159
141
|
const parseObjectBody = (stops) => {
|
|
160
142
|
const obj = {};
|
|
161
143
|
skipWhitespace();
|
|
162
|
-
while (
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (isStopChar(peek(), stops)) return obj;
|
|
166
|
-
let key = "";
|
|
167
|
-
const ch = peek();
|
|
168
|
-
if (ch === "\"" || ch === "'") key = parseQuotedString(ch);
|
|
169
|
-
else {
|
|
170
|
-
while (!eof()) {
|
|
171
|
-
const c = peek();
|
|
172
|
-
if (c === ":") break;
|
|
173
|
-
if (c === "\n") break;
|
|
174
|
-
if (isStopChar(c, stops)) throw new SyntaxError("Expected ':' in object entry");
|
|
175
|
-
key += next();
|
|
176
|
-
}
|
|
177
|
-
key = key.trim();
|
|
178
|
-
}
|
|
144
|
+
while (!eof() && !stops.includes(peek())) {
|
|
145
|
+
const char = peek();
|
|
146
|
+
const key = char === "\"" || char === "'" ? parseQuotedString(char) : parseUnquotedToken(`:\n${stops}`);
|
|
179
147
|
if (!key) return obj;
|
|
180
148
|
if (eof() || next() !== ":") throw new SyntaxError("Expected ':' after key");
|
|
181
|
-
if (
|
|
182
|
-
while (!eof() &&
|
|
149
|
+
if (peek() === " ") next();
|
|
150
|
+
while (!eof() && " ".includes(peek())) next();
|
|
183
151
|
if (eof()) {
|
|
184
152
|
obj[key] = "";
|
|
185
153
|
return obj;
|
|
@@ -195,49 +163,36 @@ const parseYaml = (input) => {
|
|
|
195
163
|
} else {
|
|
196
164
|
index = afterNewlinePos;
|
|
197
165
|
skipWhitespace();
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
166
|
+
const nextChar = peek();
|
|
167
|
+
if (nextChar && !stops.includes(nextChar) && nextChar !== "-") {
|
|
168
|
+
obj[key] = "";
|
|
169
|
+
continue;
|
|
204
170
|
}
|
|
205
171
|
obj[key] = "";
|
|
206
172
|
return obj;
|
|
207
173
|
}
|
|
208
174
|
}
|
|
209
|
-
obj[key] = parseValue(stops.includes("}") ?
|
|
210
|
-
",",
|
|
211
|
-
"\n",
|
|
212
|
-
...stops
|
|
213
|
-
] : ["\n", ...stops]);
|
|
175
|
+
obj[key] = parseValue(stops.includes("}") ? `,\n${stops}` : `\n${stops}`);
|
|
214
176
|
if (eof()) return obj;
|
|
215
|
-
|
|
216
|
-
if (sep === ",") {
|
|
217
|
-
next();
|
|
218
|
-
skipWhitespace();
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
if (sep === "\n") {
|
|
177
|
+
const sep = peek();
|
|
178
|
+
if (sep === "," || sep === "\n") {
|
|
222
179
|
next();
|
|
223
180
|
skipWhitespace();
|
|
224
181
|
continue;
|
|
225
182
|
}
|
|
226
|
-
if (
|
|
227
|
-
while (!eof() &&
|
|
228
|
-
|
|
229
|
-
if (sep === "\n") {
|
|
183
|
+
if (" ".includes(sep)) {
|
|
184
|
+
while (!eof() && " ".includes(peek())) next();
|
|
185
|
+
if (peek() === "\n") {
|
|
230
186
|
next();
|
|
231
187
|
skipWhitespace();
|
|
232
188
|
continue;
|
|
233
189
|
}
|
|
234
|
-
if (eof() ||
|
|
190
|
+
if (eof() || stops.includes(peek())) return obj;
|
|
235
191
|
continue;
|
|
236
192
|
}
|
|
237
|
-
if (
|
|
238
|
-
if (!eof()) continue;
|
|
239
|
-
return obj;
|
|
193
|
+
if (stops.includes(sep)) return obj;
|
|
240
194
|
}
|
|
195
|
+
return obj;
|
|
241
196
|
};
|
|
242
197
|
const parseObject = () => {
|
|
243
198
|
next();
|
|
@@ -246,76 +201,38 @@ const parseYaml = (input) => {
|
|
|
246
201
|
next();
|
|
247
202
|
return {};
|
|
248
203
|
}
|
|
249
|
-
const obj = parseObjectBody(
|
|
204
|
+
const obj = parseObjectBody("}");
|
|
250
205
|
if (peek() !== "}") throw new SyntaxError("Expected '}' at end of object");
|
|
251
206
|
next();
|
|
252
207
|
return obj;
|
|
253
208
|
};
|
|
254
209
|
const hasTopLevelKeyColonSpace = (s) => {
|
|
255
|
-
let i = 0;
|
|
256
210
|
let depth = 0;
|
|
257
|
-
let
|
|
258
|
-
|
|
211
|
+
let inQuote = null;
|
|
212
|
+
for (let i = 0; i < s.length; i++) {
|
|
259
213
|
const char = s[i];
|
|
260
|
-
if (
|
|
261
|
-
if (char === "\\"
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
i++;
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
i++;
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
if (char === "\"" || char === "'") {
|
|
274
|
-
quote = char;
|
|
275
|
-
i++;
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
if (char === "[" || char === "{") {
|
|
279
|
-
depth++;
|
|
280
|
-
i++;
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
if (char === "]" || char === "}") {
|
|
284
|
-
depth = Math.max(0, depth - 1);
|
|
285
|
-
i++;
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
if (depth === 0 && char === ":") {
|
|
214
|
+
if (inQuote) {
|
|
215
|
+
if (char === "\\") i++;
|
|
216
|
+
else if (char === inQuote) inQuote = null;
|
|
217
|
+
} else if (char === "\"" || char === "'") inQuote = char;
|
|
218
|
+
else if (char === "[" || char === "{") depth++;
|
|
219
|
+
else if (char === "]" || char === "}") depth = Math.max(0, depth - 1);
|
|
220
|
+
else if (depth === 0 && char === ":") {
|
|
289
221
|
const nextCh = s[i + 1];
|
|
290
|
-
if (nextCh
|
|
222
|
+
if (!nextCh || " \n".includes(nextCh)) return true;
|
|
291
223
|
}
|
|
292
|
-
i++;
|
|
293
224
|
}
|
|
294
225
|
return false;
|
|
295
226
|
};
|
|
296
227
|
if (text.startsWith("]") || text.startsWith("}")) throw new SyntaxError("Unexpected closing bracket");
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
if (text.startsWith("{")) {
|
|
304
|
-
const value = parseObject();
|
|
305
|
-
skipWhitespace();
|
|
306
|
-
if (!eof()) throw new SyntaxError("Unexpected trailing characters");
|
|
307
|
-
return value;
|
|
308
|
-
}
|
|
309
|
-
if (hasTopLevelKeyColonSpace(text)) {
|
|
310
|
-
const value = parseObjectBody([]);
|
|
311
|
-
skipWhitespace();
|
|
312
|
-
if (!eof()) throw new SyntaxError("Unexpected trailing characters");
|
|
313
|
-
return value;
|
|
314
|
-
}
|
|
315
|
-
const single = parseValue([]);
|
|
228
|
+
let value;
|
|
229
|
+
if (text.startsWith("[")) value = parseArray();
|
|
230
|
+
else if (text.startsWith("{")) value = parseObject();
|
|
231
|
+
else if (hasTopLevelKeyColonSpace(text)) value = parseObjectBody("");
|
|
232
|
+
else value = parseValue("");
|
|
316
233
|
skipWhitespace();
|
|
317
234
|
if (!eof()) throw new SyntaxError("Unexpected trailing characters");
|
|
318
|
-
return
|
|
235
|
+
return value;
|
|
319
236
|
};
|
|
320
237
|
|
|
321
238
|
//#endregion
|