@designcrowd/library.brand-page 6.0.19 → 6.0.20

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 (97) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DCwwdYPj.js → CreatedOnBrandCrowd-de-de-C52IyXZu.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-DTmZeDQ1.js → CreatedOnBrandCrowd-en-us-DhTy_dEV.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-Dbrz6TXv.js → CreatedOnBrandCrowd-es-es-BJelIAQ4.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-DLQhgn8T.js → CreatedOnBrandCrowd-fr-ca-DwJohy0T.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-DLQhgn8T.js → CreatedOnBrandCrowd-fr-fr-DwJohy0T.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-yAzzD2ik.js → CreatedOnBrandCrowd-pt-br-CMzKbxdG.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-yAzzD2ik.js → CreatedOnBrandCrowd-pt-pt-CMzKbxdG.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-CNmNNE5o.js → CreatedOnDcom-de-de-DAy1GHrw.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-BUmLFlS_.js → CreatedOnDcom-en-us-CgBDAkJN.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-DfygM_0q.js → CreatedOnDcom-es-es-Ds9d5rem.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-DIEft8xE.js → CreatedOnDcom-fr-ca-CZL0BQ-u.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-Cn3jWG2n.js → CreatedOnDcom-fr-fr-BVYh5Wvo.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-DXhgGwEh.js → CreatedOnDcom-pt-br-1hsWNXfq.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-BvE9ckw1.js → CreatedOnDcom-pt-pt-DvM0N-3M.js} +1 -1
  15. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +2 -5
  16. package/lib/src/brand-page/models/index.d.ts +26 -34
  17. package/lib/src/brand-page/utils/migration.util.js +0 -11
  18. package/lib/src/brand-page/utils/text.util.d.ts +1 -1
  19. package/lib/src/brand-page/utils/text.util.js +0 -32
  20. package/lib/src/brand-page/utils/vcard.util.js +4 -4
  21. package/lib/src/brand-page/utils/view-model.util.d.ts +0 -1
  22. package/lib/src/brand-page/utils/view-model.util.js +20 -68
  23. package/lib/src/brand-page/view-models.d.ts +3 -3
  24. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +100 -21
  25. package/lib/src/brand-page-maker/utils/index.d.ts +0 -2
  26. package/lib/src/brand-page-maker/utils/index.js +0 -2
  27. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +5 -19
  28. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +5 -35
  29. package/lib/src/brand-page-maker/validators/field.validator.js +2 -10
  30. package/lib/src/css/library.brand-page-brandCrowd.min.css +1 -1
  31. package/lib/src/css/library.brand-page-brandPage.min.css +1 -1
  32. package/lib/src/css/library.brand-page-designCom.min.css +1 -1
  33. package/lib/src/css/library.brand-page-preview.min.css +1 -1
  34. package/lib/src/index.d.ts +0 -1
  35. package/lib/src/index.mjs +138 -143
  36. package/lib/src/{lib-Bm-fYap1.js → lib-CK2FPBv5.js} +55098 -55367
  37. package/lib/src/lib.js +0 -2
  38. package/lib/src/metadata-builder/builders/update-content-text-builder.js +15 -20
  39. package/lib/src/metadata-builder/builders/update-content-text-style-builder.js +3 -8
  40. package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +2 -2
  41. package/lib/src/metadata-builder/helpers/rte.helpers.js +3 -6
  42. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.js +1 -14
  43. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +3 -12
  44. package/lib/src/utils/minify-brand-page-metadata.js +1 -4
  45. package/package.json +1 -1
  46. package/src/brand-page/components/contact-form/ContactForm.mixin.ts +2 -5
  47. package/src/brand-page/components/text-wrapper/TextWrapper.vue +6 -17
  48. package/src/brand-page/models/index.ts +26 -35
  49. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -3
  50. package/src/brand-page/utils/migration.util.ts +0 -12
  51. package/src/brand-page/utils/style.util.test.ts +0 -51
  52. package/src/brand-page/utils/text.util.ts +4 -43
  53. package/src/brand-page/utils/vcard.util.ts +4 -6
  54. package/src/brand-page/utils/view-model.util.ts +26 -94
  55. package/src/brand-page/view-models.ts +2 -3
  56. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +107 -23
  57. package/src/brand-page-maker/utils/index.ts +0 -2
  58. package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +3 -4
  59. package/src/brand-page-maker/utils/rich-text-editor.util.ts +11 -50
  60. package/src/brand-page-maker/validators/field.validator.ts +2 -10
  61. package/src/lib.ts +0 -9
  62. package/src/metadata-builder/builders/update-content-text-builder.ts +18 -32
  63. package/src/metadata-builder/builders/update-content-text-style-builder.ts +4 -14
  64. package/src/metadata-builder/helpers/rte.helpers.ts +7 -11
  65. package/src/shared/content-settings/components/GenericTextInput.mixin.ts +1 -17
  66. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +3 -16
  67. package/src/utils/minify-brand-page-metadata.ts +1 -4
  68. package/lib/src/brand-page/utils/migration/migration-19.d.ts +0 -2
  69. package/lib/src/brand-page/utils/migration/migration-19.js +0 -71
  70. package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.d.ts +0 -22
  71. package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.js +0 -22
  72. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.d.ts +0 -14
  73. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.js +0 -39
  74. package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
  75. package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.js +0 -66
  76. package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -33
  77. package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -50
  78. package/lib/src/brand-page-maker/utils/rte-sanitize.util.d.ts +0 -6
  79. package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +0 -158
  80. package/lib/src/brand-page-maker/utils/rte-serializer.d.ts +0 -5
  81. package/lib/src/brand-page-maker/utils/rte-serializer.js +0 -112
  82. package/src/brand-page/utils/migration/migration-19.test.ts +0 -72
  83. package/src/brand-page/utils/migration/migration-19.ts +0 -83
  84. package/src/brand-page/utils/text.util.test.ts +0 -47
  85. package/src/brand-page/utils/view-model.pageid-rte.test.ts +0 -104
  86. package/src/brand-page-maker/__fixtures__/complex-rte.fixture.ts +0 -23
  87. package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +0 -52
  88. package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.ts +0 -42
  89. package/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.ts +0 -113
  90. package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +0 -200
  91. package/src/brand-page-maker/utils/rte-features.test.ts +0 -330
  92. package/src/brand-page-maker/utils/rte-render-parity.test.ts +0 -156
  93. package/src/brand-page-maker/utils/rte-render.util.ts +0 -77
  94. package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +0 -158
  95. package/src/brand-page-maker/utils/rte-sanitize.util.ts +0 -195
  96. package/src/brand-page-maker/utils/rte-serializer.ts +0 -172
  97. package/src/brand-page-maker/validators/field.validator.test.ts +0 -55
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bm-fYap1.js";
2
+ import { _ as t } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, h = {
4
4
  width: "275",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bm-fYap1.js";
2
+ import { _ as t } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, h = {
4
4
  width: "251",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bm-fYap1.js";
2
+ import { _ as t } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, h = {
4
4
  width: "250",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bm-fYap1.js";
2
+ import { _ as t } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bm-fYap1.js";
2
+ import { _ as t } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bm-fYap1.js";
2
+ import { _ as t } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bm-fYap1.js";
2
+ import { _ as t } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bm-fYap1.js";
2
+ import { _ as e } from "./lib-CK2FPBv5.js";
3
3
  const M = {}, Z = {
4
4
  width: "242",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bm-fYap1.js";
2
+ import { _ as e } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, M = {
4
4
  width: "231",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bm-fYap1.js";
2
+ import { _ as e } from "./lib-CK2FPBv5.js";
3
3
  const M = {}, Z = {
4
4
  width: "230",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bm-fYap1.js";
2
+ import { _ as e } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bm-fYap1.js";
2
+ import { _ as e } from "./lib-CK2FPBv5.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-Bm-fYap1.js";
2
+ import { _ as M } from "./lib-CK2FPBv5.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-Bm-fYap1.js";
2
+ import { _ as M } from "./lib-CK2FPBv5.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -5,7 +5,7 @@ import brandPageClient from '../../clients/brand-page.client';
5
5
  import { isEmail } from '../../../utils/validator.util';
6
6
  import { ALIGN_CARD_CENTER, ALIGN_CARD_CENTER_IMAGE, ALIGN_CENTERED, ALIGN_LEFT_FULL_IMAGE, ALIGN_RIGHT_FULL_IMAGE, DISPLAY_STYLE_COLLAPSED, RECAPTCHA_ACTION_CONTACT_FORM, TEXT_ONLY, } from '../../constants';
7
7
  import { getRenderText, contentPaddingStyle as toContentPaddingStyle, mutedTextForBackground, backgroundColorFromStyle, } from '@brand-page/utils';
8
- import { hasRTEContent, getPlainTextFromRTE } from '@brand-page-maker/utils';
8
+ import { hasRTEContent } from '@brand-page-maker/utils';
9
9
  import { useReCaptcha } from '../../composables/recaptcha.composable';
10
10
  export default defineComponent({
11
11
  props: {
@@ -113,10 +113,7 @@ export default defineComponent({
113
113
  isEmail(this.viewModel.responseEmail));
114
114
  },
115
115
  title() {
116
- // BP-5787: title may be RTE JSON (not a string), so `.trim()` would
117
- // throw — read the visible text via getPlainTextFromRTE to decide
118
- // whether to fall back to the default.
119
- return getPlainTextFromRTE(this.viewModel.title)
116
+ return this.viewModel.title && this.viewModel.title.trim() !== ''
120
117
  ? this.viewModel.title
121
118
  : 'Contact Us';
122
119
  },
@@ -7,14 +7,6 @@ import { TextStyles } from './styles.model';
7
7
  import { LogoStyles } from './logo.model';
8
8
  import type { LogoImageModel, LogoTemplateImageModel } from './logo.model';
9
9
  import type { BrandPagePaymentConfig } from './payment.model';
10
- import type { JSONContent } from '@tiptap/vue-3';
11
- /**
12
- * BP-5787 — a rich-text field is either a legacy inline-HTML string or a
13
- * Tiptap JSON document. Typing RTE content fields as RichTextValue (instead of
14
- * `string`) forces every consumer to handle both forms — surfacing at compile
15
- * time any code that assumes a plain string (e.g. `.replace`, `.length`).
16
- */
17
- export type RichTextValue = string | JSONContent;
18
10
  export * from './brand-page-context.model';
19
11
  export * from './payment.model';
20
12
  export * from './content.model';
@@ -156,7 +148,7 @@ export interface TextContent extends Content {
156
148
  /**
157
149
  * For BrandPage/BrandContact only
158
150
  */
159
- text: RichTextValue;
151
+ text: string;
160
152
  /**
161
153
  * For BrandSite
162
154
  */
@@ -179,9 +171,9 @@ export interface TextContent extends Content {
179
171
  }
180
172
  export interface ProfileContent extends Content {
181
173
  avatarImageUrl: string;
182
- name: RichTextValue;
183
- title: RichTextValue;
184
- description: RichTextValue;
174
+ name: string;
175
+ title: string;
176
+ description: string;
185
177
  backgroundColor: BrandPageCssStyle;
186
178
  colorReplacements: ColorReplacement[];
187
179
  mediaType?: string;
@@ -199,7 +191,7 @@ export interface MapContent extends Content {
199
191
  }
200
192
  export interface MailingListContent extends Content {
201
193
  acceptedFields?: 'emailOnly' | 'nameAndEmail';
202
- title: RichTextValue;
194
+ title: string;
203
195
  buttonText: string;
204
196
  titleStyle: TextStyleDeclaration;
205
197
  buttonTextStyle: TextStyleDeclaration;
@@ -250,10 +242,10 @@ export interface FormField {
250
242
  export interface ContactFormContent extends Content {
251
243
  type: 'contact-form';
252
244
  displayStyle: string;
253
- title: RichTextValue;
254
- description: RichTextValue;
245
+ title: string;
246
+ description: string;
255
247
  buttonText: string;
256
- successMessage: RichTextValue;
248
+ successMessage: string;
257
249
  fields: FormField[];
258
250
  responseEmail: string;
259
251
  imageUrl?: string;
@@ -272,8 +264,8 @@ export interface ContactFormContent extends Content {
272
264
  export interface BannerSectionContent extends Content {
273
265
  type: 'banner-section';
274
266
  imageUrl: string;
275
- title: RichTextValue;
276
- description: RichTextValue;
267
+ title: string;
268
+ description: string;
277
269
  buttonText: string | false;
278
270
  url: string;
279
271
  email?: string;
@@ -300,8 +292,8 @@ export declare const MEDIA_TYPES: {
300
292
  };
301
293
  export type MediaType = keyof typeof MEDIA_TYPES;
302
294
  export interface TextMediaItem extends ImageItem {
303
- title: RichTextValue;
304
- paragraph: RichTextValue;
295
+ title: string;
296
+ paragraph: string;
305
297
  itemsId: number;
306
298
  buttonText?: string | false;
307
299
  buttonPageId?: string;
@@ -320,8 +312,8 @@ export interface TextShapeItem extends TextMediaItem {
320
312
  export interface ShapeItem extends ImageItem {
321
313
  colorReplacements: ColorReplacement[];
322
314
  mediaType: MediaType;
323
- title?: RichTextValue;
324
- paragraph?: RichTextValue;
315
+ title?: string;
316
+ paragraph?: string;
325
317
  titleOverride?: string;
326
318
  paragraphOverride?: string;
327
319
  }
@@ -329,9 +321,9 @@ export interface TestimonialItems {
329
321
  /** Stable per-item identifier. See ImageItem.id. */
330
322
  id: string;
331
323
  imageUrl: string;
332
- name: RichTextValue;
333
- position: RichTextValue;
334
- testimonials: RichTextValue;
324
+ name: string;
325
+ position: string;
326
+ testimonials: string;
335
327
  colorReplacements: ColorReplacement[];
336
328
  mediaType: string;
337
329
  size?: string;
@@ -344,7 +336,7 @@ export interface TestimonialItems {
344
336
  export interface TextItem {
345
337
  /** Stable per-item identifier. See ImageItem.id. */
346
338
  id: string;
347
- text: RichTextValue;
339
+ text: string;
348
340
  textStyle: TextStyleDeclaration;
349
341
  textOverride?: string;
350
342
  }
@@ -361,8 +353,8 @@ export interface ImagesSectionContent extends Content, MediaSection {
361
353
  enablePopup: boolean;
362
354
  }
363
355
  export interface MediaSection extends Content {
364
- title: RichTextValue;
365
- description: RichTextValue;
356
+ title: string;
357
+ description: string;
366
358
  displayStyle: ImagesSectionContentDisplayStyle;
367
359
  items: TextShapeItem[] | TextMediaItem[];
368
360
  titleStyle: TextStyleDeclaration;
@@ -379,7 +371,7 @@ export interface ColorReplacement {
379
371
  }
380
372
  export interface TestimonialSectionContent extends Content {
381
373
  type: 'testimonial-section';
382
- title: RichTextValue;
374
+ title: string;
383
375
  displayStyle: string;
384
376
  items: TestimonialItems[];
385
377
  titleStyle: TextStyleDeclaration;
@@ -393,8 +385,8 @@ export interface TestimonialSectionContent extends Content {
393
385
  export interface AboutSectionContent extends Content {
394
386
  type: 'about-section';
395
387
  imageUrl: string;
396
- title: RichTextValue;
397
- paragraph: RichTextValue;
388
+ title: string;
389
+ paragraph: string;
398
390
  displayStyle: string;
399
391
  titleStyle: TextStyleDeclaration;
400
392
  paragraphStyle: TextStyleDeclaration;
@@ -418,7 +410,7 @@ export declare const SOCIAL_LINKS_ICON_DISPLAY_STYLES: {
418
410
  export type SocialLinksIconDisplayStyle = keyof typeof SOCIAL_LINKS_ICON_DISPLAY_STYLES;
419
411
  export interface SocialLinksContent extends Content {
420
412
  type: 'social-links';
421
- title: RichTextValue;
413
+ title: string;
422
414
  links: LinksItem[];
423
415
  iconDisplayStyle: SocialLinksIconDisplayStyle;
424
416
  iconFillStyles: BrandPageCssStyle;
@@ -441,8 +433,8 @@ export interface DividerSectionContent extends Content {
441
433
  }
442
434
  export interface BookingSectionContent extends Content {
443
435
  type: 'booking-section';
444
- title: RichTextValue;
445
- description: RichTextValue;
436
+ title: string;
437
+ description: string;
446
438
  buttonText: string;
447
439
  url: string;
448
440
  email?: string;
@@ -21,7 +21,6 @@ import { migration15 } from './migration/migration-15';
21
21
  import { migration16 } from './migration/migration-16';
22
22
  import { migration17 } from './migration/migration-17';
23
23
  import { migration18 } from './migration/migration-18';
24
- import { migration19 } from './migration/migration-19';
25
24
  const MIGRATION_TABLE = [
26
25
  {
27
26
  version: 1,
@@ -139,16 +138,6 @@ const MIGRATION_TABLE = [
139
138
  migrateFn: migration18,
140
139
  description: 'BP-5603: backfill stable item ids on all nested items (gallery/section/testimonial/text items, section + footer social links) — the item id is now non-nullable',
141
140
  },
142
- {
143
- version: 19,
144
- migrateFn: migration19,
145
- // runAlways: normalise RTE to JSON on every load. Idempotent (only HTML
146
- // strings are converted; JSON is skipped), so it also catches content the
147
- // AI section builders still emit as HTML — converting it on the next read
148
- // without a new migration or changes to those builders.
149
- runAlways: true,
150
- description: 'BP-5787: convert inline-HTML RTE content to Tiptap JSON on load (lazy migrate-on-read for web-renderer; persisted on next maker save; also normalises AI-built HTML)',
151
- },
152
141
  ];
153
142
  export const GetLatestModelVersion = () => Math.max(...MIGRATION_TABLE.map((x) => x.version));
154
143
  export const migrateBrandPageModel = async (brandPageModel, options) => {
@@ -1,5 +1,5 @@
1
1
  export declare const getRenderText: (text: string) => string;
2
- export declare const escapeContentText: (text: unknown) => string | undefined;
2
+ export declare const escapeContentText: (text: string | undefined) => string | undefined;
3
3
  export declare const decodeHtmlEntities: (text: string) => string;
4
4
  export declare const unescapeContentText: (text: string) => string;
5
5
  export declare const encodeContentText: (text: string | undefined) => string | undefined;
@@ -1,43 +1,11 @@
1
1
  import { ESCAPED_NEWLINE_CHARACTER } from '../../constants/ui';
2
- /**
3
- * BP-5787 — a Tiptap JSON document is an object with `type: 'doc'`.
4
- * Inlined here (rather than importing from brand-page-maker) to avoid a
5
- * circular import: rich-text-editor.util imports getRenderText from this file.
6
- */
7
- const isTiptapDoc = (value) => typeof value === 'object' &&
8
- value !== null &&
9
- value.type === 'doc';
10
- const jsonDocPlainText = (doc) => {
11
- const parts = [];
12
- const walk = (node) => {
13
- if (typeof node?.text === 'string')
14
- parts.push(node.text);
15
- node?.content?.forEach(walk);
16
- };
17
- walk(doc);
18
- return parts.join(' ').replace(/\s+/g, ' ').trim();
19
- };
20
2
  export const getRenderText = (text) => {
21
- // BP-5787: RTE fields may now be Tiptap JSON objects. Non-strings pass
22
- // through untouched so the renderer (TextWrapper) handles them via its
23
- // JSON-aware path, instead of throwing on `.replace`.
24
- if (typeof text !== 'string') {
25
- return text;
26
- }
27
3
  return text.replace(new RegExp(`(${ESCAPED_NEWLINE_CHARACTER}|\\n)`, 'g'), '<br/>');
28
4
  };
29
- // Accepts a legacy inline-HTML string or a Tiptap JSON document (BP-5787):
30
- // for JSON it returns the concatenated visible text; for HTML it strips tags.
31
5
  export const escapeContentText = (text) => {
32
6
  if (!text) {
33
7
  return text;
34
8
  }
35
- if (isTiptapDoc(text)) {
36
- return jsonDocPlainText(text);
37
- }
38
- if (typeof text !== 'string') {
39
- return undefined;
40
- }
41
9
  return text
42
10
  .replace(/(<([^>]+)>)/gi, '')
43
11
  .replace(/(\r\n|\r|\n)/g, ESCAPED_NEWLINE_CHARACTER);
@@ -150,9 +150,9 @@ const processSocialLinks = (socialLinksContent, vcardLines, addedEntries) => {
150
150
  });
151
151
  };
152
152
  const addProfileInfo = (profile, vcardLines) => {
153
- const name = sanitizeForVCard(getPlainTextFromRTE(profile.name) || '');
154
- const title = sanitizeForVCard(getPlainTextFromRTE(profile.title) || '');
155
- const description = sanitizeForVCard(getPlainTextFromRTE(profile.description) || '');
153
+ const name = sanitizeForVCard(profile.name || '');
154
+ const title = sanitizeForVCard(profile.title || '');
155
+ const description = sanitizeForVCard(profile.description || '');
156
156
  if (name) {
157
157
  const nameParts = name.trim().split(/\s+/);
158
158
  const lastName = nameParts.length > 1 ? nameParts.pop() || '' : '';
@@ -205,6 +205,6 @@ const downloadVCard = (vcard, filename) => {
205
205
  export const saveContact = (brandPageData) => {
206
206
  const vcard = generateVCard(brandPageData);
207
207
  const profile = findProfileContent(brandPageData);
208
- const filename = generateVCardFilename(getPlainTextFromRTE(profile?.name));
208
+ const filename = generateVCardFilename(profile?.name);
209
209
  downloadVCard(vcard, filename);
210
210
  };
@@ -28,7 +28,6 @@ interface ViewModelMappingOptions {
28
28
  setVideoUrlsWithToken?: (token: string, videoUrl: string, previewImageUrl: string, assetId: string) => void;
29
29
  }
30
30
  export declare const getBrandPageViewModelFromBrandPageModel: (model: BrandPageModel, brandPageToken: string | undefined, showBrandCrowdLogo: boolean | undefined, options: ViewModelMappingOptions) => BrandPageViewModel;
31
- export declare const resolvePageIdsInRteJson: (doc: unknown, nav: NavViewModel, options: ViewModelMappingOptions) => unknown;
32
31
  export declare const isLogoViewModel: (viewModel: ContentViewModel) => viewModel is LogoViewModel;
33
32
  /** for service.brand-page website preview by logo draft token */
34
33
  export declare const applyLogoImageToBrandPageViewModel: (viewModel: BrandPageViewModel, logoImage: LogoImageModel) => BrandPageViewModel;
@@ -10,7 +10,7 @@ import { isValidSvgUrl } from './image.util';
10
10
  import { isLogoContent } from './model.util';
11
11
  import { getBoxShadowValue } from './button.util';
12
12
  import { findNavItemByPageId, getRouteNameByPageIndex, getRouteParamsByPage, } from './route.util';
13
- import { hasRTEContent, isTiptapDocument } from '../../brand-page-maker/utils';
13
+ import { hasRTEContent } from '../../brand-page-maker/utils';
14
14
  import { getPageIdFromHref, isHrefPageId, } from '../../brand-page-maker/composables/rich-text-editor/hyperlink';
15
15
  const BUTTON_BORDER_RADIUS = '9999px';
16
16
  const CONTENT_BORDER_RADIUS = '48px';
@@ -863,75 +863,13 @@ const mapPageIdReferencesToRelativePaths = (pages, nav, options) => {
863
863
  });
864
864
  });
865
865
  };
866
- // Resolve a `pageid:<id>` internal-link href to the published relative path.
867
- // Returns the resolved href, or null when `href` is not an internal pageid link
868
- // (external/absolute links are left untouched). Falls back to the site root when
869
- // the pageid can't be matched to a nav route.
870
- const resolvePageIdHref = (href, nav, options) => {
871
- // Only process internal links (no protocol, doesn't start with /)
872
- if (!href || href.match(/^(https?:\/\/|\/)/) || !isHrefPageId(href)) {
873
- return null;
874
- }
875
- const pageId = getPageIdFromHref(href);
876
- const route = findNavItemByPageId(nav.navItems, pageId);
877
- const brandPageSlugRoute = options.brandPageSlug
878
- ? `/${options.brandPageSlug}`
879
- : '/';
880
- if (route) {
881
- if (route.isRoot) {
882
- return brandPageSlugRoute;
883
- }
884
- return `${brandPageSlugRoute}${brandPageSlugRoute === '/' ? '' : '/'}${route.relativePath}`;
885
- }
886
- // fallback to root if pageid cannot be resolved.
887
- return brandPageSlugRoute;
888
- };
889
- // BP-5847: walk a Tiptap JSON doc and rewrite every link mark whose href is a
890
- // `pageid:` reference into its published relative path. Returns a NEW doc when
891
- // something changed (so the shared model doc is never mutated), else the same
892
- // reference.
893
- export const resolvePageIdsInRteJson = (doc, nav, options) => {
894
- let changed = false;
895
- const walk = (node) => {
896
- if (!node || typeof node !== 'object') {
897
- return node;
898
- }
899
- let next = node;
900
- if (Array.isArray(node.marks)) {
901
- const marks = node.marks.map((mark) => {
902
- if (mark?.type === 'link' && typeof mark.attrs?.href === 'string') {
903
- const resolved = resolvePageIdHref(mark.attrs.href, nav, options);
904
- if (resolved !== null) {
905
- changed = true;
906
- return { ...mark, attrs: { ...mark.attrs, href: resolved } };
907
- }
908
- }
909
- return mark;
910
- });
911
- next = { ...next, marks };
912
- }
913
- if (Array.isArray(node.content)) {
914
- next = { ...next, content: node.content.map(walk) };
915
- }
916
- return next;
917
- };
918
- const result = walk(doc);
919
- return changed ? result : doc;
920
- };
921
866
  const dynamicallyMapPageIdInHyperlinksToRelativePaths = (content, nav, options) => {
922
867
  Object.keys(content).forEach((key) => {
923
868
  const value = content[key];
924
869
  if (value === undefined || value === null) {
925
870
  return;
926
871
  }
927
- if (isTiptapDocument(value)) {
928
- // BP-5847: RTE fields may now be Tiptap JSON. Resolve pageid link marks
929
- // here too, or internal links render as raw `pageid:` and don't navigate.
930
- content[key] =
931
- resolvePageIdsInRteJson(value, nav, options);
932
- }
933
- else if (typeof value === 'object' &&
934
- (key === 'items' || key === 'textItems')) {
872
+ if (typeof value === 'object' && (key === 'items' || key === 'textItems')) {
935
873
  if (Array.isArray(value)) {
936
874
  value.forEach((item) => {
937
875
  dynamicallyMapPageIdInHyperlinksToRelativePaths(item, nav, options);
@@ -943,10 +881,24 @@ const dynamicallyMapPageIdInHyperlinksToRelativePaths = (content, nav, options)
943
881
  }
944
882
  else if (typeof value === 'string' && hasRTEContent(value)) {
945
883
  content[key] = value.replace(/<a\s+([^>]*?)href="([^"]*?)"([^>]*?)>/gi, (match, existingAttrsStart, href, existingAttrsEnd) => {
946
- const resolved = resolvePageIdHref(href, nav, options);
947
- return resolved === null
948
- ? match
949
- : `<a ${existingAttrsStart}href="${resolved}"${existingAttrsEnd}>`;
884
+ // Only process internal links (no protocol, doesn't start with /)
885
+ if (href && !href.match(/^(https?:\/\/|\/)/) && isHrefPageId(href)) {
886
+ const pageId = getPageIdFromHref(href);
887
+ const route = findNavItemByPageId(nav.navItems, pageId);
888
+ const brandPageSlugRoute = options.brandPageSlug
889
+ ? `/${options.brandPageSlug}`
890
+ : '/';
891
+ if (route) {
892
+ let href = `${brandPageSlugRoute}`;
893
+ if (!route.isRoot) {
894
+ href = `${brandPageSlugRoute}${brandPageSlugRoute === '/' ? '' : '/'}${route.relativePath}`;
895
+ }
896
+ return `<a ${existingAttrsStart}href="${href}"${existingAttrsEnd}>`;
897
+ }
898
+ // fallback to root if pageid cannot be resolved.
899
+ return `<a ${existingAttrsStart}href="${brandPageSlugRoute}"${existingAttrsEnd}>`;
900
+ }
901
+ return match;
950
902
  });
951
903
  }
952
904
  });
@@ -1,4 +1,4 @@
1
- import type { ButtonWithModalContent, ProfileContent, TextContent, VideoContent, ImageContent, ContentType, ButtonStyles, LogoStyles, MapContent, ImageGalleryContent, GalleryStyles, MailingListContent, RequestPaymentContent, ShopContent, SupportMeContent, ContactFormContent, BannerSectionContent, BrandPageType, SocialLinksContent, TestimonialSectionContent, AboutSectionContent, DividerSectionContent, ShapesSectionContent, ButtonLinkType, PageHeaderMobile, PageHeaderDesktop, PageFooterMobile, PageFooterDesktop, TextMediaItem, TextShapeItem, TextStyleDeclaration, AspectRatio, LogoImageModel, LogoTemplateImageModel, CookieOptions, BookingSectionContent, MediaTypes, TextStyles, BackgroundStyle, BackgroundShape, PersonalisationRole, SaveContactOptions, RichTextValue } from './models';
1
+ import type { ButtonWithModalContent, ProfileContent, TextContent, VideoContent, ImageContent, ContentType, ButtonStyles, LogoStyles, MapContent, ImageGalleryContent, GalleryStyles, MailingListContent, RequestPaymentContent, ShopContent, SupportMeContent, ContactFormContent, BannerSectionContent, BrandPageType, SocialLinksContent, TestimonialSectionContent, AboutSectionContent, DividerSectionContent, ShapesSectionContent, ButtonLinkType, PageHeaderMobile, PageHeaderDesktop, PageFooterMobile, PageFooterDesktop, TextMediaItem, TextShapeItem, TextStyleDeclaration, AspectRatio, LogoImageModel, LogoTemplateImageModel, CookieOptions, BookingSectionContent, MediaTypes, TextStyles, BackgroundStyle, BackgroundShape, PersonalisationRole, SaveContactOptions } from './models';
2
2
  import type { ImagesSectionContentDisplayStyle } from './constants';
3
3
  export type ViewModelType = 'button' | 'image' | 'image-gallery' | 'logo' | 'map' | 'mailing-list' | 'profile' | 'support-me' | 'request-payment' | 'text' | 'video' | 'contact-form' | 'banner-section' | 'images-section' | 'about-section' | 'divider-section' | 'testimonial-section' | 'social-links' | 'shapes-section' | 'shop-section' | 'booking-section';
4
4
  export interface ContentViewModel {
@@ -94,8 +94,8 @@ export interface TextImageSectionViewModel {
94
94
  id: string;
95
95
  type: 'images-section';
96
96
  role: ContentType;
97
- title: RichTextValue;
98
- description: RichTextValue;
97
+ title: string;
98
+ description: string;
99
99
  displayStyle: ImagesSectionContentDisplayStyle;
100
100
  aspectRatio: AspectRatio;
101
101
  areImagesFullWidth: boolean;