@lionrapid/core 0.6.5 → 0.7.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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -2
  3. package/dist/browser/auto-init.d.ts +6 -0
  4. package/dist/browser/auto-init.d.ts.map +1 -1
  5. package/dist/browser/auto-init.js +38 -7
  6. package/dist/browser/auto-init.js.map +1 -1
  7. package/dist/browser/editor/editor-api.d.ts +12 -0
  8. package/dist/browser/editor/editor-api.d.ts.map +1 -1
  9. package/dist/browser/editor/editor-api.js.map +1 -1
  10. package/dist/browser/editor/editor-init.js +2 -1
  11. package/dist/browser/editor/editor-init.js.map +1 -1
  12. package/dist/browser/editor/sidebar.d.ts.map +1 -1
  13. package/dist/browser/editor/sidebar.js +11 -1
  14. package/dist/browser/editor/sidebar.js.map +1 -1
  15. package/dist/browser/language-switcher.d.ts +12 -0
  16. package/dist/browser/language-switcher.d.ts.map +1 -1
  17. package/dist/browser/language-switcher.js +58 -0
  18. package/dist/browser/language-switcher.js.map +1 -1
  19. package/dist/browser/lionrapid.auto.dev.js +404 -184
  20. package/dist/browser/lionrapid.auto.dev.js.map +3 -3
  21. package/dist/browser/lionrapid.auto.js +404 -184
  22. package/dist/browser/lionrapid.auto.js.map +3 -3
  23. package/dist/browser/lionrapid.auto.min.js +6 -4
  24. package/dist/browser/lionrapid.auto.min.js.map +4 -4
  25. package/dist/browser/lionrapid.editor.js +5 -2
  26. package/dist/browser/lionrapid.editor.js.map +3 -3
  27. package/dist/browser/lionrapid.editor.min.js +4 -4
  28. package/dist/browser/lionrapid.editor.min.js.map +4 -4
  29. package/dist/browser/lionrapid.esm.js +344 -179
  30. package/dist/browser/lionrapid.esm.js.map +3 -3
  31. package/dist/browser/lionrapid.esm.min.js +5 -3
  32. package/dist/browser/lionrapid.esm.min.js.map +4 -4
  33. package/dist/browser/lionrapid.iife.dev.js +344 -179
  34. package/dist/browser/lionrapid.iife.dev.js.map +3 -3
  35. package/dist/browser/lionrapid.iife.js +344 -179
  36. package/dist/browser/lionrapid.iife.js.map +3 -3
  37. package/dist/browser/lionrapid.iife.min.js +5 -3
  38. package/dist/browser/lionrapid.iife.min.js.map +4 -4
  39. package/dist/browser/lionrapid.umd.js +344 -179
  40. package/dist/browser/lionrapid.umd.js.map +3 -3
  41. package/dist/browser/lionrapid.umd.min.js +5 -3
  42. package/dist/browser/lionrapid.umd.min.js.map +4 -4
  43. package/dist/browser/storage/cache-storage-repository.d.ts +9 -0
  44. package/dist/browser/storage/cache-storage-repository.d.ts.map +1 -1
  45. package/dist/browser/storage/cache-storage-repository.js +14 -10
  46. package/dist/browser/storage/cache-storage-repository.js.map +1 -1
  47. package/dist/browser/storage/scope.d.ts +12 -0
  48. package/dist/browser/storage/scope.d.ts.map +1 -0
  49. package/dist/browser/storage/scope.js +15 -0
  50. package/dist/browser/storage/scope.js.map +1 -0
  51. package/dist/builder.d.ts.map +1 -1
  52. package/dist/builder.js +18 -2
  53. package/dist/builder.js.map +1 -1
  54. package/dist/config/api.config.d.ts +35 -0
  55. package/dist/config/api.config.d.ts.map +1 -0
  56. package/dist/config/api.config.js +35 -0
  57. package/dist/config/api.config.js.map +1 -0
  58. package/dist/handlers/async-storage-handler.d.ts +9 -0
  59. package/dist/handlers/async-storage-handler.d.ts.map +1 -1
  60. package/dist/handlers/async-storage-handler.js +42 -0
  61. package/dist/handlers/async-storage-handler.js.map +1 -1
  62. package/dist/handlers/handler-chain.d.ts +2 -0
  63. package/dist/handlers/handler-chain.d.ts.map +1 -1
  64. package/dist/handlers/handler-chain.js +29 -0
  65. package/dist/handlers/handler-chain.js.map +1 -1
  66. package/dist/handlers/network-handler.d.ts +6 -0
  67. package/dist/handlers/network-handler.d.ts.map +1 -1
  68. package/dist/handlers/network-handler.js +9 -0
  69. package/dist/handlers/network-handler.js.map +1 -1
  70. package/dist/handlers/sync-storage-handler.d.ts +4 -0
  71. package/dist/handlers/sync-storage-handler.d.ts.map +1 -1
  72. package/dist/handlers/sync-storage-handler.js +35 -0
  73. package/dist/handlers/sync-storage-handler.js.map +1 -1
  74. package/dist/index.d.ts +2 -1
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +4 -1
  77. package/dist/index.js.map +1 -1
  78. package/dist/interfaces/handler.interface.d.ts +4 -0
  79. package/dist/interfaces/handler.interface.d.ts.map +1 -1
  80. package/dist/lionRapid.d.ts.map +1 -1
  81. package/dist/lionRapid.js +11 -2
  82. package/dist/lionRapid.js.map +1 -1
  83. package/dist/repositories/network-repository.d.ts.map +1 -1
  84. package/dist/repositories/network-repository.js +4 -3
  85. package/dist/repositories/network-repository.js.map +1 -1
  86. package/dist/utils/log-safe.d.ts +92 -0
  87. package/dist/utils/log-safe.d.ts.map +1 -0
  88. package/dist/utils/log-safe.js +168 -0
  89. package/dist/utils/log-safe.js.map +1 -0
  90. package/dist/utils/logger.d.ts.map +1 -1
  91. package/dist/utils/logger.js +3 -2
  92. package/dist/utils/logger.js.map +1 -1
  93. package/package.json +8 -5
@@ -42,6 +42,216 @@ var __lionrapidAutoExports = (() => {
42
42
  parseConfig: () => parseConfig
43
43
  });
44
44
 
45
+ // src/browser/md5.ts
46
+ function safeAdd(x, y) {
47
+ const lsw = (x & 65535) + (y & 65535);
48
+ const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
49
+ return msw << 16 | lsw & 65535;
50
+ }
51
+ function bitRotateLeft(num, cnt) {
52
+ return num << cnt | num >>> 32 - cnt;
53
+ }
54
+ function md5cmn(q, a, b, x, s, t) {
55
+ return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
56
+ }
57
+ function md5ff(a, b, c, d, x, s, t) {
58
+ return md5cmn(b & c | ~b & d, a, b, x, s, t);
59
+ }
60
+ function md5gg(a, b, c, d, x, s, t) {
61
+ return md5cmn(b & d | c & ~d, a, b, x, s, t);
62
+ }
63
+ function md5hh(a, b, c, d, x, s, t) {
64
+ return md5cmn(b ^ c ^ d, a, b, x, s, t);
65
+ }
66
+ function md5ii(a, b, c, d, x, s, t) {
67
+ return md5cmn(c ^ (b | ~d), a, b, x, s, t);
68
+ }
69
+ function binlMD5(x, len) {
70
+ x[len >> 5] |= 128 << len % 32;
71
+ x[(len + 64 >>> 9 << 4) + 14] = len;
72
+ let a = 1732584193;
73
+ let b = -271733879;
74
+ let c = -1732584194;
75
+ let d = 271733878;
76
+ for (let i = 0; i < x.length; i += 16) {
77
+ const olda = a;
78
+ const oldb = b;
79
+ const oldc = c;
80
+ const oldd = d;
81
+ a = md5ff(a, b, c, d, x[i], 7, -680876936);
82
+ d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
83
+ c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
84
+ b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
85
+ a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
86
+ d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
87
+ c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
88
+ b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
89
+ a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
90
+ d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
91
+ c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
92
+ b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
93
+ a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
94
+ d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
95
+ c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
96
+ b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
97
+ a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
98
+ d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
99
+ c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
100
+ b = md5gg(b, c, d, a, x[i], 20, -373897302);
101
+ a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
102
+ d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
103
+ c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
104
+ b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
105
+ a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
106
+ d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
107
+ c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
108
+ b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
109
+ a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
110
+ d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
111
+ c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
112
+ b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
113
+ a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
114
+ d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
115
+ c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
116
+ b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
117
+ a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
118
+ d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
119
+ c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
120
+ b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
121
+ a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
122
+ d = md5hh(d, a, b, c, x[i + 0], 11, -358537222);
123
+ c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
124
+ b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
125
+ a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
126
+ d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
127
+ c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
128
+ b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
129
+ a = md5ii(a, b, c, d, x[i], 6, -198630844);
130
+ d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
131
+ c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
132
+ b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
133
+ a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
134
+ d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
135
+ c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
136
+ b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
137
+ a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
138
+ d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
139
+ c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
140
+ b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
141
+ a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
142
+ d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
143
+ c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
144
+ b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
145
+ a = safeAdd(a, olda);
146
+ b = safeAdd(b, oldb);
147
+ c = safeAdd(c, oldc);
148
+ d = safeAdd(d, oldd);
149
+ }
150
+ return [a, b, c, d];
151
+ }
152
+ function binl2hex(binarray) {
153
+ const hexTab = "0123456789abcdef";
154
+ let str = "";
155
+ for (let i = 0; i < binarray.length * 4; i++) {
156
+ str += hexTab.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 15) + hexTab.charAt(binarray[i >> 2] >> i % 4 * 8 & 15);
157
+ }
158
+ return str;
159
+ }
160
+ function utf8Bytes(str) {
161
+ if (typeof TextEncoder !== "undefined") {
162
+ return new TextEncoder().encode(str);
163
+ }
164
+ const out = [];
165
+ for (let i = 0; i < str.length; i++) {
166
+ const c = str.charCodeAt(i);
167
+ if (c < 128) {
168
+ out.push(c);
169
+ } else if (c < 2048) {
170
+ out.push(192 | c >> 6, 128 | c & 63);
171
+ } else if (c >= 55296 && c < 56320 && i + 1 < str.length) {
172
+ const c2 = str.charCodeAt(++i);
173
+ const cp = 65536 + (c - 55296 << 10) + (c2 - 56320);
174
+ out.push(
175
+ 240 | cp >> 18,
176
+ 128 | cp >> 12 & 63,
177
+ 128 | cp >> 6 & 63,
178
+ 128 | cp & 63
179
+ );
180
+ } else {
181
+ out.push(
182
+ 224 | c >> 12,
183
+ 128 | c >> 6 & 63,
184
+ 128 | c & 63
185
+ );
186
+ }
187
+ }
188
+ return new Uint8Array(out);
189
+ }
190
+ function bytes2binl(bytes) {
191
+ const bin = [];
192
+ for (let i = 0; i < bytes.length; i++) {
193
+ bin[i >> 2] |= bytes[i] << i % 4 * 8;
194
+ }
195
+ return bin;
196
+ }
197
+ function md5(str) {
198
+ const bytes = utf8Bytes(str);
199
+ return binl2hex(binlMD5(bytes2binl(bytes), bytes.length * 8));
200
+ }
201
+ function generateAutoKey(text) {
202
+ const trimmed = text.trim();
203
+ return "auto_" + md5(trimmed).substring(0, 12);
204
+ }
205
+
206
+ // src/utils/log-safe.ts
207
+ var LOG_VALUE_FULL_MAX = 200;
208
+ var LOG_VALUE_EDGE = 90;
209
+ function contentIdentity(value) {
210
+ return `${value.length} chars, md5:${md5(value.trim()).slice(0, 12)}`;
211
+ }
212
+ function contentExcerpt(value) {
213
+ if (value.length <= LOG_VALUE_FULL_MAX) {
214
+ return JSON.stringify(value);
215
+ }
216
+ return JSON.stringify(
217
+ `${value.slice(0, LOG_VALUE_EDGE)}\u2026${value.slice(-LOG_VALUE_EDGE)}`
218
+ );
219
+ }
220
+ var LOG_ERROR_MAX = 200;
221
+ var LOG_DATA_MAX = 500;
222
+ var LOG_STACK_FRAMES = 2;
223
+ var LOG_FRAME_MAX = 120;
224
+ function bound(text, max) {
225
+ return text.length <= max ? text : `${text.slice(0, max)}\u2026 (${text.length} chars)`;
226
+ }
227
+ function oneLine(text) {
228
+ return JSON.stringify(text).slice(1, -1);
229
+ }
230
+ function describeError(error) {
231
+ if (error instanceof Error) {
232
+ const name = error.name || "Error";
233
+ return bound(oneLine(`${name}: ${error.message}`), LOG_ERROR_MAX);
234
+ }
235
+ return bound(oneLine(String(error)), LOG_ERROR_MAX);
236
+ }
237
+ function describeLogData(data) {
238
+ if (data instanceof Error) {
239
+ const headerLines = String(data.message ?? "").split("\n").length;
240
+ const frames = (data.stack ?? "").split("\n").slice(headerLines).map((frame) => frame.trim()).filter((frame) => frame.startsWith("at ")).slice(0, LOG_STACK_FRAMES).map((frame) => bound(frame, LOG_FRAME_MAX));
241
+ return [describeError(data), ...frames].join(" | ");
242
+ }
243
+ let rendered;
244
+ try {
245
+ rendered = JSON.stringify(data);
246
+ } catch {
247
+ return "[unserializable]";
248
+ }
249
+ return bound(rendered ?? oneLine(String(data)), LOG_DATA_MAX);
250
+ }
251
+ function describeContent(value) {
252
+ return `${contentIdentity(value)}, ${contentExcerpt(value)}`;
253
+ }
254
+
45
255
  // src/config/logger.config.ts
46
256
  var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
47
257
  LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
@@ -169,7 +379,7 @@ var __lionrapidAutoExports = (() => {
169
379
  const locationInfo2 = callSite ? ` (${callSite.fileName}:${callSite.lineNumber})` : "";
170
380
  let logMessage = `${this.config.prefix} ${emoji} ${levelName} ${message}${locationInfo2}`;
171
381
  if (data !== void 0) {
172
- logMessage += ` ${JSON.stringify(data)}`;
382
+ logMessage += ` ${describeLogData(data)}`;
173
383
  }
174
384
  return logMessage;
175
385
  }
@@ -180,7 +390,7 @@ var __lionrapidAutoExports = (() => {
180
390
  const coloredLevel = `${levelColor}${Colors.BOLD}${levelName}${reset}`;
181
391
  const coloredMessage = `${levelColor}${message}${reset}`;
182
392
  const locationInfo = callSite ? `${Colors.DIM}${Colors.BRIGHT_BLACK} (${callSite.fileName}:${callSite.lineNumber})${reset}` : "";
183
- const dataInfo = data !== void 0 ? `${Colors.DIM}${Colors.CYAN} ${JSON.stringify(data)}${reset}` : "";
393
+ const dataInfo = data !== void 0 ? `${Colors.DIM}${Colors.CYAN} ${describeLogData(data)}${reset}` : "";
184
394
  return `${coloredPrefix} ${coloredEmoji} ${coloredLevel} ${coloredMessage}${locationInfo}${dataInfo}`;
185
395
  }
186
396
  getLevelColor(level) {
@@ -918,6 +1128,24 @@ var __lionrapidAutoExports = (() => {
918
1128
  });
919
1129
  await Promise.allSettled(savePromises);
920
1130
  }
1131
+ /** Forget `locale:namespace` in every memory and storage handler (a 404). */
1132
+ async forgetNamespaceInHandlers(context) {
1133
+ for (const handler of this.syncHandlers) {
1134
+ try {
1135
+ handler.forgetNamespace?.(context);
1136
+ } catch (error) {
1137
+ logger.warn(`Failed to clear namespace in ${handler.name}`, error);
1138
+ }
1139
+ }
1140
+ for (const handler of this.asyncHandlers) {
1141
+ if (handler.type !== "storage" && handler.type !== "memory") continue;
1142
+ try {
1143
+ await handler.forgetNamespace?.(context);
1144
+ } catch (error) {
1145
+ logger.warn(`Failed to clear namespace in ${handler.name}`, error);
1146
+ }
1147
+ }
1148
+ }
921
1149
  async saveNamespaceToHandlers(translations, context) {
922
1150
  this.saveNamespaceToMemoryHandlers(translations, context);
923
1151
  await this.saveNamespaceToStorageHandlers(translations, context);
@@ -1019,6 +1247,10 @@ var __lionrapidAutoExports = (() => {
1019
1247
  });
1020
1248
  return result.data;
1021
1249
  }
1250
+ if (result && result.status === 404) {
1251
+ await this.forgetNamespaceInHandlers({ namespace, locale });
1252
+ return null;
1253
+ }
1022
1254
  } catch (error) {
1023
1255
  logger.warn(
1024
1256
  `Failed to load namespace: ${locale}:${namespace} from ${handler.name}`,
@@ -1402,6 +1634,7 @@ var __lionrapidAutoExports = (() => {
1402
1634
  context.locale + ":" + context.namespace,
1403
1635
  this.name
1404
1636
  );
1637
+ const previousKeys = this.storedNamespaceKeys(context.locale, context.namespace);
1405
1638
  const namespaceCacheKey = createNamespaceCacheKey(
1406
1639
  context.locale,
1407
1640
  context.namespace
@@ -1413,11 +1646,38 @@ var __lionrapidAutoExports = (() => {
1413
1646
  context.locale,
1414
1647
  context.namespace
1415
1648
  );
1649
+ for (const key of previousKeys) {
1650
+ if (!(key in flattened)) this.removeQuietly(key);
1651
+ }
1416
1652
  for (const [flatKey, flatValue] of Object.entries(flattened)) {
1417
1653
  this.setWithTTL(flatKey, flatValue);
1418
1654
  }
1419
1655
  repoBus.setSuccess(JSON.stringify(translations));
1420
1656
  }
1657
+ /** Forget a namespace the server says does not exist (404). See AsyncStorageHandler. */
1658
+ forgetNamespace(context) {
1659
+ if (!context.namespace) return;
1660
+ for (const key of this.storedNamespaceKeys(context.locale, context.namespace)) {
1661
+ this.removeQuietly(key);
1662
+ }
1663
+ this.clearNamespace(context.locale, context.namespace);
1664
+ }
1665
+ storedNamespaceKeys(locale, namespace) {
1666
+ try {
1667
+ const blob = this.repository.get(createNamespaceCacheKey(locale, namespace));
1668
+ if (!blob) return [];
1669
+ return Object.keys(flattenTranslations(JSON.parse(blob), "", locale, namespace));
1670
+ } catch {
1671
+ return [];
1672
+ }
1673
+ }
1674
+ removeQuietly(cacheKey) {
1675
+ this.ttlMap.delete(cacheKey);
1676
+ try {
1677
+ this.repository.remove(cacheKey);
1678
+ } catch {
1679
+ }
1680
+ }
1421
1681
  /**
1422
1682
  * ✅ Strategy 1: Direct cache lookup using unified pattern
1423
1683
  * Returns parsed ContentUnit (text + styles) or null
@@ -1671,6 +1931,7 @@ var __lionrapidAutoExports = (() => {
1671
1931
  logger.debug(
1672
1932
  `Saving namespace: ${context.locale}:${context.namespace} (${keyCount} keys)`
1673
1933
  );
1934
+ const previousKeys = await this.storedNamespaceKeys(context.locale, context.namespace);
1674
1935
  const namespaceCacheKey = createNamespaceCacheKey(
1675
1936
  context.locale,
1676
1937
  context.namespace
@@ -1682,6 +1943,9 @@ var __lionrapidAutoExports = (() => {
1682
1943
  context.locale,
1683
1944
  context.namespace
1684
1945
  );
1946
+ for (const key of previousKeys) {
1947
+ if (!(key in flattened)) await this.removeQuietly(key);
1948
+ }
1685
1949
  let savedCount = 0;
1686
1950
  for (const [flatKey, flatValue] of Object.entries(flattened)) {
1687
1951
  await this.setWithTTL(flatKey, flatValue);
@@ -1690,6 +1954,35 @@ var __lionrapidAutoExports = (() => {
1690
1954
  logger.debug(`Saved: ${savedCount} keys + namespace blob`);
1691
1955
  repoBus.setSuccess(JSON.stringify(translations));
1692
1956
  }
1957
+ /**
1958
+ * Forget a namespace the server says does not exist (404): its blob and
1959
+ * every per-key entry the blob listed. A network failure never gets here,
1960
+ * so the offline floor still serves when the server is unreachable.
1961
+ */
1962
+ async forgetNamespace(context) {
1963
+ if (!context.namespace) return;
1964
+ for (const key of await this.storedNamespaceKeys(context.locale, context.namespace)) {
1965
+ await this.removeQuietly(key);
1966
+ }
1967
+ await this.removeQuietly(createNamespaceCacheKey(context.locale, context.namespace));
1968
+ }
1969
+ /** The per-key cache keys (`locale:namespace:key`) the stored blob lists. */
1970
+ async storedNamespaceKeys(locale, namespace) {
1971
+ try {
1972
+ const blob = await this.repository.get(createNamespaceCacheKey(locale, namespace));
1973
+ if (!blob) return [];
1974
+ return Object.keys(flattenTranslations(JSON.parse(blob), "", locale, namespace));
1975
+ } catch {
1976
+ return [];
1977
+ }
1978
+ }
1979
+ async removeQuietly(cacheKey) {
1980
+ this.ttlMap.delete(cacheKey);
1981
+ try {
1982
+ await this.repository.remove(cacheKey);
1983
+ } catch {
1984
+ }
1985
+ }
1693
1986
  /**
1694
1987
  * ✅ Strategy 1: Direct cache lookup using unified pattern
1695
1988
  * Returns parsed ContentUnit (text + styles) or null
@@ -2234,6 +2527,15 @@ var __lionrapidAutoExports = (() => {
2234
2527
  const config = this.repository.getConfig();
2235
2528
  return config.options?.preloadNamespaces || [];
2236
2529
  }
2530
+ /**
2531
+ * The host this handler talks to. Exposed so a failure can NAME it: "the
2532
+ * server is unreachable" is not actionable, and a default pointing at a dead
2533
+ * host is exactly the case where the reader needs to be told which host.
2534
+ */
2535
+ getBaseUrl() {
2536
+ const config = this.repository.getConfig();
2537
+ return config.options?.baseUrl || "";
2538
+ }
2237
2539
  };
2238
2540
 
2239
2541
  // src/content/canonical-tag.ts
@@ -3080,7 +3382,9 @@ var __lionrapidAutoExports = (() => {
3080
3382
  const processedText = this.processTranslationValue(unit.text, request);
3081
3383
  return processedText.replace(/<\/?[0-9]+\/?>/g, "");
3082
3384
  } catch (error) {
3083
- logger.warn(`ContentUnit processing failed for "${value}":`, error);
3385
+ logger.warn(
3386
+ `ContentUnit processing failed for key "${request.cleanKey}" \u2014 ${describeContent(value)}: ${describeError(error)}`
3387
+ );
3084
3388
  return this.processTranslationValue(value, request);
3085
3389
  }
3086
3390
  }
@@ -3133,7 +3437,9 @@ var __lionrapidAutoExports = (() => {
3133
3437
  }
3134
3438
  return processedValue;
3135
3439
  } catch (error) {
3136
- logger.warn(`Translation processing failed for "${value}":`, error);
3440
+ logger.warn(
3441
+ `Translation processing failed for key "${resolvedKey ?? "(no key)"}" \u2014 ${describeContent(value)}: ${describeError(error)}`
3442
+ );
3137
3443
  return value;
3138
3444
  }
3139
3445
  }
@@ -3850,8 +4156,9 @@ var __lionrapidAutoExports = (() => {
3850
4156
  const warnLoudlyOnce = (namespaceKey, error) => {
3851
4157
  if (!isLoudPreloadFailure(error) || warnedLoudly) return;
3852
4158
  warnedLoudly = true;
4159
+ const baseUrl = networkHandler.getBaseUrl() || "(no base URL configured)";
3853
4160
  console.warn(
3854
- `[LionRapid] Could not load translations for ${namespaceKey} \u2014 the page stays untranslated until the server is reachable.`,
4161
+ `[LionRapid] Could not load translations for ${namespaceKey} from ${baseUrl} \u2014 the page stays untranslated until that host is reachable. If it is wrong, set data-base-url on the snippet tag (or \`baseUrl\` in the network repository options).`,
3855
4162
  error
3856
4163
  );
3857
4164
  };
@@ -3871,6 +4178,12 @@ var __lionrapidAutoExports = (() => {
3871
4178
  logger.debug(`Preloaded: ${namespaceKey}`);
3872
4179
  return;
3873
4180
  }
4181
+ if (result?.status === 404) {
4182
+ await handlerChain.forgetNamespaceInHandlers({
4183
+ locale: preloadConfig.locale,
4184
+ namespace: preloadConfig.namespace
4185
+ });
4186
+ }
3874
4187
  if (result?.error) {
3875
4188
  warnLoudlyOnce(namespaceKey, result.error);
3876
4189
  logger.warn(`Preload failed: ${namespaceKey}`, result.error);
@@ -3979,7 +4292,7 @@ var __lionrapidAutoExports = (() => {
3979
4292
  throw new TranslationNotFoundError(key);
3980
4293
  }
3981
4294
  if (typeof translation === "object" && "text" in translation) {
3982
- logger.debug(`ContentUnit text: "${translation.text}"`);
4295
+ logger.debug(`ContentUnit text: ${describeContent(translation.text)}`);
3983
4296
  return translation.text;
3984
4297
  }
3985
4298
  return String(translation);
@@ -4014,13 +4327,18 @@ var __lionrapidAutoExports = (() => {
4014
4327
  throw new TranslationNotFoundError(key);
4015
4328
  }
4016
4329
  if (typeof translation === "object" && "text" in translation) {
4017
- logger.debug(`ContentUnit for "${key}": text="${translation.text}", styles=`, translation.styles);
4330
+ logger.debug(
4331
+ `ContentUnit for "${key}": text=${describeContent(translation.text)}, styles=`,
4332
+ translation.styles
4333
+ );
4018
4334
  return {
4019
4335
  text: translation.text,
4020
4336
  styles: translation.styles || {}
4021
4337
  };
4022
4338
  }
4023
- logger.debug(`Plain string for "${key}": "${translation}" (no styles)`);
4339
+ logger.debug(
4340
+ `Plain string for "${key}": ${describeContent(String(translation))} (no styles)`
4341
+ );
4024
4342
  return {
4025
4343
  text: String(translation),
4026
4344
  styles: {}
@@ -4603,167 +4921,6 @@ var __lionrapidAutoExports = (() => {
4603
4921
  return { text, styles };
4604
4922
  }
4605
4923
 
4606
- // src/browser/md5.ts
4607
- function safeAdd(x, y) {
4608
- const lsw = (x & 65535) + (y & 65535);
4609
- const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
4610
- return msw << 16 | lsw & 65535;
4611
- }
4612
- function bitRotateLeft(num, cnt) {
4613
- return num << cnt | num >>> 32 - cnt;
4614
- }
4615
- function md5cmn(q, a, b, x, s, t) {
4616
- return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
4617
- }
4618
- function md5ff(a, b, c, d, x, s, t) {
4619
- return md5cmn(b & c | ~b & d, a, b, x, s, t);
4620
- }
4621
- function md5gg(a, b, c, d, x, s, t) {
4622
- return md5cmn(b & d | c & ~d, a, b, x, s, t);
4623
- }
4624
- function md5hh(a, b, c, d, x, s, t) {
4625
- return md5cmn(b ^ c ^ d, a, b, x, s, t);
4626
- }
4627
- function md5ii(a, b, c, d, x, s, t) {
4628
- return md5cmn(c ^ (b | ~d), a, b, x, s, t);
4629
- }
4630
- function binlMD5(x, len) {
4631
- x[len >> 5] |= 128 << len % 32;
4632
- x[(len + 64 >>> 9 << 4) + 14] = len;
4633
- let a = 1732584193;
4634
- let b = -271733879;
4635
- let c = -1732584194;
4636
- let d = 271733878;
4637
- for (let i = 0; i < x.length; i += 16) {
4638
- const olda = a;
4639
- const oldb = b;
4640
- const oldc = c;
4641
- const oldd = d;
4642
- a = md5ff(a, b, c, d, x[i], 7, -680876936);
4643
- d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
4644
- c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
4645
- b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
4646
- a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
4647
- d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
4648
- c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
4649
- b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
4650
- a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
4651
- d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
4652
- c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
4653
- b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
4654
- a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
4655
- d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
4656
- c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
4657
- b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
4658
- a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
4659
- d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
4660
- c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
4661
- b = md5gg(b, c, d, a, x[i], 20, -373897302);
4662
- a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
4663
- d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
4664
- c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
4665
- b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
4666
- a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
4667
- d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
4668
- c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
4669
- b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
4670
- a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
4671
- d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
4672
- c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
4673
- b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
4674
- a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
4675
- d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
4676
- c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
4677
- b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
4678
- a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
4679
- d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
4680
- c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
4681
- b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
4682
- a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
4683
- d = md5hh(d, a, b, c, x[i + 0], 11, -358537222);
4684
- c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
4685
- b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
4686
- a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
4687
- d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
4688
- c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
4689
- b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
4690
- a = md5ii(a, b, c, d, x[i], 6, -198630844);
4691
- d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
4692
- c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
4693
- b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
4694
- a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
4695
- d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
4696
- c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
4697
- b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
4698
- a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
4699
- d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
4700
- c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
4701
- b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
4702
- a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
4703
- d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
4704
- c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
4705
- b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
4706
- a = safeAdd(a, olda);
4707
- b = safeAdd(b, oldb);
4708
- c = safeAdd(c, oldc);
4709
- d = safeAdd(d, oldd);
4710
- }
4711
- return [a, b, c, d];
4712
- }
4713
- function binl2hex(binarray) {
4714
- const hexTab = "0123456789abcdef";
4715
- let str = "";
4716
- for (let i = 0; i < binarray.length * 4; i++) {
4717
- str += hexTab.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 15) + hexTab.charAt(binarray[i >> 2] >> i % 4 * 8 & 15);
4718
- }
4719
- return str;
4720
- }
4721
- function utf8Bytes(str) {
4722
- if (typeof TextEncoder !== "undefined") {
4723
- return new TextEncoder().encode(str);
4724
- }
4725
- const out = [];
4726
- for (let i = 0; i < str.length; i++) {
4727
- const c = str.charCodeAt(i);
4728
- if (c < 128) {
4729
- out.push(c);
4730
- } else if (c < 2048) {
4731
- out.push(192 | c >> 6, 128 | c & 63);
4732
- } else if (c >= 55296 && c < 56320 && i + 1 < str.length) {
4733
- const c2 = str.charCodeAt(++i);
4734
- const cp = 65536 + (c - 55296 << 10) + (c2 - 56320);
4735
- out.push(
4736
- 240 | cp >> 18,
4737
- 128 | cp >> 12 & 63,
4738
- 128 | cp >> 6 & 63,
4739
- 128 | cp & 63
4740
- );
4741
- } else {
4742
- out.push(
4743
- 224 | c >> 12,
4744
- 128 | c >> 6 & 63,
4745
- 128 | c & 63
4746
- );
4747
- }
4748
- }
4749
- return new Uint8Array(out);
4750
- }
4751
- function bytes2binl(bytes) {
4752
- const bin = [];
4753
- for (let i = 0; i < bytes.length; i++) {
4754
- bin[i >> 2] |= bytes[i] << i % 4 * 8;
4755
- }
4756
- return bin;
4757
- }
4758
- function md5(str) {
4759
- const bytes = utf8Bytes(str);
4760
- return binl2hex(binlMD5(bytes2binl(bytes), bytes.length * 8));
4761
- }
4762
- function generateAutoKey(text) {
4763
- const trimmed = text.trim();
4764
- return "auto_" + md5(trimmed).substring(0, 12);
4765
- }
4766
-
4767
4924
  // src/browser/block-extractor.ts
4768
4925
  var BLOCK_SELECTOR = "p,h1,h2,h3,h4,h5,h6,li,td,th,label,button,figcaption,dt,dd,summary,caption";
4769
4926
  var INLINE_BLOCK_SELECTOR = "a";
@@ -5563,6 +5720,32 @@ var __lionrapidAutoExports = (() => {
5563
5720
  .lionrapid-btn-row button:hover { background: #f5f5f5; }
5564
5721
  .lionrapid-btn-row button.active { background: #3b82f6; color: #fff; }
5565
5722
  `;
5723
+ var HEADER_GAP_PX = 8;
5724
+ var CORNER_INSET_PX = 20;
5725
+ function topCornerOffset(doc = document, win = window) {
5726
+ const viewport = win.innerHeight || doc.documentElement.clientHeight || 0;
5727
+ const span = (el) => {
5728
+ const style = win.getComputedStyle(el);
5729
+ if (style.display === "none" || style.visibility === "hidden") return null;
5730
+ const rect = el.getBoundingClientRect();
5731
+ if (rect.height <= 0) return null;
5732
+ const pinned = style.position === "fixed" || style.position === "sticky";
5733
+ const shift = pinned ? 0 : win.scrollY;
5734
+ return [rect.top + shift, rect.bottom + shift];
5735
+ };
5736
+ const adminBar = doc.getElementById("wpadminbar");
5737
+ const barBottom = adminBar && span(adminBar)?.[1] || 0;
5738
+ let bottom = barBottom;
5739
+ doc.querySelectorAll('header, [role="banner"]').forEach((el) => {
5740
+ if (el.closest("article, main, aside")) return;
5741
+ const s = span(el);
5742
+ if (!s || s[0] > barBottom + HEADER_GAP_PX * 4) return;
5743
+ bottom = Math.max(bottom, s[1]);
5744
+ });
5745
+ if (bottom === 0) return CORNER_INSET_PX;
5746
+ const below = Math.ceil(bottom) + HEADER_GAP_PX;
5747
+ return viewport > 0 ? Math.min(below, Math.floor(viewport / 2)) : below;
5748
+ }
5566
5749
  var LanguageSwitcher = class {
5567
5750
  constructor() {
5568
5751
  __publicField(this, "core", null);
@@ -5623,6 +5806,14 @@ var __lionrapidAutoExports = (() => {
5623
5806
  const showNames = element.dataset.lionrapidSwitcherShowNames !== "false";
5624
5807
  const customCss = element.dataset.lionrapidSwitcherCustomCss || null;
5625
5808
  element.dataset.position = position;
5809
+ if (position.startsWith("top")) {
5810
+ const place = () => {
5811
+ element.style.top = `${topCornerOffset()}px`;
5812
+ };
5813
+ place();
5814
+ window.addEventListener("load", place);
5815
+ window.addEventListener("resize", place);
5816
+ }
5626
5817
  if (customCss) {
5627
5818
  const styleEl = document.createElement("style");
5628
5819
  styleEl.textContent = customCss;
@@ -6061,6 +6252,8 @@ var __lionrapidAutoExports = (() => {
6061
6252
  __publicField(this, "type", "storage");
6062
6253
  __publicField(this, "config");
6063
6254
  __publicField(this, "cacheName");
6255
+ /** CACHE_PREFIX, plus `<scope>/` when scoped. */
6256
+ __publicField(this, "entryPrefix");
6064
6257
  __publicField(this, "defaultTTL");
6065
6258
  __publicField(this, "available");
6066
6259
  this.config = {
@@ -6074,6 +6267,8 @@ var __lionrapidAutoExports = (() => {
6074
6267
  }
6075
6268
  };
6076
6269
  this.cacheName = this.config.options?.cacheName ?? CACHE_NAME;
6270
+ const scope = this.config.options?.scope;
6271
+ this.entryPrefix = scope ? `${CACHE_PREFIX}${encodeURIComponent(scope)}/` : CACHE_PREFIX;
6077
6272
  this.defaultTTL = this.config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3;
6078
6273
  this.available = this.checkAvailability();
6079
6274
  }
@@ -6094,13 +6289,13 @@ var __lionrapidAutoExports = (() => {
6094
6289
  }
6095
6290
  try {
6096
6291
  const cache = await caches.open(this.cacheName);
6097
- const response = await cache.match(CACHE_PREFIX + key);
6292
+ const response = await cache.match(this.entryPrefix + key);
6098
6293
  if (!response) {
6099
6294
  throw new TranslationNotFoundError(key);
6100
6295
  }
6101
6296
  const data = await response.json();
6102
6297
  if (data.expiry !== null && Date.now() > data.expiry) {
6103
- await cache.delete(CACHE_PREFIX + key);
6298
+ await cache.delete(this.entryPrefix + key);
6104
6299
  throw new TranslationNotFoundError(key);
6105
6300
  }
6106
6301
  return data.value;
@@ -6124,7 +6319,7 @@ var __lionrapidAutoExports = (() => {
6124
6319
  timestamp: Date.now()
6125
6320
  };
6126
6321
  await cache.put(
6127
- CACHE_PREFIX + key,
6322
+ this.entryPrefix + key,
6128
6323
  new Response(JSON.stringify(data), {
6129
6324
  headers: { "Content-Type": "application/json" }
6130
6325
  })
@@ -6139,7 +6334,7 @@ var __lionrapidAutoExports = (() => {
6139
6334
  if (!this.available) return;
6140
6335
  try {
6141
6336
  const cache = await caches.open(this.cacheName);
6142
- await cache.delete(CACHE_PREFIX + key);
6337
+ await cache.delete(this.entryPrefix + key);
6143
6338
  } catch {
6144
6339
  }
6145
6340
  }
@@ -6152,7 +6347,7 @@ var __lionrapidAutoExports = (() => {
6152
6347
  const cache = await caches.open(this.cacheName);
6153
6348
  const keys = await cache.keys();
6154
6349
  await Promise.all(
6155
- keys.filter((request) => request.url.includes(CACHE_PREFIX)).map((request) => cache.delete(request))
6350
+ keys.filter((request) => request.url.includes(this.entryPrefix)).map((request) => cache.delete(request))
6156
6351
  );
6157
6352
  } catch {
6158
6353
  }
@@ -6170,7 +6365,7 @@ var __lionrapidAutoExports = (() => {
6170
6365
  await Promise.all(
6171
6366
  keys.filter((request) => {
6172
6367
  const url = request.url;
6173
- const key = url.includes(CACHE_PREFIX) ? url.substring(url.indexOf(CACHE_PREFIX) + CACHE_PREFIX.length) : "";
6368
+ const key = url.includes(this.entryPrefix) ? url.substring(url.indexOf(this.entryPrefix) + this.entryPrefix.length) : "";
6174
6369
  return key === namespaceCacheKey || key.startsWith(keyPrefix);
6175
6370
  }).map((request) => cache.delete(request))
6176
6371
  );
@@ -6222,9 +6417,9 @@ var __lionrapidAutoExports = (() => {
6222
6417
  const keys = await cache.keys();
6223
6418
  for (const request of keys) {
6224
6419
  const url = request.url;
6225
- if (!url.includes(CACHE_PREFIX)) continue;
6420
+ if (!url.includes(this.entryPrefix)) continue;
6226
6421
  const key = url.substring(
6227
- url.indexOf(CACHE_PREFIX) + CACHE_PREFIX.length
6422
+ url.indexOf(this.entryPrefix) + this.entryPrefix.length
6228
6423
  );
6229
6424
  try {
6230
6425
  const value = await this.get(key);
@@ -6246,7 +6441,7 @@ var __lionrapidAutoExports = (() => {
6246
6441
  try {
6247
6442
  const cache = await caches.open(this.cacheName);
6248
6443
  const keys = await cache.keys();
6249
- const size = keys.filter((r) => r.url.includes(CACHE_PREFIX)).length;
6444
+ const size = keys.filter((r) => r.url.includes(this.entryPrefix)).length;
6250
6445
  return { size, cacheName: this.cacheName };
6251
6446
  } catch {
6252
6447
  return { size: 0, cacheName: this.cacheName };
@@ -6254,6 +6449,14 @@ var __lionrapidAutoExports = (() => {
6254
6449
  }
6255
6450
  };
6256
6451
 
6452
+ // src/config/api.config.ts
6453
+ var DEFAULT_API_BASE_URL = "https://app.lionrapid.com";
6454
+
6455
+ // src/browser/storage/scope.ts
6456
+ function storageScope(apiKey) {
6457
+ return apiKey ? md5(apiKey).slice(0, 8) : "none";
6458
+ }
6459
+
6257
6460
  // src/browser/auto-init.ts
6258
6461
  function resolveWritePolicy(apiKey) {
6259
6462
  const isPublishable = apiKey.startsWith("pk_");
@@ -6302,7 +6505,7 @@ var __lionrapidAutoExports = (() => {
6302
6505
  }
6303
6506
  function parseConfig(script) {
6304
6507
  const apiKey = script.dataset.apiKey || "";
6305
- const baseUrl = script.dataset.baseUrl || "https://api.lionrapid.com";
6508
+ const baseUrl = script.dataset.baseUrl || DEFAULT_API_BASE_URL;
6306
6509
  const defaultLocale = script.dataset.defaultLocale || "en";
6307
6510
  const namespace = script.dataset.namespace || "default";
6308
6511
  const languages = (script.dataset.languages || defaultLocale).split(",").map((s) => s.trim()).filter(Boolean);
@@ -6383,6 +6586,12 @@ var __lionrapidAutoExports = (() => {
6383
6586
  document.documentElement.dir = localeDir(locale);
6384
6587
  }
6385
6588
  }
6589
+ function applyLocaleAttrs(locale) {
6590
+ if (typeof document !== "undefined" && locale) {
6591
+ document.documentElement.lang = locale;
6592
+ }
6593
+ applyLocaleDir(locale);
6594
+ }
6386
6595
  function findConfigScript() {
6387
6596
  const current = document.currentScript;
6388
6597
  if (current instanceof HTMLScriptElement && current.dataset.apiKey) {
@@ -6415,7 +6624,11 @@ var __lionrapidAutoExports = (() => {
6415
6624
  );
6416
6625
  }
6417
6626
  const initialLocale = resolveInitialLocale(config);
6418
- applyLocaleDir(initialLocale);
6627
+ if (config.mode === "dynamic-only") {
6628
+ applyLocaleDir(initialLocale);
6629
+ } else {
6630
+ applyLocaleAttrs(initialLocale);
6631
+ }
6419
6632
  const languageSwitcher = new LanguageSwitcher();
6420
6633
  languageSwitcher.setLanguages(config.languages);
6421
6634
  languageSwitcher.setInitialLocale(initialLocale);
@@ -6449,18 +6662,25 @@ var __lionrapidAutoExports = (() => {
6449
6662
  navigate: config.mode === "dynamic-only" ? (locale) => navigateToLocale(locale, config.defaultLocale, config.languages) : null
6450
6663
  });
6451
6664
  languageSwitcher.setOnLanguageChange(localeHandler.onChange);
6665
+ const storeScope = storageScope(config.apiKey);
6452
6666
  try {
6453
6667
  const builder = LionRapidBuilder.init({
6454
6668
  defaultLocale: initialLocale,
6455
6669
  namespace: config.namespace
6456
- }).use(new MemoryRepository({ enabled: true })).use(new LocalStorageRepository({ enabled: true })).use(new CacheStorageRepository({ enabled: true }));
6670
+ }).use(new MemoryRepository({ enabled: true })).use(
6671
+ new LocalStorageRepository({
6672
+ enabled: true,
6673
+ options: { prefix: `lionrapid:${storeScope}:` }
6674
+ })
6675
+ ).use(new CacheStorageRepository({ enabled: true, options: { scope: storeScope } }));
6457
6676
  if (config.offline !== false) {
6458
6677
  builder.use(
6459
6678
  new CacheStorageRepository({
6460
6679
  enabled: true,
6461
6680
  options: {
6462
6681
  ttl: Number.MAX_SAFE_INTEGER,
6463
- cacheName: CORE_CACHE_NAMES.offlineFloor
6682
+ cacheName: CORE_CACHE_NAMES.offlineFloor,
6683
+ scope: storeScope
6464
6684
  }
6465
6685
  })
6466
6686
  );
@@ -6501,7 +6721,7 @@ var __lionrapidAutoExports = (() => {
6501
6721
  await core.changeLanguage(locale, {
6502
6722
  preloadNamespaces: [config.namespace]
6503
6723
  });
6504
- applyLocaleDir(locale);
6724
+ applyLocaleAttrs(locale);
6505
6725
  autoTranslator.updateLocale(locale);
6506
6726
  autoTranslator.retranslate();
6507
6727
  });
@@ -6548,7 +6768,7 @@ var __lionrapidAutoExports = (() => {
6548
6768
  await core.changeLanguage(locale, {
6549
6769
  preloadNamespaces: [config.namespace]
6550
6770
  });
6551
- applyLocaleDir(locale);
6771
+ applyLocaleAttrs(locale);
6552
6772
  autoTranslator.updateLocale(locale);
6553
6773
  autoTranslator.retranslate();
6554
6774
  languageSwitcher.initAll();