@wix/headless-localization-utils 1.0.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.
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ getLocalizationData: () => getLocalizationData
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/localeUtils.ts
28
+ var buildLocaleString = (locale) => {
29
+ if (!locale) {
30
+ return;
31
+ }
32
+ if (locale.languageCode?.includes("-")) {
33
+ return locale.languageCode;
34
+ }
35
+ const localeParts = [locale.languageCode, locale.country].filter(Boolean);
36
+ if (localeParts.length === 0) {
37
+ return;
38
+ }
39
+ return localeParts.join("-");
40
+ };
41
+
42
+ // src/urlUtils.ts
43
+ var getLanguageFromQueryParam = (url) => url.searchParams.get("lang") ?? void 0;
44
+ var getLanguageFromSubfolder = (url) => url.pathname.split("/")[1];
45
+ var getLanguageFromSubdomain = (url) => url.hostname.split(".")[0];
46
+ var extractLanguageFromUrlAndValidate = (url, availableLocales) => {
47
+ const localeFromQueryParams = extractFromQueryParamsAndValidate(
48
+ url,
49
+ availableLocales
50
+ );
51
+ if (localeFromQueryParams?.resolutionMethod === "QUERY_PARAM") {
52
+ return localeFromQueryParams;
53
+ }
54
+ const localeFromSubfolder = extractFromSubfolderAndValidate(
55
+ url,
56
+ availableLocales
57
+ );
58
+ if (localeFromSubfolder?.resolutionMethod === "SUBDIRECTORY") {
59
+ return localeFromSubfolder;
60
+ }
61
+ const localeFromSubdomain = extractFromSubdomainAndValidate(
62
+ url,
63
+ availableLocales
64
+ );
65
+ if (localeFromSubdomain?.resolutionMethod === "SUBDOMAIN") {
66
+ return localeFromSubdomain;
67
+ }
68
+ return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;
69
+ };
70
+ var clearLanguageFromUrl = (urlString, languageCodes) => {
71
+ const url = new URL(urlString);
72
+ url.searchParams.delete("lang");
73
+ const subfolderLanguage = url.pathname.split("/")[1]?.toLowerCase();
74
+ if (languageCodes.includes(subfolderLanguage ?? "")) {
75
+ const segments = url.pathname.split("/");
76
+ segments.splice(1, 1);
77
+ url.pathname = segments.join("/");
78
+ }
79
+ const subdirectoryLanguage = url.hostname.split(".")[0]?.toLowerCase();
80
+ if (languageCodes.includes(subdirectoryLanguage ?? "")) {
81
+ const parts = url.hostname.split(".");
82
+ parts.shift();
83
+ url.hostname = parts.join(".");
84
+ }
85
+ return url.href;
86
+ };
87
+ var extractFromQueryParamsAndValidate = (url, availableLocales) => {
88
+ return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);
89
+ };
90
+ var extractFromSubfolderAndValidate = (url, availableLocales) => {
91
+ return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);
92
+ };
93
+ var extractFromSubdomainAndValidate = (url, availableLocales) => {
94
+ return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);
95
+ };
96
+ var getLanguageIfExists = (languageCode, availableLocales) => {
97
+ if (languageCode == null) {
98
+ return void 0;
99
+ }
100
+ const lowerCasedCode = languageCode.toLowerCase();
101
+ return availableLocales.find(
102
+ (locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode
103
+ );
104
+ };
105
+
106
+ // src/localizationUtils.ts
107
+ function getLocalizationData(url, siteProperties) {
108
+ const availableLocales = siteProperties?.multilingual?.supportedLanguages ?? [];
109
+ const explicitRequestedLocale = extractLanguageFromUrlAndValidate(
110
+ url,
111
+ availableLocales
112
+ );
113
+ const languageCodes = [
114
+ ...availableLocales.map((locale2) => locale2.locale?.languageCode),
115
+ siteProperties?.locale?.languageCode
116
+ ].filter((languageCode) => Boolean(languageCode));
117
+ const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
118
+ const locale = buildLocaleString(
119
+ explicitRequestedLocale?.locale ?? siteProperties?.locale
120
+ ) ?? void 0;
121
+ const language = explicitRequestedLocale?.languageCode ?? siteProperties?.language ?? void 0;
122
+ const essentials = {
123
+ language,
124
+ locale,
125
+ multilingual: siteProperties?.multilingual,
126
+ timezone: siteProperties?.timeZone ?? void 0
127
+ };
128
+ return { cleanUrl, essentials };
129
+ }
130
+ // Annotate the CommonJS export names for ESM import in node:
131
+ 0 && (module.exports = {
132
+ getLocalizationData
133
+ });
134
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/localeUtils.ts","../src/urlUtils.ts","../src/localizationUtils.ts"],"sourcesContent":["export {\n getLocalizationData,\n type LocalizationData,\n} from './localizationUtils.js';\n","import type { scripts } from '@wix/headless-site-assets';\n\n// Type for locale object\nexport type Locale = scripts.Locale;\n\n// Type for locale string building\nexport const buildLocaleString = (\n locale?: null | Locale,\n): string | undefined => {\n if (!locale) {\n return;\n }\n\n // in case of dialects, language code will be in the form of\n // en-au and not just en\n if (locale.languageCode?.includes('-')) {\n return locale.languageCode;\n }\n\n const localeParts = [locale.languageCode, locale.country].filter(Boolean);\n\n if (localeParts.length === 0) {\n return;\n }\n\n return localeParts.join('-');\n};\n","import type { scripts } from '@wix/headless-site-assets';\n\nexport type SupportedLanguage = scripts.SupportedLanguage;\n\ntype AvailableLocale = SupportedLanguage;\n\nconst getLanguageFromQueryParam = (url: URL) =>\n url.searchParams.get('lang') ?? undefined;\nconst getLanguageFromSubfolder = (url: URL) => url.pathname.split('/')[1];\nconst getLanguageFromSubdomain = (url: URL) => url.hostname.split('.')[0];\n\nexport const extractLanguageFromUrlAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n const localeFromQueryParams = extractFromQueryParamsAndValidate(\n url,\n availableLocales,\n );\n if (localeFromQueryParams?.resolutionMethod === 'QUERY_PARAM') {\n return localeFromQueryParams;\n }\n\n const localeFromSubfolder = extractFromSubfolderAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubfolder?.resolutionMethod === 'SUBDIRECTORY') {\n return localeFromSubfolder;\n }\n\n const localeFromSubdomain = extractFromSubdomainAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubdomain?.resolutionMethod === 'SUBDOMAIN') {\n return localeFromSubdomain;\n }\n\n // Fallback if a locale is available but doesn't have the correct resolution method\n return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;\n};\n\nexport const clearLanguageFromUrl = (\n urlString: string,\n languageCodes: string[],\n): string => {\n const url = new URL(urlString);\n url.searchParams.delete('lang');\n\n const subfolderLanguage = url.pathname.split('/')[1]?.toLowerCase();\n if (languageCodes.includes(subfolderLanguage ?? '')) {\n const segments = url.pathname.split('/'); // ['', 'en', 'docs', 'api']\n segments.splice(1, 1); // Remove index 1\n url.pathname = segments.join('/');\n }\n\n const subdirectoryLanguage = url.hostname.split('.')[0]?.toLowerCase();\n if (languageCodes.includes(subdirectoryLanguage ?? '')) {\n const parts = url.hostname.split('.'); // ['fr', 'example', 'com']\n parts.shift(); // ['example', 'com']\n url.hostname = parts.join('.');\n }\n\n return url.href;\n};\n\n// https://somesite.com/hello?lang:XX\nconst extractFromQueryParamsAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);\n};\n\n// https://somesite.com/XX/hello\nconst extractFromSubfolderAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);\n};\n\n// https://XX.somesite.com/hello\nconst extractFromSubdomainAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);\n};\n\nconst getLanguageIfExists = (\n languageCode: string | undefined,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n if (languageCode == null) {\n return undefined;\n }\n const lowerCasedCode = languageCode.toLowerCase();\n return availableLocales.find(\n (locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode,\n );\n};\n","import type { Essentials, Multilingual } from '@wix/headless-node';\nimport type { scripts } from '@wix/headless-site-assets';\nimport { buildLocaleString } from './localeUtils.js';\nimport {\n clearLanguageFromUrl,\n extractLanguageFromUrlAndValidate,\n} from './urlUtils.js';\n\nexport type EssentialProperties = scripts.EssentialProperties;\n\nexport type LocalizationData = {\n cleanUrl: string;\n essentials: Essentials;\n};\n\nexport function getLocalizationData(\n url: URL,\n siteProperties: EssentialProperties,\n): LocalizationData {\n const availableLocales =\n siteProperties?.multilingual?.supportedLanguages ?? [];\n const explicitRequestedLocale = extractLanguageFromUrlAndValidate(\n url,\n availableLocales,\n );\n\n const languageCodes = [\n ...availableLocales.map((locale) => locale.locale?.languageCode),\n siteProperties?.locale?.languageCode,\n ].filter((languageCode) => Boolean(languageCode)) as string[];\n\n const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);\n\n const locale =\n buildLocaleString(\n explicitRequestedLocale?.locale ?? siteProperties?.locale,\n ) ?? undefined;\n\n const language =\n explicitRequestedLocale?.languageCode ??\n siteProperties?.language ??\n undefined;\n\n const essentials: Essentials = {\n language,\n locale,\n multilingual: siteProperties?.multilingual as Multilingual | undefined,\n timezone: siteProperties?.timeZone ?? undefined,\n };\n\n return { cleanUrl, essentials };\n}\n"],"mappings":"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","names":["locale"]}
@@ -0,0 +1,11 @@
1
+ import { Essentials } from '@wix/headless-node';
2
+ import { scripts } from '@wix/headless-site-assets';
3
+
4
+ type EssentialProperties = scripts.EssentialProperties;
5
+ type LocalizationData = {
6
+ cleanUrl: string;
7
+ essentials: Essentials;
8
+ };
9
+ declare function getLocalizationData(url: URL, siteProperties: EssentialProperties): LocalizationData;
10
+
11
+ export { type LocalizationData, getLocalizationData };
@@ -0,0 +1,11 @@
1
+ import { Essentials } from '@wix/headless-node';
2
+ import { scripts } from '@wix/headless-site-assets';
3
+
4
+ type EssentialProperties = scripts.EssentialProperties;
5
+ type LocalizationData = {
6
+ cleanUrl: string;
7
+ essentials: Essentials;
8
+ };
9
+ declare function getLocalizationData(url: URL, siteProperties: EssentialProperties): LocalizationData;
10
+
11
+ export { type LocalizationData, getLocalizationData };
package/build/index.js ADDED
@@ -0,0 +1,107 @@
1
+ // src/localeUtils.ts
2
+ var buildLocaleString = (locale) => {
3
+ if (!locale) {
4
+ return;
5
+ }
6
+ if (locale.languageCode?.includes("-")) {
7
+ return locale.languageCode;
8
+ }
9
+ const localeParts = [locale.languageCode, locale.country].filter(Boolean);
10
+ if (localeParts.length === 0) {
11
+ return;
12
+ }
13
+ return localeParts.join("-");
14
+ };
15
+
16
+ // src/urlUtils.ts
17
+ var getLanguageFromQueryParam = (url) => url.searchParams.get("lang") ?? void 0;
18
+ var getLanguageFromSubfolder = (url) => url.pathname.split("/")[1];
19
+ var getLanguageFromSubdomain = (url) => url.hostname.split(".")[0];
20
+ var extractLanguageFromUrlAndValidate = (url, availableLocales) => {
21
+ const localeFromQueryParams = extractFromQueryParamsAndValidate(
22
+ url,
23
+ availableLocales
24
+ );
25
+ if (localeFromQueryParams?.resolutionMethod === "QUERY_PARAM") {
26
+ return localeFromQueryParams;
27
+ }
28
+ const localeFromSubfolder = extractFromSubfolderAndValidate(
29
+ url,
30
+ availableLocales
31
+ );
32
+ if (localeFromSubfolder?.resolutionMethod === "SUBDIRECTORY") {
33
+ return localeFromSubfolder;
34
+ }
35
+ const localeFromSubdomain = extractFromSubdomainAndValidate(
36
+ url,
37
+ availableLocales
38
+ );
39
+ if (localeFromSubdomain?.resolutionMethod === "SUBDOMAIN") {
40
+ return localeFromSubdomain;
41
+ }
42
+ return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;
43
+ };
44
+ var clearLanguageFromUrl = (urlString, languageCodes) => {
45
+ const url = new URL(urlString);
46
+ url.searchParams.delete("lang");
47
+ const subfolderLanguage = url.pathname.split("/")[1]?.toLowerCase();
48
+ if (languageCodes.includes(subfolderLanguage ?? "")) {
49
+ const segments = url.pathname.split("/");
50
+ segments.splice(1, 1);
51
+ url.pathname = segments.join("/");
52
+ }
53
+ const subdirectoryLanguage = url.hostname.split(".")[0]?.toLowerCase();
54
+ if (languageCodes.includes(subdirectoryLanguage ?? "")) {
55
+ const parts = url.hostname.split(".");
56
+ parts.shift();
57
+ url.hostname = parts.join(".");
58
+ }
59
+ return url.href;
60
+ };
61
+ var extractFromQueryParamsAndValidate = (url, availableLocales) => {
62
+ return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);
63
+ };
64
+ var extractFromSubfolderAndValidate = (url, availableLocales) => {
65
+ return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);
66
+ };
67
+ var extractFromSubdomainAndValidate = (url, availableLocales) => {
68
+ return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);
69
+ };
70
+ var getLanguageIfExists = (languageCode, availableLocales) => {
71
+ if (languageCode == null) {
72
+ return void 0;
73
+ }
74
+ const lowerCasedCode = languageCode.toLowerCase();
75
+ return availableLocales.find(
76
+ (locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode
77
+ );
78
+ };
79
+
80
+ // src/localizationUtils.ts
81
+ function getLocalizationData(url, siteProperties) {
82
+ const availableLocales = siteProperties?.multilingual?.supportedLanguages ?? [];
83
+ const explicitRequestedLocale = extractLanguageFromUrlAndValidate(
84
+ url,
85
+ availableLocales
86
+ );
87
+ const languageCodes = [
88
+ ...availableLocales.map((locale2) => locale2.locale?.languageCode),
89
+ siteProperties?.locale?.languageCode
90
+ ].filter((languageCode) => Boolean(languageCode));
91
+ const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
92
+ const locale = buildLocaleString(
93
+ explicitRequestedLocale?.locale ?? siteProperties?.locale
94
+ ) ?? void 0;
95
+ const language = explicitRequestedLocale?.languageCode ?? siteProperties?.language ?? void 0;
96
+ const essentials = {
97
+ language,
98
+ locale,
99
+ multilingual: siteProperties?.multilingual,
100
+ timezone: siteProperties?.timeZone ?? void 0
101
+ };
102
+ return { cleanUrl, essentials };
103
+ }
104
+ export {
105
+ getLocalizationData
106
+ };
107
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/localeUtils.ts","../src/urlUtils.ts","../src/localizationUtils.ts"],"sourcesContent":["import type { scripts } from '@wix/headless-site-assets';\n\n// Type for locale object\nexport type Locale = scripts.Locale;\n\n// Type for locale string building\nexport const buildLocaleString = (\n locale?: null | Locale,\n): string | undefined => {\n if (!locale) {\n return;\n }\n\n // in case of dialects, language code will be in the form of\n // en-au and not just en\n if (locale.languageCode?.includes('-')) {\n return locale.languageCode;\n }\n\n const localeParts = [locale.languageCode, locale.country].filter(Boolean);\n\n if (localeParts.length === 0) {\n return;\n }\n\n return localeParts.join('-');\n};\n","import type { scripts } from '@wix/headless-site-assets';\n\nexport type SupportedLanguage = scripts.SupportedLanguage;\n\ntype AvailableLocale = SupportedLanguage;\n\nconst getLanguageFromQueryParam = (url: URL) =>\n url.searchParams.get('lang') ?? undefined;\nconst getLanguageFromSubfolder = (url: URL) => url.pathname.split('/')[1];\nconst getLanguageFromSubdomain = (url: URL) => url.hostname.split('.')[0];\n\nexport const extractLanguageFromUrlAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n const localeFromQueryParams = extractFromQueryParamsAndValidate(\n url,\n availableLocales,\n );\n if (localeFromQueryParams?.resolutionMethod === 'QUERY_PARAM') {\n return localeFromQueryParams;\n }\n\n const localeFromSubfolder = extractFromSubfolderAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubfolder?.resolutionMethod === 'SUBDIRECTORY') {\n return localeFromSubfolder;\n }\n\n const localeFromSubdomain = extractFromSubdomainAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubdomain?.resolutionMethod === 'SUBDOMAIN') {\n return localeFromSubdomain;\n }\n\n // Fallback if a locale is available but doesn't have the correct resolution method\n return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;\n};\n\nexport const clearLanguageFromUrl = (\n urlString: string,\n languageCodes: string[],\n): string => {\n const url = new URL(urlString);\n url.searchParams.delete('lang');\n\n const subfolderLanguage = url.pathname.split('/')[1]?.toLowerCase();\n if (languageCodes.includes(subfolderLanguage ?? '')) {\n const segments = url.pathname.split('/'); // ['', 'en', 'docs', 'api']\n segments.splice(1, 1); // Remove index 1\n url.pathname = segments.join('/');\n }\n\n const subdirectoryLanguage = url.hostname.split('.')[0]?.toLowerCase();\n if (languageCodes.includes(subdirectoryLanguage ?? '')) {\n const parts = url.hostname.split('.'); // ['fr', 'example', 'com']\n parts.shift(); // ['example', 'com']\n url.hostname = parts.join('.');\n }\n\n return url.href;\n};\n\n// https://somesite.com/hello?lang:XX\nconst extractFromQueryParamsAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);\n};\n\n// https://somesite.com/XX/hello\nconst extractFromSubfolderAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);\n};\n\n// https://XX.somesite.com/hello\nconst extractFromSubdomainAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);\n};\n\nconst getLanguageIfExists = (\n languageCode: string | undefined,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n if (languageCode == null) {\n return undefined;\n }\n const lowerCasedCode = languageCode.toLowerCase();\n return availableLocales.find(\n (locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode,\n );\n};\n","import type { Essentials, Multilingual } from '@wix/headless-node';\nimport type { scripts } from '@wix/headless-site-assets';\nimport { buildLocaleString } from './localeUtils.js';\nimport {\n clearLanguageFromUrl,\n extractLanguageFromUrlAndValidate,\n} from './urlUtils.js';\n\nexport type EssentialProperties = scripts.EssentialProperties;\n\nexport type LocalizationData = {\n cleanUrl: string;\n essentials: Essentials;\n};\n\nexport function getLocalizationData(\n url: URL,\n siteProperties: EssentialProperties,\n): LocalizationData {\n const availableLocales =\n siteProperties?.multilingual?.supportedLanguages ?? [];\n const explicitRequestedLocale = extractLanguageFromUrlAndValidate(\n url,\n availableLocales,\n );\n\n const languageCodes = [\n ...availableLocales.map((locale) => locale.locale?.languageCode),\n siteProperties?.locale?.languageCode,\n ].filter((languageCode) => Boolean(languageCode)) as string[];\n\n const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);\n\n const locale =\n buildLocaleString(\n explicitRequestedLocale?.locale ?? siteProperties?.locale,\n ) ?? undefined;\n\n const language =\n explicitRequestedLocale?.languageCode ??\n siteProperties?.language ??\n undefined;\n\n const essentials: Essentials = {\n language,\n locale,\n multilingual: siteProperties?.multilingual as Multilingual | undefined,\n timezone: siteProperties?.timeZone ?? undefined,\n };\n\n return { cleanUrl, essentials };\n}\n"],"mappings":"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","names":["locale"]}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@wix/headless-localization-utils",
3
+ "version": "1.0.0",
4
+ "unpkg": true,
5
+ "license": "MIT",
6
+ "author": {
7
+ "name": "tomsa",
8
+ "email": "tomsa@wix.com"
9
+ },
10
+ "main": "build/index.cjs",
11
+ "module": "build/index.js",
12
+ "types": "build/index.d.ts",
13
+ "type": "module",
14
+ "sideEffects": false,
15
+ "files": [
16
+ "build"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "import": {
21
+ "types": "./build/index.d.ts",
22
+ "default": "./build/index.js"
23
+ },
24
+ "require": {
25
+ "types": "./build/index.d.ts",
26
+ "default": "./build/index.cjs"
27
+ },
28
+ "default": {
29
+ "types": "./build/index.d.ts",
30
+ "default": "./build/index.js"
31
+ }
32
+ }
33
+ },
34
+ "publishConfig": {
35
+ "registry": "https://registry.npmjs.org/",
36
+ "access": "public"
37
+ },
38
+ "publishScoped": true,
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "test": "vitest",
42
+ "lint": "eslint --max-warnings=0 .",
43
+ "lint:fix": "eslint --max-warnings=0 . --fix",
44
+ "typecheck": "tsc --noEmit"
45
+ },
46
+ "dependencies": {
47
+ "@wix/headless-node": "1.21.0",
48
+ "@wix/headless-site-assets": "^1.0.9"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^16.0.0",
52
+ "eslint": "^8.57.1",
53
+ "tsup": "^8.5.0",
54
+ "typescript": "~4.9.0",
55
+ "vitest": "^3.2.4"
56
+ },
57
+ "eslintConfig": {
58
+ "extends": "@wix/eslint-config-yoshi",
59
+ "ignorePatterns": [
60
+ "**/build/*"
61
+ ]
62
+ },
63
+ "wix": {
64
+ "artifact": {
65
+ "groupId": "com.wixpress",
66
+ "artifactId": "headless-localization-utils"
67
+ },
68
+ "validations": {
69
+ "source": [
70
+ "lint"
71
+ ],
72
+ "postDependenciesBuild": [
73
+ "typecheck"
74
+ ]
75
+ }
76
+ },
77
+ "falconPackageHash": "adbcff16f170e15e21f5e703cfcd0b5e183b5258f15ee998fb4dd41f"
78
+ }