@useinsider/guido 3.11.0-beta.e62ab49 → 3.11.0-beta.f2b79f2
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/@types/config/schemas.js +49 -40
- package/dist/components/organisms/header/EditorActions.vue.js +1 -1
- package/dist/components/organisms/header/HeaderWrapper.vue.js +3 -3
- package/dist/components/organisms/header/HeaderWrapper.vue2.js +2 -0
- package/dist/components/organisms/header/version-history/VersionHistory.vue.js +1 -1
- package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue.js +5 -5
- package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue2.js +2 -2
- package/dist/components/organisms/unsubscribe/UnsubscribeTypeSelection.vue.js +3 -3
- package/dist/components/organisms/unsubscribe/UnsubscribeTypeSelection.vue2.js +9 -9
- package/dist/composables/useModuleDynamicContentRepair.js +36 -0
- package/dist/composables/useStripo.js +62 -59
- package/dist/config/compiler/outlookCompilerRules.js +8 -33
- package/dist/guido.css +1 -1
- package/dist/src/@types/config/schemas.d.ts +36 -0
- package/dist/src/composables/useConfig.d.ts +18 -0
- package/dist/src/composables/useModuleDynamicContentRepair.d.ts +18 -0
- package/dist/src/stores/config.d.ts +162 -0
- package/dist/src/utils/dynamicContentConverter.d.ts +27 -0
- package/dist/src/utils/genericUtil.d.ts +7 -0
- package/dist/utils/dynamicContentConverter.js +31 -0
- package/dist/utils/genericUtil.js +26 -19
- package/package.json +10 -1
- package/dist/src/composables/useHtmlValidator.test.d.ts +0 -1
- package/dist/src/config/compiler/utils/recommendationIgnoreUtils.test.d.ts +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const c = `
|
|
2
2
|
<!--[if gte mso 9]>
|
|
3
3
|
<xml>
|
|
4
4
|
<o:OfficeDocumentSettings>
|
|
@@ -6,15 +6,15 @@ const p = `
|
|
|
6
6
|
<o:PixelsPerInch>96</o:PixelsPerInch>
|
|
7
7
|
</o:OfficeDocumentSettings>
|
|
8
8
|
</xml>
|
|
9
|
-
<![endif]-->`,
|
|
9
|
+
<![endif]-->`, s = {
|
|
10
10
|
xmlns: "http://www.w3.org/1999/xhtml",
|
|
11
11
|
"xmlns:o": "urn:schemas-microsoft-com:office:office"
|
|
12
|
-
},
|
|
12
|
+
}, r = [
|
|
13
13
|
{
|
|
14
14
|
id: "append-office-xml",
|
|
15
15
|
description: "Appending office XML into the head if it does not exist.",
|
|
16
16
|
type: "custom",
|
|
17
|
-
processor: (e) => e.includes("<o:OfficeDocumentSettings>") ? e : e.replace("</head>", `${
|
|
17
|
+
processor: (e) => e.includes("<o:OfficeDocumentSettings>") ? e : e.replace("</head>", `${c}</head>`),
|
|
18
18
|
priority: 70
|
|
19
19
|
},
|
|
20
20
|
{
|
|
@@ -23,39 +23,14 @@ const p = `
|
|
|
23
23
|
type: "custom",
|
|
24
24
|
processor: (e) => {
|
|
25
25
|
let t = e;
|
|
26
|
-
return Object.entries(
|
|
27
|
-
const
|
|
28
|
-
t.search(
|
|
26
|
+
return Object.entries(s).forEach(([o, i]) => {
|
|
27
|
+
const n = new RegExp(`${o}="[^"]*"`);
|
|
28
|
+
t.search(n) === -1 && (t = t.replace("<html", `<html ${o}="${i}"`));
|
|
29
29
|
}), t;
|
|
30
30
|
},
|
|
31
31
|
priority: 71
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
id: "sync-mso-button-href",
|
|
35
|
-
description: "Mirror the visible button's href onto its Outlook VML twin",
|
|
36
|
-
type: "custom",
|
|
37
|
-
processor: (e) => e.replace(
|
|
38
|
-
d,
|
|
39
|
-
(t, o, s, i) => {
|
|
40
|
-
var r;
|
|
41
|
-
const n = (r = i.match(h)) == null ? void 0 : r[2];
|
|
42
|
-
if (n === void 0)
|
|
43
|
-
return t;
|
|
44
|
-
const f = s.replace(
|
|
45
|
-
u,
|
|
46
|
-
(E, l, c) => `${l}${c}${n}${c}`
|
|
47
|
-
);
|
|
48
|
-
return `${o}${f}${i}`;
|
|
49
|
-
}
|
|
50
|
-
),
|
|
51
|
-
// 60 < 72 < 100. After prepare-recommendations (48) and pair-product-variables
|
|
52
|
-
// (60), so the visible href is already the `{{...url}}` merge tag we mirror.
|
|
53
|
-
// Before wrap-mobile-row-mso-conditional (100), which only then turns its
|
|
54
|
-
// MSO_MOBILE_HIDE_* markers into real `[if !mso]` delimiters — running after it
|
|
55
|
-
// would let a desktop twin pair with the mobile row and mirror the wrong product.
|
|
56
|
-
priority: 72
|
|
57
32
|
}
|
|
58
33
|
];
|
|
59
34
|
export {
|
|
60
|
-
|
|
35
|
+
r as outlookCompilerRules
|
|
61
36
|
};
|
package/dist/guido.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-
|
|
1
|
+
.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-6e711fd7]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-50dac6de]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-50dac6de]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-50dac6de]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-06afaecb]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-06afaecb]{min-height:504px}.iframe-wrapper[data-v-cbafc185]{width:258px}.iframe-scaled[data-v-cbafc185]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-7419ae06] .vueperslides__bullets,[data-v-796d193b] .vueperslides__bullets{pointer-events:none!important}[data-v-796d193b] .vueperslides__parallax-wrapper{height:110px!important}[data-v-cadfc82d] .vueperslides__bullets{pointer-events:none!important}[data-v-cadfc82d] .vueperslides__parallax-wrapper{height:110px!important}
|
|
@@ -227,6 +227,24 @@ export declare const TemplateSchema: v.ObjectSchema<{
|
|
|
227
227
|
readonly value: v.StringSchema<undefined>;
|
|
228
228
|
}, undefined>, undefined>;
|
|
229
229
|
}, undefined>, undefined>, readonly []>;
|
|
230
|
+
/**
|
|
231
|
+
* Full set of dynamic-content items the account offers (label + token).
|
|
232
|
+
* Used as the label→token map that repairs label-form placeholders
|
|
233
|
+
* (e.g. `{{ Phone Number }}`) in dropped saved modules.
|
|
234
|
+
*/
|
|
235
|
+
readonly availableDynamicContent: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
236
|
+
/** Display text for the dynamic content */
|
|
237
|
+
readonly text: v.StringSchema<undefined>;
|
|
238
|
+
/** Template variable value (e.g., {{username}}) */
|
|
239
|
+
readonly value: v.StringSchema<undefined>;
|
|
240
|
+
/** Fallback value if variable is empty */
|
|
241
|
+
readonly fallback: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
242
|
+
/** Optional formatting options */
|
|
243
|
+
readonly format: v.OptionalSchema<v.ObjectSchema<{
|
|
244
|
+
readonly key: v.StringSchema<undefined>;
|
|
245
|
+
readonly value: v.StringSchema<undefined>;
|
|
246
|
+
}, undefined>, undefined>;
|
|
247
|
+
}, undefined>, undefined>, readonly []>;
|
|
230
248
|
/** Valid custom field attribute names from the partner's categorized fields */
|
|
231
249
|
readonly customFieldAttributes: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, readonly []>;
|
|
232
250
|
/** Selected unsubscribe page IDs */
|
|
@@ -622,6 +640,24 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
|
|
|
622
640
|
readonly value: v.StringSchema<undefined>;
|
|
623
641
|
}, undefined>, undefined>;
|
|
624
642
|
}, undefined>, undefined>, readonly []>;
|
|
643
|
+
/**
|
|
644
|
+
* Full set of dynamic-content items the account offers (label + token).
|
|
645
|
+
* Used as the label→token map that repairs label-form placeholders
|
|
646
|
+
* (e.g. `{{ Phone Number }}`) in dropped saved modules.
|
|
647
|
+
*/
|
|
648
|
+
readonly availableDynamicContent: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
649
|
+
/** Display text for the dynamic content */
|
|
650
|
+
readonly text: v.StringSchema<undefined>;
|
|
651
|
+
/** Template variable value (e.g., {{username}}) */
|
|
652
|
+
readonly value: v.StringSchema<undefined>;
|
|
653
|
+
/** Fallback value if variable is empty */
|
|
654
|
+
readonly fallback: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
655
|
+
/** Optional formatting options */
|
|
656
|
+
readonly format: v.OptionalSchema<v.ObjectSchema<{
|
|
657
|
+
readonly key: v.StringSchema<undefined>;
|
|
658
|
+
readonly value: v.StringSchema<undefined>;
|
|
659
|
+
}, undefined>, undefined>;
|
|
660
|
+
}, undefined>, undefined>, readonly []>;
|
|
625
661
|
/** Valid custom field attribute names from the partner's categorized fields */
|
|
626
662
|
readonly customFieldAttributes: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, readonly []>;
|
|
627
663
|
/** Selected unsubscribe page IDs */
|
|
@@ -34,6 +34,15 @@ export declare const useConfig: () => {
|
|
|
34
34
|
value: string;
|
|
35
35
|
} | undefined;
|
|
36
36
|
}[];
|
|
37
|
+
availableDynamicContent: {
|
|
38
|
+
text: string;
|
|
39
|
+
value: string;
|
|
40
|
+
fallback?: string | undefined;
|
|
41
|
+
format?: {
|
|
42
|
+
key: string;
|
|
43
|
+
value: string;
|
|
44
|
+
} | undefined;
|
|
45
|
+
}[];
|
|
37
46
|
customFieldAttributes: string[];
|
|
38
47
|
selectedUnsubscribePages: number[];
|
|
39
48
|
forceRecreate: boolean;
|
|
@@ -162,6 +171,15 @@ export declare const useConfig: () => {
|
|
|
162
171
|
value: string;
|
|
163
172
|
} | undefined;
|
|
164
173
|
}[];
|
|
174
|
+
availableDynamicContent: {
|
|
175
|
+
text: string;
|
|
176
|
+
value: string;
|
|
177
|
+
fallback?: string | undefined;
|
|
178
|
+
format?: {
|
|
179
|
+
key: string;
|
|
180
|
+
value: string;
|
|
181
|
+
} | undefined;
|
|
182
|
+
}[];
|
|
165
183
|
customFieldAttributes: string[];
|
|
166
184
|
selectedUnsubscribePages: number[];
|
|
167
185
|
forceRecreate: boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ModuleAddData, ModuleModifier } from '@@/Types/stripo';
|
|
2
|
+
/**
|
|
3
|
+
* Host-registered translation key for the "some attributes could not be
|
|
4
|
+
* converted" toaster. Guido resolves it against the host's `window.trans.en`;
|
|
5
|
+
* the copy is registered host-side.
|
|
6
|
+
*/
|
|
7
|
+
export declare const UNRESOLVED_DYNAMIC_CONTENT_ON_DROP_KEY = "dynamic-content.unresolved-attributes-on-drop";
|
|
8
|
+
/**
|
|
9
|
+
* Repairs label-form dynamic-content tokens in saved modules as they are dropped
|
|
10
|
+
* or copied into the editor. Saved modules serialize merge-tag chips by their
|
|
11
|
+
* display label (`{{ Phone Number }}`); this maps them back to their canonical
|
|
12
|
+
* token (`{{phone_number}}`) using the account's dynamic-content list.
|
|
13
|
+
*
|
|
14
|
+
* Wired into Stripo via the `onModuleAdd` init callback (see `useStripo`).
|
|
15
|
+
*/
|
|
16
|
+
export declare const useModuleDynamicContentRepair: () => {
|
|
17
|
+
handleModuleAdd: (data: ModuleAddData, modifier: ModuleModifier) => void;
|
|
18
|
+
};
|
|
@@ -39,6 +39,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
39
39
|
value: string;
|
|
40
40
|
} | undefined;
|
|
41
41
|
}[];
|
|
42
|
+
availableDynamicContent: {
|
|
43
|
+
text: string;
|
|
44
|
+
value: string;
|
|
45
|
+
fallback?: string | undefined;
|
|
46
|
+
format?: {
|
|
47
|
+
key: string;
|
|
48
|
+
value: string;
|
|
49
|
+
} | undefined;
|
|
50
|
+
}[];
|
|
42
51
|
customFieldAttributes: string[];
|
|
43
52
|
selectedUnsubscribePages: number[];
|
|
44
53
|
forceRecreate: boolean;
|
|
@@ -173,6 +182,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
173
182
|
value: string;
|
|
174
183
|
} | undefined;
|
|
175
184
|
}[];
|
|
185
|
+
availableDynamicContent: {
|
|
186
|
+
text: string;
|
|
187
|
+
value: string;
|
|
188
|
+
fallback?: string | undefined;
|
|
189
|
+
format?: {
|
|
190
|
+
key: string;
|
|
191
|
+
value: string;
|
|
192
|
+
} | undefined;
|
|
193
|
+
}[];
|
|
176
194
|
customFieldAttributes: string[];
|
|
177
195
|
selectedUnsubscribePages: number[];
|
|
178
196
|
forceRecreate: boolean;
|
|
@@ -307,6 +325,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
307
325
|
value: string;
|
|
308
326
|
} | undefined;
|
|
309
327
|
}[];
|
|
328
|
+
availableDynamicContent: {
|
|
329
|
+
text: string;
|
|
330
|
+
value: string;
|
|
331
|
+
fallback?: string | undefined;
|
|
332
|
+
format?: {
|
|
333
|
+
key: string;
|
|
334
|
+
value: string;
|
|
335
|
+
} | undefined;
|
|
336
|
+
}[];
|
|
310
337
|
customFieldAttributes: string[];
|
|
311
338
|
selectedUnsubscribePages: number[];
|
|
312
339
|
forceRecreate: boolean;
|
|
@@ -441,6 +468,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
441
468
|
value: string;
|
|
442
469
|
} | undefined;
|
|
443
470
|
}[];
|
|
471
|
+
availableDynamicContent: {
|
|
472
|
+
text: string;
|
|
473
|
+
value: string;
|
|
474
|
+
fallback?: string | undefined;
|
|
475
|
+
format?: {
|
|
476
|
+
key: string;
|
|
477
|
+
value: string;
|
|
478
|
+
} | undefined;
|
|
479
|
+
}[];
|
|
444
480
|
customFieldAttributes: string[];
|
|
445
481
|
selectedUnsubscribePages: number[];
|
|
446
482
|
forceRecreate: boolean;
|
|
@@ -575,6 +611,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
575
611
|
value: string;
|
|
576
612
|
} | undefined;
|
|
577
613
|
}[];
|
|
614
|
+
availableDynamicContent: {
|
|
615
|
+
text: string;
|
|
616
|
+
value: string;
|
|
617
|
+
fallback?: string | undefined;
|
|
618
|
+
format?: {
|
|
619
|
+
key: string;
|
|
620
|
+
value: string;
|
|
621
|
+
} | undefined;
|
|
622
|
+
}[];
|
|
578
623
|
customFieldAttributes: string[];
|
|
579
624
|
selectedUnsubscribePages: number[];
|
|
580
625
|
forceRecreate: boolean;
|
|
@@ -709,6 +754,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
709
754
|
value: string;
|
|
710
755
|
} | undefined;
|
|
711
756
|
}[];
|
|
757
|
+
availableDynamicContent: {
|
|
758
|
+
text: string;
|
|
759
|
+
value: string;
|
|
760
|
+
fallback?: string | undefined;
|
|
761
|
+
format?: {
|
|
762
|
+
key: string;
|
|
763
|
+
value: string;
|
|
764
|
+
} | undefined;
|
|
765
|
+
}[];
|
|
712
766
|
customFieldAttributes: string[];
|
|
713
767
|
selectedUnsubscribePages: number[];
|
|
714
768
|
forceRecreate: boolean;
|
|
@@ -843,6 +897,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
843
897
|
value: string;
|
|
844
898
|
} | undefined;
|
|
845
899
|
}[];
|
|
900
|
+
availableDynamicContent: {
|
|
901
|
+
text: string;
|
|
902
|
+
value: string;
|
|
903
|
+
fallback?: string | undefined;
|
|
904
|
+
format?: {
|
|
905
|
+
key: string;
|
|
906
|
+
value: string;
|
|
907
|
+
} | undefined;
|
|
908
|
+
}[];
|
|
846
909
|
customFieldAttributes: string[];
|
|
847
910
|
selectedUnsubscribePages: number[];
|
|
848
911
|
forceRecreate: boolean;
|
|
@@ -977,6 +1040,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
977
1040
|
value: string;
|
|
978
1041
|
} | undefined;
|
|
979
1042
|
}[];
|
|
1043
|
+
availableDynamicContent: {
|
|
1044
|
+
text: string;
|
|
1045
|
+
value: string;
|
|
1046
|
+
fallback?: string | undefined;
|
|
1047
|
+
format?: {
|
|
1048
|
+
key: string;
|
|
1049
|
+
value: string;
|
|
1050
|
+
} | undefined;
|
|
1051
|
+
}[];
|
|
980
1052
|
customFieldAttributes: string[];
|
|
981
1053
|
selectedUnsubscribePages: number[];
|
|
982
1054
|
forceRecreate: boolean;
|
|
@@ -1111,6 +1183,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1111
1183
|
value: string;
|
|
1112
1184
|
} | undefined;
|
|
1113
1185
|
}[];
|
|
1186
|
+
availableDynamicContent: {
|
|
1187
|
+
text: string;
|
|
1188
|
+
value: string;
|
|
1189
|
+
fallback?: string | undefined;
|
|
1190
|
+
format?: {
|
|
1191
|
+
key: string;
|
|
1192
|
+
value: string;
|
|
1193
|
+
} | undefined;
|
|
1194
|
+
}[];
|
|
1114
1195
|
customFieldAttributes: string[];
|
|
1115
1196
|
selectedUnsubscribePages: number[];
|
|
1116
1197
|
forceRecreate: boolean;
|
|
@@ -1245,6 +1326,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1245
1326
|
value: string;
|
|
1246
1327
|
} | undefined;
|
|
1247
1328
|
}[];
|
|
1329
|
+
availableDynamicContent: {
|
|
1330
|
+
text: string;
|
|
1331
|
+
value: string;
|
|
1332
|
+
fallback?: string | undefined;
|
|
1333
|
+
format?: {
|
|
1334
|
+
key: string;
|
|
1335
|
+
value: string;
|
|
1336
|
+
} | undefined;
|
|
1337
|
+
}[];
|
|
1248
1338
|
customFieldAttributes: string[];
|
|
1249
1339
|
selectedUnsubscribePages: number[];
|
|
1250
1340
|
forceRecreate: boolean;
|
|
@@ -1379,6 +1469,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1379
1469
|
value: string;
|
|
1380
1470
|
} | undefined;
|
|
1381
1471
|
}[];
|
|
1472
|
+
availableDynamicContent: {
|
|
1473
|
+
text: string;
|
|
1474
|
+
value: string;
|
|
1475
|
+
fallback?: string | undefined;
|
|
1476
|
+
format?: {
|
|
1477
|
+
key: string;
|
|
1478
|
+
value: string;
|
|
1479
|
+
} | undefined;
|
|
1480
|
+
}[];
|
|
1382
1481
|
customFieldAttributes: string[];
|
|
1383
1482
|
selectedUnsubscribePages: number[];
|
|
1384
1483
|
forceRecreate: boolean;
|
|
@@ -1513,6 +1612,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1513
1612
|
value: string;
|
|
1514
1613
|
} | undefined;
|
|
1515
1614
|
}[];
|
|
1615
|
+
availableDynamicContent: {
|
|
1616
|
+
text: string;
|
|
1617
|
+
value: string;
|
|
1618
|
+
fallback?: string | undefined;
|
|
1619
|
+
format?: {
|
|
1620
|
+
key: string;
|
|
1621
|
+
value: string;
|
|
1622
|
+
} | undefined;
|
|
1623
|
+
}[];
|
|
1516
1624
|
customFieldAttributes: string[];
|
|
1517
1625
|
selectedUnsubscribePages: number[];
|
|
1518
1626
|
forceRecreate: boolean;
|
|
@@ -1647,6 +1755,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1647
1755
|
value: string;
|
|
1648
1756
|
} | undefined;
|
|
1649
1757
|
}[];
|
|
1758
|
+
availableDynamicContent: {
|
|
1759
|
+
text: string;
|
|
1760
|
+
value: string;
|
|
1761
|
+
fallback?: string | undefined;
|
|
1762
|
+
format?: {
|
|
1763
|
+
key: string;
|
|
1764
|
+
value: string;
|
|
1765
|
+
} | undefined;
|
|
1766
|
+
}[];
|
|
1650
1767
|
customFieldAttributes: string[];
|
|
1651
1768
|
selectedUnsubscribePages: number[];
|
|
1652
1769
|
forceRecreate: boolean;
|
|
@@ -1781,6 +1898,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1781
1898
|
value: string;
|
|
1782
1899
|
} | undefined;
|
|
1783
1900
|
}[];
|
|
1901
|
+
availableDynamicContent: {
|
|
1902
|
+
text: string;
|
|
1903
|
+
value: string;
|
|
1904
|
+
fallback?: string | undefined;
|
|
1905
|
+
format?: {
|
|
1906
|
+
key: string;
|
|
1907
|
+
value: string;
|
|
1908
|
+
} | undefined;
|
|
1909
|
+
}[];
|
|
1784
1910
|
customFieldAttributes: string[];
|
|
1785
1911
|
selectedUnsubscribePages: number[];
|
|
1786
1912
|
forceRecreate: boolean;
|
|
@@ -1915,6 +2041,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1915
2041
|
value: string;
|
|
1916
2042
|
} | undefined;
|
|
1917
2043
|
}[];
|
|
2044
|
+
availableDynamicContent: {
|
|
2045
|
+
text: string;
|
|
2046
|
+
value: string;
|
|
2047
|
+
fallback?: string | undefined;
|
|
2048
|
+
format?: {
|
|
2049
|
+
key: string;
|
|
2050
|
+
value: string;
|
|
2051
|
+
} | undefined;
|
|
2052
|
+
}[];
|
|
1918
2053
|
customFieldAttributes: string[];
|
|
1919
2054
|
selectedUnsubscribePages: number[];
|
|
1920
2055
|
forceRecreate: boolean;
|
|
@@ -2049,6 +2184,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2049
2184
|
value: string;
|
|
2050
2185
|
} | undefined;
|
|
2051
2186
|
}[];
|
|
2187
|
+
availableDynamicContent: {
|
|
2188
|
+
text: string;
|
|
2189
|
+
value: string;
|
|
2190
|
+
fallback?: string | undefined;
|
|
2191
|
+
format?: {
|
|
2192
|
+
key: string;
|
|
2193
|
+
value: string;
|
|
2194
|
+
} | undefined;
|
|
2195
|
+
}[];
|
|
2052
2196
|
customFieldAttributes: string[];
|
|
2053
2197
|
selectedUnsubscribePages: number[];
|
|
2054
2198
|
forceRecreate: boolean;
|
|
@@ -2183,6 +2327,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2183
2327
|
value: string;
|
|
2184
2328
|
} | undefined;
|
|
2185
2329
|
}[];
|
|
2330
|
+
availableDynamicContent: {
|
|
2331
|
+
text: string;
|
|
2332
|
+
value: string;
|
|
2333
|
+
fallback?: string | undefined;
|
|
2334
|
+
format?: {
|
|
2335
|
+
key: string;
|
|
2336
|
+
value: string;
|
|
2337
|
+
} | undefined;
|
|
2338
|
+
}[];
|
|
2186
2339
|
customFieldAttributes: string[];
|
|
2187
2340
|
selectedUnsubscribePages: number[];
|
|
2188
2341
|
forceRecreate: boolean;
|
|
@@ -2317,6 +2470,15 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2317
2470
|
value: string;
|
|
2318
2471
|
} | undefined;
|
|
2319
2472
|
}[];
|
|
2473
|
+
availableDynamicContent: {
|
|
2474
|
+
text: string;
|
|
2475
|
+
value: string;
|
|
2476
|
+
fallback?: string | undefined;
|
|
2477
|
+
format?: {
|
|
2478
|
+
key: string;
|
|
2479
|
+
value: string;
|
|
2480
|
+
} | undefined;
|
|
2481
|
+
}[];
|
|
2320
2482
|
customFieldAttributes: string[];
|
|
2321
2483
|
selectedUnsubscribePages: number[];
|
|
2322
2484
|
forceRecreate: boolean;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DynamicContent } from '@@/Types/generic';
|
|
2
|
+
export interface DynamicContentConversionResult {
|
|
3
|
+
html: string;
|
|
4
|
+
/** Distinct tokens that matched neither a known value nor a known label (reported to the user). */
|
|
5
|
+
unresolved: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Builds a label→item lookup from one or more dynamic-content lists, keyed by
|
|
9
|
+
* normalized label (trimmed, lowercased). When lists overlap, a later list wins
|
|
10
|
+
* for a shared key.
|
|
11
|
+
*/
|
|
12
|
+
export declare const buildDynamicContentLookup: (...lists: DynamicContent[][]) => Map<string, DynamicContent>;
|
|
13
|
+
/**
|
|
14
|
+
* Repairs dynamic-content tokens in a dropped module's HTML, using `lookup`
|
|
15
|
+
* (label→item) built from the account's full dynamic-content list. Returns the
|
|
16
|
+
* rewritten HTML plus the tokens it could not resolve.
|
|
17
|
+
*
|
|
18
|
+
* A token is rewritten to its canonical `{{value}}` form when its name matches a
|
|
19
|
+
* display label (`{{ Phone Number }}` → `{{phone_number}}`). Left untouched: an
|
|
20
|
+
* exact canonical value (already correct — this also stops a valid token being
|
|
21
|
+
* rewritten just because it coincides with an unrelated label), Liquid nested
|
|
22
|
+
* tokens (dotted, e.g. `coupon.code`), recommendation-block variables
|
|
23
|
+
* (`123_0_attr`), allowed system tokens, and `data-*` product tags. The account
|
|
24
|
+
* list is exhaustive, so any remaining token matching neither a value nor a label
|
|
25
|
+
* is reported in `unresolved`; the text itself is always left in place.
|
|
26
|
+
*/
|
|
27
|
+
export declare const convertModuleDynamicContent: (html: string, lookup: Map<string, DynamicContent>, liquidSyntax: boolean) => DynamicContentConversionResult;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { DynamicContent, MergeTag } from '@@/Types/generic';
|
|
2
2
|
export declare const mergeTagToDynamicContent: (mergeTag: MergeTag) => DynamicContent;
|
|
3
3
|
export declare const dynamicContentToMergeTags: (dynamicContentList: DynamicContent[], liquidSyntax?: boolean) => MergeTag[];
|
|
4
|
+
/**
|
|
5
|
+
* Builds the editor merge-tag entries from the template's preselected list plus
|
|
6
|
+
* the account's full available list, deduped by token value (preselected wins so
|
|
7
|
+
* its fallback/format is kept). Registering the full list lets every recognized
|
|
8
|
+
* token — including ones repaired on module drop — render as a chip.
|
|
9
|
+
*/
|
|
10
|
+
export declare const buildMergeTagEntries: (preselected: DynamicContent[], available: DynamicContent[], liquidSyntax?: boolean) => MergeTag[];
|
|
4
11
|
export declare const getCsrfToken: () => string;
|
|
5
12
|
/**
|
|
6
13
|
* URL Parameter utilities
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DATA_ATTRIBUTE_REGEX as A, DYNAMIC_CONTENT_TAG_REGEX as m, ALLOWED_DYNAMIC_SYSTEM_TOKENS as D } from "../enums/html-validator.js";
|
|
2
|
+
import { dynamicContentToMergeTags as T } from "./genericUtil.js";
|
|
3
|
+
const p = "guidoDataMask", M = "EndDataMask", f = /guidoDataMask(\d+)EndDataMask/g, h = /^\d+_\d+_.+$/, E = (o) => o.trim().toLowerCase(), I = (...o) => {
|
|
4
|
+
const r = /* @__PURE__ */ new Map();
|
|
5
|
+
return o.forEach((i) => {
|
|
6
|
+
i.forEach((s) => {
|
|
7
|
+
const a = E(s.text);
|
|
8
|
+
a && r.set(a, s);
|
|
9
|
+
});
|
|
10
|
+
}), r;
|
|
11
|
+
}, w = (o, r, i) => {
|
|
12
|
+
const s = /* @__PURE__ */ new Set(), a = new Set([...r.values()].map((e) => e.value)), u = [];
|
|
13
|
+
return { html: o.replace(A, (e) => (u.push(e), `${p}${u.length - 1}${M}`)).replace(m, (e) => {
|
|
14
|
+
const n = e.slice(2, -2), c = n.indexOf("|"), l = c === -1 ? n : n.slice(0, c), t = l.trim();
|
|
15
|
+
if (t === "" || D.includes(t) || t.includes(".") || h.test(t) || a.has(t))
|
|
16
|
+
return e;
|
|
17
|
+
const d = r.get(E(t));
|
|
18
|
+
if (d) {
|
|
19
|
+
if (c !== -1) {
|
|
20
|
+
const _ = n.slice(c);
|
|
21
|
+
return `{{${l.replace(t, () => d.value)}${_}}}`;
|
|
22
|
+
}
|
|
23
|
+
return T([d], i)[0].value;
|
|
24
|
+
}
|
|
25
|
+
return s.add(t), e;
|
|
26
|
+
}).replace(f, (e, n) => u[Number(n)]), unresolved: [...s] };
|
|
27
|
+
};
|
|
28
|
+
export {
|
|
29
|
+
I as buildDynamicContentLookup,
|
|
30
|
+
w as convertModuleDynamicContent
|
|
31
|
+
};
|
|
@@ -1,47 +1,54 @@
|
|
|
1
|
-
const
|
|
2
|
-
const a =
|
|
3
|
-
text:
|
|
1
|
+
const u = (t) => {
|
|
2
|
+
const a = t.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((l) => l.trim()), [n] = a, e = {
|
|
3
|
+
text: t.label,
|
|
4
4
|
value: n || ""
|
|
5
5
|
};
|
|
6
6
|
if (a.length >= 2) {
|
|
7
|
-
const [, l,
|
|
7
|
+
const [, l, f] = a;
|
|
8
8
|
if (l.startsWith("default:")) {
|
|
9
|
-
let
|
|
10
|
-
|
|
9
|
+
let r = l.slice(8).trim();
|
|
10
|
+
r.startsWith('"') && r.endsWith('"') && (r = r.slice(1, -1)), e.fallback = r;
|
|
11
11
|
} else {
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const r = l.includes("=") ? { key: l.split("=")[0].trim(), value: l.split("=")[1].trim() } : null;
|
|
13
|
+
r ? e.format = r : f || (e.fallback = l), f && (e.fallback = f);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
return
|
|
17
|
-
},
|
|
16
|
+
return e;
|
|
17
|
+
}, s = (t, c = !1) => t.map((a) => {
|
|
18
18
|
if (a.format)
|
|
19
19
|
return {
|
|
20
20
|
label: `${a.text} | ${a.format.key}=${a.format.value}`,
|
|
21
21
|
value: `{{${a.value}|${a.format.key}=${a.format.value}}}`
|
|
22
22
|
};
|
|
23
|
-
if (
|
|
23
|
+
if (c) {
|
|
24
24
|
if (!a.fallback)
|
|
25
25
|
return {
|
|
26
26
|
label: a.text,
|
|
27
27
|
value: `{{ ${a.value} }}`
|
|
28
28
|
};
|
|
29
|
-
const
|
|
29
|
+
const e = !Number.isNaN(Number(a.fallback)) && a.fallback.trim() !== "" ? a.fallback : `"${a.fallback}"`;
|
|
30
30
|
return {
|
|
31
31
|
label: `${a.text} | ${a.fallback}`,
|
|
32
|
-
value: `{{ ${a.value} | default: ${
|
|
32
|
+
value: `{{ ${a.value} | default: ${e} }}`
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
return {
|
|
36
36
|
label: a.fallback ? `${a.text} | ${a.fallback}` : a.text,
|
|
37
37
|
value: a.fallback ? `{{${a.value}|${a.fallback}}}` : `{{${a.value}}}`
|
|
38
38
|
};
|
|
39
|
-
}), o = () => {
|
|
40
|
-
|
|
41
|
-
return
|
|
39
|
+
}), o = (t, c, a = !1) => {
|
|
40
|
+
const n = new Set(t.map((l) => l.value)), e = c.filter((l) => n.has(l.value) ? !1 : (n.add(l.value), !0));
|
|
41
|
+
return [
|
|
42
|
+
...s(t, a),
|
|
43
|
+
...s(e, a)
|
|
44
|
+
];
|
|
45
|
+
}, b = () => {
|
|
46
|
+
var t;
|
|
47
|
+
return ((t = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : t.getAttribute("content")) ?? "";
|
|
42
48
|
};
|
|
43
49
|
export {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
o as buildMergeTagEntries,
|
|
51
|
+
s as dynamicContentToMergeTags,
|
|
52
|
+
b as getCsrfToken,
|
|
53
|
+
u as mergeTagToDynamicContent
|
|
47
54
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.11.0-beta.
|
|
3
|
+
"version": "3.11.0-beta.f2b79f2",
|
|
4
4
|
"description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
|
|
5
5
|
"main": "./dist/guido.umd.cjs",
|
|
6
6
|
"module": "./dist/library.js",
|
|
@@ -23,12 +23,19 @@
|
|
|
23
23
|
"preview": "vite preview",
|
|
24
24
|
"lint": "NODE_OPTIONS=--max-old-space-size=2048 eslint ./ && bun run type-check",
|
|
25
25
|
"lint:fix": "NODE_OPTIONS=--max-old-space-size=2048 eslint --fix ./",
|
|
26
|
+
"lint:e2e-quality": "node scripts/lint-e2e-quality.mjs",
|
|
27
|
+
"lint:e2e-quality:ci": "node scripts/lint-e2e-quality.mjs --ci",
|
|
28
|
+
"lint:e2e-quality:update": "node scripts/lint-e2e-quality.mjs --update-baseline",
|
|
29
|
+
"lint:e2e-quality:baseline-growth": "node scripts/lint-e2e-quality.mjs --check-baseline-growth",
|
|
30
|
+
"test:e2e-mutation": "node scripts/e2e-mutation-check.mjs",
|
|
26
31
|
"type-check": "vue-tsc --noEmit --project tsconfig.config.json && vue-tsc --noEmit --project tsconfig.app.json",
|
|
27
32
|
"test": "vitest run --coverage",
|
|
28
33
|
"test:watch": "vitest",
|
|
29
34
|
"test:visual-update": "npx playwright test --update-snapshots --reporter html",
|
|
30
35
|
"test:e2e:coverage": "E2E_COVERAGE=true playwright test",
|
|
31
36
|
"coverage:e2e:report": "nyc report --reporter=lcov --reporter=text-summary --report-dir=coverage/e2e",
|
|
37
|
+
"test:mutation": "stryker run",
|
|
38
|
+
"test:mutation:since": "CHANGED=$(git diff --name-only --diff-filter=AMR origin/develop...HEAD -- 'src/**/*.ts' ':(glob)src/components/organisms/onboarding/**/*.vue' ':(glob)src/components/organisms/header/**/*.vue' ':(glob)src/components/organisms/unsubscribe/**/*.vue' ':(glob)src/components/organisms/save-as-template/**/*.vue' ':(glob)src/components/organisms/email-preview/**/*.vue' ':(glob)src/components/wrappers/**/*.vue' 'src/components/Guido.vue' ':(exclude)src/**/*.test.ts' ':(exclude)src/**/index.ts' ':(exclude)src/@types/**' ':(exclude)src/enums/**' ':(exclude)src/mock/**' ':(exclude)src/**/_Boilerplate/**' | paste -sd, -); if [ -n \"$CHANGED\" ]; then stryker run --incremental --mutate \"$CHANGED\"; else echo \"No changed mutatable src files vs origin/develop\"; fi",
|
|
32
39
|
"prepare": "husky",
|
|
33
40
|
"preinstall": "rm -rf ./node_modules/.vite"
|
|
34
41
|
},
|
|
@@ -52,6 +59,8 @@
|
|
|
52
59
|
"@eslint/eslintrc": "3.3.0",
|
|
53
60
|
"@eslint/js": "8.57.1",
|
|
54
61
|
"@playwright/test": "1.57.0",
|
|
62
|
+
"@stryker-mutator/core": "9.6.1",
|
|
63
|
+
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
55
64
|
"@stylistic/eslint-plugin": "3.1.0",
|
|
56
65
|
"@stylistic/eslint-plugin-migrate": "3.1.0",
|
|
57
66
|
"@types/eslint": "8.56.12",
|