@lovalingo/lovalingo 0.5.29 → 0.6.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.
- package/README.md +34 -0
- package/dist/chunk-2FZR2AKF.mjs +88 -0
- package/dist/chunk-7D5LBV45.mjs +46 -0
- package/dist/chunk-CJOSN7RA.mjs +90 -0
- package/dist/chunk-VAHA2TOX.mjs +3440 -0
- package/dist/chunk-ZMRCSUM7.mjs +26 -0
- package/dist/chunk-ZVYKEEUF.mjs +220 -0
- package/dist/core.d.mts +131 -0
- package/dist/core.d.ts +131 -0
- package/dist/core.js +3561 -0
- package/dist/core.mjs +19 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -25
- package/dist/index.js +3885 -28
- package/dist/index.mjs +33 -0
- package/dist/react-router.d.mts +101 -0
- package/dist/react-router.d.ts +101 -0
- package/dist/react-router.js +353 -0
- package/dist/react-router.mjs +14 -0
- package/dist/tanstack-router.d.mts +22 -0
- package/dist/tanstack-router.d.ts +22 -0
- package/dist/tanstack-router.js +162 -0
- package/dist/tanstack-router.mjs +8 -0
- package/package.json +34 -3
- package/dist/__tests__/languageFlags.test.d.ts +0 -1
- package/dist/__tests__/languageFlags.test.js +0 -42
- package/dist/__tests__/mergeEntitlements.test.d.ts +0 -1
- package/dist/__tests__/mergeEntitlements.test.js +0 -27
- package/dist/components/AixsterProvider.d.ts +0 -1
- package/dist/components/AixsterProvider.js +0 -1
- package/dist/components/LangLink.d.ts +0 -20
- package/dist/components/LangLink.js +0 -38
- package/dist/components/LangRouter.d.ts +0 -37
- package/dist/components/LangRouter.js +0 -191
- package/dist/components/LanguageSwitcher.d.ts +0 -17
- package/dist/components/LanguageSwitcher.js +0 -257
- package/dist/components/LovalingoProvider.d.ts +0 -10
- package/dist/components/LovalingoProvider.js +0 -413
- package/dist/components/NavigationOverlay.d.ts +0 -6
- package/dist/components/NavigationOverlay.js +0 -22
- package/dist/components/provider/__tests__/seoUtils.test.d.ts +0 -1
- package/dist/components/provider/__tests__/seoUtils.test.js +0 -13
- package/dist/components/provider/editModeUtils.d.ts +0 -6
- package/dist/components/provider/editModeUtils.js +0 -59
- package/dist/components/provider/localeUtils.d.ts +0 -8
- package/dist/components/provider/localeUtils.js +0 -46
- package/dist/components/provider/providerConstants.d.ts +0 -12
- package/dist/components/provider/providerConstants.js +0 -11
- package/dist/components/provider/seoUtils.d.ts +0 -8
- package/dist/components/provider/seoUtils.js +0 -118
- package/dist/components/provider/useEditModeOverlay.d.ts +0 -7
- package/dist/components/provider/useEditModeOverlay.js +0 -134
- package/dist/components/provider/useHistoryNavigationPatch.d.ts +0 -3
- package/dist/components/provider/useHistoryNavigationPatch.js +0 -47
- package/dist/components/provider/useProviderCache.d.ts +0 -12
- package/dist/components/provider/useProviderCache.js +0 -82
- package/dist/context/AixsterContext.d.ts +0 -3
- package/dist/context/AixsterContext.js +0 -2
- package/dist/context/LangContext.d.ts +0 -1
- package/dist/context/LangContext.js +0 -2
- package/dist/context/LangRoutingContext.d.ts +0 -8
- package/dist/context/LangRoutingContext.js +0 -7
- package/dist/context/LovalingoContext.d.ts +0 -1
- package/dist/context/LovalingoContext.js +0 -1
- package/dist/hooks/provider/useBundleLoading.d.ts +0 -33
- package/dist/hooks/provider/useBundleLoading.js +0 -380
- package/dist/hooks/provider/useDomRules.d.ts +0 -15
- package/dist/hooks/provider/useDomRules.js +0 -38
- package/dist/hooks/provider/useLinkAutoPrefix.d.ts +0 -12
- package/dist/hooks/provider/useLinkAutoPrefix.js +0 -146
- package/dist/hooks/provider/useNavigationPrefetch.d.ts +0 -12
- package/dist/hooks/provider/useNavigationPrefetch.js +0 -82
- package/dist/hooks/provider/usePageviewTracking.d.ts +0 -10
- package/dist/hooks/provider/usePageviewTracking.js +0 -44
- package/dist/hooks/provider/usePrehide.d.ts +0 -5
- package/dist/hooks/provider/usePrehide.js +0 -72
- package/dist/hooks/provider/useSitemapLinkTag.d.ts +0 -7
- package/dist/hooks/provider/useSitemapLinkTag.js +0 -28
- package/dist/hooks/provider/useStringMissReporting.d.ts +0 -14
- package/dist/hooks/provider/useStringMissReporting.js +0 -155
- package/dist/hooks/useAixster.d.ts +0 -6
- package/dist/hooks/useAixster.js +0 -14
- package/dist/hooks/useAixsterEdit.d.ts +0 -5
- package/dist/hooks/useAixsterEdit.js +0 -13
- package/dist/hooks/useAixsterTranslate.d.ts +0 -4
- package/dist/hooks/useAixsterTranslate.js +0 -12
- package/dist/hooks/useLang.d.ts +0 -16
- package/dist/hooks/useLang.js +0 -23
- package/dist/hooks/useLangNavigate.d.ts +0 -24
- package/dist/hooks/useLangNavigate.js +0 -40
- package/dist/hooks/useLovalingo.d.ts +0 -1
- package/dist/hooks/useLovalingo.js +0 -1
- package/dist/hooks/useLovalingoEdit.d.ts +0 -1
- package/dist/hooks/useLovalingoEdit.js +0 -1
- package/dist/hooks/useLovalingoTranslate.d.ts +0 -1
- package/dist/hooks/useLovalingoTranslate.js +0 -1
- package/dist/types.d.ts +0 -76
- package/dist/types.js +0 -1
- package/dist/utils/api.d.ts +0 -42
- package/dist/utils/api.js +0 -395
- package/dist/utils/apiTypes.d.ts +0 -78
- package/dist/utils/apiTypes.js +0 -1
- package/dist/utils/apiUtils.d.ts +0 -4
- package/dist/utils/apiUtils.js +0 -54
- package/dist/utils/domRules.d.ts +0 -2
- package/dist/utils/domRules.js +0 -150
- package/dist/utils/hash.d.ts +0 -9
- package/dist/utils/hash.js +0 -27
- package/dist/utils/languageFlags.d.ts +0 -7
- package/dist/utils/languageFlags.js +0 -90
- package/dist/utils/logger.d.ts +0 -3
- package/dist/utils/logger.js +0 -40
- package/dist/utils/markerEngine.d.ts +0 -12
- package/dist/utils/markerEngine.js +0 -109
- package/dist/utils/markerEngineApply.d.ts +0 -3
- package/dist/utils/markerEngineApply.js +0 -136
- package/dist/utils/markerEngineConstants.d.ts +0 -10
- package/dist/utils/markerEngineConstants.js +0 -12
- package/dist/utils/markerEngineCritical.d.ts +0 -2
- package/dist/utils/markerEngineCritical.js +0 -98
- package/dist/utils/markerEngineDomUtils.d.ts +0 -8
- package/dist/utils/markerEngineDomUtils.js +0 -74
- package/dist/utils/markerEngineFilters.d.ts +0 -2
- package/dist/utils/markerEngineFilters.js +0 -26
- package/dist/utils/markerEngineMisses.d.ts +0 -5
- package/dist/utils/markerEngineMisses.js +0 -81
- package/dist/utils/markerEngineOriginals.d.ts +0 -5
- package/dist/utils/markerEngineOriginals.js +0 -29
- package/dist/utils/markerEngineScan.d.ts +0 -5
- package/dist/utils/markerEngineScan.js +0 -162
- package/dist/utils/markerEngineState.d.ts +0 -4
- package/dist/utils/markerEngineState.js +0 -14
- package/dist/utils/markerEngineStats.d.ts +0 -3
- package/dist/utils/markerEngineStats.js +0 -28
- package/dist/utils/markerEngineTranslations.d.ts +0 -3
- package/dist/utils/markerEngineTranslations.js +0 -49
- package/dist/utils/markerEngineTypes.d.ts +0 -62
- package/dist/utils/markerEngineTypes.js +0 -1
- package/dist/utils/markerEngineViewport.d.ts +0 -2
- package/dist/utils/markerEngineViewport.js +0 -27
- package/dist/utils/mergeEntitlements.d.ts +0 -2
- package/dist/utils/mergeEntitlements.js +0 -7
- package/dist/utils/nonLocalizedPaths.d.ts +0 -12
- package/dist/utils/nonLocalizedPaths.js +0 -136
- package/dist/utils/pathNormalizer.d.ts +0 -49
- package/dist/utils/pathNormalizer.js +0 -115
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export function isInViewport(rect, viewportHeight, bufferPx) {
|
|
2
|
-
if (!rect)
|
|
3
|
-
return false;
|
|
4
|
-
if (!Number.isFinite(rect.top) || !Number.isFinite(rect.bottom))
|
|
5
|
-
return false;
|
|
6
|
-
if (rect.width <= 0 || rect.height <= 0)
|
|
7
|
-
return false;
|
|
8
|
-
return rect.bottom > -bufferPx && rect.top < viewportHeight + bufferPx;
|
|
9
|
-
}
|
|
10
|
-
export function getTextNodeRect(node) {
|
|
11
|
-
try {
|
|
12
|
-
const range = document.createRange();
|
|
13
|
-
range.selectNodeContents(node);
|
|
14
|
-
const rect = range.getBoundingClientRect();
|
|
15
|
-
if (rect && rect.width > 0 && rect.height > 0)
|
|
16
|
-
return rect;
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
// ignore
|
|
20
|
-
}
|
|
21
|
-
try {
|
|
22
|
-
return node.parentElement ? node.parentElement.getBoundingClientRect() : null;
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type NonLocalizedPathRule = {
|
|
2
|
-
pattern: string;
|
|
3
|
-
match_type: "exact" | "prefix" | "regex";
|
|
4
|
-
};
|
|
5
|
-
export declare function isGlobalNonLocalizedPath(pathname: string): boolean;
|
|
6
|
-
export declare function matchesNonLocalizedRules(pathname: string, rules: NonLocalizedPathRule[]): boolean;
|
|
7
|
-
export declare function isNonLocalizedPath(pathname: string, rules: NonLocalizedPathRule[]): boolean;
|
|
8
|
-
export declare function stripLocalePrefix(pathname: string, locales: string[]): string;
|
|
9
|
-
export declare function parseBootstrapNonLocalizedPaths(value: unknown): NonLocalizedPathRule[];
|
|
10
|
-
export declare function parseBootstrapInactivePages(value: unknown): string[];
|
|
11
|
-
export declare function matchesRouteTemplate(pathname: string, template: string): boolean;
|
|
12
|
-
export declare function isInactivePagePath(pathname: string, inactivePages: string[]): boolean;
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
const GLOBAL_NON_LOCALIZED_APP_PATHS = new Set(["/robots.txt", "/sitemap.xml"]);
|
|
2
|
-
export function isGlobalNonLocalizedPath(pathname) {
|
|
3
|
-
const input = (pathname || "").toString();
|
|
4
|
-
if (!input.startsWith("/"))
|
|
5
|
-
return false;
|
|
6
|
-
if (GLOBAL_NON_LOCALIZED_APP_PATHS.has(input))
|
|
7
|
-
return true;
|
|
8
|
-
if (input.startsWith("/.well-known/"))
|
|
9
|
-
return true;
|
|
10
|
-
return /\.(?:png|jpg|jpeg|gif|svg|webp|avif|ico|css|js|map|json|xml|txt|pdf|zip|gz|br|woff2?|ttf|eot)$/i.test(input);
|
|
11
|
-
}
|
|
12
|
-
export function matchesNonLocalizedRules(pathname, rules) {
|
|
13
|
-
const input = (pathname || "").toString();
|
|
14
|
-
if (!input.startsWith("/"))
|
|
15
|
-
return false;
|
|
16
|
-
if (!Array.isArray(rules) || rules.length === 0)
|
|
17
|
-
return false;
|
|
18
|
-
for (const rule of rules) {
|
|
19
|
-
const pattern = typeof rule?.pattern === "string" ? rule.pattern : "";
|
|
20
|
-
const matchType = rule?.match_type;
|
|
21
|
-
if (!pattern)
|
|
22
|
-
continue;
|
|
23
|
-
if (matchType === "exact") {
|
|
24
|
-
if (input === pattern)
|
|
25
|
-
return true;
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
if (matchType === "prefix") {
|
|
29
|
-
if (input === pattern)
|
|
30
|
-
return true;
|
|
31
|
-
const normalizedPrefix = pattern.endsWith("/") ? pattern.slice(0, -1) : pattern;
|
|
32
|
-
if (!normalizedPrefix || normalizedPrefix === "/")
|
|
33
|
-
return true;
|
|
34
|
-
if (input.startsWith(`${normalizedPrefix}/`))
|
|
35
|
-
return true;
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
if (matchType === "regex") {
|
|
39
|
-
try {
|
|
40
|
-
if (new RegExp(pattern).test(input))
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// ignore invalid regex rules
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
export function isNonLocalizedPath(pathname, rules) {
|
|
51
|
-
return isGlobalNonLocalizedPath(pathname) || matchesNonLocalizedRules(pathname, rules);
|
|
52
|
-
}
|
|
53
|
-
export function stripLocalePrefix(pathname, locales) {
|
|
54
|
-
const input = (pathname || "").toString();
|
|
55
|
-
if (!input.startsWith("/"))
|
|
56
|
-
return input;
|
|
57
|
-
const parts = input.split("/").filter(Boolean);
|
|
58
|
-
if (parts.length === 0)
|
|
59
|
-
return "/";
|
|
60
|
-
const first = parts[0] || "";
|
|
61
|
-
if (!first || !Array.isArray(locales) || !locales.includes(first))
|
|
62
|
-
return input;
|
|
63
|
-
const rest = `/${parts.slice(1).join("/")}`;
|
|
64
|
-
return rest === "" ? "/" : rest;
|
|
65
|
-
}
|
|
66
|
-
export function parseBootstrapNonLocalizedPaths(value) {
|
|
67
|
-
if (!Array.isArray(value))
|
|
68
|
-
return [];
|
|
69
|
-
const out = [];
|
|
70
|
-
for (const row of value) {
|
|
71
|
-
if (!row || typeof row !== "object")
|
|
72
|
-
continue;
|
|
73
|
-
const record = row;
|
|
74
|
-
const pattern = typeof record.pattern === "string" ? record.pattern.trim() : "";
|
|
75
|
-
const match_type = typeof record.match_type === "string" ? record.match_type.trim() : "";
|
|
76
|
-
if (!pattern)
|
|
77
|
-
continue;
|
|
78
|
-
if (match_type !== "exact" && match_type !== "prefix" && match_type !== "regex")
|
|
79
|
-
continue;
|
|
80
|
-
out.push({ pattern, match_type: match_type });
|
|
81
|
-
}
|
|
82
|
-
return out;
|
|
83
|
-
}
|
|
84
|
-
export function parseBootstrapInactivePages(value) {
|
|
85
|
-
if (!Array.isArray(value))
|
|
86
|
-
return [];
|
|
87
|
-
const out = [];
|
|
88
|
-
for (const row of value) {
|
|
89
|
-
if (typeof row === "string") {
|
|
90
|
-
const pagePath = row.trim();
|
|
91
|
-
if (pagePath && pagePath.startsWith("/"))
|
|
92
|
-
out.push(pagePath);
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (!row || typeof row !== "object")
|
|
96
|
-
continue;
|
|
97
|
-
const record = row;
|
|
98
|
-
const pagePath = typeof record.page_path === "string" ? record.page_path.trim() : "";
|
|
99
|
-
if (!pagePath || !pagePath.startsWith("/"))
|
|
100
|
-
continue;
|
|
101
|
-
out.push(pagePath);
|
|
102
|
-
}
|
|
103
|
-
return out;
|
|
104
|
-
}
|
|
105
|
-
function escapeRegexLiteral(value) {
|
|
106
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
107
|
-
}
|
|
108
|
-
export function matchesRouteTemplate(pathname, template) {
|
|
109
|
-
const input = (pathname || "").toString();
|
|
110
|
-
const pattern = (template || "").toString();
|
|
111
|
-
if (!input.startsWith("/") || !pattern.startsWith("/"))
|
|
112
|
-
return false;
|
|
113
|
-
if (input === pattern)
|
|
114
|
-
return true;
|
|
115
|
-
// Convert "/dashboard/projects/:id/pages" or "/use-cases/[slug]" into a safe regex.
|
|
116
|
-
const parts = pattern.split("/").filter(Boolean);
|
|
117
|
-
const regexParts = parts.map((part) => {
|
|
118
|
-
if (part === "*")
|
|
119
|
-
return ".*";
|
|
120
|
-
if (part.startsWith(":"))
|
|
121
|
-
return "[^/]+";
|
|
122
|
-
if (part.startsWith("[") && part.endsWith("]"))
|
|
123
|
-
return "[^/]+";
|
|
124
|
-
return escapeRegexLiteral(part);
|
|
125
|
-
});
|
|
126
|
-
const regex = new RegExp(`^/${regexParts.join("/")}$`);
|
|
127
|
-
return regex.test(input);
|
|
128
|
-
}
|
|
129
|
-
export function isInactivePagePath(pathname, inactivePages) {
|
|
130
|
-
const input = (pathname || "").toString();
|
|
131
|
-
if (!input.startsWith("/"))
|
|
132
|
-
return false;
|
|
133
|
-
if (!Array.isArray(inactivePages) || inactivePages.length === 0)
|
|
134
|
-
return false;
|
|
135
|
-
return inactivePages.some((pattern) => matchesRouteTemplate(input, pattern));
|
|
136
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path Normalization Utility
|
|
3
|
-
*
|
|
4
|
-
* Normalizes URL paths by replacing dynamic segments (UUIDs, IDs, slugs)
|
|
5
|
-
* with placeholders to enable translation bundle sharing across similar pages.
|
|
6
|
-
*
|
|
7
|
-
* Example:
|
|
8
|
-
* /dashboard/projects/4458eb10-608c-4622-a92e-ec3ed2eeb524/setup
|
|
9
|
-
* → /dashboard/projects/:id/setup
|
|
10
|
-
*/
|
|
11
|
-
export interface PathNormalizationRule {
|
|
12
|
-
pattern: string;
|
|
13
|
-
replacement: string;
|
|
14
|
-
includeSubpaths?: boolean;
|
|
15
|
-
}
|
|
16
|
-
export interface PathNormalizationConfig {
|
|
17
|
-
enabled: boolean;
|
|
18
|
-
rules?: PathNormalizationRule[];
|
|
19
|
-
supportedLocales?: string[];
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Normalizes a path by replacing dynamic segments with placeholders
|
|
23
|
-
*/
|
|
24
|
-
export declare function normalizePath(path: string, config?: PathNormalizationConfig): string;
|
|
25
|
-
/**
|
|
26
|
-
* Cleans path by removing locale prefix and trailing slashes
|
|
27
|
-
*/
|
|
28
|
-
export declare function cleanPath(path: string, supportedLocales?: string[]): string;
|
|
29
|
-
/**
|
|
30
|
-
* Combined path processing: clean + normalize
|
|
31
|
-
*/
|
|
32
|
-
export declare function processPath(path: string, config?: PathNormalizationConfig): string;
|
|
33
|
-
/**
|
|
34
|
-
* Detects if a path segment looks like a dynamic ID
|
|
35
|
-
*/
|
|
36
|
-
export declare function isDynamicSegment(segment: string): boolean;
|
|
37
|
-
/**
|
|
38
|
-
* Analyzes a path and returns which segments are dynamic
|
|
39
|
-
*/
|
|
40
|
-
export interface PathAnalysis {
|
|
41
|
-
original: string;
|
|
42
|
-
normalized: string;
|
|
43
|
-
segments: Array<{
|
|
44
|
-
original: string;
|
|
45
|
-
normalized: string;
|
|
46
|
-
isDynamic: boolean;
|
|
47
|
-
}>;
|
|
48
|
-
}
|
|
49
|
-
export declare function analyzePath(path: string, supportedLocales?: string[]): PathAnalysis;
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path Normalization Utility
|
|
3
|
-
*
|
|
4
|
-
* Normalizes URL paths by replacing dynamic segments (UUIDs, IDs, slugs)
|
|
5
|
-
* with placeholders to enable translation bundle sharing across similar pages.
|
|
6
|
-
*
|
|
7
|
-
* Example:
|
|
8
|
-
* /dashboard/projects/4458eb10-608c-4622-a92e-ec3ed2eeb524/setup
|
|
9
|
-
* → /dashboard/projects/:id/setup
|
|
10
|
-
*/
|
|
11
|
-
import { warnDebug } from "./logger";
|
|
12
|
-
// Common patterns for dynamic segments
|
|
13
|
-
const UUID_PATTERN = /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/gi;
|
|
14
|
-
const NUMERIC_ID_PATTERN = /\/\d+(?=\/|$)/g;
|
|
15
|
-
const HASH_PATTERN = /\/[a-f0-9]{32,}(?=\/|$)/gi; // MD5, SHA hashes
|
|
16
|
-
const ALPHANUMERIC_ID_PATTERN = /\/[a-z0-9]{20,}(?=\/|$)/gi; // Long random IDs
|
|
17
|
-
/**
|
|
18
|
-
* Normalizes a path by replacing dynamic segments with placeholders
|
|
19
|
-
*/
|
|
20
|
-
export function normalizePath(path, config) {
|
|
21
|
-
if (config?.enabled === false) {
|
|
22
|
-
return path;
|
|
23
|
-
}
|
|
24
|
-
let normalized = path;
|
|
25
|
-
let shouldIncludeSubpaths = false;
|
|
26
|
-
// Apply automatic detection patterns
|
|
27
|
-
normalized = normalized.replace(UUID_PATTERN, ':id');
|
|
28
|
-
normalized = normalized.replace(HASH_PATTERN, ':hash');
|
|
29
|
-
normalized = normalized.replace(ALPHANUMERIC_ID_PATTERN, ':id');
|
|
30
|
-
normalized = normalized.replace(NUMERIC_ID_PATTERN, '/:id');
|
|
31
|
-
// Apply custom user-defined rules
|
|
32
|
-
if (config?.rules) {
|
|
33
|
-
for (const rule of config.rules) {
|
|
34
|
-
try {
|
|
35
|
-
const regex = new RegExp(rule.pattern, 'gi');
|
|
36
|
-
const beforeReplace = normalized;
|
|
37
|
-
normalized = normalized.replace(regex, rule.replacement);
|
|
38
|
-
// Track if this rule was applied and has includeSubpaths enabled
|
|
39
|
-
if (beforeReplace !== normalized && rule.includeSubpaths) {
|
|
40
|
-
shouldIncludeSubpaths = true;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
warnDebug('[PathNormalizer] Invalid pattern:', rule.pattern, error);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// Collapse consecutive :id placeholders (e.g., /:id/:id → /:id)
|
|
49
|
-
normalized = normalized.replace(/\/:id(\/):id/g, '/:id$1*');
|
|
50
|
-
// If includeSubpaths is enabled, replace everything after the first placeholder with /*
|
|
51
|
-
if (shouldIncludeSubpaths) {
|
|
52
|
-
// Find the first placeholder (:id, :hash, :slug, etc.)
|
|
53
|
-
const placeholderMatch = normalized.match(/(:[a-z]+)/);
|
|
54
|
-
if (placeholderMatch) {
|
|
55
|
-
const placeholderIndex = normalized.indexOf(placeholderMatch[0]);
|
|
56
|
-
const beforePlaceholder = normalized.substring(0, placeholderIndex + placeholderMatch[0].length);
|
|
57
|
-
normalized = beforePlaceholder + '/*';
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return normalized;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Cleans path by removing locale prefix and trailing slashes
|
|
64
|
-
*/
|
|
65
|
-
export function cleanPath(path, supportedLocales) {
|
|
66
|
-
let cleaned = path;
|
|
67
|
-
// Strip locale prefix from path if it matches a supported locale
|
|
68
|
-
// e.g., /fr/pricing -> /pricing, /en -> /
|
|
69
|
-
if (supportedLocales && supportedLocales.length > 0) {
|
|
70
|
-
const segments = cleaned.split('/').filter(Boolean);
|
|
71
|
-
if (segments.length > 0 && supportedLocales.includes(segments[0])) {
|
|
72
|
-
// First segment is a valid locale - remove it
|
|
73
|
-
cleaned = '/' + segments.slice(1).join('/');
|
|
74
|
-
if (cleaned === '')
|
|
75
|
-
cleaned = '/';
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
// Remove trailing slash except for root
|
|
79
|
-
if (cleaned !== '/' && cleaned.endsWith('/')) {
|
|
80
|
-
cleaned = cleaned.slice(0, -1);
|
|
81
|
-
}
|
|
82
|
-
return cleaned;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Combined path processing: clean + normalize
|
|
86
|
-
*/
|
|
87
|
-
export function processPath(path, config) {
|
|
88
|
-
const cleaned = cleanPath(path, config?.supportedLocales);
|
|
89
|
-
const normalized = normalizePath(cleaned, config);
|
|
90
|
-
return normalized;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Detects if a path segment looks like a dynamic ID
|
|
94
|
-
*/
|
|
95
|
-
export function isDynamicSegment(segment) {
|
|
96
|
-
return (UUID_PATTERN.test(segment) ||
|
|
97
|
-
/^\d+$/.test(segment) ||
|
|
98
|
-
HASH_PATTERN.test(segment) ||
|
|
99
|
-
ALPHANUMERIC_ID_PATTERN.test(segment));
|
|
100
|
-
}
|
|
101
|
-
export function analyzePath(path, supportedLocales) {
|
|
102
|
-
const cleaned = cleanPath(path, supportedLocales);
|
|
103
|
-
const normalized = normalizePath(cleaned);
|
|
104
|
-
const originalSegments = cleaned.split('/').filter(Boolean);
|
|
105
|
-
const normalizedSegments = normalized.split('/').filter(Boolean);
|
|
106
|
-
return {
|
|
107
|
-
original: cleaned,
|
|
108
|
-
normalized,
|
|
109
|
-
segments: originalSegments.map((seg, idx) => ({
|
|
110
|
-
original: seg,
|
|
111
|
-
normalized: normalizedSegments[idx] || seg,
|
|
112
|
-
isDynamic: seg !== normalizedSegments[idx],
|
|
113
|
-
})),
|
|
114
|
-
};
|
|
115
|
-
}
|
package/dist/version.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const VERSION = "0.5.29";
|
package/dist/version.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const VERSION = "0.5.29";
|