@lovalingo/lovalingo 0.5.25 → 0.5.28
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/__tests__/languageFlags.test.d.ts +1 -0
- package/dist/__tests__/languageFlags.test.js +42 -0
- package/dist/__tests__/mergeEntitlements.test.d.ts +1 -0
- package/dist/__tests__/mergeEntitlements.test.js +27 -0
- package/dist/components/LanguageSwitcher.js +80 -53
- package/dist/components/LovalingoProvider.js +18 -473
- package/dist/components/provider/__tests__/seoUtils.test.d.ts +1 -0
- package/dist/components/provider/__tests__/seoUtils.test.js +13 -0
- package/dist/components/provider/editModeUtils.d.ts +6 -0
- package/dist/components/provider/editModeUtils.js +59 -0
- package/dist/components/provider/localeUtils.d.ts +8 -0
- package/dist/components/provider/localeUtils.js +46 -0
- package/dist/components/provider/providerConstants.d.ts +12 -0
- package/dist/components/provider/providerConstants.js +11 -0
- package/dist/components/provider/seoUtils.d.ts +8 -0
- package/dist/components/provider/seoUtils.js +118 -0
- package/dist/components/provider/useEditModeOverlay.d.ts +7 -0
- package/dist/components/provider/useEditModeOverlay.js +134 -0
- package/dist/components/provider/useHistoryNavigationPatch.d.ts +3 -0
- package/dist/components/provider/useHistoryNavigationPatch.js +47 -0
- package/dist/components/provider/useProviderCache.d.ts +12 -0
- package/dist/components/provider/useProviderCache.js +82 -0
- package/dist/hooks/provider/useBundleLoading.d.ts +2 -1
- package/dist/hooks/provider/useBundleLoading.js +15 -3
- package/dist/utils/api.d.ts +3 -78
- package/dist/utils/api.js +1 -53
- package/dist/utils/apiTypes.d.ts +78 -0
- package/dist/utils/apiTypes.js +1 -0
- package/dist/utils/apiUtils.d.ts +4 -0
- package/dist/utils/apiUtils.js +54 -0
- package/dist/utils/languageFlags.d.ts +7 -0
- package/dist/utils/languageFlags.js +90 -0
- package/dist/utils/markerEngine.d.ts +8 -66
- package/dist/utils/markerEngine.js +19 -703
- package/dist/utils/markerEngineApply.d.ts +3 -0
- package/dist/utils/markerEngineApply.js +136 -0
- package/dist/utils/markerEngineConstants.d.ts +10 -0
- package/dist/utils/markerEngineConstants.js +12 -0
- package/dist/utils/markerEngineCritical.d.ts +2 -0
- package/dist/utils/markerEngineCritical.js +98 -0
- package/dist/utils/markerEngineDomUtils.d.ts +8 -0
- package/dist/utils/markerEngineDomUtils.js +74 -0
- package/dist/utils/markerEngineFilters.d.ts +2 -0
- package/dist/utils/markerEngineFilters.js +26 -0
- package/dist/utils/markerEngineMisses.d.ts +5 -0
- package/dist/utils/markerEngineMisses.js +81 -0
- package/dist/utils/markerEngineOriginals.d.ts +5 -0
- package/dist/utils/markerEngineOriginals.js +29 -0
- package/dist/utils/markerEngineScan.d.ts +5 -0
- package/dist/utils/markerEngineScan.js +162 -0
- package/dist/utils/markerEngineState.d.ts +4 -0
- package/dist/utils/markerEngineState.js +14 -0
- package/dist/utils/markerEngineStats.d.ts +3 -0
- package/dist/utils/markerEngineStats.js +28 -0
- package/dist/utils/markerEngineTranslations.d.ts +3 -0
- package/dist/utils/markerEngineTranslations.js +49 -0
- package/dist/utils/markerEngineTypes.d.ts +62 -0
- package/dist/utils/markerEngineTypes.js +1 -0
- package/dist/utils/markerEngineViewport.d.ts +2 -0
- package/dist/utils/markerEngineViewport.js +27 -0
- package/dist/utils/mergeEntitlements.d.ts +2 -0
- package/dist/utils/mergeEntitlements.js +7 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/utils/translator.d.ts +0 -80
- package/dist/utils/translator.js +0 -802
package/dist/utils/api.js
CHANGED
|
@@ -1,57 +1,5 @@
|
|
|
1
|
+
import { getNavigationResponseStatus, isOkHttpStatus, looksLikeNotFoundDocument, normalizeApiBase } from './apiUtils';
|
|
1
2
|
import { warnDebug, errorDebug } from './logger';
|
|
2
|
-
const OK_HTTP_STATUSES = new Set([200, 201]);
|
|
3
|
-
const NOT_FOUND_TITLE_HINTS = /404|not found|page not found|page missing|does not exist|error 404/i;
|
|
4
|
-
function getNavigationResponseStatus() {
|
|
5
|
-
if (typeof performance === "undefined" || typeof performance.getEntriesByType !== "function")
|
|
6
|
-
return null;
|
|
7
|
-
const entries = performance.getEntriesByType("navigation");
|
|
8
|
-
if (!entries || entries.length === 0)
|
|
9
|
-
return null;
|
|
10
|
-
const entry = entries[0];
|
|
11
|
-
const rawStatus = entry?.responseStatus;
|
|
12
|
-
const status = typeof rawStatus === "number" ? Math.floor(rawStatus) : NaN;
|
|
13
|
-
if (!Number.isFinite(status) || status <= 0)
|
|
14
|
-
return null;
|
|
15
|
-
return status;
|
|
16
|
-
}
|
|
17
|
-
// Why: avoid tracking misses/pageviews for non-OK responses (404/5xx) so bad routes don't pollute discovery.
|
|
18
|
-
function isOkHttpStatus(status) {
|
|
19
|
-
if (typeof status !== "number")
|
|
20
|
-
return true;
|
|
21
|
-
return OK_HTTP_STATUSES.has(status);
|
|
22
|
-
}
|
|
23
|
-
function looksLikeNotFoundDocument() {
|
|
24
|
-
if (typeof document === "undefined")
|
|
25
|
-
return false;
|
|
26
|
-
const title = (document.title || "").toString().trim().toLowerCase();
|
|
27
|
-
if (title && NOT_FOUND_TITLE_HINTS.test(title))
|
|
28
|
-
return true;
|
|
29
|
-
const bodyText = (document.body?.textContent || "").toString().slice(0, 2000).toLowerCase();
|
|
30
|
-
if (!bodyText)
|
|
31
|
-
return false;
|
|
32
|
-
const has404 = /\b404\b/.test(bodyText);
|
|
33
|
-
const hasNotFound = /not found|page not found|page missing|does not exist|error 404/.test(bodyText);
|
|
34
|
-
return has404 && hasNotFound;
|
|
35
|
-
}
|
|
36
|
-
function normalizeApiBase(raw) {
|
|
37
|
-
const input = (raw || "").toString().trim();
|
|
38
|
-
if (!input)
|
|
39
|
-
return "https://cdn.lovalingo.com";
|
|
40
|
-
let base = input.replace(/\/functions\/v1\/?$/i, "").replace(/\/$/, "");
|
|
41
|
-
try {
|
|
42
|
-
const parsed = new URL(base);
|
|
43
|
-
const host = parsed.hostname.toLowerCase();
|
|
44
|
-
// Why: runtime endpoints moved off Supabase Edge Functions; fall back to CDN if a Supabase host is supplied.
|
|
45
|
-
if (host.endsWith(".supabase.co")) {
|
|
46
|
-
warnDebug("LovalingoAPI", `apiBase points to Supabase (${host}); falling back to https://cdn.lovalingo.com`);
|
|
47
|
-
return "https://cdn.lovalingo.com";
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// Ignore parse errors and keep the raw base.
|
|
52
|
-
}
|
|
53
|
-
return base;
|
|
54
|
-
}
|
|
55
3
|
export class LovalingoAPI {
|
|
56
4
|
constructor(apiKey, apiBase, pathConfig, editKey) {
|
|
57
5
|
this.entitlements = null;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { DomRule } from "../types";
|
|
2
|
+
export interface ProjectEntitlements {
|
|
3
|
+
tier: "starter" | "startup" | "global";
|
|
4
|
+
maxTargetLocales: number;
|
|
5
|
+
allowedTargetLocales: string[];
|
|
6
|
+
brandingRequired: boolean;
|
|
7
|
+
hreflangEnabled: boolean;
|
|
8
|
+
seoEnabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export type SeoBundleResponse = {
|
|
11
|
+
locale?: string;
|
|
12
|
+
normalized_path?: string;
|
|
13
|
+
routing_strategy?: string;
|
|
14
|
+
seo?: Record<string, unknown>;
|
|
15
|
+
alternates?: {
|
|
16
|
+
canonical?: string;
|
|
17
|
+
xDefault?: string;
|
|
18
|
+
languages?: Record<string, string>;
|
|
19
|
+
};
|
|
20
|
+
seoEnabled?: boolean;
|
|
21
|
+
entitlements?: ProjectEntitlements;
|
|
22
|
+
};
|
|
23
|
+
export type BootstrapResponse = {
|
|
24
|
+
locale?: string;
|
|
25
|
+
normalized_path?: string;
|
|
26
|
+
routing_strategy?: string;
|
|
27
|
+
non_localized_paths?: Array<{
|
|
28
|
+
pattern?: string;
|
|
29
|
+
match_type?: string;
|
|
30
|
+
updated_at?: string | null;
|
|
31
|
+
}>;
|
|
32
|
+
inactive_pages?: Array<{
|
|
33
|
+
page_path?: string;
|
|
34
|
+
updated_at?: string | null;
|
|
35
|
+
}>;
|
|
36
|
+
loading_bg_color?: string | null;
|
|
37
|
+
branding_enabled?: boolean;
|
|
38
|
+
seoEnabled?: boolean;
|
|
39
|
+
entitlements?: ProjectEntitlements;
|
|
40
|
+
alternates?: {
|
|
41
|
+
canonical?: string;
|
|
42
|
+
xDefault?: string;
|
|
43
|
+
languages?: Record<string, string>;
|
|
44
|
+
} | null;
|
|
45
|
+
seo?: Record<string, unknown>;
|
|
46
|
+
jsonld?: Array<{
|
|
47
|
+
type: string;
|
|
48
|
+
json: unknown;
|
|
49
|
+
hash?: string;
|
|
50
|
+
}>;
|
|
51
|
+
dom_rules?: DomRule[];
|
|
52
|
+
exclusions?: unknown[];
|
|
53
|
+
critical?: {
|
|
54
|
+
map?: Record<string, string>;
|
|
55
|
+
keys?: number;
|
|
56
|
+
viewport?: unknown;
|
|
57
|
+
etag?: string;
|
|
58
|
+
};
|
|
59
|
+
etag?: string;
|
|
60
|
+
};
|
|
61
|
+
export type MissReportItem = {
|
|
62
|
+
source_text: string;
|
|
63
|
+
semantic_context?: string | null;
|
|
64
|
+
};
|
|
65
|
+
export type MissReportResponse = {
|
|
66
|
+
translations?: Array<{
|
|
67
|
+
source_text: string;
|
|
68
|
+
translated_text: string;
|
|
69
|
+
}>;
|
|
70
|
+
pii?: string[];
|
|
71
|
+
ignored?: boolean;
|
|
72
|
+
reason?: string;
|
|
73
|
+
};
|
|
74
|
+
export type MissReportOptions = {
|
|
75
|
+
pathOrUrl?: string;
|
|
76
|
+
sourceLocale?: string;
|
|
77
|
+
locales?: string[];
|
|
78
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { warnDebug } from "./logger";
|
|
2
|
+
const OK_HTTP_STATUSES = new Set([200, 201]);
|
|
3
|
+
const NOT_FOUND_TITLE_HINTS = /404|not found|page not found|page missing|does not exist|error 404/i;
|
|
4
|
+
export function getNavigationResponseStatus() {
|
|
5
|
+
if (typeof performance === "undefined" || typeof performance.getEntriesByType !== "function")
|
|
6
|
+
return null;
|
|
7
|
+
const entries = performance.getEntriesByType("navigation");
|
|
8
|
+
if (!entries || entries.length === 0)
|
|
9
|
+
return null;
|
|
10
|
+
const entry = entries[0];
|
|
11
|
+
const rawStatus = entry?.responseStatus;
|
|
12
|
+
const status = typeof rawStatus === "number" ? Math.floor(rawStatus) : NaN;
|
|
13
|
+
if (!Number.isFinite(status) || status <= 0)
|
|
14
|
+
return null;
|
|
15
|
+
return status;
|
|
16
|
+
}
|
|
17
|
+
// Why: avoid tracking misses/pageviews for non-OK responses (404/5xx) so bad routes don't pollute discovery.
|
|
18
|
+
export function isOkHttpStatus(status) {
|
|
19
|
+
if (typeof status !== "number")
|
|
20
|
+
return true;
|
|
21
|
+
return OK_HTTP_STATUSES.has(status);
|
|
22
|
+
}
|
|
23
|
+
export function looksLikeNotFoundDocument() {
|
|
24
|
+
if (typeof document === "undefined")
|
|
25
|
+
return false;
|
|
26
|
+
const title = (document.title || "").toString().trim().toLowerCase();
|
|
27
|
+
if (title && NOT_FOUND_TITLE_HINTS.test(title))
|
|
28
|
+
return true;
|
|
29
|
+
const bodyText = (document.body?.textContent || "").toString().slice(0, 2000).toLowerCase();
|
|
30
|
+
if (!bodyText)
|
|
31
|
+
return false;
|
|
32
|
+
const has404 = /\b404\b/.test(bodyText);
|
|
33
|
+
const hasNotFound = /not found|page not found|page missing|does not exist|error 404/.test(bodyText);
|
|
34
|
+
return has404 && hasNotFound;
|
|
35
|
+
}
|
|
36
|
+
export function normalizeApiBase(raw) {
|
|
37
|
+
const input = (raw || "").toString().trim();
|
|
38
|
+
if (!input)
|
|
39
|
+
return "https://cdn.lovalingo.com";
|
|
40
|
+
let base = input.replace(/\/functions\/v1\/?$/i, "").replace(/\/$/, "");
|
|
41
|
+
try {
|
|
42
|
+
const parsed = new URL(base);
|
|
43
|
+
const host = parsed.hostname.toLowerCase();
|
|
44
|
+
// Why: runtime endpoints moved off Supabase Edge Functions; fall back to CDN if a Supabase host is supplied.
|
|
45
|
+
if (host.endsWith(".supabase.co")) {
|
|
46
|
+
warnDebug("LovalingoAPI", `apiBase points to Supabase (${host}); falling back to https://cdn.lovalingo.com`);
|
|
47
|
+
return "https://cdn.lovalingo.com";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Ignore parse errors and keep the raw base.
|
|
52
|
+
}
|
|
53
|
+
return base;
|
|
54
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function normalizeLocaleCode(locale: unknown): string;
|
|
2
|
+
export declare function parseLocale(locale: unknown): {
|
|
3
|
+
language: string;
|
|
4
|
+
region: string | null;
|
|
5
|
+
};
|
|
6
|
+
export declare function countryCodeToFlagEmoji(countryCode: unknown): string | null;
|
|
7
|
+
export declare function resolveLocaleFlag(locale: unknown): string;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const EXACT_LOCALE_FLAG_OVERRIDES = {
|
|
2
|
+
en: "🇬🇧",
|
|
3
|
+
ar: "🇸🇦",
|
|
4
|
+
zh: "🇨🇳",
|
|
5
|
+
fa: "🇮🇷",
|
|
6
|
+
he: "🇮🇱",
|
|
7
|
+
};
|
|
8
|
+
const LANGUAGE_DEFAULT_REGION = {
|
|
9
|
+
ar: "SA",
|
|
10
|
+
bn: "BD",
|
|
11
|
+
cs: "CZ",
|
|
12
|
+
da: "DK",
|
|
13
|
+
de: "DE",
|
|
14
|
+
el: "GR",
|
|
15
|
+
en: "GB",
|
|
16
|
+
es: "ES",
|
|
17
|
+
fa: "IR",
|
|
18
|
+
fi: "FI",
|
|
19
|
+
fr: "FR",
|
|
20
|
+
he: "IL",
|
|
21
|
+
hi: "IN",
|
|
22
|
+
hu: "HU",
|
|
23
|
+
hy: "AM",
|
|
24
|
+
id: "ID",
|
|
25
|
+
it: "IT",
|
|
26
|
+
ja: "JP",
|
|
27
|
+
ko: "KR",
|
|
28
|
+
nl: "NL",
|
|
29
|
+
no: "NO",
|
|
30
|
+
pl: "PL",
|
|
31
|
+
pt: "PT",
|
|
32
|
+
ro: "RO",
|
|
33
|
+
ru: "RU",
|
|
34
|
+
sk: "SK",
|
|
35
|
+
sv: "SE",
|
|
36
|
+
th: "TH",
|
|
37
|
+
tr: "TR",
|
|
38
|
+
uk: "UA",
|
|
39
|
+
vi: "VN",
|
|
40
|
+
yo: "NG",
|
|
41
|
+
zh: "CN",
|
|
42
|
+
};
|
|
43
|
+
export function normalizeLocaleCode(locale) {
|
|
44
|
+
if (typeof locale !== "string")
|
|
45
|
+
return "";
|
|
46
|
+
return locale.trim().replace(/_/g, "-").toLowerCase();
|
|
47
|
+
}
|
|
48
|
+
export function parseLocale(locale) {
|
|
49
|
+
const normalized = normalizeLocaleCode(locale);
|
|
50
|
+
if (!normalized)
|
|
51
|
+
return { language: "", region: null };
|
|
52
|
+
const parts = normalized.split("-").filter(Boolean);
|
|
53
|
+
const language = parts[0] || "";
|
|
54
|
+
const regionPart = parts.find((part, index) => index > 0 && /^[a-z]{2}$/.test(part));
|
|
55
|
+
const region = regionPart ? regionPart.toUpperCase() : null;
|
|
56
|
+
return { language, region };
|
|
57
|
+
}
|
|
58
|
+
export function countryCodeToFlagEmoji(countryCode) {
|
|
59
|
+
if (typeof countryCode !== "string")
|
|
60
|
+
return null;
|
|
61
|
+
const normalized = countryCode.trim().toUpperCase();
|
|
62
|
+
if (!/^[A-Z]{2}$/.test(normalized))
|
|
63
|
+
return null;
|
|
64
|
+
const first = normalized.charCodeAt(0) + 127397;
|
|
65
|
+
const second = normalized.charCodeAt(1) + 127397;
|
|
66
|
+
return String.fromCodePoint(first, second);
|
|
67
|
+
}
|
|
68
|
+
export function resolveLocaleFlag(locale) {
|
|
69
|
+
const normalized = normalizeLocaleCode(locale);
|
|
70
|
+
if (!normalized)
|
|
71
|
+
return "🌐";
|
|
72
|
+
const exact = EXACT_LOCALE_FLAG_OVERRIDES[normalized];
|
|
73
|
+
if (exact)
|
|
74
|
+
return exact;
|
|
75
|
+
const { language, region } = parseLocale(normalized);
|
|
76
|
+
if (!language)
|
|
77
|
+
return "🌐";
|
|
78
|
+
if (region) {
|
|
79
|
+
const regionFlag = countryCodeToFlagEmoji(region);
|
|
80
|
+
if (regionFlag)
|
|
81
|
+
return regionFlag;
|
|
82
|
+
}
|
|
83
|
+
const defaultRegion = LANGUAGE_DEFAULT_REGION[language];
|
|
84
|
+
if (defaultRegion) {
|
|
85
|
+
const defaultFlag = countryCodeToFlagEmoji(defaultRegion);
|
|
86
|
+
if (defaultFlag)
|
|
87
|
+
return defaultFlag;
|
|
88
|
+
}
|
|
89
|
+
return "🌐";
|
|
90
|
+
}
|
|
@@ -1,70 +1,12 @@
|
|
|
1
|
-
import type { Exclusion
|
|
2
|
-
type MarkerStats
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
skippedNonTranslatableNodes: number;
|
|
8
|
-
totalChars: number;
|
|
9
|
-
markedChars: number;
|
|
10
|
-
skippedUnsafeChars: number;
|
|
11
|
-
skippedExcludedChars: number;
|
|
12
|
-
skippedNonTranslatableChars: number;
|
|
13
|
-
coverageRatio: number;
|
|
14
|
-
coverageRatioChars: number;
|
|
15
|
-
};
|
|
16
|
-
type MarkerEngineOptions = {
|
|
17
|
-
throttleMs?: number;
|
|
18
|
-
};
|
|
19
|
-
export type DomScanOccurrence = {
|
|
20
|
-
source_text: string;
|
|
21
|
-
semantic_context?: string;
|
|
22
|
-
};
|
|
23
|
-
export type DomScanSegment = {
|
|
24
|
-
kind: "text" | "title" | "aria-label" | "placeholder";
|
|
25
|
-
selector: string | null;
|
|
26
|
-
original: string | null;
|
|
27
|
-
current: string | null;
|
|
28
|
-
html: null;
|
|
29
|
-
};
|
|
30
|
-
export type DomScanResult = {
|
|
31
|
-
version: 1;
|
|
32
|
-
stats: MarkerStats;
|
|
33
|
-
segments: DomScanSegment[];
|
|
34
|
-
occurrences: DomScanOccurrence[];
|
|
35
|
-
critical_occurrences?: DomScanOccurrence[];
|
|
36
|
-
viewport?: {
|
|
37
|
-
width: number;
|
|
38
|
-
height: number;
|
|
39
|
-
};
|
|
40
|
-
truncated: boolean;
|
|
41
|
-
};
|
|
42
|
-
export type DomMiss = {
|
|
43
|
-
source_text: string;
|
|
44
|
-
semantic_context: string;
|
|
45
|
-
};
|
|
46
|
-
export type DomMissScanResult = {
|
|
47
|
-
misses: DomMiss[];
|
|
48
|
-
};
|
|
49
|
-
export type CriticalFingerprint = {
|
|
50
|
-
critical_count: number;
|
|
51
|
-
critical_hash: string;
|
|
52
|
-
viewport: {
|
|
53
|
-
width: number;
|
|
54
|
-
height: number;
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
export declare function getCriticalFingerprint(): CriticalFingerprint;
|
|
1
|
+
import type { Exclusion } from "../types";
|
|
2
|
+
import type { MarkerEngineOptions, MarkerStats } from "./markerEngineTypes";
|
|
3
|
+
import { applyActiveTranslations, restoreDom } from "./markerEngineApply";
|
|
4
|
+
import { getCriticalFingerprint } from "./markerEngineCritical";
|
|
5
|
+
import { scanDomForMisses } from "./markerEngineMisses";
|
|
6
|
+
import { addActiveTranslations, setActiveTranslations } from "./markerEngineTranslations";
|
|
58
7
|
export declare function startMarkerEngine(options?: MarkerEngineOptions): typeof stopMarkerEngine;
|
|
59
8
|
export declare function stopMarkerEngine(): void;
|
|
60
9
|
export declare function getMarkerStats(): MarkerStats;
|
|
61
10
|
export declare function setMarkerEngineExclusions(exclusions: Exclusion[] | null): void;
|
|
62
|
-
export
|
|
63
|
-
export
|
|
64
|
-
export declare function applyActiveTranslations(root?: ParentNode | null): number;
|
|
65
|
-
export declare function scanDomForMisses(opts: {
|
|
66
|
-
max: number;
|
|
67
|
-
ignore?: Set<string>;
|
|
68
|
-
}): DomMissScanResult;
|
|
69
|
-
export declare function restoreDom(root?: ParentNode | null): void;
|
|
70
|
-
export {};
|
|
11
|
+
export { applyActiveTranslations, scanDomForMisses, restoreDom, setActiveTranslations, addActiveTranslations, getCriticalFingerprint };
|
|
12
|
+
export type { MarkerStats, MarkerEngineOptions, DomScanOccurrence, DomScanSegment, DomScanResult, DomMiss, DomMissScanResult, CriticalFingerprint, } from "./markerEngineTypes";
|