@salesforce/angular-plugin-ui-bundle 12.3.13 → 12.4.1
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/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/middleware/html.d.ts +54 -2
- package/dist/middleware/html.d.ts.map +1 -1
- package/dist/middleware/html.js +60 -22
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +30 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +39 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* For full license text, see the LICENSE.txt file
|
|
5
5
|
*/
|
|
6
|
-
export type { SalesforceOptions, Middleware } from "./types.ts";
|
|
6
|
+
export type { SalesforceOptions, Middleware, SiteOptions } from "./types.ts";
|
|
7
7
|
export type { ApiVersionResult } from "./plugins/api-version.ts";
|
|
8
8
|
export { createApiVersionPlugin } from "./plugins/api-version.ts";
|
|
9
9
|
export { createGraphQLCodegenPlugin } from "./plugins/graphql-codegen.ts";
|
|
10
10
|
export { DEFAULT_API_VERSION, DEFAULT_PORT, getPort } from "./utils.ts";
|
|
11
11
|
export { createProxyMiddleware } from "./middleware/proxy.ts";
|
|
12
|
-
export { createHtmlMiddleware } from "./middleware/html.ts";
|
|
12
|
+
export { createHtmlMiddleware, createSiteHtmlMiddleware } from "./middleware/html.ts";
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,4 +7,4 @@ export { createApiVersionPlugin } from "./plugins/api-version.js";
|
|
|
7
7
|
export { createGraphQLCodegenPlugin } from "./plugins/graphql-codegen.js";
|
|
8
8
|
export { DEFAULT_API_VERSION, DEFAULT_PORT, getPort } from "./utils.js";
|
|
9
9
|
export { createProxyMiddleware } from "./middleware/proxy.js";
|
|
10
|
-
export { createHtmlMiddleware } from "./middleware/html.js";
|
|
10
|
+
export { createHtmlMiddleware, createSiteHtmlMiddleware } from "./middleware/html.js";
|
|
@@ -3,6 +3,58 @@
|
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* For full license text, see the LICENSE.txt file
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* HTML injection middleware for ng serve.
|
|
8
|
+
* Intercepts SPA navigation responses and injects the Live Preview script,
|
|
9
|
+
* SFDC_ENV global, and base href. Skips static files and /services/ paths.
|
|
10
|
+
* In design mode (SF_DESIGN_MODE) it also injects the runtime <script> tag
|
|
11
|
+
* (proxy.ts serves that script).
|
|
12
|
+
*
|
|
13
|
+
* Runs BEFORE the proxy middleware (wrapping must happen first).
|
|
14
|
+
*
|
|
15
|
+
* Split into a pure createIndexHtmlTransformer (string→string, unit-testable)
|
|
16
|
+
* and createHtmlMiddleware (req/res plumbing). The transformer is not public API.
|
|
17
|
+
*
|
|
18
|
+
* The optional `hooks.resolveRequest` callback enables per-request basePath and
|
|
19
|
+
* language injection — used by the site middleware (`/site` subpath) for
|
|
20
|
+
* language-prefixed URL support.
|
|
21
|
+
*/
|
|
22
|
+
import type { IncomingMessage } from "node:http";
|
|
23
|
+
import type { Middleware, SalesforceOptions, SiteOptions } from "../types.ts";
|
|
24
|
+
/**
|
|
25
|
+
* Per-request context returned by a `RequestResolver`. When provided, these
|
|
26
|
+
* values override the static basePath resolved at startup.
|
|
27
|
+
*/
|
|
28
|
+
export interface RequestContext {
|
|
29
|
+
/** The basePath to inject into `<base href>` and `SFDC_ENV.basePath`. */
|
|
30
|
+
basePath: string;
|
|
31
|
+
/** The language to inject into `SFDC_ENV.language` (omitted when undefined). */
|
|
32
|
+
language?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A per-request hook that resolves basePath and language from the incoming
|
|
36
|
+
* request. May also mutate `req.url` (e.g., strip a language segment).
|
|
37
|
+
*/
|
|
38
|
+
export type RequestResolver = (req: IncomingMessage) => RequestContext;
|
|
39
|
+
export interface HtmlMiddlewareHooks {
|
|
40
|
+
resolveRequest?: RequestResolver;
|
|
41
|
+
}
|
|
42
|
+
export declare function createHtmlMiddleware(options?: SalesforceOptions, hooks?: HtmlMiddlewareHooks): Promise<Middleware>;
|
|
43
|
+
/**
|
|
44
|
+
* Site-aware HTML middleware for Angular apps with language-prefixed URLs.
|
|
45
|
+
*
|
|
46
|
+
* Thin wrapper around `createHtmlMiddleware` that supplies a per-request
|
|
47
|
+
* `resolveRequest` hook. On each request the hook:
|
|
48
|
+
*
|
|
49
|
+
* 1. Resolves the active language from the leading URL path segment.
|
|
50
|
+
* 2. Strips the language segment from `req.url` so Angular's SPA routing
|
|
51
|
+
* sees `/accounts/1` instead of `/fr/accounts/1`.
|
|
52
|
+
* 3. Returns `{ basePath, language }` so the HTML transform injects the
|
|
53
|
+
* correct per-request `SFDC_ENV.language` and `SFDC_ENV.basePath`.
|
|
54
|
+
*
|
|
55
|
+
* When languages are empty, the feature is absent (CodeBuilder), or in
|
|
56
|
+
* production mode, the middleware degrades to the generic `createHtmlMiddleware`
|
|
57
|
+
* (no hook supplied — identity behavior).
|
|
58
|
+
*/
|
|
59
|
+
export declare function createSiteHtmlMiddleware(options?: SiteOptions): Promise<Middleware>;
|
|
8
60
|
//# sourceMappingURL=html.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/middleware/html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/middleware/html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAIjD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI9E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,cAAc,CAAC;AAEvE,MAAM,WAAW,mBAAmB;IACnC,cAAc,CAAC,EAAE,eAAe,CAAC;CACjC;AAiGD,wBAAsB,oBAAoB,CACzC,OAAO,GAAE,iBAAsB,EAC/B,KAAK,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,UAAU,CAAC,CAmFrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CA4B7F"}
|
package/dist/middleware/html.js
CHANGED
|
@@ -3,33 +3,23 @@
|
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* For full license text, see the LICENSE.txt file
|
|
5
5
|
*/
|
|
6
|
-
/**
|
|
7
|
-
* HTML injection middleware for ng serve.
|
|
8
|
-
* Intercepts SPA navigation responses and injects the Live Preview script,
|
|
9
|
-
* SFDC_ENV global, and base href. Skips static files and /services/ paths.
|
|
10
|
-
* In design mode (SF_DESIGN_MODE) it also injects the runtime <script> tag
|
|
11
|
-
* (proxy.ts serves that script).
|
|
12
|
-
*
|
|
13
|
-
* Runs BEFORE the proxy middleware (wrapping must happen first).
|
|
14
|
-
*
|
|
15
|
-
* Split into a pure createIndexHtmlTransformer (string→string, unit-testable)
|
|
16
|
-
* and createHtmlMiddleware (req/res plumbing). The transformer is not public API.
|
|
17
|
-
*/
|
|
18
6
|
import { getOrgInfo } from "@salesforce/ui-bundle/app";
|
|
19
7
|
import { injectLivePreviewScript } from "@salesforce/ui-bundle/proxy";
|
|
20
8
|
import { DESIGN_MODE_HYDRATE_PATH, DESIGN_MODE_SCRIPT_PATH } from "./proxy.js";
|
|
21
9
|
import { getAppName, getCodeBuilderBasePath, getNamespace, getPort } from "../utils.js";
|
|
10
|
+
import { normalizeLanguages, resolveLanguageFromUrl } from "../utils.js";
|
|
22
11
|
/**
|
|
23
|
-
* Builds a pure HTML transform
|
|
24
|
-
*
|
|
25
|
-
*
|
|
12
|
+
* Builds a pure HTML transform. When `ctx` is provided (per-request overrides),
|
|
13
|
+
* its `basePath` and `language` are used; otherwise the static basePath resolved
|
|
14
|
+
* at startup is used. The transform injects Live Preview, <base href>,
|
|
15
|
+
* SFDC_ENV global, and (optionally) design-mode scripts.
|
|
26
16
|
*/
|
|
27
17
|
async function createIndexHtmlTransformer(options = {}) {
|
|
28
18
|
const port = getPort();
|
|
29
19
|
const codeBuilderProxyUrl = process.env.CODE_BUILDER_FRAMEWORK_PROXY_URI;
|
|
30
20
|
const isCodeBuilder = !!codeBuilderProxyUrl;
|
|
31
|
-
const
|
|
32
|
-
const
|
|
21
|
+
const staticBasePath = isCodeBuilder ? getCodeBuilderBasePath(codeBuilderProxyUrl, port) : "/";
|
|
22
|
+
const staticApiPath = staticBasePath;
|
|
33
23
|
// App identity for SFDC_ENV (namespace + appName). Resolved from the app root
|
|
34
24
|
// (cwd — where ng serve runs), matching the server injector so local dev sees
|
|
35
25
|
// the same values a deployed bundle would.
|
|
@@ -47,9 +37,12 @@ async function createIndexHtmlTransformer(options = {}) {
|
|
|
47
37
|
orgUrl = undefined;
|
|
48
38
|
}
|
|
49
39
|
if (options.debug) {
|
|
50
|
-
console.log(`[angular-plugin-ui-bundle] HTML transformer: basePath="${
|
|
40
|
+
console.log(`[angular-plugin-ui-bundle] HTML transformer: basePath="${staticBasePath}", isCodeBuilder=${isCodeBuilder}, port=${port}, orgUrl=${orgUrl}`);
|
|
51
41
|
}
|
|
52
|
-
return (html) => {
|
|
42
|
+
return (html, ctx) => {
|
|
43
|
+
// Resolve per-request basePath or fall back to static
|
|
44
|
+
const basePath = ctx?.basePath ?? staticBasePath;
|
|
45
|
+
const apiPath = staticApiPath;
|
|
53
46
|
// 1. Live Preview script (enables VS Code extension communication)
|
|
54
47
|
html = injectLivePreviewScript(html);
|
|
55
48
|
// 2. <base href>: replace an existing tag, else inject after <head>.
|
|
@@ -61,13 +54,15 @@ async function createIndexHtmlTransformer(options = {}) {
|
|
|
61
54
|
else if (/<head(\s[^>]*)?>/i.test(html)) {
|
|
62
55
|
html = html.replace(/<head(\s[^>]*)?>/i, (match) => `${match}\n <base href="${baseHref}">`);
|
|
63
56
|
}
|
|
64
|
-
// 3. SFDC_ENV global (basePath + apiPath + orgUrl + app identity).
|
|
57
|
+
// 3. SFDC_ENV global (basePath + apiPath + orgUrl + app identity + language).
|
|
65
58
|
// JSON.stringify escapes quotes/backslashes in every value (e.g. an
|
|
66
59
|
// appName derived from a dir name), so no single field can break the
|
|
67
60
|
// emitted SFDC_ENV object. It does NOT escape `<`, so we also escape it
|
|
68
61
|
// to `<` to prevent a `</script>` in a value from closing this
|
|
69
62
|
// inline <script> element early.
|
|
70
63
|
const sfdcEnv = { basePath, apiPath };
|
|
64
|
+
if (ctx?.language)
|
|
65
|
+
sfdcEnv.language = ctx.language;
|
|
71
66
|
if (orgUrl)
|
|
72
67
|
sfdcEnv.orgUrl = orgUrl;
|
|
73
68
|
if (namespace)
|
|
@@ -96,9 +91,12 @@ async function createIndexHtmlTransformer(options = {}) {
|
|
|
96
91
|
return html;
|
|
97
92
|
};
|
|
98
93
|
}
|
|
99
|
-
export async function createHtmlMiddleware(options = {}) {
|
|
94
|
+
export async function createHtmlMiddleware(options = {}, hooks) {
|
|
100
95
|
const htmlTransformer = await createIndexHtmlTransformer(options);
|
|
101
96
|
return (req, res, next) => {
|
|
97
|
+
// Call the resolver hook BEFORE checking for static files — the hook may
|
|
98
|
+
// mutate req.url (e.g., strip a language segment).
|
|
99
|
+
const ctx = hooks?.resolveRequest?.(req);
|
|
102
100
|
// Skip static files (.js, .css, .ico) and internal paths
|
|
103
101
|
const url = req.url?.split("?")[0] ?? "/";
|
|
104
102
|
const hasExtension = url.lastIndexOf(".") > url.lastIndexOf("/");
|
|
@@ -132,7 +130,7 @@ export async function createHtmlMiddleware(options = {}) {
|
|
|
132
130
|
}
|
|
133
131
|
const html = body.toString("utf8");
|
|
134
132
|
try {
|
|
135
|
-
const transformedResult = htmlTransformer(html);
|
|
133
|
+
const transformedResult = htmlTransformer(html, ctx);
|
|
136
134
|
Promise.resolve(transformedResult)
|
|
137
135
|
.then((finalHtml) => {
|
|
138
136
|
if (options.debug) {
|
|
@@ -168,3 +166,43 @@ export async function createHtmlMiddleware(options = {}) {
|
|
|
168
166
|
next();
|
|
169
167
|
};
|
|
170
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Site-aware HTML middleware for Angular apps with language-prefixed URLs.
|
|
171
|
+
*
|
|
172
|
+
* Thin wrapper around `createHtmlMiddleware` that supplies a per-request
|
|
173
|
+
* `resolveRequest` hook. On each request the hook:
|
|
174
|
+
*
|
|
175
|
+
* 1. Resolves the active language from the leading URL path segment.
|
|
176
|
+
* 2. Strips the language segment from `req.url` so Angular's SPA routing
|
|
177
|
+
* sees `/accounts/1` instead of `/fr/accounts/1`.
|
|
178
|
+
* 3. Returns `{ basePath, language }` so the HTML transform injects the
|
|
179
|
+
* correct per-request `SFDC_ENV.language` and `SFDC_ENV.basePath`.
|
|
180
|
+
*
|
|
181
|
+
* When languages are empty, the feature is absent (CodeBuilder), or in
|
|
182
|
+
* production mode, the middleware degrades to the generic `createHtmlMiddleware`
|
|
183
|
+
* (no hook supplied — identity behavior).
|
|
184
|
+
*/
|
|
185
|
+
export async function createSiteHtmlMiddleware(options = {}) {
|
|
186
|
+
const supported = normalizeLanguages(options.languages ?? []);
|
|
187
|
+
const defaultLang = options.defaultLanguage
|
|
188
|
+
? normalizeLanguages([options.defaultLanguage])[0]
|
|
189
|
+
: supported[0];
|
|
190
|
+
const isCodeBuilder = !!process.env.CODE_BUILDER_FRAMEWORK_PROXY_URI;
|
|
191
|
+
const siteEnabled = supported.length > 0 && !isCodeBuilder && !!defaultLang;
|
|
192
|
+
const resolveRequest = siteEnabled
|
|
193
|
+
? (req) => {
|
|
194
|
+
const rawUrl = req.url ?? "/";
|
|
195
|
+
const resolved = resolveLanguageFromUrl(rawUrl, supported, defaultLang);
|
|
196
|
+
if (resolved?.segment) {
|
|
197
|
+
// Non-default language: strip the segment from req.url so
|
|
198
|
+
// Angular's SPA routing sees the path without it.
|
|
199
|
+
const rest = rawUrl.slice(`/${resolved.segment}`.length);
|
|
200
|
+
req.url = rest.startsWith("/") ? rest : `/${rest}`;
|
|
201
|
+
return { basePath: `/${resolved.segment}`, language: resolved.language };
|
|
202
|
+
}
|
|
203
|
+
// Default language or no match: un-prefixed
|
|
204
|
+
return { basePath: "/", language: resolved?.language };
|
|
205
|
+
}
|
|
206
|
+
: undefined;
|
|
207
|
+
return createHtmlMiddleware(options, resolveRequest ? { resolveRequest } : undefined);
|
|
208
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,4 +9,17 @@ export interface SalesforceOptions {
|
|
|
9
9
|
debug?: boolean;
|
|
10
10
|
}
|
|
11
11
|
export type Middleware = (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void;
|
|
12
|
+
export interface SiteOptions extends SalesforceOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Supported language codes (e.g. `["en_US", "fr", "es"]`).
|
|
15
|
+
* Codes are normalized from underscores to hyphens for URL use.
|
|
16
|
+
* When empty or omitted, site features are disabled.
|
|
17
|
+
*/
|
|
18
|
+
languages?: string[];
|
|
19
|
+
/**
|
|
20
|
+
* The default language code (served un-prefixed at `/`).
|
|
21
|
+
* When omitted, the first entry in `languages` is used.
|
|
22
|
+
*/
|
|
23
|
+
defaultLanguage?: string;
|
|
24
|
+
}
|
|
12
25
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,CACxB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,KACzB,IAAI,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,CACxB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,KACzB,IAAI,CAAC;AAEV,MAAM,WAAW,WAAY,SAAQ,iBAAiB;IACrD;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -30,4 +30,34 @@ export declare function getAppName(rootPath: string): string;
|
|
|
30
30
|
* @returns The registered namespace, or "c" when none is found
|
|
31
31
|
*/
|
|
32
32
|
export declare function getNamespace(startDir: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the active language for a request, in hyphenated URL form.
|
|
35
|
+
*
|
|
36
|
+
* The default language (the FIRST supported entry) is served un-prefixed, so:
|
|
37
|
+
* - a leading URL segment matching a NON-DEFAULT supported language -> that
|
|
38
|
+
* language (it carries a "/<lang>" segment);
|
|
39
|
+
* - no segment, or a segment equal to the default -> the default language.
|
|
40
|
+
*
|
|
41
|
+
* Returns `undefined` only when there are no supported languages (feature
|
|
42
|
+
* absent), so `SFDC_ENV.language` is otherwise ALWAYS set — matching production,
|
|
43
|
+
* which sets it even for the default at the root.
|
|
44
|
+
*
|
|
45
|
+
* Detection is anchored to the exact supported set, so a real route segment
|
|
46
|
+
* (e.g. a page named like a locale) is never mistaken for a language.
|
|
47
|
+
*
|
|
48
|
+
* @param url The request URL (may include a query string) or `undefined`.
|
|
49
|
+
* @param supported Supported languages in hyphenated form.
|
|
50
|
+
* @param defaultLanguage The default language code (served un-prefixed at `/`).
|
|
51
|
+
* @returns The resolved `language` and, when present, the leading `segment`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveLanguageFromUrl(url: string | undefined, supported: string[], defaultLanguage: string): {
|
|
54
|
+
language: string;
|
|
55
|
+
segment?: string;
|
|
56
|
+
} | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Normalize the feature's `LANGUAGES` codes to hyphenated URL form
|
|
59
|
+
* (`en_US` -> `en-US`), dropping blanks. This mirrors how the switcher's client
|
|
60
|
+
* code (`buildLanguageUrl`) and the platform both use hyphens in URL segments.
|
|
61
|
+
*/
|
|
62
|
+
export declare function normalizeLanguages(languages: string[]): string[];
|
|
33
63
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAE1C,eAAO,MAAM,YAAY,OAAO,CAAC;AAEjC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ7E;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwBrD"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAE1C,eAAO,MAAM,YAAY,OAAO,CAAC;AAEjC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ7E;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwBrD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACrC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,SAAS,EAAE,MAAM,EAAE,EACnB,eAAe,EAAE,MAAM,GACrB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CASpD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEhE"}
|
package/dist/utils.js
CHANGED
|
@@ -81,3 +81,42 @@ export function getNamespace(startDir) {
|
|
|
81
81
|
}
|
|
82
82
|
return DEFAULT_NAMESPACE;
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the active language for a request, in hyphenated URL form.
|
|
86
|
+
*
|
|
87
|
+
* The default language (the FIRST supported entry) is served un-prefixed, so:
|
|
88
|
+
* - a leading URL segment matching a NON-DEFAULT supported language -> that
|
|
89
|
+
* language (it carries a "/<lang>" segment);
|
|
90
|
+
* - no segment, or a segment equal to the default -> the default language.
|
|
91
|
+
*
|
|
92
|
+
* Returns `undefined` only when there are no supported languages (feature
|
|
93
|
+
* absent), so `SFDC_ENV.language` is otherwise ALWAYS set — matching production,
|
|
94
|
+
* which sets it even for the default at the root.
|
|
95
|
+
*
|
|
96
|
+
* Detection is anchored to the exact supported set, so a real route segment
|
|
97
|
+
* (e.g. a page named like a locale) is never mistaken for a language.
|
|
98
|
+
*
|
|
99
|
+
* @param url The request URL (may include a query string) or `undefined`.
|
|
100
|
+
* @param supported Supported languages in hyphenated form.
|
|
101
|
+
* @param defaultLanguage The default language code (served un-prefixed at `/`).
|
|
102
|
+
* @returns The resolved `language` and, when present, the leading `segment`.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveLanguageFromUrl(url, supported, defaultLanguage) {
|
|
105
|
+
if (supported.length === 0)
|
|
106
|
+
return undefined;
|
|
107
|
+
const nonDefault = supported.filter((lang) => lang !== defaultLanguage);
|
|
108
|
+
const path = (url ?? "").split("?")[0] ?? "";
|
|
109
|
+
const [first] = path.replace(/^\/+/, "").split("/");
|
|
110
|
+
if (first && nonDefault.includes(first)) {
|
|
111
|
+
return { language: first, segment: first };
|
|
112
|
+
}
|
|
113
|
+
return { language: defaultLanguage }; // no segment (or the default): un-prefixed
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Normalize the feature's `LANGUAGES` codes to hyphenated URL form
|
|
117
|
+
* (`en_US` -> `en-US`), dropping blanks. This mirrors how the switcher's client
|
|
118
|
+
* code (`buildLanguageUrl`) and the platform both use hyphens in URL segments.
|
|
119
|
+
*/
|
|
120
|
+
export function normalizeLanguages(languages) {
|
|
121
|
+
return languages.map((s) => s.trim().replace(/_/g, "-")).filter(Boolean);
|
|
122
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/angular-plugin-ui-bundle",
|
|
3
3
|
"description": "Angular CLI plugin for Salesforce UI Bundles",
|
|
4
|
-
"version": "12.
|
|
4
|
+
"version": "12.4.1",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"test:coverage": "vitest run --coverage"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@salesforce/ui-bundle": "^12.
|
|
33
|
-
"@salesforce/ui-design-mode": "^12.
|
|
32
|
+
"@salesforce/ui-bundle": "^12.4.1",
|
|
33
|
+
"@salesforce/ui-design-mode": "^12.4.1",
|
|
34
34
|
"chokidar": "^4.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|