@useinsider/guido 3.12.0-beta.3450e5f → 3.12.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 (33) hide show
  1. package/README.md +29 -0
  2. package/dist/@types/config/schemas.js +104 -84
  3. package/dist/components/organisms/onboarding/AMPOnboarding.vue.js +11 -10
  4. package/dist/components/organisms/onboarding/GenericOnboarding.vue.js +1 -1
  5. package/dist/components/organisms/onboarding/ItemsOnboarding.vue.js +6 -6
  6. package/dist/components/organisms/onboarding/NewVersionPopup.vue2.js +20 -23
  7. package/dist/components/organisms/onboarding/TextBlockOnboarding.vue.js +3 -3
  8. package/dist/components/organisms/onboarding/VersionHistoryOnboarding.vue.js +8 -7
  9. package/dist/composables/useModuleDynamicContentRepair.js +37 -0
  10. package/dist/composables/useStripo.js +70 -67
  11. package/dist/config/migrator/index.js +7 -6
  12. package/dist/config/migrator/socialIconMigrator.js +29 -0
  13. package/dist/enums/academy.js +1 -1
  14. package/dist/enums/date.js +3 -4
  15. package/dist/extensions/Blocks/Items/controls/price/formattedPrice.js +43 -41
  16. package/dist/guido.css +1 -1
  17. package/dist/node_modules/valibot/dist/index.js +148 -112
  18. package/dist/src/@types/config/schemas.d.ts +30 -0
  19. package/dist/src/@types/generic.d.ts +18 -0
  20. package/dist/src/composables/useConfig.d.ts +6 -0
  21. package/dist/src/composables/useModuleDynamicContentRepair.d.ts +18 -0
  22. package/dist/src/config/migrator/socialIconMigrator.d.ts +1 -0
  23. package/dist/src/enums/academy.d.ts +3 -3
  24. package/dist/src/library.d.ts +1 -1
  25. package/dist/src/stores/config.d.ts +54 -0
  26. package/dist/src/utils/dynamicContentConverter.d.ts +27 -0
  27. package/dist/src/utils/environmentUtil.d.ts +5 -2
  28. package/dist/src/utils/genericUtil.d.ts +18 -1
  29. package/dist/utils/dateUtil.js +10 -23
  30. package/dist/utils/dynamicContentConverter.js +31 -0
  31. package/dist/utils/environmentUtil.js +3 -2
  32. package/dist/utils/genericUtil.js +42 -21
  33. package/package.json +1 -1
@@ -5,6 +5,7 @@
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';
8
9
  import type { SavedTemplateDetails } from '../stripo';
9
10
  import * as v from 'valibot';
10
11
  /**
@@ -86,6 +87,21 @@ export declare const DynamicContentSchema: v.ObjectSchema<{
86
87
  readonly value: v.StringSchema<undefined>;
87
88
  }, undefined>, undefined>;
88
89
  }, 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>;
89
105
  /**
90
106
  * Legacy recommendation block config (v1 format) keyed by block ID.
91
107
  *
@@ -227,6 +243,13 @@ export declare const TemplateSchema: v.ObjectSchema<{
227
243
  readonly value: v.StringSchema<undefined>;
228
244
  }, undefined>, undefined>;
229
245
  }, undefined>, undefined>, readonly []>;
246
+ /**
247
+ * Partner-keyed set of dynamic-content items the account offers, e.g.
248
+ * `{ [partnerName]: [{ text, value, children }] }`. Guido flattens the active
249
+ * (first) partner's leaf attributes into the label→token map that repairs
250
+ * label-form placeholders (`{{ Phone Number }}`) in dropped saved modules.
251
+ */
252
+ readonly dynamicContentList: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.SchemaWithFallback<v.ArraySchema<v.GenericSchema<DynamicContentNode>, undefined>, readonly []>, undefined>, {}>;
230
253
  /** Valid custom field attribute names from the partner's categorized fields */
231
254
  readonly customFieldAttributes: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, readonly []>;
232
255
  /** Selected unsubscribe page IDs */
@@ -622,6 +645,13 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
622
645
  readonly value: v.StringSchema<undefined>;
623
646
  }, undefined>, undefined>;
624
647
  }, undefined>, undefined>, readonly []>;
648
+ /**
649
+ * Partner-keyed set of dynamic-content items the account offers, e.g.
650
+ * `{ [partnerName]: [{ text, value, children }] }`. Guido flattens the active
651
+ * (first) partner's leaf attributes into the label→token map that repairs
652
+ * label-form placeholders (`{{ Phone Number }}`) in dropped saved modules.
653
+ */
654
+ readonly dynamicContentList: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.SchemaWithFallback<v.ArraySchema<v.GenericSchema<DynamicContentNode>, undefined>, readonly []>, undefined>, {}>;
625
655
  /** Valid custom field attribute names from the partner's categorized fields */
626
656
  readonly customFieldAttributes: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, readonly []>;
627
657
  /** Selected unsubscribe page IDs */
@@ -13,6 +13,24 @@ 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 the active (first) partner's leaf attributes into a `DynamicContent[]`.
32
+ */
33
+ export type DynamicContentList = Record<string, DynamicContentNode[]>;
16
34
  export type MergeTag = BaseDynamicContent & {
17
35
  label: string;
18
36
  selStart?: number;
@@ -34,6 +34,9 @@ export declare const useConfig: () => {
34
34
  value: string;
35
35
  } | undefined;
36
36
  }[];
37
+ dynamicContentList: {
38
+ [x: string]: import("../library").DynamicContentNode[];
39
+ };
37
40
  customFieldAttributes: string[];
38
41
  selectedUnsubscribePages: number[];
39
42
  forceRecreate: boolean;
@@ -162,6 +165,9 @@ export declare const useConfig: () => {
162
165
  value: string;
163
166
  } | undefined;
164
167
  }[];
168
+ dynamicContentList: {
169
+ [x: string]: import("../library").DynamicContentNode[];
170
+ };
165
171
  customFieldAttributes: string[];
166
172
  selectedUnsubscribePages: number[];
167
173
  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
+ };
@@ -0,0 +1 @@
1
+ export declare function migrateSocialIcons(html: string): string;
@@ -5,8 +5,8 @@
5
5
  * for easy maintenance and domain migration.
6
6
  */
7
7
  export declare const ACADEMY_LINKS: {
8
- readonly EMAIL_EDITOR: "https://academy.insiderone.com//docs/email-drag-and-drop-editor";
9
- readonly GLOBAL_UNSUBSCRIBE: "https://academy.insiderone.com//docs/global-unsubscribe-preference-center";
10
- readonly AMP_FOR_EMAILS: "https://academy.insiderone.com//docs/amp-for-emails";
8
+ readonly EMAIL_EDITOR: "https://academy.insiderone.com/docs/email-drag-and-drop-editor";
9
+ readonly GLOBAL_UNSUBSCRIBE: "https://academy.insiderone.com/docs/global-unsubscribe-preference-center";
10
+ readonly AMP_FOR_EMAILS: "https://academy.insiderone.com/docs/amp-for-emails";
11
11
  };
12
12
  export type AcademyLinkKey = keyof typeof ACADEMY_LINKS;
@@ -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, TooltipOptions, TextValueObject, L10n, } from './@types/generic';
5
+ export type { PositionData, DynamicContentEvent, MergeTagClickEvent, MergeTag, BaseDynamicContent, DynamicContentNode, DynamicContentList, TooltipOptions, TextValueObject, L10n, } from './@types/generic';
@@ -39,6 +39,9 @@ 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
+ };
42
45
  customFieldAttributes: string[];
43
46
  selectedUnsubscribePages: number[];
44
47
  forceRecreate: boolean;
@@ -173,6 +176,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
173
176
  value: string;
174
177
  } | undefined;
175
178
  }[];
179
+ dynamicContentList: {
180
+ [x: string]: import("../library").DynamicContentNode[];
181
+ };
176
182
  customFieldAttributes: string[];
177
183
  selectedUnsubscribePages: number[];
178
184
  forceRecreate: boolean;
@@ -307,6 +313,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
307
313
  value: string;
308
314
  } | undefined;
309
315
  }[];
316
+ dynamicContentList: {
317
+ [x: string]: import("../library").DynamicContentNode[];
318
+ };
310
319
  customFieldAttributes: string[];
311
320
  selectedUnsubscribePages: number[];
312
321
  forceRecreate: boolean;
@@ -441,6 +450,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
441
450
  value: string;
442
451
  } | undefined;
443
452
  }[];
453
+ dynamicContentList: {
454
+ [x: string]: import("../library").DynamicContentNode[];
455
+ };
444
456
  customFieldAttributes: string[];
445
457
  selectedUnsubscribePages: number[];
446
458
  forceRecreate: boolean;
@@ -575,6 +587,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
575
587
  value: string;
576
588
  } | undefined;
577
589
  }[];
590
+ dynamicContentList: {
591
+ [x: string]: import("../library").DynamicContentNode[];
592
+ };
578
593
  customFieldAttributes: string[];
579
594
  selectedUnsubscribePages: number[];
580
595
  forceRecreate: boolean;
@@ -709,6 +724,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
709
724
  value: string;
710
725
  } | undefined;
711
726
  }[];
727
+ dynamicContentList: {
728
+ [x: string]: import("../library").DynamicContentNode[];
729
+ };
712
730
  customFieldAttributes: string[];
713
731
  selectedUnsubscribePages: number[];
714
732
  forceRecreate: boolean;
@@ -843,6 +861,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
843
861
  value: string;
844
862
  } | undefined;
845
863
  }[];
864
+ dynamicContentList: {
865
+ [x: string]: import("../library").DynamicContentNode[];
866
+ };
846
867
  customFieldAttributes: string[];
847
868
  selectedUnsubscribePages: number[];
848
869
  forceRecreate: boolean;
@@ -977,6 +998,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
977
998
  value: string;
978
999
  } | undefined;
979
1000
  }[];
1001
+ dynamicContentList: {
1002
+ [x: string]: import("../library").DynamicContentNode[];
1003
+ };
980
1004
  customFieldAttributes: string[];
981
1005
  selectedUnsubscribePages: number[];
982
1006
  forceRecreate: boolean;
@@ -1111,6 +1135,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1111
1135
  value: string;
1112
1136
  } | undefined;
1113
1137
  }[];
1138
+ dynamicContentList: {
1139
+ [x: string]: import("../library").DynamicContentNode[];
1140
+ };
1114
1141
  customFieldAttributes: string[];
1115
1142
  selectedUnsubscribePages: number[];
1116
1143
  forceRecreate: boolean;
@@ -1245,6 +1272,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1245
1272
  value: string;
1246
1273
  } | undefined;
1247
1274
  }[];
1275
+ dynamicContentList: {
1276
+ [x: string]: import("../library").DynamicContentNode[];
1277
+ };
1248
1278
  customFieldAttributes: string[];
1249
1279
  selectedUnsubscribePages: number[];
1250
1280
  forceRecreate: boolean;
@@ -1379,6 +1409,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1379
1409
  value: string;
1380
1410
  } | undefined;
1381
1411
  }[];
1412
+ dynamicContentList: {
1413
+ [x: string]: import("../library").DynamicContentNode[];
1414
+ };
1382
1415
  customFieldAttributes: string[];
1383
1416
  selectedUnsubscribePages: number[];
1384
1417
  forceRecreate: boolean;
@@ -1513,6 +1546,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1513
1546
  value: string;
1514
1547
  } | undefined;
1515
1548
  }[];
1549
+ dynamicContentList: {
1550
+ [x: string]: import("../library").DynamicContentNode[];
1551
+ };
1516
1552
  customFieldAttributes: string[];
1517
1553
  selectedUnsubscribePages: number[];
1518
1554
  forceRecreate: boolean;
@@ -1647,6 +1683,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1647
1683
  value: string;
1648
1684
  } | undefined;
1649
1685
  }[];
1686
+ dynamicContentList: {
1687
+ [x: string]: import("../library").DynamicContentNode[];
1688
+ };
1650
1689
  customFieldAttributes: string[];
1651
1690
  selectedUnsubscribePages: number[];
1652
1691
  forceRecreate: boolean;
@@ -1781,6 +1820,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1781
1820
  value: string;
1782
1821
  } | undefined;
1783
1822
  }[];
1823
+ dynamicContentList: {
1824
+ [x: string]: import("../library").DynamicContentNode[];
1825
+ };
1784
1826
  customFieldAttributes: string[];
1785
1827
  selectedUnsubscribePages: number[];
1786
1828
  forceRecreate: boolean;
@@ -1915,6 +1957,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1915
1957
  value: string;
1916
1958
  } | undefined;
1917
1959
  }[];
1960
+ dynamicContentList: {
1961
+ [x: string]: import("../library").DynamicContentNode[];
1962
+ };
1918
1963
  customFieldAttributes: string[];
1919
1964
  selectedUnsubscribePages: number[];
1920
1965
  forceRecreate: boolean;
@@ -2049,6 +2094,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2049
2094
  value: string;
2050
2095
  } | undefined;
2051
2096
  }[];
2097
+ dynamicContentList: {
2098
+ [x: string]: import("../library").DynamicContentNode[];
2099
+ };
2052
2100
  customFieldAttributes: string[];
2053
2101
  selectedUnsubscribePages: number[];
2054
2102
  forceRecreate: boolean;
@@ -2183,6 +2231,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2183
2231
  value: string;
2184
2232
  } | undefined;
2185
2233
  }[];
2234
+ dynamicContentList: {
2235
+ [x: string]: import("../library").DynamicContentNode[];
2236
+ };
2186
2237
  customFieldAttributes: string[];
2187
2238
  selectedUnsubscribePages: number[];
2188
2239
  forceRecreate: boolean;
@@ -2317,6 +2368,9 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2317
2368
  value: string;
2318
2369
  } | undefined;
2319
2370
  }[];
2371
+ dynamicContentList: {
2372
+ [x: string]: import("../library").DynamicContentNode[];
2373
+ };
2320
2374
  customFieldAttributes: string[];
2321
2375
  selectedUnsubscribePages: number[];
2322
2376
  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,5 +1,8 @@
1
+ /** Production default — pony-express builds unsubscribe links on mail.useinsider.com. */
2
+ export declare const DEFAULT_ENVIRONMENT_PREFIX = "useinsider";
1
3
  /**
2
- * Gets the appropriate environment prefix by parsing from current hostname
3
- * Extracts environment prefix from domains by splitting hostname
4
+ * Gets the environment prefix by parsing the current hostname (third segment),
5
+ * falling back to the production default when that segment is absent or empty —
6
+ * so unsubscribe links never compile to `https://mail.undefined.com/...` (SD-145225).
4
7
  */
5
8
  export declare const getEnvironmentPrefix: () => string;
@@ -1,6 +1,23 @@
1
- import type { DynamicContent, MergeTag } from '@@/Types/generic';
1
+ import type { DynamicContent, DynamicContentList, 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[];
4
21
  export declare const getCsrfToken: () => string;
5
22
  /**
6
23
  * URL Parameter utilities
@@ -1,19 +1,10 @@
1
- import { DEFAULT_LOCALE as r, DEFAULT as a, DEFAULT_TZ as c } from "../enums/date.js";
2
- const m = (t) => t ? t instanceof Date ? t : typeof t == "string" ? t.length === 10 ? new Date(Number(t) * 1e3) : new Date(t) : typeof t == "number" ? t.toString().length === 10 ? new Date(t * 1e3) : new Date(t) : /* @__PURE__ */ new Date() : /* @__PURE__ */ new Date(), s = () => {
1
+ import { DEFAULT_LOCALE as r, DEFAULT as o } from "../enums/date.js";
2
+ const c = () => {
3
3
  const t = window.l10n;
4
- return (t == null ? void 0 : t.locale) === a ? r : (t == null ? void 0 : t.locale) || r;
5
- }, u = new Intl.DateTimeFormat().resolvedOptions().timeZone, f = () => {
6
- const t = window.l10n;
7
- return (t == null ? void 0 : t.timezone) || u || c;
8
- }, D = (t, e = s(), n = f()) => {
9
- const o = {
10
- year: "numeric",
11
- month: "2-digit",
12
- day: "2-digit",
13
- timeZone: n
14
- }, i = m(t);
15
- return new Intl.DateTimeFormat(e, o).format(i);
16
- }, T = (t) => {
4
+ return (t == null ? void 0 : t.locale) === o ? r : (t == null ? void 0 : t.locale) || r;
5
+ };
6
+ new Intl.DateTimeFormat().resolvedOptions().timeZone;
7
+ const i = (t) => {
17
8
  if (!t)
18
9
  return "";
19
10
  const e = new Date(t);
@@ -25,13 +16,9 @@ const m = (t) => t ? t instanceof Date ? t : typeof t == "string" ? t.length ===
25
16
  second: "2-digit",
26
17
  hour12: !1
27
18
  }).format(e);
28
- }, h = (t) => t ? Math.floor(Date.now() / 1e3) >= t : !1;
19
+ }, m = (t) => t ? Math.floor(Date.now() / 1e3) >= t : !1;
29
20
  export {
30
- m as convertToDateObject,
31
- T as formatPatchDate,
32
- D as formatShortDate,
33
- h as isAfterDate,
34
- u as localTz,
35
- s as locale,
36
- f as timezone
21
+ i as formatPatchDate,
22
+ m as isAfterDate,
23
+ c as locale
37
24
  };
@@ -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,4 +1,5 @@
1
- const n = () => window.location.hostname.split(".")[2];
1
+ const n = "useinsider", o = () => window.location.hostname.split(".")[2] || n;
2
2
  export {
3
- n as getEnvironmentPrefix
3
+ n as DEFAULT_ENVIRONMENT_PREFIX,
4
+ o as getEnvironmentPrefix
4
5
  };
@@ -1,47 +1,68 @@
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 || ""
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 || ""
5
5
  };
6
6
  if (a.length >= 2) {
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;
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;
11
11
  } else {
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);
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);
14
14
  }
15
15
  }
16
- return c;
17
- }, u = (e, f = !1) => e.map((a) => {
16
+ return r;
17
+ }, f = (l, s = !1) => l.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 (f) {
23
+ if (s) {
24
24
  if (!a.fallback)
25
25
  return {
26
26
  label: a.text,
27
27
  value: `{{ ${a.value} }}`
28
28
  };
29
- const c = !Number.isNaN(Number(a.fallback)) && a.fallback.trim() !== "" ? a.fallback : `"${a.fallback}"`;
29
+ const r = !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: ${c} }}`
32
+ value: `{{ ${a.value} | default: ${r} }}`
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
- var e;
41
- return ((e = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : e.getAttribute("content")) ?? "";
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")) ?? "";
42
61
  };
43
62
  export {
44
- u as dynamicContentToMergeTags,
45
- o as getCsrfToken,
46
- s as mergeTagToDynamicContent
63
+ v as buildMergeTagEntries,
64
+ f as dynamicContentToMergeTags,
65
+ b as flattenDynamicContentList,
66
+ i as getCsrfToken,
67
+ o as mergeTagToDynamicContent
47
68
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.12.0-beta.3450e5f",
3
+ "version": "3.12.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",