@contentstorage/i18next-plugin 1.0.1 → 1.1.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/dist/index.d.ts CHANGED
@@ -4,7 +4,8 @@
4
4
  * i18next backend plugin for ContentStorage live editor translation tracking
5
5
  */
6
6
  export { ContentStorageBackend, createContentStorageBackend } from './plugin';
7
- export { debugMemoryMap } from './utils';
7
+ export { ContentStoragePostProcessor, createContentStoragePostProcessor } from './post-processor';
8
+ export { debugMemoryMap, loadLiveEditorScript } from './utils';
8
9
  export type { ContentStoragePluginOptions, MemoryMap, MemoryMapEntry, ContentStorageWindow, TranslationData, } from './types';
9
10
  export { default } from './plugin';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,YAAY,EACV,2BAA2B,EAC3B,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,eAAe,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAAE,2BAA2B,EAAE,iCAAiC,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/D,YAAY,EACV,2BAA2B,EAC3B,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,eAAe,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.esm.js CHANGED
@@ -53,6 +53,56 @@ function initializeMemoryMap() {
53
53
  }
54
54
  return win.memoryMap;
55
55
  }
56
+ /**
57
+ * Load the ContentStorage live editor script
58
+ * This script enables the click-to-edit functionality in the live editor
59
+ */
60
+ let liveEditorReadyPromise = null;
61
+ function loadLiveEditorScript(retries = 2, delay = 3000, debug = false) {
62
+ // Return existing promise if already loading
63
+ if (liveEditorReadyPromise) {
64
+ return liveEditorReadyPromise;
65
+ }
66
+ liveEditorReadyPromise = new Promise((resolve) => {
67
+ const win = getContentStorageWindow();
68
+ if (!win) {
69
+ resolve(false);
70
+ return;
71
+ }
72
+ const cdnScriptUrl = 'https://cdn.contentstorage.app/live-editor.js?contentstorage-live-editor=true';
73
+ const loadScript = (attempt = 1) => {
74
+ if (debug) {
75
+ console.log(`[ContentStorage] Attempting to load live editor script (attempt ${attempt}/${retries})`);
76
+ }
77
+ const scriptElement = win.document.createElement('script');
78
+ scriptElement.type = 'text/javascript';
79
+ scriptElement.src = cdnScriptUrl;
80
+ scriptElement.onload = () => {
81
+ if (debug) {
82
+ console.log(`[ContentStorage] Live editor script loaded successfully`);
83
+ }
84
+ resolve(true);
85
+ };
86
+ scriptElement.onerror = (error) => {
87
+ // Clean up the failed script element
88
+ scriptElement.remove();
89
+ if (debug) {
90
+ console.error(`[ContentStorage] Failed to load live editor script (attempt ${attempt}/${retries})`, error);
91
+ }
92
+ if (attempt < retries) {
93
+ setTimeout(() => loadScript(attempt + 1), delay);
94
+ }
95
+ else {
96
+ console.error(`[ContentStorage] All ${retries} attempts to load live editor script failed`);
97
+ resolve(false);
98
+ }
99
+ };
100
+ win.document.head.appendChild(scriptElement);
101
+ };
102
+ loadScript();
103
+ });
104
+ return liveEditorReadyPromise;
105
+ }
56
106
  /**
57
107
  * Gets the global memory map
58
108
  */
@@ -240,7 +290,6 @@ class ContentStorageBackend {
240
290
  */
241
291
  init(services, backendOptions = {}, i18nextOptions = {}) {
242
292
  this.options = {
243
- cdnBaseUrl: 'https://cdn.contentstorage.app',
244
293
  debug: false,
245
294
  maxMemoryMapSize: 10000,
246
295
  liveEditorParam: 'contentstorage_live_editor',
@@ -252,6 +301,17 @@ class ContentStorageBackend {
252
301
  if (this.isLiveMode) {
253
302
  // Initialize memory map
254
303
  initializeMemoryMap();
304
+ // Load the live editor script
305
+ loadLiveEditorScript(2, 3000, this.options.debug).then((loaded) => {
306
+ if (loaded) {
307
+ if (this.options.debug) {
308
+ console.log('[ContentStorage] Live editor ready');
309
+ }
310
+ }
311
+ else {
312
+ console.warn('[ContentStorage] Failed to load live editor script');
313
+ }
314
+ });
255
315
  if (this.options.debug) {
256
316
  console.log('[ContentStorage] Live editor mode enabled');
257
317
  console.log('[ContentStorage] Plugin initialized with options:', this.options);
@@ -326,7 +386,7 @@ class ContentStorageBackend {
326
386
  * Get the URL to load translations from
327
387
  */
328
388
  getLoadPath(language, namespace) {
329
- const { loadPath, cdnBaseUrl, contentKey } = this.options;
389
+ const { loadPath, contentKey } = this.options;
330
390
  // Custom load path function
331
391
  if (typeof loadPath === 'function') {
332
392
  return loadPath(language, namespace);
@@ -341,7 +401,10 @@ class ContentStorageBackend {
341
401
  if (!contentKey) {
342
402
  throw new Error('[ContentStorage] contentKey is required when using default CDN path');
343
403
  }
344
- return `${cdnBaseUrl}/${contentKey}/content/${language}/${namespace}.json`;
404
+ // Default: Always use uppercase language code
405
+ const lng = language.toUpperCase();
406
+ // Default: https://cdn.contentstorage.app/{contentKey}/content/{LNG}.json
407
+ return `https://cdn.contentstorage.app/${contentKey}/content/${lng}.json`;
345
408
  }
346
409
  /**
347
410
  * Check if a namespace should be tracked
@@ -380,5 +443,83 @@ function createContentStorageBackend(options) {
380
443
  return new ContentStorageBackend(undefined, options);
381
444
  }
382
445
 
383
- export { ContentStorageBackend, createContentStorageBackend, debugMemoryMap, ContentStorageBackend as default };
446
+ /**
447
+ * ContentStorage Post-Processor
448
+ *
449
+ * This post-processor tracks translations at the point of resolution,
450
+ * capturing the actual values returned by i18next including interpolations
451
+ * and plural forms.
452
+ *
453
+ * Use this in addition to or instead of the backend plugin for more
454
+ * comprehensive tracking, especially for dynamic translations.
455
+ *
456
+ * @example
457
+ * ```typescript
458
+ * import i18next from 'i18next';
459
+ * import { ContentStoragePostProcessor } from '@contentstorage/i18next-plugin';
460
+ *
461
+ * i18next
462
+ * .use(new ContentStoragePostProcessor({ debug: true }))
463
+ * .init({
464
+ * // ... your config
465
+ * });
466
+ * ```
467
+ */
468
+ class ContentStoragePostProcessor {
469
+ constructor(options = {}) {
470
+ this.type = 'postProcessor';
471
+ this.name = 'contentStorageTracker';
472
+ this.isLiveMode = false;
473
+ this.options = {
474
+ debug: false,
475
+ liveEditorParam: 'contentstorage_live_editor',
476
+ forceLiveMode: false,
477
+ ...options,
478
+ };
479
+ // Detect live editor mode
480
+ this.isLiveMode = detectLiveEditorMode(this.options.liveEditorParam, this.options.forceLiveMode);
481
+ if (this.isLiveMode) {
482
+ initializeMemoryMap();
483
+ // Load the live editor script
484
+ loadLiveEditorScript(2, 3000, this.options.debug);
485
+ if (this.options.debug) {
486
+ console.log('[ContentStorage] Post-processor initialized in live mode');
487
+ }
488
+ }
489
+ }
490
+ /**
491
+ * Process the translated value
492
+ * Called by i18next after translation resolution
493
+ */
494
+ process(value, key, options, translator) {
495
+ // Only track in live mode
496
+ if (!this.isLiveMode) {
497
+ return value;
498
+ }
499
+ // Handle array of keys (fallback keys)
500
+ const translationKey = Array.isArray(key) ? key[0] : key;
501
+ // Extract namespace from options or key
502
+ let namespace;
503
+ if (options === null || options === void 0 ? void 0 : options.ns) {
504
+ namespace = Array.isArray(options.ns) ? options.ns[0] : options.ns;
505
+ }
506
+ else if (translationKey.includes(':')) {
507
+ [namespace] = translationKey.split(':');
508
+ }
509
+ // Extract language
510
+ const language = (options === null || options === void 0 ? void 0 : options.lng) || (translator === null || translator === void 0 ? void 0 : translator.language);
511
+ // Track the translation
512
+ trackTranslation(value, translationKey, namespace, language, this.options.debug);
513
+ return value;
514
+ }
515
+ }
516
+ ContentStoragePostProcessor.type = 'postProcessor';
517
+ /**
518
+ * Create a new instance of the ContentStorage post-processor
519
+ */
520
+ function createContentStoragePostProcessor(options) {
521
+ return new ContentStoragePostProcessor(options);
522
+ }
523
+
524
+ export { ContentStorageBackend, ContentStoragePostProcessor, createContentStorageBackend, createContentStoragePostProcessor, debugMemoryMap, ContentStorageBackend as default, loadLiveEditorScript };
384
525
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/utils.ts","../src/plugin.ts"],"sourcesContent":["import type { ContentStorageWindow, MemoryMap, MemoryMapEntry } from './types';\n\n/**\n * Checks if the code is running in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Gets the ContentStorage window object with type safety\n */\nexport function getContentStorageWindow(): ContentStorageWindow | null {\n if (!isBrowser()) return null;\n return window as ContentStorageWindow;\n}\n\n/**\n * Detects if the application is running in ContentStorage live editor mode\n *\n * @param liveEditorParam - Query parameter name to check\n * @param forceLiveMode - Force live mode regardless of environment\n * @returns true if in live editor mode\n */\nexport function detectLiveEditorMode(\n liveEditorParam: string = 'contentstorage_live_editor',\n forceLiveMode: boolean = false\n): boolean {\n if (forceLiveMode) return true;\n if (!isBrowser()) return false;\n\n try {\n const win = getContentStorageWindow();\n if (!win) return false;\n\n // Check 1: Running in an iframe\n const inIframe = win.self !== win.top;\n\n // Check 2: URL has the live editor marker\n const urlParams = new URLSearchParams(win.location.search);\n const hasMarker = urlParams.has(liveEditorParam);\n\n return !!(inIframe && hasMarker);\n } catch (e) {\n // Cross-origin restrictions might block window.top access\n // This is expected when not in live editor mode\n return false;\n }\n}\n\n/**\n * Initializes the global memory map if it doesn't exist\n */\nexport function initializeMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n if (!win) return null;\n\n if (!win.memoryMap) {\n win.memoryMap = new Map<string, MemoryMapEntry>();\n }\n\n return win.memoryMap;\n}\n\n/**\n * Gets the global memory map\n */\nexport function getMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n return win?.memoryMap || null;\n}\n\n/**\n * Normalizes i18next key format to consistent dot notation\n * Converts namespace:key format to namespace.key\n *\n * @param key - The translation key\n * @param namespace - Optional namespace\n * @returns Normalized key in dot notation\n */\nexport function normalizeKey(key: string, namespace?: string): string {\n let normalizedKey = key;\n\n // Convert colon notation to dot notation\n if (normalizedKey.includes(':')) {\n normalizedKey = normalizedKey.replace(':', '.');\n }\n\n // Prepend namespace if provided and not already in key\n if (namespace && !normalizedKey.startsWith(`${namespace}.`)) {\n normalizedKey = `${namespace}.${normalizedKey}`;\n }\n\n return normalizedKey;\n}\n\n/**\n * Extracts the base translation key without interpolation context\n * Handles plural forms, contexts, and other i18next features\n *\n * Examples:\n * - 'welcome' -> 'welcome'\n * - 'items_plural' -> 'items'\n * - 'friend_male' -> 'friend'\n *\n * @param key - The translation key\n * @returns Base key without suffixes\n */\nexport function extractBaseKey(key: string): string {\n // Remove plural suffixes (_zero, _one, _two, _few, _many, _other, _plural)\n let baseKey = key.replace(/_(zero|one|two|few|many|other|plural)$/, '');\n\n // Remove context suffixes (anything after last underscore that's not a nested key)\n // Be careful not to remove underscores that are part of the actual key\n // This is a heuristic - contexts usually come at the end\n const lastUnderscore = baseKey.lastIndexOf('_');\n if (lastUnderscore > 0) {\n // Only remove if it looks like a context (short suffix, typically lowercase)\n const suffix = baseKey.substring(lastUnderscore + 1);\n if (suffix.length < 10 && suffix.toLowerCase() === suffix) {\n // This might be a context, but we'll keep it for now to avoid false positives\n // Real context handling should be done at a higher level\n }\n }\n\n return baseKey;\n}\n\n/**\n * Removes interpolation variables from a translated string\n *\n * Examples:\n * - 'Hello {{name}}!' -> 'Hello !'\n * - 'You have {{count}} items' -> 'You have items'\n *\n * @param value - The translated string\n * @returns String with interpolations removed\n */\nexport function removeInterpolation(value: string): string {\n // Remove i18next interpolation syntax: {{variable}}\n return value.replace(/\\{\\{[^}]+\\}\\}/g, '').trim();\n}\n\n/**\n * Tracks a translation in the memory map\n *\n * @param translationValue - The actual translated text\n * @param translationKey - The content ID (i18next key)\n * @param namespace - Optional namespace\n * @param language - Optional language code\n * @param debug - Enable debug logging\n */\nexport function trackTranslation(\n translationValue: string,\n translationKey: string,\n namespace?: string,\n language?: string,\n debug: boolean = false\n): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) return;\n\n // Normalize the key\n const normalizedKey = normalizeKey(translationKey, namespace);\n\n // Get or create entry\n const existingEntry = memoryMap.get(translationValue);\n const idSet = existingEntry ? existingEntry.ids : new Set<string>();\n idSet.add(normalizedKey);\n\n const entry: MemoryMapEntry = {\n ids: idSet,\n type: 'text',\n metadata: {\n namespace,\n language,\n trackedAt: Date.now(),\n },\n };\n\n memoryMap.set(translationValue, entry);\n\n if (debug) {\n console.log('[ContentStorage] Tracked translation:', {\n value: translationValue,\n key: normalizedKey,\n namespace,\n language,\n });\n }\n}\n\n/**\n * Cleans up old entries from memory map when size exceeds limit\n * Removes oldest entries first (based on trackedAt timestamp)\n *\n * @param maxSize - Maximum number of entries to keep\n */\nexport function cleanupMemoryMap(maxSize: number): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap || memoryMap.size <= maxSize) return;\n\n // Convert to array with timestamps\n const entries = Array.from(memoryMap.entries()).map(([key, value]) => ({\n key,\n value,\n timestamp: value.metadata?.trackedAt || 0,\n }));\n\n // Sort by timestamp (oldest first)\n entries.sort((a, b) => a.timestamp - b.timestamp);\n\n // Calculate how many to remove\n const toRemove = memoryMap.size - maxSize;\n\n // Remove oldest entries\n for (let i = 0; i < toRemove; i++) {\n memoryMap.delete(entries[i].key);\n }\n}\n\n/**\n * Deeply traverses a translation object and extracts all string values with their keys\n *\n * @param obj - Translation object to traverse\n * @param prefix - Current key prefix (for nested objects)\n * @returns Array of [key, value] pairs\n */\nexport function flattenTranslations(\n obj: any,\n prefix: string = ''\n): Array<[string, string]> {\n const results: Array<[string, string]> = [];\n\n for (const key in obj) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;\n\n const value = obj[key];\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === 'string') {\n results.push([fullKey, value]);\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Recurse into nested objects\n results.push(...flattenTranslations(value, fullKey));\n }\n }\n\n return results;\n}\n\n/**\n * Debug helper to log memory map contents\n */\nexport function debugMemoryMap(): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) {\n console.log('[ContentStorage] Memory map not initialized');\n return;\n }\n\n console.log('[ContentStorage] Memory map contents:');\n console.log(`Total entries: ${memoryMap.size}`);\n\n const entries = Array.from(memoryMap.entries()).slice(0, 10);\n console.table(\n entries.map(([value, entry]) => ({\n value: value.substring(0, 50),\n keys: Array.from(entry.ids).join(', '),\n namespace: entry.metadata?.namespace || 'N/A',\n }))\n );\n\n if (memoryMap.size > 10) {\n console.log(`... and ${memoryMap.size - 10} more entries`);\n }\n}\n","import type {\n BackendModule,\n ReadCallback,\n Services,\n InitOptions,\n} from 'i18next';\nimport type {\n ContentStoragePluginOptions,\n TranslationData,\n} from './types';\nimport {\n detectLiveEditorMode,\n initializeMemoryMap,\n trackTranslation,\n cleanupMemoryMap,\n flattenTranslations,\n isBrowser,\n} from './utils';\n\n/**\n * ContentStorage i18next Backend Plugin\n *\n * This plugin enables translation tracking for the ContentStorage live editor\n * by maintaining a memory map of translations and their keys.\n *\n * Features:\n * - Automatic live editor mode detection\n * - Translation tracking with memory map\n * - Support for nested translations\n * - Memory management with size limits\n * - Custom CDN or load path support\n *\n * @example\n * ```typescript\n * import i18next from 'i18next';\n * import ContentStorageBackend from '@contentstorage/i18next-plugin';\n *\n * i18next\n * .use(ContentStorageBackend)\n * .init({\n * backend: {\n * contentKey: 'your-content-key',\n * debug: true\n * }\n * });\n * ```\n */\nexport class ContentStorageBackend implements BackendModule<ContentStoragePluginOptions> {\n static type: 'backend' = 'backend';\n type: 'backend' = 'backend';\n\n private options: ContentStoragePluginOptions;\n private isLiveMode: boolean = false;\n\n constructor(_services?: Services, options?: ContentStoragePluginOptions, _i18nextOptions?: InitOptions) {\n this.options = options || {};\n\n // Initialize if services and i18nextOptions are provided\n // This allows i18next to initialize the plugin automatically\n if (_services && _i18nextOptions) {\n this.init(_services, options, _i18nextOptions);\n }\n }\n\n /**\n * Initialize the plugin\n * Called by i18next during initialization\n */\n init(\n services: Services,\n backendOptions: ContentStoragePluginOptions = {},\n i18nextOptions: InitOptions = {}\n ): void {\n // Store services and i18nextOptions for potential future use\n // Note: Currently not used but kept in signature for i18next compatibility\n void services;\n void i18nextOptions;\n\n this.options = {\n cdnBaseUrl: 'https://cdn.contentstorage.app',\n debug: false,\n maxMemoryMapSize: 10000,\n liveEditorParam: 'contentstorage_live_editor',\n forceLiveMode: false,\n ...backendOptions,\n };\n\n // Detect live editor mode\n this.isLiveMode = detectLiveEditorMode(\n this.options.liveEditorParam,\n this.options.forceLiveMode\n );\n\n if (this.isLiveMode) {\n // Initialize memory map\n initializeMemoryMap();\n\n if (this.options.debug) {\n console.log('[ContentStorage] Live editor mode enabled');\n console.log('[ContentStorage] Plugin initialized with options:', this.options);\n }\n } else if (this.options.debug) {\n console.log('[ContentStorage] Running in normal mode (not live editor)');\n }\n }\n\n /**\n * Read translations for a given language and namespace\n * This is the main method called by i18next to load translations\n */\n read(\n language: string,\n namespace: string,\n callback: ReadCallback\n ): void {\n if (this.options.debug) {\n console.log(`[ContentStorage] Loading translations: ${language}/${namespace}`);\n }\n\n this.loadTranslations(language, namespace)\n .then((translations) => {\n // Track translations if in live mode\n if (this.isLiveMode && this.shouldTrackNamespace(namespace)) {\n this.trackTranslations(translations, namespace, language);\n\n // Cleanup if needed\n if (this.options.maxMemoryMapSize) {\n cleanupMemoryMap(this.options.maxMemoryMapSize);\n }\n }\n\n callback(null, translations);\n })\n .catch((error) => {\n if (this.options.debug) {\n console.error('[ContentStorage] Failed to load translations:', error);\n }\n callback(error, false);\n });\n }\n\n /**\n * Load translations from CDN or custom source\n */\n private async loadTranslations(\n language: string,\n namespace: string\n ): Promise<TranslationData> {\n const url = this.getLoadPath(language, namespace);\n\n if (this.options.debug) {\n console.log(`[ContentStorage] Fetching from: ${url}`);\n }\n\n try {\n const fetchFn = this.options.request || this.defaultFetch.bind(this);\n return await fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n },\n });\n } catch (error) {\n if (this.options.debug) {\n console.error('[ContentStorage] Fetch error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Default fetch implementation\n */\n private async defaultFetch(url: string, options: RequestInit): Promise<any> {\n const response = await fetch(url, options);\n\n if (!response.ok) {\n throw new Error(\n `Failed to load translations: ${response.status} ${response.statusText}`\n );\n }\n\n return response.json();\n }\n\n /**\n * Get the URL to load translations from\n */\n private getLoadPath(language: string, namespace: string): string {\n const { loadPath, cdnBaseUrl, contentKey } = this.options;\n\n // Custom load path function\n if (typeof loadPath === 'function') {\n return loadPath(language, namespace);\n }\n\n // Custom load path string with interpolation\n if (typeof loadPath === 'string') {\n return loadPath\n .replace('{{lng}}', language)\n .replace('{{ns}}', namespace);\n }\n\n // Default CDN path\n if (!contentKey) {\n throw new Error(\n '[ContentStorage] contentKey is required when using default CDN path'\n );\n }\n\n return `${cdnBaseUrl}/${contentKey}/content/${language}/${namespace}.json`;\n }\n\n /**\n * Check if a namespace should be tracked\n */\n private shouldTrackNamespace(namespace: string): boolean {\n const { trackNamespaces } = this.options;\n\n // If no filter specified, track all namespaces\n if (!trackNamespaces || trackNamespaces.length === 0) {\n return true;\n }\n\n return trackNamespaces.includes(namespace);\n }\n\n /**\n * Track all translations in the loaded data\n */\n private trackTranslations(\n translations: TranslationData,\n namespace: string,\n language: string\n ): void {\n if (!isBrowser()) return;\n\n const flatTranslations = flattenTranslations(translations);\n\n for (const [key, value] of flatTranslations) {\n // Skip empty values\n if (!value) continue;\n\n trackTranslation(\n value,\n key,\n namespace,\n language,\n this.options.debug\n );\n }\n\n if (this.options.debug) {\n console.log(\n `[ContentStorage] Tracked ${flatTranslations.length} translations for ${namespace}`\n );\n }\n }\n}\n\n/**\n * Create a new instance of the ContentStorage backend\n */\nexport function createContentStorageBackend(\n options?: ContentStoragePluginOptions\n): ContentStorageBackend {\n return new ContentStorageBackend(undefined, options);\n}\n\n// Default export\nexport default ContentStorageBackend;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/utils.ts","../src/plugin.ts","../src/post-processor.ts"],"sourcesContent":["import type { ContentStorageWindow, MemoryMap, MemoryMapEntry } from './types';\n\n/**\n * Checks if the code is running in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Gets the ContentStorage window object with type safety\n */\nexport function getContentStorageWindow(): ContentStorageWindow | null {\n if (!isBrowser()) return null;\n return window as ContentStorageWindow;\n}\n\n/**\n * Detects if the application is running in ContentStorage live editor mode\n *\n * @param liveEditorParam - Query parameter name to check\n * @param forceLiveMode - Force live mode regardless of environment\n * @returns true if in live editor mode\n */\nexport function detectLiveEditorMode(\n liveEditorParam: string = 'contentstorage_live_editor',\n forceLiveMode: boolean = false\n): boolean {\n if (forceLiveMode) return true;\n if (!isBrowser()) return false;\n\n try {\n const win = getContentStorageWindow();\n if (!win) return false;\n\n // Check 1: Running in an iframe\n const inIframe = win.self !== win.top;\n\n // Check 2: URL has the live editor marker\n const urlParams = new URLSearchParams(win.location.search);\n const hasMarker = urlParams.has(liveEditorParam);\n\n return !!(inIframe && hasMarker);\n } catch (e) {\n // Cross-origin restrictions might block window.top access\n // This is expected when not in live editor mode\n return false;\n }\n}\n\n/**\n * Initializes the global memory map if it doesn't exist\n */\nexport function initializeMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n if (!win) return null;\n\n if (!win.memoryMap) {\n win.memoryMap = new Map<string, MemoryMapEntry>();\n }\n\n return win.memoryMap;\n}\n\n/**\n * Load the ContentStorage live editor script\n * This script enables the click-to-edit functionality in the live editor\n */\nlet liveEditorReadyPromise: Promise<boolean> | null = null;\n\nexport function loadLiveEditorScript(\n retries: number = 2,\n delay: number = 3000,\n debug: boolean = false\n): Promise<boolean> {\n // Return existing promise if already loading\n if (liveEditorReadyPromise) {\n return liveEditorReadyPromise;\n }\n\n liveEditorReadyPromise = new Promise<boolean>((resolve) => {\n const win = getContentStorageWindow();\n if (!win) {\n resolve(false);\n return;\n }\n\n const cdnScriptUrl = 'https://cdn.contentstorage.app/live-editor.js?contentstorage-live-editor=true';\n\n const loadScript = (attempt: number = 1) => {\n if (debug) {\n console.log(`[ContentStorage] Attempting to load live editor script (attempt ${attempt}/${retries})`);\n }\n\n const scriptElement = win.document.createElement('script');\n scriptElement.type = 'text/javascript';\n scriptElement.src = cdnScriptUrl;\n\n scriptElement.onload = () => {\n if (debug) {\n console.log(`[ContentStorage] Live editor script loaded successfully`);\n }\n resolve(true);\n };\n\n scriptElement.onerror = (error) => {\n // Clean up the failed script element\n scriptElement.remove();\n\n if (debug) {\n console.error(`[ContentStorage] Failed to load live editor script (attempt ${attempt}/${retries})`, error);\n }\n\n if (attempt < retries) {\n setTimeout(() => loadScript(attempt + 1), delay);\n } else {\n console.error(`[ContentStorage] All ${retries} attempts to load live editor script failed`);\n resolve(false);\n }\n };\n\n win.document.head.appendChild(scriptElement);\n };\n\n loadScript();\n });\n\n return liveEditorReadyPromise;\n}\n\n/**\n * Gets the global memory map\n */\nexport function getMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n return win?.memoryMap || null;\n}\n\n/**\n * Normalizes i18next key format to consistent dot notation\n * Converts namespace:key format to namespace.key\n *\n * @param key - The translation key\n * @param namespace - Optional namespace\n * @returns Normalized key in dot notation\n */\nexport function normalizeKey(key: string, namespace?: string): string {\n let normalizedKey = key;\n\n // Convert colon notation to dot notation\n if (normalizedKey.includes(':')) {\n normalizedKey = normalizedKey.replace(':', '.');\n }\n\n // Prepend namespace if provided and not already in key\n if (namespace && !normalizedKey.startsWith(`${namespace}.`)) {\n normalizedKey = `${namespace}.${normalizedKey}`;\n }\n\n return normalizedKey;\n}\n\n/**\n * Extracts the base translation key without interpolation context\n * Handles plural forms, contexts, and other i18next features\n *\n * Examples:\n * - 'welcome' -> 'welcome'\n * - 'items_plural' -> 'items'\n * - 'friend_male' -> 'friend'\n *\n * @param key - The translation key\n * @returns Base key without suffixes\n */\nexport function extractBaseKey(key: string): string {\n // Remove plural suffixes (_zero, _one, _two, _few, _many, _other, _plural)\n let baseKey = key.replace(/_(zero|one|two|few|many|other|plural)$/, '');\n\n // Remove context suffixes (anything after last underscore that's not a nested key)\n // Be careful not to remove underscores that are part of the actual key\n // This is a heuristic - contexts usually come at the end\n const lastUnderscore = baseKey.lastIndexOf('_');\n if (lastUnderscore > 0) {\n // Only remove if it looks like a context (short suffix, typically lowercase)\n const suffix = baseKey.substring(lastUnderscore + 1);\n if (suffix.length < 10 && suffix.toLowerCase() === suffix) {\n // This might be a context, but we'll keep it for now to avoid false positives\n // Real context handling should be done at a higher level\n }\n }\n\n return baseKey;\n}\n\n/**\n * Removes interpolation variables from a translated string\n *\n * Examples:\n * - 'Hello {{name}}!' -> 'Hello !'\n * - 'You have {{count}} items' -> 'You have items'\n *\n * @param value - The translated string\n * @returns String with interpolations removed\n */\nexport function removeInterpolation(value: string): string {\n // Remove i18next interpolation syntax: {{variable}}\n return value.replace(/\\{\\{[^}]+\\}\\}/g, '').trim();\n}\n\n/**\n * Tracks a translation in the memory map\n *\n * @param translationValue - The actual translated text\n * @param translationKey - The content ID (i18next key)\n * @param namespace - Optional namespace\n * @param language - Optional language code\n * @param debug - Enable debug logging\n */\nexport function trackTranslation(\n translationValue: string,\n translationKey: string,\n namespace?: string,\n language?: string,\n debug: boolean = false\n): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) return;\n\n // Normalize the key\n const normalizedKey = normalizeKey(translationKey, namespace);\n\n // Get or create entry\n const existingEntry = memoryMap.get(translationValue);\n const idSet = existingEntry ? existingEntry.ids : new Set<string>();\n idSet.add(normalizedKey);\n\n const entry: MemoryMapEntry = {\n ids: idSet,\n type: 'text',\n metadata: {\n namespace,\n language,\n trackedAt: Date.now(),\n },\n };\n\n memoryMap.set(translationValue, entry);\n\n if (debug) {\n console.log('[ContentStorage] Tracked translation:', {\n value: translationValue,\n key: normalizedKey,\n namespace,\n language,\n });\n }\n}\n\n/**\n * Cleans up old entries from memory map when size exceeds limit\n * Removes oldest entries first (based on trackedAt timestamp)\n *\n * @param maxSize - Maximum number of entries to keep\n */\nexport function cleanupMemoryMap(maxSize: number): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap || memoryMap.size <= maxSize) return;\n\n // Convert to array with timestamps\n const entries = Array.from(memoryMap.entries()).map(([key, value]) => ({\n key,\n value,\n timestamp: value.metadata?.trackedAt || 0,\n }));\n\n // Sort by timestamp (oldest first)\n entries.sort((a, b) => a.timestamp - b.timestamp);\n\n // Calculate how many to remove\n const toRemove = memoryMap.size - maxSize;\n\n // Remove oldest entries\n for (let i = 0; i < toRemove; i++) {\n memoryMap.delete(entries[i].key);\n }\n}\n\n/**\n * Deeply traverses a translation object and extracts all string values with their keys\n *\n * @param obj - Translation object to traverse\n * @param prefix - Current key prefix (for nested objects)\n * @returns Array of [key, value] pairs\n */\nexport function flattenTranslations(\n obj: any,\n prefix: string = ''\n): Array<[string, string]> {\n const results: Array<[string, string]> = [];\n\n for (const key in obj) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;\n\n const value = obj[key];\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === 'string') {\n results.push([fullKey, value]);\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Recurse into nested objects\n results.push(...flattenTranslations(value, fullKey));\n }\n }\n\n return results;\n}\n\n/**\n * Debug helper to log memory map contents\n */\nexport function debugMemoryMap(): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) {\n console.log('[ContentStorage] Memory map not initialized');\n return;\n }\n\n console.log('[ContentStorage] Memory map contents:');\n console.log(`Total entries: ${memoryMap.size}`);\n\n const entries = Array.from(memoryMap.entries()).slice(0, 10);\n console.table(\n entries.map(([value, entry]) => ({\n value: value.substring(0, 50),\n keys: Array.from(entry.ids).join(', '),\n namespace: entry.metadata?.namespace || 'N/A',\n }))\n );\n\n if (memoryMap.size > 10) {\n console.log(`... and ${memoryMap.size - 10} more entries`);\n }\n}\n","import type {\n BackendModule,\n ReadCallback,\n Services,\n InitOptions,\n} from 'i18next';\nimport type {\n ContentStoragePluginOptions,\n TranslationData,\n} from './types';\nimport {\n detectLiveEditorMode,\n initializeMemoryMap,\n trackTranslation,\n cleanupMemoryMap,\n flattenTranslations,\n isBrowser,\n loadLiveEditorScript,\n} from './utils';\n\n/**\n * ContentStorage i18next Backend Plugin\n *\n * This plugin enables translation tracking for the ContentStorage live editor\n * by maintaining a memory map of translations and their keys.\n *\n * Features:\n * - Automatic live editor mode detection\n * - Translation tracking with memory map\n * - Support for nested translations\n * - Memory management with size limits\n * - Custom CDN or load path support\n *\n * @example\n * ```typescript\n * import i18next from 'i18next';\n * import ContentStorageBackend from '@contentstorage/i18next-plugin';\n *\n * i18next\n * .use(ContentStorageBackend)\n * .init({\n * backend: {\n * contentKey: 'your-content-key',\n * debug: true\n * }\n * });\n * ```\n */\nexport class ContentStorageBackend implements BackendModule<ContentStoragePluginOptions> {\n static type: 'backend' = 'backend';\n type: 'backend' = 'backend';\n\n private options: ContentStoragePluginOptions;\n private isLiveMode: boolean = false;\n\n constructor(_services?: Services, options?: ContentStoragePluginOptions, _i18nextOptions?: InitOptions) {\n this.options = options || {};\n\n // Initialize if services and i18nextOptions are provided\n // This allows i18next to initialize the plugin automatically\n if (_services && _i18nextOptions) {\n this.init(_services, options, _i18nextOptions);\n }\n }\n\n /**\n * Initialize the plugin\n * Called by i18next during initialization\n */\n init(\n services: Services,\n backendOptions: ContentStoragePluginOptions = {},\n i18nextOptions: InitOptions = {}\n ): void {\n // Store services and i18nextOptions for potential future use\n // Note: Currently not used but kept in signature for i18next compatibility\n void services;\n void i18nextOptions;\n\n this.options = {\n debug: false,\n maxMemoryMapSize: 10000,\n liveEditorParam: 'contentstorage_live_editor',\n forceLiveMode: false,\n ...backendOptions,\n };\n\n // Detect live editor mode\n this.isLiveMode = detectLiveEditorMode(\n this.options.liveEditorParam,\n this.options.forceLiveMode\n );\n\n if (this.isLiveMode) {\n // Initialize memory map\n initializeMemoryMap();\n\n // Load the live editor script\n loadLiveEditorScript(2, 3000, this.options.debug).then((loaded) => {\n if (loaded) {\n if (this.options.debug) {\n console.log('[ContentStorage] Live editor ready');\n }\n } else {\n console.warn('[ContentStorage] Failed to load live editor script');\n }\n });\n\n if (this.options.debug) {\n console.log('[ContentStorage] Live editor mode enabled');\n console.log('[ContentStorage] Plugin initialized with options:', this.options);\n }\n } else if (this.options.debug) {\n console.log('[ContentStorage] Running in normal mode (not live editor)');\n }\n }\n\n /**\n * Read translations for a given language and namespace\n * This is the main method called by i18next to load translations\n */\n read(\n language: string,\n namespace: string,\n callback: ReadCallback\n ): void {\n if (this.options.debug) {\n console.log(`[ContentStorage] Loading translations: ${language}/${namespace}`);\n }\n\n this.loadTranslations(language, namespace)\n .then((translations) => {\n // Track translations if in live mode\n if (this.isLiveMode && this.shouldTrackNamespace(namespace)) {\n this.trackTranslations(translations, namespace, language);\n\n // Cleanup if needed\n if (this.options.maxMemoryMapSize) {\n cleanupMemoryMap(this.options.maxMemoryMapSize);\n }\n }\n\n callback(null, translations);\n })\n .catch((error) => {\n if (this.options.debug) {\n console.error('[ContentStorage] Failed to load translations:', error);\n }\n callback(error, false);\n });\n }\n\n /**\n * Load translations from CDN or custom source\n */\n private async loadTranslations(\n language: string,\n namespace: string\n ): Promise<TranslationData> {\n const url = this.getLoadPath(language, namespace);\n\n if (this.options.debug) {\n console.log(`[ContentStorage] Fetching from: ${url}`);\n }\n\n try {\n const fetchFn = this.options.request || this.defaultFetch.bind(this);\n return await fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n },\n });\n } catch (error) {\n if (this.options.debug) {\n console.error('[ContentStorage] Fetch error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Default fetch implementation\n */\n private async defaultFetch(url: string, options: RequestInit): Promise<any> {\n const response = await fetch(url, options);\n\n if (!response.ok) {\n throw new Error(\n `Failed to load translations: ${response.status} ${response.statusText}`\n );\n }\n\n return response.json();\n }\n\n /**\n * Get the URL to load translations from\n */\n private getLoadPath(language: string, namespace: string): string {\n const { loadPath, contentKey } = this.options;\n\n // Custom load path function\n if (typeof loadPath === 'function') {\n return loadPath(language, namespace);\n }\n\n // Custom load path string with interpolation\n if (typeof loadPath === 'string') {\n return loadPath\n .replace('{{lng}}', language)\n .replace('{{ns}}', namespace);\n }\n\n // Default CDN path\n if (!contentKey) {\n throw new Error(\n '[ContentStorage] contentKey is required when using default CDN path'\n );\n }\n\n // Default: Always use uppercase language code\n const lng = language.toUpperCase();\n\n // Default: https://cdn.contentstorage.app/{contentKey}/content/{LNG}.json\n return `https://cdn.contentstorage.app/${contentKey}/content/${lng}.json`;\n }\n\n /**\n * Check if a namespace should be tracked\n */\n private shouldTrackNamespace(namespace: string): boolean {\n const { trackNamespaces } = this.options;\n\n // If no filter specified, track all namespaces\n if (!trackNamespaces || trackNamespaces.length === 0) {\n return true;\n }\n\n return trackNamespaces.includes(namespace);\n }\n\n /**\n * Track all translations in the loaded data\n */\n private trackTranslations(\n translations: TranslationData,\n namespace: string,\n language: string\n ): void {\n if (!isBrowser()) return;\n\n const flatTranslations = flattenTranslations(translations);\n\n for (const [key, value] of flatTranslations) {\n // Skip empty values\n if (!value) continue;\n\n trackTranslation(\n value,\n key,\n namespace,\n language,\n this.options.debug\n );\n }\n\n if (this.options.debug) {\n console.log(\n `[ContentStorage] Tracked ${flatTranslations.length} translations for ${namespace}`\n );\n }\n }\n}\n\n/**\n * Create a new instance of the ContentStorage backend\n */\nexport function createContentStorageBackend(\n options?: ContentStoragePluginOptions\n): ContentStorageBackend {\n return new ContentStorageBackend(undefined, options);\n}\n\n// Default export\nexport default ContentStorageBackend;\n","import type { PostProcessorModule } from 'i18next';\nimport type { ContentStoragePluginOptions } from './types';\nimport { trackTranslation, detectLiveEditorMode, initializeMemoryMap, loadLiveEditorScript } from './utils';\n\n/**\n * ContentStorage Post-Processor\n *\n * This post-processor tracks translations at the point of resolution,\n * capturing the actual values returned by i18next including interpolations\n * and plural forms.\n *\n * Use this in addition to or instead of the backend plugin for more\n * comprehensive tracking, especially for dynamic translations.\n *\n * @example\n * ```typescript\n * import i18next from 'i18next';\n * import { ContentStoragePostProcessor } from '@contentstorage/i18next-plugin';\n *\n * i18next\n * .use(new ContentStoragePostProcessor({ debug: true }))\n * .init({\n * // ... your config\n * });\n * ```\n */\nexport class ContentStoragePostProcessor implements PostProcessorModule {\n static type: 'postProcessor' = 'postProcessor';\n type: 'postProcessor' = 'postProcessor';\n name: string = 'contentStorageTracker';\n\n private options: ContentStoragePluginOptions;\n private isLiveMode: boolean = false;\n\n constructor(options: ContentStoragePluginOptions = {}) {\n this.options = {\n debug: false,\n liveEditorParam: 'contentstorage_live_editor',\n forceLiveMode: false,\n ...options,\n };\n\n // Detect live editor mode\n this.isLiveMode = detectLiveEditorMode(\n this.options.liveEditorParam,\n this.options.forceLiveMode\n );\n\n if (this.isLiveMode) {\n initializeMemoryMap();\n\n // Load the live editor script\n loadLiveEditorScript(2, 3000, this.options.debug);\n\n if (this.options.debug) {\n console.log('[ContentStorage] Post-processor initialized in live mode');\n }\n }\n }\n\n /**\n * Process the translated value\n * Called by i18next after translation resolution\n */\n process(\n value: string,\n key: string | string[],\n options: any,\n translator: any\n ): string {\n // Only track in live mode\n if (!this.isLiveMode) {\n return value;\n }\n\n // Handle array of keys (fallback keys)\n const translationKey = Array.isArray(key) ? key[0] : key;\n\n // Extract namespace from options or key\n let namespace: string | undefined;\n if (options?.ns) {\n namespace = Array.isArray(options.ns) ? options.ns[0] : options.ns;\n } else if (translationKey.includes(':')) {\n [namespace] = translationKey.split(':');\n }\n\n // Extract language\n const language = options?.lng || translator?.language;\n\n // Track the translation\n trackTranslation(\n value,\n translationKey,\n namespace,\n language,\n this.options.debug\n );\n\n return value;\n }\n}\n\n/**\n * Create a new instance of the ContentStorage post-processor\n */\nexport function createContentStoragePostProcessor(\n options?: ContentStoragePluginOptions\n): ContentStoragePostProcessor {\n return new ContentStoragePostProcessor(options);\n}\n"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -57,6 +57,56 @@ function initializeMemoryMap() {
57
57
  }
58
58
  return win.memoryMap;
59
59
  }
60
+ /**
61
+ * Load the ContentStorage live editor script
62
+ * This script enables the click-to-edit functionality in the live editor
63
+ */
64
+ let liveEditorReadyPromise = null;
65
+ function loadLiveEditorScript(retries = 2, delay = 3000, debug = false) {
66
+ // Return existing promise if already loading
67
+ if (liveEditorReadyPromise) {
68
+ return liveEditorReadyPromise;
69
+ }
70
+ liveEditorReadyPromise = new Promise((resolve) => {
71
+ const win = getContentStorageWindow();
72
+ if (!win) {
73
+ resolve(false);
74
+ return;
75
+ }
76
+ const cdnScriptUrl = 'https://cdn.contentstorage.app/live-editor.js?contentstorage-live-editor=true';
77
+ const loadScript = (attempt = 1) => {
78
+ if (debug) {
79
+ console.log(`[ContentStorage] Attempting to load live editor script (attempt ${attempt}/${retries})`);
80
+ }
81
+ const scriptElement = win.document.createElement('script');
82
+ scriptElement.type = 'text/javascript';
83
+ scriptElement.src = cdnScriptUrl;
84
+ scriptElement.onload = () => {
85
+ if (debug) {
86
+ console.log(`[ContentStorage] Live editor script loaded successfully`);
87
+ }
88
+ resolve(true);
89
+ };
90
+ scriptElement.onerror = (error) => {
91
+ // Clean up the failed script element
92
+ scriptElement.remove();
93
+ if (debug) {
94
+ console.error(`[ContentStorage] Failed to load live editor script (attempt ${attempt}/${retries})`, error);
95
+ }
96
+ if (attempt < retries) {
97
+ setTimeout(() => loadScript(attempt + 1), delay);
98
+ }
99
+ else {
100
+ console.error(`[ContentStorage] All ${retries} attempts to load live editor script failed`);
101
+ resolve(false);
102
+ }
103
+ };
104
+ win.document.head.appendChild(scriptElement);
105
+ };
106
+ loadScript();
107
+ });
108
+ return liveEditorReadyPromise;
109
+ }
60
110
  /**
61
111
  * Gets the global memory map
62
112
  */
@@ -244,7 +294,6 @@ class ContentStorageBackend {
244
294
  */
245
295
  init(services, backendOptions = {}, i18nextOptions = {}) {
246
296
  this.options = {
247
- cdnBaseUrl: 'https://cdn.contentstorage.app',
248
297
  debug: false,
249
298
  maxMemoryMapSize: 10000,
250
299
  liveEditorParam: 'contentstorage_live_editor',
@@ -256,6 +305,17 @@ class ContentStorageBackend {
256
305
  if (this.isLiveMode) {
257
306
  // Initialize memory map
258
307
  initializeMemoryMap();
308
+ // Load the live editor script
309
+ loadLiveEditorScript(2, 3000, this.options.debug).then((loaded) => {
310
+ if (loaded) {
311
+ if (this.options.debug) {
312
+ console.log('[ContentStorage] Live editor ready');
313
+ }
314
+ }
315
+ else {
316
+ console.warn('[ContentStorage] Failed to load live editor script');
317
+ }
318
+ });
259
319
  if (this.options.debug) {
260
320
  console.log('[ContentStorage] Live editor mode enabled');
261
321
  console.log('[ContentStorage] Plugin initialized with options:', this.options);
@@ -330,7 +390,7 @@ class ContentStorageBackend {
330
390
  * Get the URL to load translations from
331
391
  */
332
392
  getLoadPath(language, namespace) {
333
- const { loadPath, cdnBaseUrl, contentKey } = this.options;
393
+ const { loadPath, contentKey } = this.options;
334
394
  // Custom load path function
335
395
  if (typeof loadPath === 'function') {
336
396
  return loadPath(language, namespace);
@@ -345,7 +405,10 @@ class ContentStorageBackend {
345
405
  if (!contentKey) {
346
406
  throw new Error('[ContentStorage] contentKey is required when using default CDN path');
347
407
  }
348
- return `${cdnBaseUrl}/${contentKey}/content/${language}/${namespace}.json`;
408
+ // Default: Always use uppercase language code
409
+ const lng = language.toUpperCase();
410
+ // Default: https://cdn.contentstorage.app/{contentKey}/content/{LNG}.json
411
+ return `https://cdn.contentstorage.app/${contentKey}/content/${lng}.json`;
349
412
  }
350
413
  /**
351
414
  * Check if a namespace should be tracked
@@ -384,8 +447,89 @@ function createContentStorageBackend(options) {
384
447
  return new ContentStorageBackend(undefined, options);
385
448
  }
386
449
 
450
+ /**
451
+ * ContentStorage Post-Processor
452
+ *
453
+ * This post-processor tracks translations at the point of resolution,
454
+ * capturing the actual values returned by i18next including interpolations
455
+ * and plural forms.
456
+ *
457
+ * Use this in addition to or instead of the backend plugin for more
458
+ * comprehensive tracking, especially for dynamic translations.
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * import i18next from 'i18next';
463
+ * import { ContentStoragePostProcessor } from '@contentstorage/i18next-plugin';
464
+ *
465
+ * i18next
466
+ * .use(new ContentStoragePostProcessor({ debug: true }))
467
+ * .init({
468
+ * // ... your config
469
+ * });
470
+ * ```
471
+ */
472
+ class ContentStoragePostProcessor {
473
+ constructor(options = {}) {
474
+ this.type = 'postProcessor';
475
+ this.name = 'contentStorageTracker';
476
+ this.isLiveMode = false;
477
+ this.options = {
478
+ debug: false,
479
+ liveEditorParam: 'contentstorage_live_editor',
480
+ forceLiveMode: false,
481
+ ...options,
482
+ };
483
+ // Detect live editor mode
484
+ this.isLiveMode = detectLiveEditorMode(this.options.liveEditorParam, this.options.forceLiveMode);
485
+ if (this.isLiveMode) {
486
+ initializeMemoryMap();
487
+ // Load the live editor script
488
+ loadLiveEditorScript(2, 3000, this.options.debug);
489
+ if (this.options.debug) {
490
+ console.log('[ContentStorage] Post-processor initialized in live mode');
491
+ }
492
+ }
493
+ }
494
+ /**
495
+ * Process the translated value
496
+ * Called by i18next after translation resolution
497
+ */
498
+ process(value, key, options, translator) {
499
+ // Only track in live mode
500
+ if (!this.isLiveMode) {
501
+ return value;
502
+ }
503
+ // Handle array of keys (fallback keys)
504
+ const translationKey = Array.isArray(key) ? key[0] : key;
505
+ // Extract namespace from options or key
506
+ let namespace;
507
+ if (options === null || options === void 0 ? void 0 : options.ns) {
508
+ namespace = Array.isArray(options.ns) ? options.ns[0] : options.ns;
509
+ }
510
+ else if (translationKey.includes(':')) {
511
+ [namespace] = translationKey.split(':');
512
+ }
513
+ // Extract language
514
+ const language = (options === null || options === void 0 ? void 0 : options.lng) || (translator === null || translator === void 0 ? void 0 : translator.language);
515
+ // Track the translation
516
+ trackTranslation(value, translationKey, namespace, language, this.options.debug);
517
+ return value;
518
+ }
519
+ }
520
+ ContentStoragePostProcessor.type = 'postProcessor';
521
+ /**
522
+ * Create a new instance of the ContentStorage post-processor
523
+ */
524
+ function createContentStoragePostProcessor(options) {
525
+ return new ContentStoragePostProcessor(options);
526
+ }
527
+
387
528
  exports.ContentStorageBackend = ContentStorageBackend;
529
+ exports.ContentStoragePostProcessor = ContentStoragePostProcessor;
388
530
  exports.createContentStorageBackend = createContentStorageBackend;
531
+ exports.createContentStoragePostProcessor = createContentStoragePostProcessor;
389
532
  exports.debugMemoryMap = debugMemoryMap;
390
533
  exports.default = ContentStorageBackend;
534
+ exports.loadLiveEditorScript = loadLiveEditorScript;
391
535
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils.ts","../src/plugin.ts"],"sourcesContent":["import type { ContentStorageWindow, MemoryMap, MemoryMapEntry } from './types';\n\n/**\n * Checks if the code is running in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Gets the ContentStorage window object with type safety\n */\nexport function getContentStorageWindow(): ContentStorageWindow | null {\n if (!isBrowser()) return null;\n return window as ContentStorageWindow;\n}\n\n/**\n * Detects if the application is running in ContentStorage live editor mode\n *\n * @param liveEditorParam - Query parameter name to check\n * @param forceLiveMode - Force live mode regardless of environment\n * @returns true if in live editor mode\n */\nexport function detectLiveEditorMode(\n liveEditorParam: string = 'contentstorage_live_editor',\n forceLiveMode: boolean = false\n): boolean {\n if (forceLiveMode) return true;\n if (!isBrowser()) return false;\n\n try {\n const win = getContentStorageWindow();\n if (!win) return false;\n\n // Check 1: Running in an iframe\n const inIframe = win.self !== win.top;\n\n // Check 2: URL has the live editor marker\n const urlParams = new URLSearchParams(win.location.search);\n const hasMarker = urlParams.has(liveEditorParam);\n\n return !!(inIframe && hasMarker);\n } catch (e) {\n // Cross-origin restrictions might block window.top access\n // This is expected when not in live editor mode\n return false;\n }\n}\n\n/**\n * Initializes the global memory map if it doesn't exist\n */\nexport function initializeMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n if (!win) return null;\n\n if (!win.memoryMap) {\n win.memoryMap = new Map<string, MemoryMapEntry>();\n }\n\n return win.memoryMap;\n}\n\n/**\n * Gets the global memory map\n */\nexport function getMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n return win?.memoryMap || null;\n}\n\n/**\n * Normalizes i18next key format to consistent dot notation\n * Converts namespace:key format to namespace.key\n *\n * @param key - The translation key\n * @param namespace - Optional namespace\n * @returns Normalized key in dot notation\n */\nexport function normalizeKey(key: string, namespace?: string): string {\n let normalizedKey = key;\n\n // Convert colon notation to dot notation\n if (normalizedKey.includes(':')) {\n normalizedKey = normalizedKey.replace(':', '.');\n }\n\n // Prepend namespace if provided and not already in key\n if (namespace && !normalizedKey.startsWith(`${namespace}.`)) {\n normalizedKey = `${namespace}.${normalizedKey}`;\n }\n\n return normalizedKey;\n}\n\n/**\n * Extracts the base translation key without interpolation context\n * Handles plural forms, contexts, and other i18next features\n *\n * Examples:\n * - 'welcome' -> 'welcome'\n * - 'items_plural' -> 'items'\n * - 'friend_male' -> 'friend'\n *\n * @param key - The translation key\n * @returns Base key without suffixes\n */\nexport function extractBaseKey(key: string): string {\n // Remove plural suffixes (_zero, _one, _two, _few, _many, _other, _plural)\n let baseKey = key.replace(/_(zero|one|two|few|many|other|plural)$/, '');\n\n // Remove context suffixes (anything after last underscore that's not a nested key)\n // Be careful not to remove underscores that are part of the actual key\n // This is a heuristic - contexts usually come at the end\n const lastUnderscore = baseKey.lastIndexOf('_');\n if (lastUnderscore > 0) {\n // Only remove if it looks like a context (short suffix, typically lowercase)\n const suffix = baseKey.substring(lastUnderscore + 1);\n if (suffix.length < 10 && suffix.toLowerCase() === suffix) {\n // This might be a context, but we'll keep it for now to avoid false positives\n // Real context handling should be done at a higher level\n }\n }\n\n return baseKey;\n}\n\n/**\n * Removes interpolation variables from a translated string\n *\n * Examples:\n * - 'Hello {{name}}!' -> 'Hello !'\n * - 'You have {{count}} items' -> 'You have items'\n *\n * @param value - The translated string\n * @returns String with interpolations removed\n */\nexport function removeInterpolation(value: string): string {\n // Remove i18next interpolation syntax: {{variable}}\n return value.replace(/\\{\\{[^}]+\\}\\}/g, '').trim();\n}\n\n/**\n * Tracks a translation in the memory map\n *\n * @param translationValue - The actual translated text\n * @param translationKey - The content ID (i18next key)\n * @param namespace - Optional namespace\n * @param language - Optional language code\n * @param debug - Enable debug logging\n */\nexport function trackTranslation(\n translationValue: string,\n translationKey: string,\n namespace?: string,\n language?: string,\n debug: boolean = false\n): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) return;\n\n // Normalize the key\n const normalizedKey = normalizeKey(translationKey, namespace);\n\n // Get or create entry\n const existingEntry = memoryMap.get(translationValue);\n const idSet = existingEntry ? existingEntry.ids : new Set<string>();\n idSet.add(normalizedKey);\n\n const entry: MemoryMapEntry = {\n ids: idSet,\n type: 'text',\n metadata: {\n namespace,\n language,\n trackedAt: Date.now(),\n },\n };\n\n memoryMap.set(translationValue, entry);\n\n if (debug) {\n console.log('[ContentStorage] Tracked translation:', {\n value: translationValue,\n key: normalizedKey,\n namespace,\n language,\n });\n }\n}\n\n/**\n * Cleans up old entries from memory map when size exceeds limit\n * Removes oldest entries first (based on trackedAt timestamp)\n *\n * @param maxSize - Maximum number of entries to keep\n */\nexport function cleanupMemoryMap(maxSize: number): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap || memoryMap.size <= maxSize) return;\n\n // Convert to array with timestamps\n const entries = Array.from(memoryMap.entries()).map(([key, value]) => ({\n key,\n value,\n timestamp: value.metadata?.trackedAt || 0,\n }));\n\n // Sort by timestamp (oldest first)\n entries.sort((a, b) => a.timestamp - b.timestamp);\n\n // Calculate how many to remove\n const toRemove = memoryMap.size - maxSize;\n\n // Remove oldest entries\n for (let i = 0; i < toRemove; i++) {\n memoryMap.delete(entries[i].key);\n }\n}\n\n/**\n * Deeply traverses a translation object and extracts all string values with their keys\n *\n * @param obj - Translation object to traverse\n * @param prefix - Current key prefix (for nested objects)\n * @returns Array of [key, value] pairs\n */\nexport function flattenTranslations(\n obj: any,\n prefix: string = ''\n): Array<[string, string]> {\n const results: Array<[string, string]> = [];\n\n for (const key in obj) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;\n\n const value = obj[key];\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === 'string') {\n results.push([fullKey, value]);\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Recurse into nested objects\n results.push(...flattenTranslations(value, fullKey));\n }\n }\n\n return results;\n}\n\n/**\n * Debug helper to log memory map contents\n */\nexport function debugMemoryMap(): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) {\n console.log('[ContentStorage] Memory map not initialized');\n return;\n }\n\n console.log('[ContentStorage] Memory map contents:');\n console.log(`Total entries: ${memoryMap.size}`);\n\n const entries = Array.from(memoryMap.entries()).slice(0, 10);\n console.table(\n entries.map(([value, entry]) => ({\n value: value.substring(0, 50),\n keys: Array.from(entry.ids).join(', '),\n namespace: entry.metadata?.namespace || 'N/A',\n }))\n );\n\n if (memoryMap.size > 10) {\n console.log(`... and ${memoryMap.size - 10} more entries`);\n }\n}\n","import type {\n BackendModule,\n ReadCallback,\n Services,\n InitOptions,\n} from 'i18next';\nimport type {\n ContentStoragePluginOptions,\n TranslationData,\n} from './types';\nimport {\n detectLiveEditorMode,\n initializeMemoryMap,\n trackTranslation,\n cleanupMemoryMap,\n flattenTranslations,\n isBrowser,\n} from './utils';\n\n/**\n * ContentStorage i18next Backend Plugin\n *\n * This plugin enables translation tracking for the ContentStorage live editor\n * by maintaining a memory map of translations and their keys.\n *\n * Features:\n * - Automatic live editor mode detection\n * - Translation tracking with memory map\n * - Support for nested translations\n * - Memory management with size limits\n * - Custom CDN or load path support\n *\n * @example\n * ```typescript\n * import i18next from 'i18next';\n * import ContentStorageBackend from '@contentstorage/i18next-plugin';\n *\n * i18next\n * .use(ContentStorageBackend)\n * .init({\n * backend: {\n * contentKey: 'your-content-key',\n * debug: true\n * }\n * });\n * ```\n */\nexport class ContentStorageBackend implements BackendModule<ContentStoragePluginOptions> {\n static type: 'backend' = 'backend';\n type: 'backend' = 'backend';\n\n private options: ContentStoragePluginOptions;\n private isLiveMode: boolean = false;\n\n constructor(_services?: Services, options?: ContentStoragePluginOptions, _i18nextOptions?: InitOptions) {\n this.options = options || {};\n\n // Initialize if services and i18nextOptions are provided\n // This allows i18next to initialize the plugin automatically\n if (_services && _i18nextOptions) {\n this.init(_services, options, _i18nextOptions);\n }\n }\n\n /**\n * Initialize the plugin\n * Called by i18next during initialization\n */\n init(\n services: Services,\n backendOptions: ContentStoragePluginOptions = {},\n i18nextOptions: InitOptions = {}\n ): void {\n // Store services and i18nextOptions for potential future use\n // Note: Currently not used but kept in signature for i18next compatibility\n void services;\n void i18nextOptions;\n\n this.options = {\n cdnBaseUrl: 'https://cdn.contentstorage.app',\n debug: false,\n maxMemoryMapSize: 10000,\n liveEditorParam: 'contentstorage_live_editor',\n forceLiveMode: false,\n ...backendOptions,\n };\n\n // Detect live editor mode\n this.isLiveMode = detectLiveEditorMode(\n this.options.liveEditorParam,\n this.options.forceLiveMode\n );\n\n if (this.isLiveMode) {\n // Initialize memory map\n initializeMemoryMap();\n\n if (this.options.debug) {\n console.log('[ContentStorage] Live editor mode enabled');\n console.log('[ContentStorage] Plugin initialized with options:', this.options);\n }\n } else if (this.options.debug) {\n console.log('[ContentStorage] Running in normal mode (not live editor)');\n }\n }\n\n /**\n * Read translations for a given language and namespace\n * This is the main method called by i18next to load translations\n */\n read(\n language: string,\n namespace: string,\n callback: ReadCallback\n ): void {\n if (this.options.debug) {\n console.log(`[ContentStorage] Loading translations: ${language}/${namespace}`);\n }\n\n this.loadTranslations(language, namespace)\n .then((translations) => {\n // Track translations if in live mode\n if (this.isLiveMode && this.shouldTrackNamespace(namespace)) {\n this.trackTranslations(translations, namespace, language);\n\n // Cleanup if needed\n if (this.options.maxMemoryMapSize) {\n cleanupMemoryMap(this.options.maxMemoryMapSize);\n }\n }\n\n callback(null, translations);\n })\n .catch((error) => {\n if (this.options.debug) {\n console.error('[ContentStorage] Failed to load translations:', error);\n }\n callback(error, false);\n });\n }\n\n /**\n * Load translations from CDN or custom source\n */\n private async loadTranslations(\n language: string,\n namespace: string\n ): Promise<TranslationData> {\n const url = this.getLoadPath(language, namespace);\n\n if (this.options.debug) {\n console.log(`[ContentStorage] Fetching from: ${url}`);\n }\n\n try {\n const fetchFn = this.options.request || this.defaultFetch.bind(this);\n return await fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n },\n });\n } catch (error) {\n if (this.options.debug) {\n console.error('[ContentStorage] Fetch error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Default fetch implementation\n */\n private async defaultFetch(url: string, options: RequestInit): Promise<any> {\n const response = await fetch(url, options);\n\n if (!response.ok) {\n throw new Error(\n `Failed to load translations: ${response.status} ${response.statusText}`\n );\n }\n\n return response.json();\n }\n\n /**\n * Get the URL to load translations from\n */\n private getLoadPath(language: string, namespace: string): string {\n const { loadPath, cdnBaseUrl, contentKey } = this.options;\n\n // Custom load path function\n if (typeof loadPath === 'function') {\n return loadPath(language, namespace);\n }\n\n // Custom load path string with interpolation\n if (typeof loadPath === 'string') {\n return loadPath\n .replace('{{lng}}', language)\n .replace('{{ns}}', namespace);\n }\n\n // Default CDN path\n if (!contentKey) {\n throw new Error(\n '[ContentStorage] contentKey is required when using default CDN path'\n );\n }\n\n return `${cdnBaseUrl}/${contentKey}/content/${language}/${namespace}.json`;\n }\n\n /**\n * Check if a namespace should be tracked\n */\n private shouldTrackNamespace(namespace: string): boolean {\n const { trackNamespaces } = this.options;\n\n // If no filter specified, track all namespaces\n if (!trackNamespaces || trackNamespaces.length === 0) {\n return true;\n }\n\n return trackNamespaces.includes(namespace);\n }\n\n /**\n * Track all translations in the loaded data\n */\n private trackTranslations(\n translations: TranslationData,\n namespace: string,\n language: string\n ): void {\n if (!isBrowser()) return;\n\n const flatTranslations = flattenTranslations(translations);\n\n for (const [key, value] of flatTranslations) {\n // Skip empty values\n if (!value) continue;\n\n trackTranslation(\n value,\n key,\n namespace,\n language,\n this.options.debug\n );\n }\n\n if (this.options.debug) {\n console.log(\n `[ContentStorage] Tracked ${flatTranslations.length} translations for ${namespace}`\n );\n }\n }\n}\n\n/**\n * Create a new instance of the ContentStorage backend\n */\nexport function createContentStorageBackend(\n options?: ContentStoragePluginOptions\n): ContentStorageBackend {\n return new ContentStorageBackend(undefined, options);\n}\n\n// Default export\nexport default ContentStorageBackend;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils.ts","../src/plugin.ts","../src/post-processor.ts"],"sourcesContent":["import type { ContentStorageWindow, MemoryMap, MemoryMapEntry } from './types';\n\n/**\n * Checks if the code is running in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Gets the ContentStorage window object with type safety\n */\nexport function getContentStorageWindow(): ContentStorageWindow | null {\n if (!isBrowser()) return null;\n return window as ContentStorageWindow;\n}\n\n/**\n * Detects if the application is running in ContentStorage live editor mode\n *\n * @param liveEditorParam - Query parameter name to check\n * @param forceLiveMode - Force live mode regardless of environment\n * @returns true if in live editor mode\n */\nexport function detectLiveEditorMode(\n liveEditorParam: string = 'contentstorage_live_editor',\n forceLiveMode: boolean = false\n): boolean {\n if (forceLiveMode) return true;\n if (!isBrowser()) return false;\n\n try {\n const win = getContentStorageWindow();\n if (!win) return false;\n\n // Check 1: Running in an iframe\n const inIframe = win.self !== win.top;\n\n // Check 2: URL has the live editor marker\n const urlParams = new URLSearchParams(win.location.search);\n const hasMarker = urlParams.has(liveEditorParam);\n\n return !!(inIframe && hasMarker);\n } catch (e) {\n // Cross-origin restrictions might block window.top access\n // This is expected when not in live editor mode\n return false;\n }\n}\n\n/**\n * Initializes the global memory map if it doesn't exist\n */\nexport function initializeMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n if (!win) return null;\n\n if (!win.memoryMap) {\n win.memoryMap = new Map<string, MemoryMapEntry>();\n }\n\n return win.memoryMap;\n}\n\n/**\n * Load the ContentStorage live editor script\n * This script enables the click-to-edit functionality in the live editor\n */\nlet liveEditorReadyPromise: Promise<boolean> | null = null;\n\nexport function loadLiveEditorScript(\n retries: number = 2,\n delay: number = 3000,\n debug: boolean = false\n): Promise<boolean> {\n // Return existing promise if already loading\n if (liveEditorReadyPromise) {\n return liveEditorReadyPromise;\n }\n\n liveEditorReadyPromise = new Promise<boolean>((resolve) => {\n const win = getContentStorageWindow();\n if (!win) {\n resolve(false);\n return;\n }\n\n const cdnScriptUrl = 'https://cdn.contentstorage.app/live-editor.js?contentstorage-live-editor=true';\n\n const loadScript = (attempt: number = 1) => {\n if (debug) {\n console.log(`[ContentStorage] Attempting to load live editor script (attempt ${attempt}/${retries})`);\n }\n\n const scriptElement = win.document.createElement('script');\n scriptElement.type = 'text/javascript';\n scriptElement.src = cdnScriptUrl;\n\n scriptElement.onload = () => {\n if (debug) {\n console.log(`[ContentStorage] Live editor script loaded successfully`);\n }\n resolve(true);\n };\n\n scriptElement.onerror = (error) => {\n // Clean up the failed script element\n scriptElement.remove();\n\n if (debug) {\n console.error(`[ContentStorage] Failed to load live editor script (attempt ${attempt}/${retries})`, error);\n }\n\n if (attempt < retries) {\n setTimeout(() => loadScript(attempt + 1), delay);\n } else {\n console.error(`[ContentStorage] All ${retries} attempts to load live editor script failed`);\n resolve(false);\n }\n };\n\n win.document.head.appendChild(scriptElement);\n };\n\n loadScript();\n });\n\n return liveEditorReadyPromise;\n}\n\n/**\n * Gets the global memory map\n */\nexport function getMemoryMap(): MemoryMap | null {\n const win = getContentStorageWindow();\n return win?.memoryMap || null;\n}\n\n/**\n * Normalizes i18next key format to consistent dot notation\n * Converts namespace:key format to namespace.key\n *\n * @param key - The translation key\n * @param namespace - Optional namespace\n * @returns Normalized key in dot notation\n */\nexport function normalizeKey(key: string, namespace?: string): string {\n let normalizedKey = key;\n\n // Convert colon notation to dot notation\n if (normalizedKey.includes(':')) {\n normalizedKey = normalizedKey.replace(':', '.');\n }\n\n // Prepend namespace if provided and not already in key\n if (namespace && !normalizedKey.startsWith(`${namespace}.`)) {\n normalizedKey = `${namespace}.${normalizedKey}`;\n }\n\n return normalizedKey;\n}\n\n/**\n * Extracts the base translation key without interpolation context\n * Handles plural forms, contexts, and other i18next features\n *\n * Examples:\n * - 'welcome' -> 'welcome'\n * - 'items_plural' -> 'items'\n * - 'friend_male' -> 'friend'\n *\n * @param key - The translation key\n * @returns Base key without suffixes\n */\nexport function extractBaseKey(key: string): string {\n // Remove plural suffixes (_zero, _one, _two, _few, _many, _other, _plural)\n let baseKey = key.replace(/_(zero|one|two|few|many|other|plural)$/, '');\n\n // Remove context suffixes (anything after last underscore that's not a nested key)\n // Be careful not to remove underscores that are part of the actual key\n // This is a heuristic - contexts usually come at the end\n const lastUnderscore = baseKey.lastIndexOf('_');\n if (lastUnderscore > 0) {\n // Only remove if it looks like a context (short suffix, typically lowercase)\n const suffix = baseKey.substring(lastUnderscore + 1);\n if (suffix.length < 10 && suffix.toLowerCase() === suffix) {\n // This might be a context, but we'll keep it for now to avoid false positives\n // Real context handling should be done at a higher level\n }\n }\n\n return baseKey;\n}\n\n/**\n * Removes interpolation variables from a translated string\n *\n * Examples:\n * - 'Hello {{name}}!' -> 'Hello !'\n * - 'You have {{count}} items' -> 'You have items'\n *\n * @param value - The translated string\n * @returns String with interpolations removed\n */\nexport function removeInterpolation(value: string): string {\n // Remove i18next interpolation syntax: {{variable}}\n return value.replace(/\\{\\{[^}]+\\}\\}/g, '').trim();\n}\n\n/**\n * Tracks a translation in the memory map\n *\n * @param translationValue - The actual translated text\n * @param translationKey - The content ID (i18next key)\n * @param namespace - Optional namespace\n * @param language - Optional language code\n * @param debug - Enable debug logging\n */\nexport function trackTranslation(\n translationValue: string,\n translationKey: string,\n namespace?: string,\n language?: string,\n debug: boolean = false\n): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) return;\n\n // Normalize the key\n const normalizedKey = normalizeKey(translationKey, namespace);\n\n // Get or create entry\n const existingEntry = memoryMap.get(translationValue);\n const idSet = existingEntry ? existingEntry.ids : new Set<string>();\n idSet.add(normalizedKey);\n\n const entry: MemoryMapEntry = {\n ids: idSet,\n type: 'text',\n metadata: {\n namespace,\n language,\n trackedAt: Date.now(),\n },\n };\n\n memoryMap.set(translationValue, entry);\n\n if (debug) {\n console.log('[ContentStorage] Tracked translation:', {\n value: translationValue,\n key: normalizedKey,\n namespace,\n language,\n });\n }\n}\n\n/**\n * Cleans up old entries from memory map when size exceeds limit\n * Removes oldest entries first (based on trackedAt timestamp)\n *\n * @param maxSize - Maximum number of entries to keep\n */\nexport function cleanupMemoryMap(maxSize: number): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap || memoryMap.size <= maxSize) return;\n\n // Convert to array with timestamps\n const entries = Array.from(memoryMap.entries()).map(([key, value]) => ({\n key,\n value,\n timestamp: value.metadata?.trackedAt || 0,\n }));\n\n // Sort by timestamp (oldest first)\n entries.sort((a, b) => a.timestamp - b.timestamp);\n\n // Calculate how many to remove\n const toRemove = memoryMap.size - maxSize;\n\n // Remove oldest entries\n for (let i = 0; i < toRemove; i++) {\n memoryMap.delete(entries[i].key);\n }\n}\n\n/**\n * Deeply traverses a translation object and extracts all string values with their keys\n *\n * @param obj - Translation object to traverse\n * @param prefix - Current key prefix (for nested objects)\n * @returns Array of [key, value] pairs\n */\nexport function flattenTranslations(\n obj: any,\n prefix: string = ''\n): Array<[string, string]> {\n const results: Array<[string, string]> = [];\n\n for (const key in obj) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;\n\n const value = obj[key];\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === 'string') {\n results.push([fullKey, value]);\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Recurse into nested objects\n results.push(...flattenTranslations(value, fullKey));\n }\n }\n\n return results;\n}\n\n/**\n * Debug helper to log memory map contents\n */\nexport function debugMemoryMap(): void {\n const memoryMap = getMemoryMap();\n if (!memoryMap) {\n console.log('[ContentStorage] Memory map not initialized');\n return;\n }\n\n console.log('[ContentStorage] Memory map contents:');\n console.log(`Total entries: ${memoryMap.size}`);\n\n const entries = Array.from(memoryMap.entries()).slice(0, 10);\n console.table(\n entries.map(([value, entry]) => ({\n value: value.substring(0, 50),\n keys: Array.from(entry.ids).join(', '),\n namespace: entry.metadata?.namespace || 'N/A',\n }))\n );\n\n if (memoryMap.size > 10) {\n console.log(`... and ${memoryMap.size - 10} more entries`);\n }\n}\n","import type {\n BackendModule,\n ReadCallback,\n Services,\n InitOptions,\n} from 'i18next';\nimport type {\n ContentStoragePluginOptions,\n TranslationData,\n} from './types';\nimport {\n detectLiveEditorMode,\n initializeMemoryMap,\n trackTranslation,\n cleanupMemoryMap,\n flattenTranslations,\n isBrowser,\n loadLiveEditorScript,\n} from './utils';\n\n/**\n * ContentStorage i18next Backend Plugin\n *\n * This plugin enables translation tracking for the ContentStorage live editor\n * by maintaining a memory map of translations and their keys.\n *\n * Features:\n * - Automatic live editor mode detection\n * - Translation tracking with memory map\n * - Support for nested translations\n * - Memory management with size limits\n * - Custom CDN or load path support\n *\n * @example\n * ```typescript\n * import i18next from 'i18next';\n * import ContentStorageBackend from '@contentstorage/i18next-plugin';\n *\n * i18next\n * .use(ContentStorageBackend)\n * .init({\n * backend: {\n * contentKey: 'your-content-key',\n * debug: true\n * }\n * });\n * ```\n */\nexport class ContentStorageBackend implements BackendModule<ContentStoragePluginOptions> {\n static type: 'backend' = 'backend';\n type: 'backend' = 'backend';\n\n private options: ContentStoragePluginOptions;\n private isLiveMode: boolean = false;\n\n constructor(_services?: Services, options?: ContentStoragePluginOptions, _i18nextOptions?: InitOptions) {\n this.options = options || {};\n\n // Initialize if services and i18nextOptions are provided\n // This allows i18next to initialize the plugin automatically\n if (_services && _i18nextOptions) {\n this.init(_services, options, _i18nextOptions);\n }\n }\n\n /**\n * Initialize the plugin\n * Called by i18next during initialization\n */\n init(\n services: Services,\n backendOptions: ContentStoragePluginOptions = {},\n i18nextOptions: InitOptions = {}\n ): void {\n // Store services and i18nextOptions for potential future use\n // Note: Currently not used but kept in signature for i18next compatibility\n void services;\n void i18nextOptions;\n\n this.options = {\n debug: false,\n maxMemoryMapSize: 10000,\n liveEditorParam: 'contentstorage_live_editor',\n forceLiveMode: false,\n ...backendOptions,\n };\n\n // Detect live editor mode\n this.isLiveMode = detectLiveEditorMode(\n this.options.liveEditorParam,\n this.options.forceLiveMode\n );\n\n if (this.isLiveMode) {\n // Initialize memory map\n initializeMemoryMap();\n\n // Load the live editor script\n loadLiveEditorScript(2, 3000, this.options.debug).then((loaded) => {\n if (loaded) {\n if (this.options.debug) {\n console.log('[ContentStorage] Live editor ready');\n }\n } else {\n console.warn('[ContentStorage] Failed to load live editor script');\n }\n });\n\n if (this.options.debug) {\n console.log('[ContentStorage] Live editor mode enabled');\n console.log('[ContentStorage] Plugin initialized with options:', this.options);\n }\n } else if (this.options.debug) {\n console.log('[ContentStorage] Running in normal mode (not live editor)');\n }\n }\n\n /**\n * Read translations for a given language and namespace\n * This is the main method called by i18next to load translations\n */\n read(\n language: string,\n namespace: string,\n callback: ReadCallback\n ): void {\n if (this.options.debug) {\n console.log(`[ContentStorage] Loading translations: ${language}/${namespace}`);\n }\n\n this.loadTranslations(language, namespace)\n .then((translations) => {\n // Track translations if in live mode\n if (this.isLiveMode && this.shouldTrackNamespace(namespace)) {\n this.trackTranslations(translations, namespace, language);\n\n // Cleanup if needed\n if (this.options.maxMemoryMapSize) {\n cleanupMemoryMap(this.options.maxMemoryMapSize);\n }\n }\n\n callback(null, translations);\n })\n .catch((error) => {\n if (this.options.debug) {\n console.error('[ContentStorage] Failed to load translations:', error);\n }\n callback(error, false);\n });\n }\n\n /**\n * Load translations from CDN or custom source\n */\n private async loadTranslations(\n language: string,\n namespace: string\n ): Promise<TranslationData> {\n const url = this.getLoadPath(language, namespace);\n\n if (this.options.debug) {\n console.log(`[ContentStorage] Fetching from: ${url}`);\n }\n\n try {\n const fetchFn = this.options.request || this.defaultFetch.bind(this);\n return await fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'application/json',\n },\n });\n } catch (error) {\n if (this.options.debug) {\n console.error('[ContentStorage] Fetch error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Default fetch implementation\n */\n private async defaultFetch(url: string, options: RequestInit): Promise<any> {\n const response = await fetch(url, options);\n\n if (!response.ok) {\n throw new Error(\n `Failed to load translations: ${response.status} ${response.statusText}`\n );\n }\n\n return response.json();\n }\n\n /**\n * Get the URL to load translations from\n */\n private getLoadPath(language: string, namespace: string): string {\n const { loadPath, contentKey } = this.options;\n\n // Custom load path function\n if (typeof loadPath === 'function') {\n return loadPath(language, namespace);\n }\n\n // Custom load path string with interpolation\n if (typeof loadPath === 'string') {\n return loadPath\n .replace('{{lng}}', language)\n .replace('{{ns}}', namespace);\n }\n\n // Default CDN path\n if (!contentKey) {\n throw new Error(\n '[ContentStorage] contentKey is required when using default CDN path'\n );\n }\n\n // Default: Always use uppercase language code\n const lng = language.toUpperCase();\n\n // Default: https://cdn.contentstorage.app/{contentKey}/content/{LNG}.json\n return `https://cdn.contentstorage.app/${contentKey}/content/${lng}.json`;\n }\n\n /**\n * Check if a namespace should be tracked\n */\n private shouldTrackNamespace(namespace: string): boolean {\n const { trackNamespaces } = this.options;\n\n // If no filter specified, track all namespaces\n if (!trackNamespaces || trackNamespaces.length === 0) {\n return true;\n }\n\n return trackNamespaces.includes(namespace);\n }\n\n /**\n * Track all translations in the loaded data\n */\n private trackTranslations(\n translations: TranslationData,\n namespace: string,\n language: string\n ): void {\n if (!isBrowser()) return;\n\n const flatTranslations = flattenTranslations(translations);\n\n for (const [key, value] of flatTranslations) {\n // Skip empty values\n if (!value) continue;\n\n trackTranslation(\n value,\n key,\n namespace,\n language,\n this.options.debug\n );\n }\n\n if (this.options.debug) {\n console.log(\n `[ContentStorage] Tracked ${flatTranslations.length} translations for ${namespace}`\n );\n }\n }\n}\n\n/**\n * Create a new instance of the ContentStorage backend\n */\nexport function createContentStorageBackend(\n options?: ContentStoragePluginOptions\n): ContentStorageBackend {\n return new ContentStorageBackend(undefined, options);\n}\n\n// Default export\nexport default ContentStorageBackend;\n","import type { PostProcessorModule } from 'i18next';\nimport type { ContentStoragePluginOptions } from './types';\nimport { trackTranslation, detectLiveEditorMode, initializeMemoryMap, loadLiveEditorScript } from './utils';\n\n/**\n * ContentStorage Post-Processor\n *\n * This post-processor tracks translations at the point of resolution,\n * capturing the actual values returned by i18next including interpolations\n * and plural forms.\n *\n * Use this in addition to or instead of the backend plugin for more\n * comprehensive tracking, especially for dynamic translations.\n *\n * @example\n * ```typescript\n * import i18next from 'i18next';\n * import { ContentStoragePostProcessor } from '@contentstorage/i18next-plugin';\n *\n * i18next\n * .use(new ContentStoragePostProcessor({ debug: true }))\n * .init({\n * // ... your config\n * });\n * ```\n */\nexport class ContentStoragePostProcessor implements PostProcessorModule {\n static type: 'postProcessor' = 'postProcessor';\n type: 'postProcessor' = 'postProcessor';\n name: string = 'contentStorageTracker';\n\n private options: ContentStoragePluginOptions;\n private isLiveMode: boolean = false;\n\n constructor(options: ContentStoragePluginOptions = {}) {\n this.options = {\n debug: false,\n liveEditorParam: 'contentstorage_live_editor',\n forceLiveMode: false,\n ...options,\n };\n\n // Detect live editor mode\n this.isLiveMode = detectLiveEditorMode(\n this.options.liveEditorParam,\n this.options.forceLiveMode\n );\n\n if (this.isLiveMode) {\n initializeMemoryMap();\n\n // Load the live editor script\n loadLiveEditorScript(2, 3000, this.options.debug);\n\n if (this.options.debug) {\n console.log('[ContentStorage] Post-processor initialized in live mode');\n }\n }\n }\n\n /**\n * Process the translated value\n * Called by i18next after translation resolution\n */\n process(\n value: string,\n key: string | string[],\n options: any,\n translator: any\n ): string {\n // Only track in live mode\n if (!this.isLiveMode) {\n return value;\n }\n\n // Handle array of keys (fallback keys)\n const translationKey = Array.isArray(key) ? key[0] : key;\n\n // Extract namespace from options or key\n let namespace: string | undefined;\n if (options?.ns) {\n namespace = Array.isArray(options.ns) ? options.ns[0] : options.ns;\n } else if (translationKey.includes(':')) {\n [namespace] = translationKey.split(':');\n }\n\n // Extract language\n const language = options?.lng || translator?.language;\n\n // Track the translation\n trackTranslation(\n value,\n translationKey,\n namespace,\n language,\n this.options.debug\n );\n\n return value;\n }\n}\n\n/**\n * Create a new instance of the ContentStorage post-processor\n */\nexport function createContentStoragePostProcessor(\n options?: ContentStoragePluginOptions\n): ContentStoragePostProcessor {\n return new ContentStoragePostProcessor(options);\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,WAAW,EACZ,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,SAAS,CAAC;AAUjB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,qBAAsB,YAAW,aAAa,CAAC,2BAA2B,CAAC;IACtF,MAAM,CAAC,IAAI,EAAE,SAAS,CAAa;IACnC,IAAI,EAAE,SAAS,CAAa;IAE5B,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,UAAU,CAAkB;gBAExB,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,2BAA2B,EAAE,eAAe,CAAC,EAAE,WAAW;IAUtG;;;OAGG;IACH,IAAI,CACF,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE,2BAAgC,EAChD,cAAc,GAAE,WAAgB,GAC/B,IAAI;IAkCP;;;OAGG;IACH,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,YAAY,GACrB,IAAI;IA2BP;;OAEG;YACW,gBAAgB;IA0B9B;;OAEG;YACW,YAAY;IAY1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAyBnB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CA4B1B;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,CAAC,EAAE,2BAA2B,GACpC,qBAAqB,CAEvB;AAGD,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,WAAW,EACZ,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,SAAS,CAAC;AAWjB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,qBAAsB,YAAW,aAAa,CAAC,2BAA2B,CAAC;IACtF,MAAM,CAAC,IAAI,EAAE,SAAS,CAAa;IACnC,IAAI,EAAE,SAAS,CAAa;IAE5B,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,UAAU,CAAkB;gBAExB,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,2BAA2B,EAAE,eAAe,CAAC,EAAE,WAAW;IAUtG;;;OAGG;IACH,IAAI,CACF,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE,2BAAgC,EAChD,cAAc,GAAE,WAAgB,GAC/B,IAAI;IA4CP;;;OAGG;IACH,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,YAAY,GACrB,IAAI;IA2BP;;OAEG;YACW,gBAAgB;IA0B9B;;OAEG;YACW,YAAY;IAY1B;;OAEG;IACH,OAAO,CAAC,WAAW;IA6BnB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CA4B1B;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,CAAC,EAAE,2BAA2B,GACpC,qBAAqB,CAEvB;AAGD,eAAe,qBAAqB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"post-processor.d.ts","sourceRoot":"","sources":["../src/post-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAG3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,2BAA4B,YAAW,mBAAmB;IACrE,MAAM,CAAC,IAAI,EAAE,eAAe,CAAmB;IAC/C,IAAI,EAAE,eAAe,CAAmB;IACxC,IAAI,EAAE,MAAM,CAA2B;IAEvC,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,UAAU,CAAkB;gBAExB,OAAO,GAAE,2BAAgC;IAuBrD;;;OAGG;IACH,OAAO,CACL,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,EACtB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,GAAG,GACd,MAAM;CA+BV;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,CAAC,EAAE,2BAA2B,GACpC,2BAA2B,CAE7B"}
1
+ {"version":3,"file":"post-processor.d.ts","sourceRoot":"","sources":["../src/post-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAG3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,2BAA4B,YAAW,mBAAmB;IACrE,MAAM,CAAC,IAAI,EAAE,eAAe,CAAmB;IAC/C,IAAI,EAAE,eAAe,CAAmB;IACxC,IAAI,EAAE,MAAM,CAA2B;IAEvC,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,UAAU,CAAkB;gBAExB,OAAO,GAAE,2BAAgC;IA0BrD;;;OAGG;IACH,OAAO,CACL,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,EACtB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,GAAG,GACd,MAAM;CA+BV;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,CAAC,EAAE,2BAA2B,GACpC,2BAA2B,CAE7B"}
package/dist/types.d.ts CHANGED
@@ -35,13 +35,9 @@ export interface ContentStoragePluginOptions {
35
35
  /**
36
36
  * Your ContentStorage content key
37
37
  * Used to construct CDN URLs for fetching translations
38
+ * Default URL format: https://cdn.contentstorage.app/{contentKey}/content/{LNG}.json
38
39
  */
39
40
  contentKey?: string;
40
- /**
41
- * Custom CDN base URL
42
- * @default 'https://cdn.contentstorage.app'
43
- */
44
- cdnBaseUrl?: string;
45
41
  /**
46
42
  * Enable debug logging
47
43
  * @default false
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,QAAQ,CAAC,EAAE;QACT,iDAAiD;QACjD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,oBAAoB;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,6BAA6B;QAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,MAAM;IAClD,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAEtE;;;OAGG;IACH,OAAO,CAAC,EAAE,CACR,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,GAAG,CAAC,CAAC;IAElB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC;CACzC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EAAE,KAAK,GAAG,IAAI,EACnB,IAAI,EAAE,eAAe,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,KAC/C,IAAI,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,QAAQ,CAAC,EAAE;QACT,iDAAiD;QACjD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,oBAAoB;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,6BAA6B;QAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,MAAM;IAClD,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAEtE;;;OAGG;IACH,OAAO,CAAC,EAAE,CACR,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,GAAG,CAAC,CAAC;IAElB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC;CACzC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EAAE,KAAK,GAAG,IAAI,EACnB,IAAI,EAAE,eAAe,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,KAC/C,IAAI,CAAC"}
package/dist/utils.d.ts CHANGED
@@ -19,6 +19,7 @@ export declare function detectLiveEditorMode(liveEditorParam?: string, forceLive
19
19
  * Initializes the global memory map if it doesn't exist
20
20
  */
21
21
  export declare function initializeMemoryMap(): MemoryMap | null;
22
+ export declare function loadLiveEditorScript(retries?: number, delay?: number, debug?: boolean): Promise<boolean>;
22
23
  /**
23
24
  * Gets the global memory map
24
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAkB,MAAM,SAAS,CAAC;AAE/E;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,IAAI,CAGrE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,GAAE,MAAqC,EACtD,aAAa,GAAE,OAAe,GAC7B,OAAO,CAqBT;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,GAAG,IAAI,CAStD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAG/C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAcpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkBlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,GAAE,OAAe,GACrB,IAAI,CAgCN;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAqBtD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,GAAG,EACR,MAAM,GAAE,MAAW,GAClB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkBzB;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAsBrC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAkB,MAAM,SAAS,CAAC;AAE/E;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,IAAI,CAGrE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,GAAE,MAAqC,EACtD,aAAa,GAAE,OAAe,GAC7B,OAAO,CAqBT;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,GAAG,IAAI,CAStD;AAQD,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,MAAU,EACnB,KAAK,GAAE,MAAa,EACpB,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,CAAC,CAsDlB;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAG/C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAcpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkBlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,GAAE,OAAe,GACrB,IAAI,CAgCN;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAqBtD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,GAAG,EACR,MAAM,GAAE,MAAW,GAClB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkBzB;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAsBrC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentstorage/i18next-plugin",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "i18next plugin for Contentstorage live editor translation tracking",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -48,6 +48,6 @@
48
48
  },
49
49
  "repository": {
50
50
  "type": "git",
51
- "url": "https://github.com/contentstorage/i18next-plugin.git"
51
+ "url": "git+https://github.com/contentstorage/i18next-plugin.git"
52
52
  }
53
53
  }