@lovalingo/lovalingo 0.5.15 → 0.5.17
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/components/LovalingoProvider.js +245 -9
- package/dist/utils/api.d.ts +10 -2
- package/dist/utils/api.js +21 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -16,10 +16,75 @@ import { LanguageSwitcher } from './LanguageSwitcher';
|
|
|
16
16
|
const LOCALE_STORAGE_KEY = 'Lovalingo_locale';
|
|
17
17
|
const LOADING_BG_STORAGE_PREFIX = "Lovalingo_loading_bg_color";
|
|
18
18
|
const BRANDING_STORAGE_PREFIX = "Lovalingo_branding_enabled";
|
|
19
|
+
const EDIT_MODE_PARAM = "edit_mode";
|
|
20
|
+
const EDIT_KEY_PARAM = "edit_key";
|
|
19
21
|
// Why: run initial load before first paint on the client to avoid a prehide flash; useEffect on SSR.
|
|
20
22
|
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
|
23
|
+
const DEFAULT_PATH_NORMALIZATION = { enabled: true };
|
|
24
|
+
const EDIT_MODE_VALUES = new Set(["1", "true", "yes", "on"]);
|
|
25
|
+
const EDIT_UI_ATTR = "data-lovalingo-edit-ui";
|
|
26
|
+
const EDIT_HIGHLIGHT_ID = "lovalingo-edit-highlight";
|
|
27
|
+
const EDIT_HINT_ID = "lovalingo-edit-hint";
|
|
28
|
+
function readEditParams() {
|
|
29
|
+
if (typeof window === "undefined")
|
|
30
|
+
return { enabled: false, editKey: null };
|
|
31
|
+
const params = new URLSearchParams(window.location.search);
|
|
32
|
+
const rawFlag = (params.get(EDIT_MODE_PARAM) || params.get("editMode") || "").trim().toLowerCase();
|
|
33
|
+
const enabled = EDIT_MODE_VALUES.has(rawFlag);
|
|
34
|
+
const editKey = (params.get(EDIT_KEY_PARAM) || params.get("editKey") || "").trim() || null;
|
|
35
|
+
return { enabled, editKey };
|
|
36
|
+
}
|
|
37
|
+
function cssEscape(value) {
|
|
38
|
+
const esc = typeof window !== "undefined" && window?.CSS?.escape;
|
|
39
|
+
if (typeof esc === "function")
|
|
40
|
+
return esc(value);
|
|
41
|
+
return value.replace(/[ !"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
42
|
+
}
|
|
43
|
+
// Why: build stable, short selectors for exclusions without requiring IDs.
|
|
44
|
+
function buildCssSelector(element, maxDepth = 5) {
|
|
45
|
+
if (!element || !element.tagName)
|
|
46
|
+
return null;
|
|
47
|
+
if (element.id)
|
|
48
|
+
return `#${cssEscape(element.id)}`;
|
|
49
|
+
const parts = [];
|
|
50
|
+
let node = element;
|
|
51
|
+
let depth = 0;
|
|
52
|
+
while (node && depth < maxDepth) {
|
|
53
|
+
const tag = node.tagName.toLowerCase();
|
|
54
|
+
if (!tag || tag === "html")
|
|
55
|
+
break;
|
|
56
|
+
let part = tag;
|
|
57
|
+
const nodeTag = node.tagName;
|
|
58
|
+
const classes = Array.from(node.classList || [])
|
|
59
|
+
.filter(Boolean)
|
|
60
|
+
.filter((cls) => !cls.startsWith("lovalingo-"))
|
|
61
|
+
.slice(0, 2);
|
|
62
|
+
if (classes.length > 0) {
|
|
63
|
+
part += `.${classes.map(cssEscape).join(".")}`;
|
|
64
|
+
}
|
|
65
|
+
const parentEl = node.parentElement;
|
|
66
|
+
if (parentEl) {
|
|
67
|
+
const siblings = Array.from(parentEl.children).filter((child) => child instanceof HTMLElement && child.tagName === nodeTag);
|
|
68
|
+
if (siblings.length > 1) {
|
|
69
|
+
part += `:nth-of-type(${siblings.indexOf(node) + 1})`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
parts.unshift(part);
|
|
73
|
+
const selector = parts.join(" > ");
|
|
74
|
+
try {
|
|
75
|
+
if (document.querySelectorAll(selector).length === 1)
|
|
76
|
+
return selector;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// ignore invalid selector attempts
|
|
80
|
+
}
|
|
81
|
+
node = parentEl;
|
|
82
|
+
depth += 1;
|
|
83
|
+
}
|
|
84
|
+
return parts.join(" > ") || null;
|
|
85
|
+
}
|
|
21
86
|
export const LovalingoProvider = ({ children, apiKey: apiKeyProp, publicAnonKey, defaultLocale, locales, apiBase = 'https://cdn.lovalingo.com', routing = 'path', // Default to path mode (SEO-friendly, recommended)
|
|
22
|
-
autoPrefixLinks = true, overlayBgColor, autoApplyRules = true, switcherPosition = 'bottom-right', switcherOffsetY = 20, switcherTheme = 'dark', editMode: initialEditMode = false, editKey = 'KeyE', pathNormalization =
|
|
87
|
+
autoPrefixLinks = true, overlayBgColor, autoApplyRules = true, switcherPosition = 'bottom-right', switcherOffsetY = 20, switcherTheme = 'dark', editMode: initialEditMode = false, editKey = 'KeyE', pathNormalization = DEFAULT_PATH_NORMALIZATION, // Enable by default
|
|
23
88
|
mode = 'dom', // Default to legacy DOM mode for backward compatibility
|
|
24
89
|
sitemap = true, // Default: true - Auto-inject sitemap link tag
|
|
25
90
|
seo = true, // Default: true - Can be disabled per project entitlements
|
|
@@ -44,7 +109,19 @@ navigateRef, // For path mode routing
|
|
|
44
109
|
const allLocales = useMemo(() => {
|
|
45
110
|
const base = rawLocales.includes(defaultLocale) ? rawLocales : [defaultLocale, ...rawLocales];
|
|
46
111
|
return Array.from(new Set(base));
|
|
47
|
-
}, [defaultLocale, localesKey
|
|
112
|
+
}, [defaultLocale, localesKey]);
|
|
113
|
+
const pathNormalizationKey = (() => {
|
|
114
|
+
const enabled = pathNormalization?.enabled !== false;
|
|
115
|
+
const rules = Array.isArray(pathNormalization?.rules) ? pathNormalization.rules : [];
|
|
116
|
+
// Why: callers often pass inline objects/arrays; derive a stable key to prevent request storms from re-initializing effects.
|
|
117
|
+
const rulesKey = rules.map((r) => `${r.pattern}=>${r.replacement}:${r.includeSubpaths ? 1 : 0}`).join("|");
|
|
118
|
+
return `${enabled ? 1 : 0}:${rulesKey}`;
|
|
119
|
+
})();
|
|
120
|
+
const stablePathNormalization = useMemo(() => {
|
|
121
|
+
const enabled = pathNormalization?.enabled !== false;
|
|
122
|
+
const rules = Array.isArray(pathNormalization?.rules) ? pathNormalization.rules : undefined;
|
|
123
|
+
return rules ? { enabled, rules } : { enabled };
|
|
124
|
+
}, [pathNormalizationKey]);
|
|
48
125
|
// Why: read locale synchronously from the URL to avoid an initial default-locale render (EN → FR flash) before effects run.
|
|
49
126
|
const [locale, setLocaleState] = useState(() => {
|
|
50
127
|
if (typeof window === "undefined")
|
|
@@ -73,17 +150,20 @@ navigateRef, // For path mode routing
|
|
|
73
150
|
}
|
|
74
151
|
return defaultLocale;
|
|
75
152
|
});
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const
|
|
153
|
+
const initialEditParams = readEditParams();
|
|
154
|
+
const [editMode, setEditMode] = useState(initialEditMode || initialEditParams.enabled);
|
|
155
|
+
const [editSecretKey] = useState(initialEditParams.editKey);
|
|
156
|
+
const enhancedPathConfig = useMemo(() => (routing === "path" ? { ...stablePathNormalization, supportedLocales: allLocales } : stablePathNormalization), [allLocales, routing, stablePathNormalization]);
|
|
157
|
+
const apiRef = useRef(new LovalingoAPI(resolvedApiKey, apiBase, enhancedPathConfig, editSecretKey ?? undefined));
|
|
79
158
|
useEffect(() => {
|
|
80
|
-
apiRef.current = new LovalingoAPI(resolvedApiKey, apiBase, enhancedPathConfig);
|
|
81
|
-
}, [apiBase, enhancedPathConfig, resolvedApiKey]);
|
|
159
|
+
apiRef.current = new LovalingoAPI(resolvedApiKey, apiBase, enhancedPathConfig, editSecretKey ?? undefined);
|
|
160
|
+
}, [apiBase, editSecretKey, enhancedPathConfig, resolvedApiKey]);
|
|
82
161
|
const routingConfig = useContext(LangRoutingContext);
|
|
83
162
|
const [entitlements, setEntitlements] = useState(() => apiRef.current.getEntitlements());
|
|
84
163
|
const { trackPageviewOnce } = usePageviewTracking({ apiRef, resolvedApiKey });
|
|
85
164
|
const lastNormalizedPathRef = useRef("");
|
|
86
165
|
const historyPatchedRef = useRef(false);
|
|
166
|
+
const editSavingRef = useRef(false);
|
|
87
167
|
const originalHistoryRef = useRef(null);
|
|
88
168
|
const onNavigateRef = useRef(() => undefined);
|
|
89
169
|
const isInternalNavigationRef = useRef(false);
|
|
@@ -115,6 +195,18 @@ navigateRef, // For path mode routing
|
|
|
115
195
|
catch {
|
|
116
196
|
// ignore
|
|
117
197
|
}
|
|
198
|
+
// Why: default to the site's existing background to reduce a visible white flash on non-white themes.
|
|
199
|
+
try {
|
|
200
|
+
const bodyBg = window.getComputedStyle(document.body).backgroundColor;
|
|
201
|
+
if (bodyBg && bodyBg !== "transparent" && bodyBg !== "rgba(0, 0, 0, 0)")
|
|
202
|
+
return bodyBg;
|
|
203
|
+
const htmlBg = window.getComputedStyle(document.documentElement).backgroundColor;
|
|
204
|
+
if (htmlBg && htmlBg !== "transparent" && htmlBg !== "rgba(0, 0, 0, 0)")
|
|
205
|
+
return htmlBg;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// ignore
|
|
209
|
+
}
|
|
118
210
|
return "#ffffff";
|
|
119
211
|
}, [loadingBgStorageKey, overlayBgColor]);
|
|
120
212
|
const setCachedLoadingBgColor = useCallback((color) => {
|
|
@@ -526,6 +618,11 @@ navigateRef, // For path mode routing
|
|
|
526
618
|
useEffect(() => {
|
|
527
619
|
detectLocaleRef.current = detectLocale;
|
|
528
620
|
}, [detectLocale]);
|
|
621
|
+
useEffect(() => {
|
|
622
|
+
if (editMode && !editSecretKey) {
|
|
623
|
+
warnDebug('[Lovalingo] Edit Mode is active but no edit_key was provided in the URL.');
|
|
624
|
+
}
|
|
625
|
+
}, [editMode, editSecretKey]);
|
|
529
626
|
// Initialize
|
|
530
627
|
useIsomorphicLayoutEffect(() => {
|
|
531
628
|
const initialLocale = detectLocaleRef.current();
|
|
@@ -591,10 +688,149 @@ navigateRef, // For path mode routing
|
|
|
591
688
|
setEditMode(prev => !prev);
|
|
592
689
|
}, []);
|
|
593
690
|
const excludeElement = useCallback(async (selector) => {
|
|
594
|
-
|
|
691
|
+
if (!editSecretKey) {
|
|
692
|
+
warnDebug('[Lovalingo] Edit Mode is active but no edit_key was provided in the URL.');
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
// Why: store exclusions on the normalized path so they apply across locales.
|
|
696
|
+
const pagePath = lastNormalizedPathRef.current || processPath(window.location.pathname, enhancedPathConfig);
|
|
697
|
+
await apiRef.current.saveExclusion({
|
|
698
|
+
selector,
|
|
699
|
+
type: 'css',
|
|
700
|
+
pagePath,
|
|
701
|
+
editKey: editSecretKey,
|
|
702
|
+
});
|
|
595
703
|
const exclusions = await apiRef.current.fetchExclusions();
|
|
596
704
|
setMarkerEngineExclusions(exclusions);
|
|
597
|
-
}, []);
|
|
705
|
+
}, [editSecretKey, enhancedPathConfig]);
|
|
706
|
+
useEffect(() => {
|
|
707
|
+
if (typeof window === "undefined")
|
|
708
|
+
return;
|
|
709
|
+
const existingHighlight = document.getElementById(EDIT_HIGHLIGHT_ID);
|
|
710
|
+
const existingHint = document.getElementById(EDIT_HINT_ID);
|
|
711
|
+
if (!editMode) {
|
|
712
|
+
existingHighlight?.remove();
|
|
713
|
+
existingHint?.remove();
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
const highlight = existingHighlight ||
|
|
717
|
+
(() => {
|
|
718
|
+
const node = document.createElement("div");
|
|
719
|
+
node.id = EDIT_HIGHLIGHT_ID;
|
|
720
|
+
node.setAttribute(EDIT_UI_ATTR, "true");
|
|
721
|
+
node.setAttribute("data-lovalingo-exclude", "true");
|
|
722
|
+
node.style.position = "fixed";
|
|
723
|
+
node.style.pointerEvents = "none";
|
|
724
|
+
node.style.zIndex = "2147483646";
|
|
725
|
+
node.style.border = "2px solid #22c55e";
|
|
726
|
+
node.style.background = "rgba(34, 197, 94, 0.12)";
|
|
727
|
+
node.style.borderRadius = "8px";
|
|
728
|
+
node.style.boxSizing = "border-box";
|
|
729
|
+
node.style.transition = "transform 80ms ease, width 80ms ease, height 80ms ease";
|
|
730
|
+
node.style.display = "none";
|
|
731
|
+
document.body.appendChild(node);
|
|
732
|
+
return node;
|
|
733
|
+
})();
|
|
734
|
+
const hint = existingHint ||
|
|
735
|
+
(() => {
|
|
736
|
+
const node = document.createElement("div");
|
|
737
|
+
node.id = EDIT_HINT_ID;
|
|
738
|
+
node.setAttribute(EDIT_UI_ATTR, "true");
|
|
739
|
+
node.setAttribute("data-lovalingo-exclude", "true");
|
|
740
|
+
node.style.position = "fixed";
|
|
741
|
+
node.style.left = "12px";
|
|
742
|
+
node.style.bottom = "12px";
|
|
743
|
+
node.style.zIndex = "2147483647";
|
|
744
|
+
node.style.background = "rgba(10, 10, 10, 0.85)";
|
|
745
|
+
node.style.color = "#ffffff";
|
|
746
|
+
node.style.fontSize = "12px";
|
|
747
|
+
node.style.lineHeight = "1.4";
|
|
748
|
+
node.style.padding = "8px 10px";
|
|
749
|
+
node.style.borderRadius = "8px";
|
|
750
|
+
node.style.border = "1px solid rgba(255, 255, 255, 0.15)";
|
|
751
|
+
node.style.pointerEvents = "none";
|
|
752
|
+
node.style.maxWidth = "280px";
|
|
753
|
+
node.textContent = "Edit Mode: click an element to exclude. Press Esc to exit.";
|
|
754
|
+
document.body.appendChild(node);
|
|
755
|
+
return node;
|
|
756
|
+
})();
|
|
757
|
+
let rafId = null;
|
|
758
|
+
let pendingTarget = null;
|
|
759
|
+
const previousCursor = document.body.style.cursor;
|
|
760
|
+
document.body.style.cursor = "crosshair";
|
|
761
|
+
const updateHighlight = () => {
|
|
762
|
+
rafId = null;
|
|
763
|
+
if (!pendingTarget) {
|
|
764
|
+
highlight.style.display = "none";
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
const rect = pendingTarget.getBoundingClientRect();
|
|
768
|
+
if (rect.width <= 0 || rect.height <= 0) {
|
|
769
|
+
highlight.style.display = "none";
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
highlight.style.display = "block";
|
|
773
|
+
highlight.style.width = `${rect.width}px`;
|
|
774
|
+
highlight.style.height = `${rect.height}px`;
|
|
775
|
+
highlight.style.transform = `translate(${rect.left}px, ${rect.top}px)`;
|
|
776
|
+
};
|
|
777
|
+
const onMove = (event) => {
|
|
778
|
+
const rawTarget = event.target;
|
|
779
|
+
const target = rawTarget instanceof HTMLElement ? rawTarget : rawTarget instanceof Node ? rawTarget.parentElement : null;
|
|
780
|
+
if (!target || target.closest(`[${EDIT_UI_ATTR}="true"]`)) {
|
|
781
|
+
pendingTarget = null;
|
|
782
|
+
}
|
|
783
|
+
else if (target === document.body || target === document.documentElement) {
|
|
784
|
+
pendingTarget = null;
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
pendingTarget = target;
|
|
788
|
+
}
|
|
789
|
+
if (rafId !== null)
|
|
790
|
+
return;
|
|
791
|
+
rafId = window.requestAnimationFrame(updateHighlight);
|
|
792
|
+
};
|
|
793
|
+
const onClick = async (event) => {
|
|
794
|
+
const rawTarget = event.target;
|
|
795
|
+
const target = rawTarget instanceof HTMLElement ? rawTarget : rawTarget instanceof Node ? rawTarget.parentElement : null;
|
|
796
|
+
if (!target || target.closest(`[${EDIT_UI_ATTR}="true"]`))
|
|
797
|
+
return;
|
|
798
|
+
event.preventDefault();
|
|
799
|
+
event.stopPropagation();
|
|
800
|
+
event.stopImmediatePropagation();
|
|
801
|
+
const selector = buildCssSelector(target);
|
|
802
|
+
if (!selector)
|
|
803
|
+
return;
|
|
804
|
+
if (editSavingRef.current)
|
|
805
|
+
return;
|
|
806
|
+
editSavingRef.current = true;
|
|
807
|
+
try {
|
|
808
|
+
await excludeElement(selector);
|
|
809
|
+
}
|
|
810
|
+
finally {
|
|
811
|
+
editSavingRef.current = false;
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
const onKeyDown = (event) => {
|
|
815
|
+
if (event.key === "Escape") {
|
|
816
|
+
event.preventDefault();
|
|
817
|
+
setEditMode(false);
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
document.addEventListener("mousemove", onMove, true);
|
|
821
|
+
document.addEventListener("click", onClick, true);
|
|
822
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
823
|
+
return () => {
|
|
824
|
+
document.removeEventListener("mousemove", onMove, true);
|
|
825
|
+
document.removeEventListener("click", onClick, true);
|
|
826
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
827
|
+
if (rafId !== null)
|
|
828
|
+
window.cancelAnimationFrame(rafId);
|
|
829
|
+
highlight.remove();
|
|
830
|
+
hint.remove();
|
|
831
|
+
document.body.style.cursor = previousCursor;
|
|
832
|
+
};
|
|
833
|
+
}, [editMode, excludeElement, setEditMode]);
|
|
598
834
|
const contextValue = {
|
|
599
835
|
locale,
|
|
600
836
|
setLocale,
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -81,11 +81,13 @@ export declare class LovalingoAPI {
|
|
|
81
81
|
private apiKey;
|
|
82
82
|
private apiBase;
|
|
83
83
|
private pathConfig?;
|
|
84
|
+
private editKey?;
|
|
84
85
|
private entitlements;
|
|
85
|
-
constructor(apiKey: string, apiBase: string, pathConfig?: PathNormalizationConfig);
|
|
86
|
+
constructor(apiKey: string, apiBase: string, pathConfig?: PathNormalizationConfig, editKey?: string);
|
|
86
87
|
private hasApiKey;
|
|
87
88
|
private buildPathParam;
|
|
88
89
|
private warnMissingApiKey;
|
|
90
|
+
private warnMissingEditKey;
|
|
89
91
|
private logActivationRequired;
|
|
90
92
|
private isActivationRequiredPayload;
|
|
91
93
|
private isActivationRequiredResponse;
|
|
@@ -105,5 +107,11 @@ export declare class LovalingoAPI {
|
|
|
105
107
|
fetchBootstrap(localeHint: string, pathOrUrl?: string): Promise<BootstrapResponse | null>;
|
|
106
108
|
fetchExclusions(): Promise<Exclusion[]>;
|
|
107
109
|
fetchDomRules(targetLocale: string): Promise<DomRule[]>;
|
|
108
|
-
saveExclusion(
|
|
110
|
+
saveExclusion(args: {
|
|
111
|
+
selector: string;
|
|
112
|
+
type: 'css' | 'xpath';
|
|
113
|
+
pagePath?: string;
|
|
114
|
+
editKey?: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
}): Promise<void>;
|
|
109
117
|
}
|
package/dist/utils/api.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { warnDebug, errorDebug } from './logger';
|
|
2
2
|
export class LovalingoAPI {
|
|
3
|
-
constructor(apiKey, apiBase, pathConfig) {
|
|
3
|
+
constructor(apiKey, apiBase, pathConfig, editKey) {
|
|
4
4
|
this.entitlements = null;
|
|
5
5
|
this.apiKey = apiKey;
|
|
6
6
|
this.apiBase = apiBase;
|
|
7
7
|
this.pathConfig = pathConfig;
|
|
8
|
+
this.editKey = editKey;
|
|
8
9
|
}
|
|
9
10
|
hasApiKey() {
|
|
10
11
|
return typeof this.apiKey === 'string' && this.apiKey.trim().length > 0;
|
|
@@ -30,6 +31,9 @@ export class LovalingoAPI {
|
|
|
30
31
|
// Avoid hard-crashing apps; make the failure mode obvious.
|
|
31
32
|
warnDebug(`[Lovalingo] Missing public project key: ${action} was skipped. Pass publicAnonKey to <LovalingoProvider ...> (or set VITE_LOVALINGO_PUBLIC_ANON_KEY).`);
|
|
32
33
|
}
|
|
34
|
+
warnMissingEditKey(action) {
|
|
35
|
+
warnDebug(`[Lovalingo] Missing edit key: ${action} was skipped. Open the edit link from the dashboard to continue.`);
|
|
36
|
+
}
|
|
33
37
|
logActivationRequired(context, response) {
|
|
34
38
|
errorDebug(`[Lovalingo] ${context} blocked (HTTP ${response.status}). ` +
|
|
35
39
|
`This project is not activated yet. ` +
|
|
@@ -338,16 +342,30 @@ export class LovalingoAPI {
|
|
|
338
342
|
return [];
|
|
339
343
|
}
|
|
340
344
|
}
|
|
341
|
-
async saveExclusion(
|
|
345
|
+
async saveExclusion(args) {
|
|
342
346
|
try {
|
|
343
347
|
if (!this.hasApiKey()) {
|
|
344
348
|
this.warnMissingApiKey('saveExclusion');
|
|
345
349
|
return;
|
|
346
350
|
}
|
|
351
|
+
const editKey = (args.editKey || this.editKey || "").trim();
|
|
352
|
+
if (!editKey) {
|
|
353
|
+
this.warnMissingEditKey('saveExclusion');
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
// Why: persist exclusions against a normalized path to keep locales in sync.
|
|
357
|
+
const pagePath = (args.pagePath || this.buildPathParam()).toString();
|
|
347
358
|
const response = await fetch(`${this.apiBase}/functions/v1/exclusions?key=${this.apiKey}`, {
|
|
348
359
|
method: 'POST',
|
|
349
360
|
headers: { 'Content-Type': 'application/json' },
|
|
350
|
-
body: JSON.stringify({
|
|
361
|
+
body: JSON.stringify({
|
|
362
|
+
key: this.apiKey,
|
|
363
|
+
edit_key: editKey,
|
|
364
|
+
page_path: pagePath,
|
|
365
|
+
selector_type: args.type,
|
|
366
|
+
selector_value: args.selector,
|
|
367
|
+
description: args.description,
|
|
368
|
+
}),
|
|
351
369
|
});
|
|
352
370
|
if (response.status === 403) {
|
|
353
371
|
this.logActivationRequired('saveExclusion', response);
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.5.
|
|
1
|
+
export declare const VERSION = "0.5.16";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.5.
|
|
1
|
+
export const VERSION = "0.5.16";
|
package/package.json
CHANGED