@lovalingo/lovalingo 0.5.12 → 0.5.13

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.
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useRef } from "react";
2
- import { addActiveTranslations, applyActiveTranslations, clearMissBlur, scanDomForMisses } from "../../utils/markerEngine";
2
+ import { addActiveTranslations, applyActiveTranslations, scanDomForMisses } from "../../utils/markerEngine";
3
3
  import { logDebug } from "../../utils/logger";
4
4
  import { isNonLocalizedPath, stripLocalePrefix } from "../../utils/nonLocalizedPaths";
5
5
  // Why: throttle miss scans so we stay responsive on DOM-heavy pages.
@@ -9,33 +9,11 @@ const MISS_MAX_PER_PAGE = 500;
9
9
  export function useStringMissReporting(args) {
10
10
  const pendingRef = useRef(new Set());
11
11
  const seenRef = useRef(new Set());
12
- const blurredRef = useRef(new Map());
13
12
  const scheduledRef = useRef(null);
14
13
  const inFlightRef = useRef(false);
15
- const mergeBlurred = useCallback((incoming) => {
16
- for (const [text, elements] of incoming.entries()) {
17
- let set = blurredRef.current.get(text);
18
- if (!set) {
19
- set = new Set();
20
- blurredRef.current.set(text, set);
21
- }
22
- elements.forEach((el) => set.add(el));
23
- }
24
- }, []);
25
- const clearBlurForText = useCallback((text) => {
26
- const elements = blurredRef.current.get(text);
27
- if (!elements)
28
- return;
29
- clearMissBlur(elements);
30
- blurredRef.current.delete(text);
31
- }, []);
32
14
  useEffect(() => {
33
15
  pendingRef.current.clear();
34
16
  seenRef.current.clear();
35
- for (const elements of blurredRef.current.values()) {
36
- clearMissBlur(elements);
37
- }
38
- blurredRef.current.clear();
39
17
  }, [args.locale]);
40
18
  const shouldSkip = useCallback(() => {
41
19
  if (typeof window === "undefined" || typeof document === "undefined")
@@ -62,11 +40,10 @@ export function useStringMissReporting(args) {
62
40
  if (inFlightRef.current)
63
41
  return;
64
42
  const ignore = new Set([...pendingRef.current, ...seenRef.current]);
65
- const { misses, blurred } = scanDomForMisses({ max: MISS_MAX_PER_PAGE, ignore, blur: true });
43
+ const { misses } = scanDomForMisses({ max: MISS_MAX_PER_PAGE, ignore });
66
44
  if (misses.length === 0)
67
45
  return;
68
46
  logDebug(`[Lovalingo] Live misses detected: ${misses.length}`);
69
- mergeBlurred(blurred);
70
47
  misses.forEach((miss) => pendingRef.current.add(miss.source_text));
71
48
  inFlightRef.current = true;
72
49
  try {
@@ -77,7 +54,6 @@ export function useStringMissReporting(args) {
77
54
  if (response?.ignored) {
78
55
  for (const miss of misses) {
79
56
  pendingRef.current.delete(miss.source_text);
80
- clearBlurForText(miss.source_text);
81
57
  seenRef.current.add(miss.source_text);
82
58
  }
83
59
  return;
@@ -107,7 +83,6 @@ export function useStringMissReporting(args) {
107
83
  }
108
84
  for (const miss of misses) {
109
85
  pendingRef.current.delete(miss.source_text);
110
- clearBlurForText(miss.source_text);
111
86
  if (resolved.has(miss.source_text)) {
112
87
  seenRef.current.add(miss.source_text);
113
88
  }
@@ -116,13 +91,12 @@ export function useStringMissReporting(args) {
116
91
  catch {
117
92
  for (const miss of misses) {
118
93
  pendingRef.current.delete(miss.source_text);
119
- clearBlurForText(miss.source_text);
120
94
  }
121
95
  }
122
96
  finally {
123
97
  inFlightRef.current = false;
124
98
  }
125
- }, [args.apiRef, args.defaultLocale, args.locale, clearBlurForText, mergeBlurred, shouldSkip]);
99
+ }, [args.apiRef, args.defaultLocale, args.locale, shouldSkip]);
126
100
  const scheduleScan = useCallback(() => {
127
101
  if (scheduledRef.current != null)
128
102
  return;
@@ -45,7 +45,6 @@ export type DomMiss = {
45
45
  };
46
46
  export type DomMissScanResult = {
47
47
  misses: DomMiss[];
48
- blurred: Map<string, Set<HTMLElement>>;
49
48
  };
50
49
  export type CriticalFingerprint = {
51
50
  critical_count: number;
@@ -63,11 +62,9 @@ export declare function setMarkerEngineExclusions(exclusions: Exclusion[] | null
63
62
  export declare function setActiveTranslations(translations: Translation[] | null): void;
64
63
  export declare function addActiveTranslations(translations: Translation[] | Record<string, string> | null): number;
65
64
  export declare function applyActiveTranslations(root?: ParentNode | null): number;
66
- export declare function clearMissBlur(elements: Iterable<HTMLElement>): void;
67
65
  export declare function scanDomForMisses(opts: {
68
66
  max: number;
69
67
  ignore?: Set<string>;
70
- blur?: boolean;
71
68
  }): DomMissScanResult;
72
69
  export declare function restoreDom(root?: ParentNode | null): void;
73
70
  export {};
@@ -10,8 +10,6 @@ const ATTRIBUTE_MARKS = [
10
10
  { attr: "aria-label", marker: "data-lovalingo-aria-label-original" },
11
11
  { attr: "placeholder", marker: "data-lovalingo-placeholder-original" },
12
12
  ];
13
- const MISS_BLUR_ATTR = "data-lovalingo-miss-blur";
14
- const MISS_BLUR_STYLE_ID = "lovalingo-miss-blur-style";
15
13
  const unsafeSelector = Array.from(UNSAFE_CONTAINER_TAGS).join(",");
16
14
  let observer = null;
17
15
  let scheduled = null;
@@ -203,31 +201,6 @@ function getOrInitAttrOriginal(el, attr) {
203
201
  map.set(attr, value);
204
202
  return value;
205
203
  }
206
- // Why: avoid blurring large containers; keep the effect scoped to leaf text nodes.
207
- function shouldBlurElement(el) {
208
- if (!el)
209
- return false;
210
- if (el.tagName === "HTML" || el.tagName === "BODY")
211
- return false;
212
- if (el.childElementCount > 0)
213
- return false;
214
- return true;
215
- }
216
- function ensureMissBlurStyles() {
217
- if (typeof document === "undefined")
218
- return;
219
- if (document.getElementById(MISS_BLUR_STYLE_ID))
220
- return;
221
- const style = document.createElement("style");
222
- style.id = MISS_BLUR_STYLE_ID;
223
- style.textContent =
224
- `[${MISS_BLUR_ATTR}="1"] {` +
225
- "filter: blur(2px);" +
226
- "transition: filter 0.18s ease-out;" +
227
- "will-change: filter;" +
228
- "}";
229
- document.head.appendChild(style);
230
- }
231
204
  function isInViewport(rect, viewportHeight, bufferPx) {
232
205
  if (!rect)
233
206
  return false;
@@ -732,33 +705,21 @@ export function applyActiveTranslations(root = document.body) {
732
705
  }
733
706
  return applied;
734
707
  }
735
- export function clearMissBlur(elements) {
736
- for (const el of elements) {
737
- if (!el)
738
- continue;
739
- if (el.getAttribute(MISS_BLUR_ATTR) !== "1")
740
- continue;
741
- el.removeAttribute(MISS_BLUR_ATTR);
742
- }
743
- }
744
708
  export function scanDomForMisses(opts) {
745
709
  const root = document.body;
746
710
  const misses = [];
747
- const blurred = new Map();
748
711
  if (!root) {
749
- return { misses, blurred };
712
+ return { misses };
750
713
  }
751
714
  // Why: allow live miss scans even when bundles are empty so first-time pages still report.
752
715
  const translationMap = activeTranslationMap;
753
716
  const hasTranslations = Boolean(translationMap && translationMap.size > 0);
754
717
  const max = Math.max(0, Math.floor(opts.max || 0));
755
718
  if (max <= 0)
756
- return { misses, blurred };
757
- if (opts.blur)
758
- ensureMissBlurStyles();
719
+ return { misses };
759
720
  const ignore = opts.ignore || new Set();
760
721
  const seen = new Set();
761
- const recordMiss = (text, context, el) => {
722
+ const recordMiss = (text, context) => {
762
723
  if (!text || seen.has(text) || ignore.has(text))
763
724
  return;
764
725
  if (hasTranslations && translationMap.has(text))
@@ -767,15 +728,6 @@ export function scanDomForMisses(opts) {
767
728
  return;
768
729
  seen.add(text);
769
730
  misses.push({ source_text: text, semantic_context: context });
770
- if (opts.blur && el instanceof HTMLElement && shouldBlurElement(el)) {
771
- el.setAttribute(MISS_BLUR_ATTR, "1");
772
- let set = blurred.get(text);
773
- if (!set) {
774
- set = new Set();
775
- blurred.set(text, set);
776
- }
777
- set.add(el);
778
- }
779
731
  };
780
732
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
781
733
  let node = walker.nextNode();
@@ -799,7 +751,7 @@ export function scanDomForMisses(opts) {
799
751
  const original = getOrInitTextOriginal(textNode, parent);
800
752
  const key = normalizeWhitespace(original.trimmed);
801
753
  if (key) {
802
- recordMiss(key, "text", parent);
754
+ recordMiss(key, "text");
803
755
  }
804
756
  node = walker.nextNode();
805
757
  }
@@ -827,7 +779,7 @@ export function scanDomForMisses(opts) {
827
779
  }
828
780
  });
829
781
  }
830
- return { misses, blurred };
782
+ return { misses };
831
783
  }
832
784
  export function restoreDom(root = document.body) {
833
785
  if (!root)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovalingo/lovalingo",
3
- "version": "0.5.12",
3
+ "version": "0.5.13",
4
4
  "description": "React translation runtime with i18n routing, deterministic bundles + DOM rules, and zero-flash rendering.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",