@useinsider/guido 3.11.0-beta.f4ab671 → 3.11.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.
Files changed (26) hide show
  1. package/dist/@types/config/schemas.js +84 -105
  2. package/dist/components/organisms/header/EditorActions.vue.js +1 -1
  3. package/dist/components/organisms/header/HeaderWrapper.vue.js +3 -3
  4. package/dist/components/organisms/header/HeaderWrapper.vue2.js +0 -2
  5. package/dist/components/organisms/header/version-history/VersionHistory.vue.js +1 -1
  6. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue.js +5 -5
  7. package/dist/components/organisms/unsubscribe/UnsubscribePageSelection.vue2.js +2 -2
  8. package/dist/components/organisms/unsubscribe/UnsubscribeTypeSelection.vue.js +3 -3
  9. package/dist/components/organisms/unsubscribe/UnsubscribeTypeSelection.vue2.js +9 -9
  10. package/dist/composables/useStripo.js +67 -70
  11. package/dist/guido.css +1 -1
  12. package/dist/node_modules/valibot/dist/index.js +112 -148
  13. package/dist/src/@types/config/schemas.d.ts +0 -32
  14. package/dist/src/@types/generic.d.ts +0 -18
  15. package/dist/src/composables/useConfig.d.ts +0 -6
  16. package/dist/src/composables/useHtmlValidator.test.d.ts +1 -0
  17. package/dist/src/config/compiler/utils/recommendationIgnoreUtils.test.d.ts +1 -0
  18. package/dist/src/library.d.ts +1 -1
  19. package/dist/src/stores/config.d.ts +0 -54
  20. package/dist/src/utils/genericUtil.d.ts +1 -18
  21. package/dist/utils/genericUtil.js +21 -42
  22. package/package.json +1 -10
  23. package/dist/composables/useModuleDynamicContentRepair.js +0 -37
  24. package/dist/src/composables/useModuleDynamicContentRepair.d.ts +0 -18
  25. package/dist/src/utils/dynamicContentConverter.d.ts +0 -27
  26. package/dist/utils/dynamicContentConverter.js +0 -31
@@ -5,7 +5,6 @@
5
5
  * All types are inferred from these schemas to ensure single source of truth.
6
6
  * @module @types/config/schemas
7
7
  */
8
- import type { DynamicContentNode } from '../generic';
9
8
  import type { SavedTemplateDetails } from '../stripo';
10
9
  import * as v from 'valibot';
11
10
  /**
@@ -87,21 +86,6 @@ export declare const DynamicContentSchema: v.ObjectSchema<{
87
86
  readonly value: v.StringSchema<undefined>;
88
87
  }, undefined>, undefined>;
89
88
  }, undefined>;
90
- /**
91
- * A node in the partner-keyed dynamic-content tree (backend categorized-fields
92
- * shape). Loose so the many extra backend fields pass through untouched; Guido
93
- * only reads text/tag_text/value and recurses children/select_items.
94
- */
95
- export declare const DynamicContentNodeSchema: v.GenericSchema<DynamicContentNode>;
96
- /**
97
- * Partner-keyed dynamic-content list: `{ [partnerName]: DynamicContentNode[] }`.
98
- * Architect is multi-partner, so the raw structure is keyed by partner name.
99
- *
100
- * Per-entry `fallback`: the raw backend payload may carry non-array metadata
101
- * keys, so a value that is not a node array degrades to `[]` instead of failing
102
- * the whole config validation (the repair feature is fail-open).
103
- */
104
- export declare const DynamicContentListSchema: v.RecordSchema<v.StringSchema<undefined>, v.SchemaWithFallback<v.ArraySchema<v.GenericSchema<DynamicContentNode>, undefined>, readonly []>, undefined>;
105
89
  /**
106
90
  * Legacy recommendation block config (v1 format) keyed by block ID.
107
91
  *
@@ -243,14 +227,6 @@ export declare const TemplateSchema: v.ObjectSchema<{
243
227
  readonly value: v.StringSchema<undefined>;
244
228
  }, undefined>, undefined>;
245
229
  }, undefined>, undefined>, readonly []>;
246
- /**
247
- * Partner-keyed set of dynamic-content items the account offers, e.g.
248
- * `{ [partnerName]: [{ text, value, children }] }`. Guido flattens it
249
- * (union across partners, leaf attributes only) into the label→token map
250
- * that repairs label-form placeholders (`{{ Phone Number }}`) in dropped
251
- * saved modules.
252
- */
253
- readonly dynamicContentList: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.SchemaWithFallback<v.ArraySchema<v.GenericSchema<DynamicContentNode>, undefined>, readonly []>, undefined>, {}>;
254
230
  /** Valid custom field attribute names from the partner's categorized fields */
255
231
  readonly customFieldAttributes: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, readonly []>;
256
232
  /** Selected unsubscribe page IDs */
@@ -646,14 +622,6 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
646
622
  readonly value: v.StringSchema<undefined>;
647
623
  }, undefined>, undefined>;
648
624
  }, undefined>, undefined>, readonly []>;
649
- /**
650
- * Partner-keyed set of dynamic-content items the account offers, e.g.
651
- * `{ [partnerName]: [{ text, value, children }] }`. Guido flattens it
652
- * (union across partners, leaf attributes only) into the label→token map
653
- * that repairs label-form placeholders (`{{ Phone Number }}`) in dropped
654
- * saved modules.
655
- */
656
- readonly dynamicContentList: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.SchemaWithFallback<v.ArraySchema<v.GenericSchema<DynamicContentNode>, undefined>, readonly []>, undefined>, {}>;
657
625
  /** Valid custom field attribute names from the partner's categorized fields */
658
626
  readonly customFieldAttributes: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, readonly []>;
659
627
  /** Selected unsubscribe page IDs */
@@ -13,24 +13,6 @@ export type BaseDynamicContent = {
13
13
  export type DynamicContent = BaseDynamicContent & {
14
14
  text: string;
15
15
  };
16
- /**
17
- * A node in the partner-keyed dynamic-content tree (backend categorized-fields
18
- * shape). Category nodes carry `children`/`select_items`; leaf nodes are the
19
- * real attributes. Extra backend fields are allowed and ignored.
20
- */
21
- export type DynamicContentNode = {
22
- text?: string;
23
- tag_text?: string;
24
- value?: string;
25
- children?: DynamicContentNode[];
26
- select_items?: DynamicContentNode[];
27
- };
28
- /**
29
- * Partner-keyed dynamic-content list. Architect is multi-partner, so the map is
30
- * keyed by partner name; each entry is that partner's category tree. Guido
31
- * flattens it (union across partners, leaf attributes only) into a `DynamicContent[]`.
32
- */
33
- export type DynamicContentList = Record<string, DynamicContentNode[]>;
34
16
  export type MergeTag = BaseDynamicContent & {
35
17
  label: string;
36
18
  selStart?: number;
@@ -34,9 +34,6 @@ export declare const useConfig: () => {
34
34
  value: string;
35
35
  } | undefined;
36
36
  }[];
37
- dynamicContentList: {
38
- [x: string]: import("../library").DynamicContentNode[];
39
- };
40
37
  customFieldAttributes: string[];
41
38
  selectedUnsubscribePages: number[];
42
39
  forceRecreate: boolean;
@@ -165,9 +162,6 @@ export declare const useConfig: () => {
165
162
  value: string;
166
163
  } | undefined;
167
164
  }[];
168
- dynamicContentList: {
169
- [x: string]: import("../library").DynamicContentNode[];
170
- };
171
165
  customFieldAttributes: string[];
172
166
  selectedUnsubscribePages: number[];
173
167
  forceRecreate: boolean;
@@ -0,0 +1 @@
1
+ export {};
@@ -2,4 +2,4 @@ export { default as Guido } from './components/Guido.vue';
2
2
  export type { GuidoConfig, GuidoConfigInput, IdentityConfig, PartnerConfig, TemplateConfig, TemplateMigrationConfig, LegacyRecommendationConfig, EditorConfig, UIConfig, FeaturesConfig, BlocksConfig, CompilerConfig, DynamicContent, EmailHeader, DefaultBlockType, CustomBlockType, ValidationResult, ValidationError, } from './@types/config';
3
3
  export { validateConfig, parseConfig, parseConfigSafe, isValidConfig, getValidationErrors, MessageType, ProductType, } from './@types/config';
4
4
  export type { StripoEventType } from './@types/events';
5
- export type { PositionData, DynamicContentEvent, MergeTagClickEvent, MergeTag, BaseDynamicContent, DynamicContentNode, DynamicContentList, TooltipOptions, TextValueObject, L10n, } from './@types/generic';
5
+ export type { PositionData, DynamicContentEvent, MergeTagClickEvent, MergeTag, BaseDynamicContent, TooltipOptions, TextValueObject, L10n, } from './@types/generic';
@@ -39,9 +39,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
39
39
  value: string;
40
40
  } | undefined;
41
41
  }[];
42
- dynamicContentList: {
43
- [x: string]: import("../library").DynamicContentNode[];
44
- };
45
42
  customFieldAttributes: string[];
46
43
  selectedUnsubscribePages: number[];
47
44
  forceRecreate: boolean;
@@ -176,9 +173,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
176
173
  value: string;
177
174
  } | undefined;
178
175
  }[];
179
- dynamicContentList: {
180
- [x: string]: import("../library").DynamicContentNode[];
181
- };
182
176
  customFieldAttributes: string[];
183
177
  selectedUnsubscribePages: number[];
184
178
  forceRecreate: boolean;
@@ -313,9 +307,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
313
307
  value: string;
314
308
  } | undefined;
315
309
  }[];
316
- dynamicContentList: {
317
- [x: string]: import("../library").DynamicContentNode[];
318
- };
319
310
  customFieldAttributes: string[];
320
311
  selectedUnsubscribePages: number[];
321
312
  forceRecreate: boolean;
@@ -450,9 +441,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
450
441
  value: string;
451
442
  } | undefined;
452
443
  }[];
453
- dynamicContentList: {
454
- [x: string]: import("../library").DynamicContentNode[];
455
- };
456
444
  customFieldAttributes: string[];
457
445
  selectedUnsubscribePages: number[];
458
446
  forceRecreate: boolean;
@@ -587,9 +575,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
587
575
  value: string;
588
576
  } | undefined;
589
577
  }[];
590
- dynamicContentList: {
591
- [x: string]: import("../library").DynamicContentNode[];
592
- };
593
578
  customFieldAttributes: string[];
594
579
  selectedUnsubscribePages: number[];
595
580
  forceRecreate: boolean;
@@ -724,9 +709,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
724
709
  value: string;
725
710
  } | undefined;
726
711
  }[];
727
- dynamicContentList: {
728
- [x: string]: import("../library").DynamicContentNode[];
729
- };
730
712
  customFieldAttributes: string[];
731
713
  selectedUnsubscribePages: number[];
732
714
  forceRecreate: boolean;
@@ -861,9 +843,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
861
843
  value: string;
862
844
  } | undefined;
863
845
  }[];
864
- dynamicContentList: {
865
- [x: string]: import("../library").DynamicContentNode[];
866
- };
867
846
  customFieldAttributes: string[];
868
847
  selectedUnsubscribePages: number[];
869
848
  forceRecreate: boolean;
@@ -998,9 +977,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
998
977
  value: string;
999
978
  } | undefined;
1000
979
  }[];
1001
- dynamicContentList: {
1002
- [x: string]: import("../library").DynamicContentNode[];
1003
- };
1004
980
  customFieldAttributes: string[];
1005
981
  selectedUnsubscribePages: number[];
1006
982
  forceRecreate: boolean;
@@ -1135,9 +1111,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1135
1111
  value: string;
1136
1112
  } | undefined;
1137
1113
  }[];
1138
- dynamicContentList: {
1139
- [x: string]: import("../library").DynamicContentNode[];
1140
- };
1141
1114
  customFieldAttributes: string[];
1142
1115
  selectedUnsubscribePages: number[];
1143
1116
  forceRecreate: boolean;
@@ -1272,9 +1245,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1272
1245
  value: string;
1273
1246
  } | undefined;
1274
1247
  }[];
1275
- dynamicContentList: {
1276
- [x: string]: import("../library").DynamicContentNode[];
1277
- };
1278
1248
  customFieldAttributes: string[];
1279
1249
  selectedUnsubscribePages: number[];
1280
1250
  forceRecreate: boolean;
@@ -1409,9 +1379,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1409
1379
  value: string;
1410
1380
  } | undefined;
1411
1381
  }[];
1412
- dynamicContentList: {
1413
- [x: string]: import("../library").DynamicContentNode[];
1414
- };
1415
1382
  customFieldAttributes: string[];
1416
1383
  selectedUnsubscribePages: number[];
1417
1384
  forceRecreate: boolean;
@@ -1546,9 +1513,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1546
1513
  value: string;
1547
1514
  } | undefined;
1548
1515
  }[];
1549
- dynamicContentList: {
1550
- [x: string]: import("../library").DynamicContentNode[];
1551
- };
1552
1516
  customFieldAttributes: string[];
1553
1517
  selectedUnsubscribePages: number[];
1554
1518
  forceRecreate: boolean;
@@ -1683,9 +1647,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1683
1647
  value: string;
1684
1648
  } | undefined;
1685
1649
  }[];
1686
- dynamicContentList: {
1687
- [x: string]: import("../library").DynamicContentNode[];
1688
- };
1689
1650
  customFieldAttributes: string[];
1690
1651
  selectedUnsubscribePages: number[];
1691
1652
  forceRecreate: boolean;
@@ -1820,9 +1781,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1820
1781
  value: string;
1821
1782
  } | undefined;
1822
1783
  }[];
1823
- dynamicContentList: {
1824
- [x: string]: import("../library").DynamicContentNode[];
1825
- };
1826
1784
  customFieldAttributes: string[];
1827
1785
  selectedUnsubscribePages: number[];
1828
1786
  forceRecreate: boolean;
@@ -1957,9 +1915,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1957
1915
  value: string;
1958
1916
  } | undefined;
1959
1917
  }[];
1960
- dynamicContentList: {
1961
- [x: string]: import("../library").DynamicContentNode[];
1962
- };
1963
1918
  customFieldAttributes: string[];
1964
1919
  selectedUnsubscribePages: number[];
1965
1920
  forceRecreate: boolean;
@@ -2094,9 +2049,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2094
2049
  value: string;
2095
2050
  } | undefined;
2096
2051
  }[];
2097
- dynamicContentList: {
2098
- [x: string]: import("../library").DynamicContentNode[];
2099
- };
2100
2052
  customFieldAttributes: string[];
2101
2053
  selectedUnsubscribePages: number[];
2102
2054
  forceRecreate: boolean;
@@ -2231,9 +2183,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2231
2183
  value: string;
2232
2184
  } | undefined;
2233
2185
  }[];
2234
- dynamicContentList: {
2235
- [x: string]: import("../library").DynamicContentNode[];
2236
- };
2237
2186
  customFieldAttributes: string[];
2238
2187
  selectedUnsubscribePages: number[];
2239
2188
  forceRecreate: boolean;
@@ -2368,9 +2317,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2368
2317
  value: string;
2369
2318
  } | undefined;
2370
2319
  }[];
2371
- dynamicContentList: {
2372
- [x: string]: import("../library").DynamicContentNode[];
2373
- };
2374
2320
  customFieldAttributes: string[];
2375
2321
  selectedUnsubscribePages: number[];
2376
2322
  forceRecreate: boolean;
@@ -1,23 +1,6 @@
1
- import type { DynamicContent, DynamicContentList, MergeTag } from '@@/Types/generic';
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
- * Flattens the partner-keyed dynamic-content tree into a deduped flat list of the
6
- * ACTIVE partner's leaf attributes. A single editor session targets one partner,
7
- * so only the FIRST partner entry is used (the sole entry for a single-partner
8
- * host like email-fe; merging all partners would risk cross-partner label
9
- * collisions). A node carrying `children`/`select_items` is a category grouping:
10
- * recursed into but never collected itself — only real leaf attributes
11
- * (`text`/`tag_text` + `value`) become `{ text, value }` pairs.
12
- */
13
- export declare const flattenDynamicContentList: (list: DynamicContentList | undefined | null) => DynamicContent[];
14
- /**
15
- * Builds the editor merge-tag entries from the template's preselected list plus
16
- * the account's full available list, deduped by token value (preselected wins so
17
- * its fallback/format is kept). Registering the full list lets every recognized
18
- * token — including ones repaired on module drop — render as a chip.
19
- */
20
- export declare const buildMergeTagEntries: (preselected: DynamicContent[], available: DynamicContent[], liquidSyntax?: boolean) => MergeTag[];
21
4
  export declare const getCsrfToken: () => string;
22
5
  /**
23
6
  * URL Parameter utilities
@@ -1,68 +1,47 @@
1
- const o = (l) => {
2
- const a = l.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((t) => t.trim()), [c] = a, r = {
3
- text: l.label,
4
- value: c || ""
1
+ const s = (e) => {
2
+ const a = e.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((l) => l.trim()), [n] = a, c = {
3
+ text: e.label,
4
+ value: n || ""
5
5
  };
6
6
  if (a.length >= 2) {
7
- const [, t, e] = a;
8
- if (t.startsWith("default:")) {
9
- let n = t.slice(8).trim();
10
- n.startsWith('"') && n.endsWith('"') && (n = n.slice(1, -1)), r.fallback = n;
7
+ const [, l, r] = a;
8
+ if (l.startsWith("default:")) {
9
+ let t = l.slice(8).trim();
10
+ t.startsWith('"') && t.endsWith('"') && (t = t.slice(1, -1)), c.fallback = t;
11
11
  } else {
12
- const n = t.includes("=") ? { key: t.split("=")[0].trim(), value: t.split("=")[1].trim() } : null;
13
- n ? r.format = n : e || (r.fallback = t), e && (r.fallback = e);
12
+ const t = l.includes("=") ? { key: l.split("=")[0].trim(), value: l.split("=")[1].trim() } : null;
13
+ t ? c.format = t : r || (c.fallback = l), r && (c.fallback = r);
14
14
  }
15
15
  }
16
- return r;
17
- }, f = (l, s = !1) => l.map((a) => {
16
+ return c;
17
+ }, u = (e, f = !1) => e.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 (s) {
23
+ if (f) {
24
24
  if (!a.fallback)
25
25
  return {
26
26
  label: a.text,
27
27
  value: `{{ ${a.value} }}`
28
28
  };
29
- const r = !Number.isNaN(Number(a.fallback)) && a.fallback.trim() !== "" ? a.fallback : `"${a.fallback}"`;
29
+ const c = !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: ${r} }}`
32
+ value: `{{ ${a.value} | default: ${c} }}`
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
- }), b = (l) => {
40
- const s = [], a = /* @__PURE__ */ new Set(), c = (t) => {
41
- Array.isArray(t) && t.forEach((e) => {
42
- const n = [...e.children ?? [], ...e.select_items ?? []];
43
- if (n.length > 0) {
44
- c(n);
45
- return;
46
- }
47
- const u = e.text || e.tag_text;
48
- u && e.value && !a.has(e.value) && (a.add(e.value), s.push({ text: u, value: e.value }));
49
- });
50
- }, [r] = Object.values(l ?? {});
51
- return c(r), s;
52
- }, v = (l, s, a = !1) => {
53
- const c = new Set(l.map((t) => t.value)), r = s.filter((t) => c.has(t.value) ? !1 : (c.add(t.value), !0));
54
- return [
55
- ...f(l, a),
56
- ...f(r, a)
57
- ];
58
- }, i = () => {
59
- var l;
60
- return ((l = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : l.getAttribute("content")) ?? "";
39
+ }), o = () => {
40
+ var e;
41
+ return ((e = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : e.getAttribute("content")) ?? "";
61
42
  };
62
43
  export {
63
- v as buildMergeTagEntries,
64
- f as dynamicContentToMergeTags,
65
- b as flattenDynamicContentList,
66
- i as getCsrfToken,
67
- o as mergeTagToDynamicContent
44
+ u as dynamicContentToMergeTags,
45
+ o as getCsrfToken,
46
+ s as mergeTagToDynamicContent
68
47
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.11.0-beta.f4ab671",
3
+ "version": "3.11.0",
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,19 +23,12 @@
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",
31
26
  "type-check": "vue-tsc --noEmit --project tsconfig.config.json && vue-tsc --noEmit --project tsconfig.app.json",
32
27
  "test": "vitest run --coverage",
33
28
  "test:watch": "vitest",
34
29
  "test:visual-update": "npx playwright test --update-snapshots --reporter html",
35
30
  "test:e2e:coverage": "E2E_COVERAGE=true playwright test",
36
31
  "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",
39
32
  "prepare": "husky",
40
33
  "preinstall": "rm -rf ./node_modules/.vite"
41
34
  },
@@ -59,8 +52,6 @@
59
52
  "@eslint/eslintrc": "3.3.0",
60
53
  "@eslint/js": "8.57.1",
61
54
  "@playwright/test": "1.57.0",
62
- "@stryker-mutator/core": "9.6.1",
63
- "@stryker-mutator/vitest-runner": "9.6.1",
64
55
  "@stylistic/eslint-plugin": "3.1.0",
65
56
  "@stylistic/eslint-plugin-migrate": "3.1.0",
66
57
  "@types/eslint": "8.56.12",
@@ -1,37 +0,0 @@
1
- import { useConfig as C } from "./useConfig.js";
2
- import { useToaster as D } from "./useToaster.js";
3
- import { useTranslations as T } from "./useTranslations.js";
4
- import { ToasterTypeOptions as g } from "../enums/toaster.js";
5
- import { buildDynamicContentLookup as h, convertModuleDynamicContent as O } from "../utils/dynamicContentConverter.js";
6
- import { flattenDynamicContentList as f } from "../utils/genericUtil.js";
7
- const M = "dynamic-content.unresolved-attributes-on-drop", b = () => {
8
- const { template: i, isFeatureEnabled: p } = C(), { showToaster: m } = D(), a = T();
9
- return { handleModuleAdd: (n, o) => {
10
- var s, c, l;
11
- try {
12
- if ((n == null ? void 0 : n.action) !== "ADD" && (n == null ? void 0 : n.action) !== "COPY")
13
- return;
14
- const e = h(f((s = i.value) == null ? void 0 : s.dynamicContentList));
15
- if (e.size === 0)
16
- return;
17
- const t = (c = o == null ? void 0 : o.getTargetNode) == null ? void 0 : c.call(o), r = (l = t == null ? void 0 : t.getOuterHTML) == null ? void 0 : l.call(t);
18
- if (!t || typeof r != "string")
19
- return;
20
- const { html: u, unresolved: y } = O(
21
- r,
22
- e,
23
- p("liquidSyntax")
24
- );
25
- u !== r && o.modifyHtml(t).replaceWith(u), y.length > 0 && m({
26
- type: g.Warning,
27
- message: a(M)
28
- });
29
- } catch (e) {
30
- console.error("Failed to repair dynamic content on module add:", e);
31
- }
32
- } };
33
- };
34
- export {
35
- M as UNRESOLVED_DYNAMIC_CONTENT_ON_DROP_KEY,
36
- b as useModuleDynamicContentRepair
37
- };
@@ -1,18 +0,0 @@
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
- };
@@ -1,27 +0,0 @@
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,31 +0,0 @@
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
- };