@lionrapid/core 0.2.1 → 0.3.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 (95) hide show
  1. package/dist/browser/auto-translator.d.ts.map +1 -1
  2. package/dist/browser/auto-translator.js +15 -4
  3. package/dist/browser/auto-translator.js.map +1 -1
  4. package/dist/browser/block-extractor.d.ts.map +1 -1
  5. package/dist/browser/block-extractor.js +6 -0
  6. package/dist/browser/block-extractor.js.map +1 -1
  7. package/dist/browser/editor/editor-api.d.ts +31 -1
  8. package/dist/browser/editor/editor-api.d.ts.map +1 -1
  9. package/dist/browser/editor/editor-api.js +43 -1
  10. package/dist/browser/editor/editor-api.js.map +1 -1
  11. package/dist/browser/editor/editor-init.js +25 -0
  12. package/dist/browser/editor/editor-init.js.map +1 -1
  13. package/dist/browser/editor/editor-styles.d.ts +1 -1
  14. package/dist/browser/editor/editor-styles.d.ts.map +1 -1
  15. package/dist/browser/editor/editor-styles.js +55 -0
  16. package/dist/browser/editor/editor-styles.js.map +1 -1
  17. package/dist/browser/editor/live-preview.d.ts.map +1 -1
  18. package/dist/browser/editor/live-preview.js +20 -3
  19. package/dist/browser/editor/live-preview.js.map +1 -1
  20. package/dist/browser/editor/sidebar.d.ts +20 -1
  21. package/dist/browser/editor/sidebar.d.ts.map +1 -1
  22. package/dist/browser/editor/sidebar.js +147 -9
  23. package/dist/browser/editor/sidebar.js.map +1 -1
  24. package/dist/browser/lionrapid.auto.dev.js +125 -311
  25. package/dist/browser/lionrapid.auto.dev.js.map +3 -3
  26. package/dist/browser/lionrapid.auto.js +125 -311
  27. package/dist/browser/lionrapid.auto.js.map +3 -3
  28. package/dist/browser/lionrapid.auto.min.js +3 -3
  29. package/dist/browser/lionrapid.auto.min.js.map +4 -4
  30. package/dist/browser/lionrapid.editor.js +274 -181
  31. package/dist/browser/lionrapid.editor.js.map +3 -3
  32. package/dist/browser/lionrapid.editor.min.js +58 -3
  33. package/dist/browser/lionrapid.editor.min.js.map +4 -4
  34. package/dist/browser/lionrapid.esm.js +108 -294
  35. package/dist/browser/lionrapid.esm.js.map +3 -3
  36. package/dist/browser/lionrapid.esm.min.js +2 -2
  37. package/dist/browser/lionrapid.esm.min.js.map +4 -4
  38. package/dist/browser/lionrapid.iife.dev.js +108 -294
  39. package/dist/browser/lionrapid.iife.dev.js.map +3 -3
  40. package/dist/browser/lionrapid.iife.js +108 -294
  41. package/dist/browser/lionrapid.iife.js.map +3 -3
  42. package/dist/browser/lionrapid.iife.min.js +2 -2
  43. package/dist/browser/lionrapid.iife.min.js.map +4 -4
  44. package/dist/browser/lionrapid.umd.js +108 -294
  45. package/dist/browser/lionrapid.umd.js.map +3 -3
  46. package/dist/browser/lionrapid.umd.min.js +2 -2
  47. package/dist/browser/lionrapid.umd.min.js.map +4 -4
  48. package/dist/browser/markup-parser.d.ts +9 -5
  49. package/dist/browser/markup-parser.d.ts.map +1 -1
  50. package/dist/browser/markup-parser.js +19 -23
  51. package/dist/browser/markup-parser.js.map +1 -1
  52. package/dist/content/canonical-tag.d.ts +34 -0
  53. package/dist/content/canonical-tag.d.ts.map +1 -0
  54. package/dist/content/canonical-tag.js +57 -0
  55. package/dist/content/canonical-tag.js.map +1 -0
  56. package/dist/content/index.d.ts +1 -4
  57. package/dist/content/index.d.ts.map +1 -1
  58. package/dist/content/index.js +3 -1
  59. package/dist/content/index.js.map +1 -1
  60. package/dist/content/parser/MarkupParser.d.ts +9 -49
  61. package/dist/content/parser/MarkupParser.d.ts.map +1 -1
  62. package/dist/content/parser/MarkupParser.js +37 -157
  63. package/dist/content/parser/MarkupParser.js.map +1 -1
  64. package/dist/content/serializer/HTMLSerializer.d.ts +10 -43
  65. package/dist/content/serializer/HTMLSerializer.d.ts.map +1 -1
  66. package/dist/content/serializer/HTMLSerializer.js +29 -69
  67. package/dist/content/serializer/HTMLSerializer.js.map +1 -1
  68. package/dist/content/types.d.ts +21 -12
  69. package/dist/content/types.d.ts.map +1 -1
  70. package/dist/content/validator/ContentValidator.d.ts +2 -2
  71. package/dist/content/validator/ContentValidator.js +2 -2
  72. package/dist/index.d.ts +2 -3
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +4 -1
  75. package/dist/index.js.map +1 -1
  76. package/dist/lionRapid.d.ts +1 -1
  77. package/dist/lionRapid.js +4 -4
  78. package/dist/lionRapid.js.map +1 -1
  79. package/dist/repositories/network-repository.d.ts +14 -0
  80. package/dist/repositories/network-repository.d.ts.map +1 -1
  81. package/dist/repositories/network-repository.js +26 -4
  82. package/dist/repositories/network-repository.js.map +1 -1
  83. package/package.json +1 -1
  84. package/dist/content/safe-href.d.ts +0 -22
  85. package/dist/content/safe-href.d.ts.map +0 -1
  86. package/dist/content/safe-href.js +0 -48
  87. package/dist/content/safe-href.js.map +0 -1
  88. package/dist/content/style-mapper/DefaultStyleMapper.d.ts +0 -59
  89. package/dist/content/style-mapper/DefaultStyleMapper.d.ts.map +0 -1
  90. package/dist/content/style-mapper/DefaultStyleMapper.js +0 -132
  91. package/dist/content/style-mapper/DefaultStyleMapper.js.map +0 -1
  92. package/dist/content/style-mapper/IStyleMapper.d.ts +0 -50
  93. package/dist/content/style-mapper/IStyleMapper.d.ts.map +0 -1
  94. package/dist/content/style-mapper/IStyleMapper.js +0 -6
  95. package/dist/content/style-mapper/IStyleMapper.js.map +0 -1
@@ -2158,153 +2158,51 @@ var NetworkHandler = class {
2158
2158
  }
2159
2159
  };
2160
2160
 
2161
- // src/content/safe-href.ts
2162
- var SAFE_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
2163
- var ALLOWED_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:", "sms:"]);
2164
- function safeHref(href) {
2165
- if (!href) return "#";
2166
- const trimmed = href.trim();
2167
- if (!trimmed) return "#";
2168
- if (trimmed.startsWith("//")) {
2169
- return "#";
2170
- }
2171
- if (trimmed.startsWith("/") || trimmed.startsWith("?") || trimmed.startsWith("#") || trimmed.startsWith("./") || trimmed.startsWith("../")) {
2172
- return trimmed;
2173
- }
2174
- const schemeMatch = SAFE_SCHEME.exec(trimmed);
2175
- if (schemeMatch) {
2176
- const scheme = schemeMatch[0].toLowerCase();
2177
- return ALLOWED_SCHEMES.has(scheme) ? trimmed : "#";
2178
- }
2179
- return trimmed;
2161
+ // src/content/canonical-tag.ts
2162
+ var VOID_TAGS = /* @__PURE__ */ new Set([
2163
+ "area",
2164
+ "base",
2165
+ "br",
2166
+ "col",
2167
+ "embed",
2168
+ "hr",
2169
+ "img",
2170
+ "input",
2171
+ "link",
2172
+ "meta",
2173
+ "param",
2174
+ "source",
2175
+ "track",
2176
+ "wbr"
2177
+ ]);
2178
+ function escapeAttrValue(value) {
2179
+ return value.replace(/"/g, """);
2180
2180
  }
2181
-
2182
- // src/content/style-mapper/DefaultStyleMapper.ts
2183
- var DefaultStyleMapper = class {
2184
- constructor() {
2185
- /**
2186
- * Element → Style mapping
2187
- * Maps HTML element names to their style property
2188
- */
2189
- __publicField(this, "elementToStyles", {
2190
- b: "bold",
2191
- strong: "bold",
2192
- i: "italic",
2193
- em: "italic",
2194
- u: "underline",
2195
- s: "strikethrough",
2196
- del: "strikethrough",
2197
- strike: "strikethrough",
2198
- code: "code",
2199
- mark: "highlight",
2200
- sub: "subscript",
2201
- sup: "superscript"
2202
- });
2203
- /**
2204
- * Style → Element mapping (reverse)
2205
- * Uses simple, familiar elements for developer convenience
2206
- * Also accepts element names directly (strong, em, etc.)
2207
- */
2208
- __publicField(this, "styleToElement", {
2209
- // Semantic style names → simple elements
2210
- bold: "b",
2211
- italic: "i",
2212
- underline: "u",
2213
- strikethrough: "s",
2214
- code: "code",
2215
- highlight: "mark",
2216
- subscript: "sub",
2217
- superscript: "sup",
2218
- // Element names (for servers that store styles as element names)
2219
- strong: "b",
2220
- b: "b",
2221
- em: "i",
2222
- i: "i",
2223
- u: "u",
2224
- s: "s",
2225
- del: "s",
2226
- strike: "s",
2227
- mark: "mark",
2228
- sub: "sub",
2229
- sup: "sup"
2230
- });
2231
- }
2232
- /**
2233
- * Convert HTML element to style properties
2234
- *
2235
- * @param element - Tag name (e.g., "b", "a", "strong")
2236
- * @param attrs - Element attributes (e.g., { href: "/url" })
2237
- * @returns Array of style strings
2238
- */
2239
- mapElementToStyles(element, attrs) {
2240
- const styles = [];
2241
- const tag = element.toLowerCase();
2242
- const mappedStyle = this.elementToStyles[tag];
2243
- if (mappedStyle) {
2244
- styles.push(mappedStyle);
2245
- }
2246
- if (tag === "a" && attrs.href) {
2247
- styles.push(`hyperlink:${attrs.href}`);
2248
- }
2249
- return styles;
2250
- }
2251
- /**
2252
- * Convert style properties to HTML element
2253
- *
2254
- * Priority order:
2255
- * 1. Hyperlink (becomes wrapper element with href)
2256
- * 2. First recognized style property
2257
- * 3. Fallback to span
2258
- *
2259
- * @param styles - Array of style strings
2260
- * @returns Element info for serialization
2261
- */
2262
- mapStylesToElement(styles) {
2263
- for (const style of styles) {
2264
- if (style.startsWith("hyperlink:")) {
2265
- return {
2266
- element: "a",
2267
- attrs: { href: safeHref(style.slice("hyperlink:".length)) }
2268
- };
2269
- }
2270
- }
2271
- for (const style of styles) {
2272
- const element = this.styleToElement[style];
2273
- if (element) {
2274
- return {
2275
- element,
2276
- attrs: {}
2277
- };
2278
- }
2279
- }
2280
- return { element: "span", attrs: {} };
2181
+ function serializeOpeningTag(tagName, attrs) {
2182
+ const tag = tagName.toLowerCase();
2183
+ let result = `<${tag}`;
2184
+ for (const [name, value] of Object.entries(attrs)) {
2185
+ result += ` ${name.toLowerCase()}="${escapeAttrValue(value)}"`;
2186
+ }
2187
+ result += ">";
2188
+ return result;
2189
+ }
2190
+ function extractTagName(rawOpenTag) {
2191
+ const end = rawOpenTag.search(/[\s>]/);
2192
+ return rawOpenTag.slice(1, end === -1 ? rawOpenTag.length : end).toLowerCase();
2193
+ }
2194
+ function readRawStyle(styles) {
2195
+ for (const s of styles) {
2196
+ if (s.startsWith("raw:")) return s.slice(4);
2281
2197
  }
2282
- };
2198
+ return null;
2199
+ }
2283
2200
 
2284
2201
  // src/content/parser/MarkupParser.ts
2285
2202
  var MarkupParser = class {
2286
- constructor(options = {}) {
2287
- __publicField(this, "styleMapper");
2288
- this.styleMapper = options.styleMapper ?? new DefaultStyleMapper();
2289
- }
2290
- /**
2291
- * Parse HTML string into ContentUnit
2292
- *
2293
- * Handles two input formats:
2294
- * 1. HTML tags: `<b>text</b>` → converts to indexed `<1>text</1>` with styles
2295
- * 2. Already indexed: `<1>text</1>` → passes through as-is (from server)
2296
- *
2297
- * @param input - HTML string with inline elements or already indexed
2298
- * @returns ContentUnit with indexed tags and styles
2299
- */
2300
2203
  parse(input) {
2301
- const hasIndexedTags = /<\/?[0-9]+>/.test(input);
2302
- if (hasIndexedTags) {
2303
- return {
2304
- text: input,
2305
- styles: {}
2306
- // Empty - styles determined by children
2307
- };
2204
+ if (/<\/?[0-9]+>/.test(input)) {
2205
+ return { text: input, styles: {} };
2308
2206
  }
2309
2207
  const styles = {};
2310
2208
  let tagIndex = 0;
@@ -2312,88 +2210,45 @@ var MarkupParser = class {
2312
2210
  let result = "";
2313
2211
  let pos = 0;
2314
2212
  while (pos < input.length) {
2315
- const tagMatch = this.matchTag(input, pos);
2316
- if (!tagMatch) {
2213
+ const tag = this.matchTag(input, pos);
2214
+ if (!tag) {
2317
2215
  result += input.slice(pos);
2318
2216
  break;
2319
2217
  }
2320
- result += input.slice(pos, tagMatch.startIndex);
2321
- if (tagMatch.isClosing) {
2322
- const matchingOpen = this.findMatchingOpenTag(
2323
- tagStack,
2324
- tagMatch.tag.toLowerCase()
2325
- );
2326
- if (matchingOpen !== null) {
2327
- result += `</${matchingOpen}>`;
2328
- const stackIndex = tagStack.findIndex(
2329
- (t) => t.index === matchingOpen
2330
- );
2331
- if (stackIndex !== -1) {
2332
- tagStack.splice(stackIndex, 1);
2218
+ result += input.slice(pos, tag.startIndex);
2219
+ if (tag.isClosing) {
2220
+ let matchIdx = null;
2221
+ for (let i = tagStack.length - 1; i >= 0; i--) {
2222
+ if (tagStack[i].tag === tag.tag.toLowerCase()) {
2223
+ matchIdx = tagStack[i].index;
2224
+ tagStack.splice(i, 1);
2225
+ break;
2333
2226
  }
2334
- } else {
2335
- result += input.slice(tagMatch.startIndex, tagMatch.endIndex);
2336
2227
  }
2337
- } else if (tagMatch.isSelfClosing) {
2338
- tagIndex++;
2339
- const styleList = this.styleMapper.mapElementToStyles(
2340
- tagMatch.tag,
2341
- tagMatch.attrs
2342
- );
2343
- if (styleList.length > 0) {
2344
- styles[String(tagIndex)] = styleList;
2345
- result += `<${tagIndex}/>`;
2228
+ if (matchIdx !== null) {
2229
+ result += `</${matchIdx}>`;
2346
2230
  }
2347
2231
  } else {
2348
- const styleList = this.styleMapper.mapElementToStyles(
2349
- tagMatch.tag,
2350
- tagMatch.attrs
2351
- );
2352
- if (styleList.length > 0) {
2353
- tagIndex++;
2354
- styles[String(tagIndex)] = styleList;
2355
- result += `<${tagIndex}>`;
2356
- tagStack.push({ tag: tagMatch.tag.toLowerCase(), index: tagIndex });
2232
+ const tagName = tag.tag.toLowerCase();
2233
+ const isVoid = VOID_TAGS.has(tagName);
2234
+ const isSelfClosing = tag.isSelfClosing || isVoid;
2235
+ tagIndex++;
2236
+ styles[String(tagIndex)] = [`raw:${serializeOpeningTag(tagName, tag.attrs)}`];
2237
+ if (isSelfClosing) {
2238
+ result += `<${tagIndex}/>`;
2357
2239
  } else {
2358
- const closingIndex = this.findClosingTagIndex(
2359
- input,
2360
- tagMatch.endIndex,
2361
- tagMatch.tag
2362
- );
2363
- if (closingIndex !== -1) {
2364
- const innerContent = input.slice(tagMatch.endIndex, closingIndex);
2365
- const innerUnit = this.parse(innerContent);
2366
- const baseIndex = tagIndex;
2367
- for (const [key, value] of Object.entries(innerUnit.styles)) {
2368
- const adjustedKey = String(baseIndex + parseInt(key, 10));
2369
- styles[adjustedKey] = value;
2370
- }
2371
- result += innerUnit.text.replace(/<(\/?)\d+>/g, (match, slash) => {
2372
- const num = parseInt(match.replace(/[</>]/g, ""), 10);
2373
- return `<${slash}${baseIndex + num}>`;
2374
- });
2375
- const closingMatch = this.matchTag(input, closingIndex);
2376
- pos = closingMatch ? closingMatch.endIndex : closingIndex;
2377
- const maxInnerIndex = Object.keys(innerUnit.styles).length > 0 ? Math.max(...Object.keys(innerUnit.styles).map(Number)) : 0;
2378
- tagIndex = baseIndex + maxInnerIndex;
2379
- continue;
2380
- }
2240
+ result += `<${tagIndex}>`;
2241
+ tagStack.push({ tag: tagName, index: tagIndex });
2381
2242
  }
2382
2243
  }
2383
- pos = tagMatch.endIndex;
2244
+ pos = tag.endIndex;
2384
2245
  }
2385
2246
  while (tagStack.length > 0) {
2386
2247
  const unclosed = tagStack.pop();
2387
2248
  result += `</${unclosed.index}>`;
2388
2249
  }
2389
- return {
2390
- text: result,
2391
- styles
2392
- };
2250
+ return { text: result, styles };
2393
2251
  }
2394
- /**
2395
- * Match an HTML tag at the given position
2396
- */
2397
2252
  matchTag(input, startPos) {
2398
2253
  const tagStart = input.indexOf("<", startPos);
2399
2254
  if (tagStart === -1) return null;
@@ -2416,9 +2271,6 @@ var MarkupParser = class {
2416
2271
  endIndex: tagStart + fullMatch.length
2417
2272
  };
2418
2273
  }
2419
- /**
2420
- * Parse HTML attributes string into key-value pairs
2421
- */
2422
2274
  parseAttributes(attrsString) {
2423
2275
  const attrs = {};
2424
2276
  if (!attrsString.trim()) return attrs;
@@ -2426,60 +2278,14 @@ var MarkupParser = class {
2426
2278
  let match;
2427
2279
  while ((match = attrPattern.exec(attrsString)) !== null) {
2428
2280
  const [, name, doubleQuoted, singleQuoted, unquoted] = match;
2429
- const value = doubleQuoted ?? singleQuoted ?? unquoted ?? "";
2430
- attrs[name.toLowerCase()] = value;
2281
+ attrs[name.toLowerCase()] = doubleQuoted ?? singleQuoted ?? unquoted ?? "";
2431
2282
  }
2432
2283
  return attrs;
2433
2284
  }
2434
- /**
2435
- * Find matching opening tag in the stack
2436
- */
2437
- findMatchingOpenTag(stack, tagName) {
2438
- for (let i = stack.length - 1; i >= 0; i--) {
2439
- if (stack[i].tag === tagName) {
2440
- return stack[i].index;
2441
- }
2442
- }
2443
- return null;
2444
- }
2445
- /**
2446
- * Find the closing tag index for a given opening tag
2447
- */
2448
- findClosingTagIndex(input, startPos, tagName) {
2449
- const lowerTag = tagName.toLowerCase();
2450
- let depth = 1;
2451
- let pos = startPos;
2452
- while (pos < input.length && depth > 0) {
2453
- const tagMatch = this.matchTag(input, pos);
2454
- if (!tagMatch) break;
2455
- if (tagMatch.tag.toLowerCase() === lowerTag) {
2456
- if (tagMatch.isClosing) {
2457
- depth--;
2458
- if (depth === 0) {
2459
- return tagMatch.startIndex;
2460
- }
2461
- } else if (!tagMatch.isSelfClosing) {
2462
- depth++;
2463
- }
2464
- }
2465
- pos = tagMatch.endIndex;
2466
- }
2467
- return -1;
2468
- }
2469
2285
  };
2470
2286
 
2471
2287
  // src/content/serializer/HTMLSerializer.ts
2472
2288
  var HTMLSerializer = class {
2473
- constructor(options = {}) {
2474
- __publicField(this, "styleMapper");
2475
- this.styleMapper = options.styleMapper ?? new DefaultStyleMapper();
2476
- }
2477
- /**
2478
- * Serialize ContentUnit to HTML string
2479
- *
2480
- * @param unit - ContentUnit with indexed tags and styles
2481
- * @returns HTML string with semantic elements
2482
- */
2483
2289
  serialize(unit) {
2484
2290
  const { text, styles } = unit;
2485
2291
  const tagPattern = /<(\/?)?(\d+)(\/)?>/g;
@@ -2488,40 +2294,25 @@ var HTMLSerializer = class {
2488
2294
  let match;
2489
2295
  while ((match = tagPattern.exec(text)) !== null) {
2490
2296
  result += text.slice(lastIndex, match.index);
2491
- const [fullMatch, closingSlash, indexStr, selfClosingSlash] = match;
2492
- const tagIndex = indexStr;
2493
- const styleList = styles[tagIndex] || [];
2494
- if (closingSlash) {
2495
- const mapping = this.styleMapper.mapStylesToElement(styleList);
2496
- result += `</${mapping.element}>`;
2497
- } else if (selfClosingSlash) {
2498
- const mapping = this.styleMapper.mapStylesToElement(styleList);
2499
- const attrs = this.formatAttributes(mapping.attrs);
2500
- result += `<${mapping.element}${attrs} />`;
2297
+ const [fullMatch, closingSlash, indexStr] = match;
2298
+ const styleList = styles[indexStr] ?? [];
2299
+ const rawOpen = readRawStyle(styleList);
2300
+ if (rawOpen) {
2301
+ const tagName = extractTagName(rawOpen);
2302
+ const isVoid = VOID_TAGS.has(tagName);
2303
+ if (closingSlash) {
2304
+ if (!isVoid) result += `</${tagName}>`;
2305
+ } else {
2306
+ result += rawOpen;
2307
+ }
2501
2308
  } else {
2502
- const mapping = this.styleMapper.mapStylesToElement(styleList);
2503
- const attrs = this.formatAttributes(mapping.attrs);
2504
- result += `<${mapping.element}${attrs}>`;
2309
+ result += fullMatch;
2505
2310
  }
2506
2311
  lastIndex = match.index + fullMatch.length;
2507
2312
  }
2508
2313
  result += text.slice(lastIndex);
2509
2314
  return result;
2510
2315
  }
2511
- /**
2512
- * Format attributes object into HTML attribute string
2513
- */
2514
- formatAttributes(attrs) {
2515
- const entries = Object.entries(attrs);
2516
- if (entries.length === 0) return "";
2517
- return " " + entries.map(([key, value]) => `${key}="${this.escapeAttributeValue(value)}"`).join(" ");
2518
- }
2519
- /**
2520
- * Escape special characters in attribute values
2521
- */
2522
- escapeAttributeValue(value) {
2523
- return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
2524
- }
2525
2316
  };
2526
2317
 
2527
2318
  // src/cache/CacheManager.ts
@@ -2755,7 +2546,7 @@ var CacheManager = class {
2755
2546
  };
2756
2547
 
2757
2548
  // src/lionRapid.ts
2758
- var INDEXED_TAG_REGEX = /<\/?[0-9]+>/;
2549
+ var INDEXED_TAG_REGEX = /<\/?[0-9]+\/?>/;
2759
2550
  var HTML_TAG_REGEX = /<[a-z][a-z0-9]*(?:\s+[^>]*)?\/?>/i;
2760
2551
  var LionRapidCore = class {
2761
2552
  constructor(eventEmitter, handlerChain, defaultLocale = "en", fallbackLocale = "en", defaultNamespace) {
@@ -2980,7 +2771,7 @@ var LionRapidCore = class {
2980
2771
  */
2981
2772
  processIndexedValue(value, request) {
2982
2773
  const processedText = this.processTranslationValue(value, request);
2983
- return processedText.replace(/<\/?[0-9]+>/g, "");
2774
+ return processedText.replace(/<\/?[0-9]+\/?>/g, "");
2984
2775
  }
2985
2776
  /**
2986
2777
  * 📦 Get styles for a translation key from namespace cache (fallback)
@@ -3026,7 +2817,7 @@ var LionRapidCore = class {
3026
2817
  try {
3027
2818
  const unit = this.markupParser.parse(value);
3028
2819
  const processedText = this.processTranslationValue(unit.text, request);
3029
- return processedText.replace(/<\/?[0-9]+>/g, "");
2820
+ return processedText.replace(/<\/?[0-9]+\/?>/g, "");
3030
2821
  } catch (error) {
3031
2822
  logger.warn(`ContentUnit processing failed for "${value}":`, error);
3032
2823
  return this.processTranslationValue(value, request);
@@ -3095,7 +2886,7 @@ var LionRapidCore = class {
3095
2886
  * @example
3096
2887
  * ```typescript
3097
2888
  * const unit = i18n.getContentUnit('terms', {}, 'Read our <b>Terms</b>.');
3098
- * // → { text: "Read our <1>Terms</1>.", styles: {"1": ["bold"]} }
2889
+ * // → { text: "Read our <1>Terms</1>.", styles: {"1": ["raw:<b>"]} }
3099
2890
  * ```
3100
2891
  */
3101
2892
  getContentUnit(key, params, defaultValue) {
@@ -3704,7 +3495,7 @@ var _NetworkRepository = class _NetworkRepository {
3704
3495
  logger.debug("API base URL is not set");
3705
3496
  throw new NetworkError("API base URL is not set");
3706
3497
  }
3707
- const url = this.buildUrl("getTranslation", { key });
3498
+ const url = this.withDraftsParam(this.buildUrl("getTranslation", { key }));
3708
3499
  logger.debug(`API GET: ${url}`);
3709
3500
  try {
3710
3501
  const response = await this.makeRequest(url, "GET");
@@ -3740,7 +3531,7 @@ var _NetworkRepository = class _NetworkRepository {
3740
3531
  logger.debug("API base URL is not set");
3741
3532
  throw new NetworkError("API base URL is not set");
3742
3533
  }
3743
- const url = this.buildUrl("getTranslation", { key });
3534
+ const url = this.withDraftsParam(this.buildUrl("getTranslation", { key }));
3744
3535
  logger.debug(`API GET ContentUnit: ${url}`);
3745
3536
  try {
3746
3537
  const response = await this.makeRequest(url, "GET");
@@ -3781,7 +3572,7 @@ var _NetworkRepository = class _NetworkRepository {
3781
3572
  logger.debug("API base URL is not set");
3782
3573
  throw new NetworkError("API base URL is not set");
3783
3574
  }
3784
- const url = this.buildUrl("getNamespace", { locale, namespace });
3575
+ const url = this.withDraftsParam(this.buildUrl("getNamespace", { locale, namespace }));
3785
3576
  logger.debug(`API GET Namespace: ${url}`);
3786
3577
  const namespaceKey = `${locale}:${namespace}`;
3787
3578
  try {
@@ -3895,7 +3686,7 @@ var _NetworkRepository = class _NetworkRepository {
3895
3686
  logger.debug("API base URL is not set");
3896
3687
  throw new NetworkError("API base URL is not set");
3897
3688
  }
3898
- const url = this.buildUrl("getNamespace", { locale, namespace });
3689
+ const url = this.withDraftsParam(this.buildUrl("getNamespace", { locale, namespace }));
3899
3690
  logger.debug(`API GET Namespace ContentUnits: ${url}`);
3900
3691
  const namespaceKey = `${locale}:${namespace}`;
3901
3692
  try {
@@ -4107,6 +3898,26 @@ var _NetworkRepository = class _NetworkRepository {
4107
3898
  }
4108
3899
  return `${baseUrl}${path}`;
4109
3900
  }
3901
+ /**
3902
+ * Check whether the current page is running inside an active visual-editor
3903
+ * session. The editor JS sets `__lr_editor_active=1` as a session cookie
3904
+ * when its JWT is established; we read it here so client-side translation
3905
+ * fetches request draft content too, matching what the edge proxy does
3906
+ * server-side. Outside a browser (Node/SSR) this is always false.
3907
+ */
3908
+ isEditorPreviewSession() {
3909
+ if (typeof document === "undefined") return false;
3910
+ return document.cookie.split("; ").some((c) => c === "__lr_editor_active=1");
3911
+ }
3912
+ /**
3913
+ * Append `include_drafts=true` to a built URL when an editor session is
3914
+ * active. Leaves the URL unchanged for normal visitors so the delivery
3915
+ * gate continues to apply in production.
3916
+ */
3917
+ withDraftsParam(url) {
3918
+ if (!this.isEditorPreviewSession()) return url;
3919
+ return url + (url.includes("?") ? "&" : "?") + "include_drafts=true";
3920
+ }
4110
3921
  /**
4111
3922
  * Make HTTP request with timeout and headers
4112
3923
  */
@@ -4789,7 +4600,6 @@ export {
4789
4600
  CacheStorageRepository,
4790
4601
  Colors,
4791
4602
  ContentValidator,
4792
- DefaultStyleMapper,
4793
4603
  EventEmitter,
4794
4604
  HTMLSerializer,
4795
4605
  HandlerChain,
@@ -4808,7 +4618,9 @@ export {
4808
4618
  TranslationLockedError,
4809
4619
  TranslationNotFoundError,
4810
4620
  VERSION,
4621
+ VOID_TAGS,
4811
4622
  createPackageLogger,
4623
+ extractTagName,
4812
4624
  isClientError,
4813
4625
  isRetryableError,
4814
4626
  isTranslationError,
@@ -4816,6 +4628,8 @@ export {
4816
4628
  measure,
4817
4629
  parseKeyPath,
4818
4630
  prepareTranslationRequest,
4819
- resolveNestedKey
4631
+ readRawStyle,
4632
+ resolveNestedKey,
4633
+ serializeOpeningTag
4820
4634
  };
4821
4635
  //# sourceMappingURL=lionrapid.esm.js.map