@designcrowd/library.brand-page 6.0.6-json-prereq-7 → 6.0.6-undo-2
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/lib/src/{CreatedOnBrandCrowd-de-de-SPVLPi8n.js → CreatedOnBrandCrowd-de-de-BSFTp6yl.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-CvtrCPHd.js → CreatedOnBrandCrowd-en-us-rPQrOY1L.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-BSsac7jB.js → CreatedOnBrandCrowd-es-es-awd8-QFa.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-BauENV2a.js → CreatedOnBrandCrowd-fr-ca-CwJ4J7Ow.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-BauENV2a.js → CreatedOnBrandCrowd-fr-fr-CwJ4J7Ow.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-Be0hawmr.js → CreatedOnBrandCrowd-pt-br-BXYfTLlD.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-Be0hawmr.js → CreatedOnBrandCrowd-pt-pt-BXYfTLlD.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-CTjE2Tmn.js → CreatedOnDcom-de-de-kX6u1lNK.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-DnZRp5Pg.js → CreatedOnDcom-en-us-Bkq5sgFs.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-J-9qvjy8.js → CreatedOnDcom-es-es-zCAC9ujj.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-BDNHqm4G.js → CreatedOnDcom-fr-ca-BYz6Wzg5.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-B_2-ceuO.js → CreatedOnDcom-fr-fr-CN-wAaSH.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-76lJVrAY.js → CreatedOnDcom-pt-br-BrK4Ngg-.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-TQp3CNcu.js → CreatedOnDcom-pt-pt-AfI_g7xJ.js} +1 -1
- package/lib/src/brand-page/models/index.d.ts +26 -34
- package/lib/src/brand-page/utils/logo.util.d.ts +14 -0
- package/lib/src/brand-page/utils/logo.util.js +19 -0
- package/lib/src/brand-page/utils/migration.util.js +0 -11
- package/lib/src/brand-page/utils/text.util.d.ts +1 -1
- package/lib/src/brand-page/utils/text.util.js +0 -32
- package/lib/src/brand-page/utils/vcard.util.js +4 -4
- package/lib/src/brand-page/utils/view-model.util.d.ts +0 -1
- package/lib/src/brand-page/utils/view-model.util.js +20 -68
- package/lib/src/brand-page/view-models.d.ts +3 -3
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +115 -20
- package/lib/src/brand-page-maker/composables/useUndoRedoFlag.d.ts +6 -7
- package/lib/src/brand-page-maker/composables/useUndoRedoFlag.js +7 -12
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +1 -1
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +12 -7
- package/lib/src/brand-page-maker/stores/history/history-store.d.ts +6 -0
- package/lib/src/brand-page-maker/stores/history/history-store.js +11 -1
- package/lib/src/brand-page-maker/utils/index.d.ts +0 -2
- package/lib/src/brand-page-maker/utils/index.js +0 -2
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +5 -19
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +5 -35
- package/lib/src/brand-page-maker/validators/field.validator.js +2 -10
- package/lib/src/css/library.brand-page-brandCrowd.min.css +1 -1
- package/lib/src/css/library.brand-page-brandPage.min.css +1 -1
- package/lib/src/css/library.brand-page-designCom.min.css +1 -1
- package/lib/src/css/library.brand-page-preview.min.css +1 -1
- package/lib/src/index.d.ts +0 -1
- package/lib/src/index.mjs +145 -150
- package/lib/src/{lib-Bh9Y5_-x.js → lib-BYFWAvIq.js} +55864 -56119
- package/lib/src/lib.js +0 -2
- package/lib/src/metadata-builder/builders/reorder-pages-builder.d.ts +13 -0
- package/lib/src/metadata-builder/builders/reorder-pages-builder.js +49 -0
- package/lib/src/metadata-builder/builders/update-content-text-builder.js +15 -20
- package/lib/src/metadata-builder/builders/update-content-text-style-builder.js +3 -5
- package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +1 -1
- package/lib/src/metadata-builder/helpers/rte.helpers.js +3 -6
- package/lib/src/shared/content-settings/components/GenericTextInput.mixin.js +1 -14
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +3 -12
- package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +1 -0
- package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.js +18 -7
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +1 -1
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -1
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +1 -1
- package/lib/src/utils/minify-brand-page-metadata.js +1 -4
- package/package.json +1 -1
- package/src/brand-page/components/text-wrapper/TextWrapper.vue +6 -17
- package/src/brand-page/models/index.ts +26 -35
- package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -3
- package/src/brand-page/utils/logo.util.test.ts +54 -1
- package/src/brand-page/utils/logo.util.ts +23 -0
- package/src/brand-page/utils/migration.util.ts +0 -12
- package/src/brand-page/utils/style.util.test.ts +0 -51
- package/src/brand-page/utils/text.util.ts +4 -43
- package/src/brand-page/utils/vcard.util.ts +4 -6
- package/src/brand-page/utils/view-model.util.ts +26 -94
- package/src/brand-page/view-models.ts +2 -3
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +123 -22
- package/src/brand-page-maker/composables/useUndoRedoFlag.ts +7 -13
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +53 -0
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +13 -16
- package/src/brand-page-maker/stores/history/history-store.test.ts +51 -0
- package/src/brand-page-maker/stores/history/history-store.ts +19 -0
- package/src/brand-page-maker/utils/index.ts +0 -2
- package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +3 -4
- package/src/brand-page-maker/utils/rich-text-editor.util.ts +11 -50
- package/src/brand-page-maker/validators/field.validator.ts +2 -10
- package/src/lib.ts +0 -9
- package/src/metadata-builder/builders/reorder-pages-builder.ts +80 -0
- package/src/metadata-builder/builders/update-content-text-builder.ts +18 -32
- package/src/metadata-builder/builders/update-content-text-style-builder.ts +4 -6
- package/src/metadata-builder/helpers/rte.helpers.ts +7 -11
- package/src/shared/content-settings/components/GenericTextInput.mixin.ts +1 -17
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +3 -16
- package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.ts +19 -11
- package/src/utils/minify-brand-page-metadata.ts +1 -4
- package/lib/src/brand-page/utils/migration/migration-18.d.ts +0 -2
- package/lib/src/brand-page/utils/migration/migration-18.js +0 -71
- package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.d.ts +0 -22
- package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.js +0 -22
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.d.ts +0 -14
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.js +0 -39
- package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
- package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.js +0 -66
- package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -33
- package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -50
- package/lib/src/brand-page-maker/utils/rte-sanitize.util.d.ts +0 -6
- package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +0 -158
- package/lib/src/brand-page-maker/utils/rte-serializer.d.ts +0 -5
- package/lib/src/brand-page-maker/utils/rte-serializer.js +0 -112
- package/src/brand-page/utils/migration/migration-18.test.ts +0 -72
- package/src/brand-page/utils/migration/migration-18.ts +0 -83
- package/src/brand-page/utils/text.util.test.ts +0 -47
- package/src/brand-page/utils/view-model.pageid-rte.test.ts +0 -104
- package/src/brand-page-maker/__fixtures__/complex-rte.fixture.ts +0 -23
- package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +0 -52
- package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.ts +0 -42
- package/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.ts +0 -113
- package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +0 -200
- package/src/brand-page-maker/utils/rte-render-parity.test.ts +0 -156
- package/src/brand-page-maker/utils/rte-render.util.ts +0 -77
- package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +0 -158
- package/src/brand-page-maker/utils/rte-sanitize.util.ts +0 -195
- package/src/brand-page-maker/utils/rte-serializer.ts +0 -172
- package/src/brand-page-maker/validators/field.validator.test.ts +0 -55
|
@@ -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';
|
|
@@ -149,7 +141,7 @@ export interface TextContent extends Content {
|
|
|
149
141
|
/**
|
|
150
142
|
* For BrandPage/BrandContact only
|
|
151
143
|
*/
|
|
152
|
-
text:
|
|
144
|
+
text: string;
|
|
153
145
|
/**
|
|
154
146
|
* For BrandSite
|
|
155
147
|
*/
|
|
@@ -172,9 +164,9 @@ export interface TextContent extends Content {
|
|
|
172
164
|
}
|
|
173
165
|
export interface ProfileContent extends Content {
|
|
174
166
|
avatarImageUrl: string;
|
|
175
|
-
name:
|
|
176
|
-
title:
|
|
177
|
-
description:
|
|
167
|
+
name: string;
|
|
168
|
+
title: string;
|
|
169
|
+
description: string;
|
|
178
170
|
backgroundColor: BrandPageCssStyle;
|
|
179
171
|
colorReplacements: ColorReplacement[];
|
|
180
172
|
mediaType?: string;
|
|
@@ -192,7 +184,7 @@ export interface MapContent extends Content {
|
|
|
192
184
|
}
|
|
193
185
|
export interface MailingListContent extends Content {
|
|
194
186
|
acceptedFields?: 'emailOnly' | 'nameAndEmail';
|
|
195
|
-
title:
|
|
187
|
+
title: string;
|
|
196
188
|
buttonText: string;
|
|
197
189
|
titleStyle: TextStyleDeclaration;
|
|
198
190
|
buttonTextStyle: TextStyleDeclaration;
|
|
@@ -243,10 +235,10 @@ export interface FormField {
|
|
|
243
235
|
export interface ContactFormContent extends Content {
|
|
244
236
|
type: 'contact-form';
|
|
245
237
|
displayStyle: string;
|
|
246
|
-
title:
|
|
247
|
-
description:
|
|
238
|
+
title: string;
|
|
239
|
+
description: string;
|
|
248
240
|
buttonText: string;
|
|
249
|
-
successMessage:
|
|
241
|
+
successMessage: string;
|
|
250
242
|
fields: FormField[];
|
|
251
243
|
responseEmail: string;
|
|
252
244
|
imageUrl?: string;
|
|
@@ -265,8 +257,8 @@ export interface ContactFormContent extends Content {
|
|
|
265
257
|
export interface BannerSectionContent extends Content {
|
|
266
258
|
type: 'banner-section';
|
|
267
259
|
imageUrl: string;
|
|
268
|
-
title:
|
|
269
|
-
description:
|
|
260
|
+
title: string;
|
|
261
|
+
description: string;
|
|
270
262
|
buttonText: string | false;
|
|
271
263
|
url: string;
|
|
272
264
|
email?: string;
|
|
@@ -293,8 +285,8 @@ export declare const MEDIA_TYPES: {
|
|
|
293
285
|
};
|
|
294
286
|
export type MediaType = keyof typeof MEDIA_TYPES;
|
|
295
287
|
export interface TextMediaItem extends ImageItem {
|
|
296
|
-
title:
|
|
297
|
-
paragraph:
|
|
288
|
+
title: string;
|
|
289
|
+
paragraph: string;
|
|
298
290
|
itemsId: number;
|
|
299
291
|
buttonText?: string | false;
|
|
300
292
|
buttonPageId?: string;
|
|
@@ -313,16 +305,16 @@ export interface TextShapeItem extends TextMediaItem {
|
|
|
313
305
|
export interface ShapeItem extends ImageItem {
|
|
314
306
|
colorReplacements: ColorReplacement[];
|
|
315
307
|
mediaType: MediaType;
|
|
316
|
-
title?:
|
|
317
|
-
paragraph?:
|
|
308
|
+
title?: string;
|
|
309
|
+
paragraph?: string;
|
|
318
310
|
titleOverride?: string;
|
|
319
311
|
paragraphOverride?: string;
|
|
320
312
|
}
|
|
321
313
|
export interface TestimonialItems {
|
|
322
314
|
imageUrl: string;
|
|
323
|
-
name:
|
|
324
|
-
position:
|
|
325
|
-
testimonials:
|
|
315
|
+
name: string;
|
|
316
|
+
position: string;
|
|
317
|
+
testimonials: string;
|
|
326
318
|
colorReplacements: ColorReplacement[];
|
|
327
319
|
mediaType: string;
|
|
328
320
|
size?: string;
|
|
@@ -333,7 +325,7 @@ export interface TestimonialItems {
|
|
|
333
325
|
positionOverride?: string;
|
|
334
326
|
}
|
|
335
327
|
export interface TextItem {
|
|
336
|
-
text:
|
|
328
|
+
text: string;
|
|
337
329
|
textStyle: TextStyleDeclaration;
|
|
338
330
|
textOverride?: string;
|
|
339
331
|
}
|
|
@@ -350,8 +342,8 @@ export interface ImagesSectionContent extends Content, MediaSection {
|
|
|
350
342
|
enablePopup: boolean;
|
|
351
343
|
}
|
|
352
344
|
export interface MediaSection extends Content {
|
|
353
|
-
title:
|
|
354
|
-
description:
|
|
345
|
+
title: string;
|
|
346
|
+
description: string;
|
|
355
347
|
displayStyle: ImagesSectionContentDisplayStyle;
|
|
356
348
|
items: TextShapeItem[] | TextMediaItem[];
|
|
357
349
|
titleStyle: TextStyleDeclaration;
|
|
@@ -368,7 +360,7 @@ export interface ColorReplacement {
|
|
|
368
360
|
}
|
|
369
361
|
export interface TestimonialSectionContent extends Content {
|
|
370
362
|
type: 'testimonial-section';
|
|
371
|
-
title:
|
|
363
|
+
title: string;
|
|
372
364
|
displayStyle: string;
|
|
373
365
|
items: TestimonialItems[];
|
|
374
366
|
titleStyle: TextStyleDeclaration;
|
|
@@ -382,8 +374,8 @@ export interface TestimonialSectionContent extends Content {
|
|
|
382
374
|
export interface AboutSectionContent extends Content {
|
|
383
375
|
type: 'about-section';
|
|
384
376
|
imageUrl: string;
|
|
385
|
-
title:
|
|
386
|
-
paragraph:
|
|
377
|
+
title: string;
|
|
378
|
+
paragraph: string;
|
|
387
379
|
displayStyle: string;
|
|
388
380
|
titleStyle: TextStyleDeclaration;
|
|
389
381
|
paragraphStyle: TextStyleDeclaration;
|
|
@@ -405,7 +397,7 @@ export declare const SOCIAL_LINKS_ICON_DISPLAY_STYLES: {
|
|
|
405
397
|
export type SocialLinksIconDisplayStyle = keyof typeof SOCIAL_LINKS_ICON_DISPLAY_STYLES;
|
|
406
398
|
export interface SocialLinksContent extends Content {
|
|
407
399
|
type: 'social-links';
|
|
408
|
-
title:
|
|
400
|
+
title: string;
|
|
409
401
|
links: LinksItem[];
|
|
410
402
|
iconDisplayStyle: SocialLinksIconDisplayStyle;
|
|
411
403
|
iconFillStyles: BrandPageCssStyle;
|
|
@@ -428,8 +420,8 @@ export interface DividerSectionContent extends Content {
|
|
|
428
420
|
}
|
|
429
421
|
export interface BookingSectionContent extends Content {
|
|
430
422
|
type: 'booking-section';
|
|
431
|
-
title:
|
|
432
|
-
description:
|
|
423
|
+
title: string;
|
|
424
|
+
description: string;
|
|
433
425
|
buttonText: string;
|
|
434
426
|
url: string;
|
|
435
427
|
email?: string;
|
|
@@ -30,6 +30,20 @@ export declare const calculateOptimizedLogoDimensions: (logoData: {
|
|
|
30
30
|
width: string;
|
|
31
31
|
height: string;
|
|
32
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Resolves the "current" logo image from a brand-page MODEL (the raw,
|
|
35
|
+
* deserialized shape — not the live stores, whose contents are wrapped in
|
|
36
|
+
* `settings.content`).
|
|
37
|
+
*
|
|
38
|
+
* Brand-site keeps its logo in the page header; brand-page and brand-contact
|
|
39
|
+
* keep it as a logo CONTENT block on the home page — the same `isBrandSite ?
|
|
40
|
+
* header : content` split the logo-settings store getters/setter use. This is
|
|
41
|
+
* the single source of truth for model-level logo reads: initial load and
|
|
42
|
+
* history-restore both call it so the two paths can't drift. They previously
|
|
43
|
+
* hard-coded `=== brandPage`, which silently excluded brand-contact and read a
|
|
44
|
+
* stale header logo on undo.
|
|
45
|
+
*/
|
|
46
|
+
export declare const getLogoImageFromModel: (model: BrandPageModel) => LogoImageModel | undefined;
|
|
33
47
|
export declare const recalculateLogoContentDimensions: (pageData: any, editableLogoVariations: {
|
|
34
48
|
variationId: number;
|
|
35
49
|
width: number;
|
|
@@ -225,6 +225,25 @@ export const calculateOptimizedLogoDimensions = (logoData, currentWidth, current
|
|
|
225
225
|
}
|
|
226
226
|
return { width: currentWidth, height: currentHeight };
|
|
227
227
|
};
|
|
228
|
+
/**
|
|
229
|
+
* Resolves the "current" logo image from a brand-page MODEL (the raw,
|
|
230
|
+
* deserialized shape — not the live stores, whose contents are wrapped in
|
|
231
|
+
* `settings.content`).
|
|
232
|
+
*
|
|
233
|
+
* Brand-site keeps its logo in the page header; brand-page and brand-contact
|
|
234
|
+
* keep it as a logo CONTENT block on the home page — the same `isBrandSite ?
|
|
235
|
+
* header : content` split the logo-settings store getters/setter use. This is
|
|
236
|
+
* the single source of truth for model-level logo reads: initial load and
|
|
237
|
+
* history-restore both call it so the two paths can't drift. They previously
|
|
238
|
+
* hard-coded `=== brandPage`, which silently excluded brand-contact and read a
|
|
239
|
+
* stale header logo on undo.
|
|
240
|
+
*/
|
|
241
|
+
export const getLogoImageFromModel = (model) => {
|
|
242
|
+
if (model.brandPageType === BRAND_PAGE_TYPES.brandSite) {
|
|
243
|
+
return model.pageHeaderDesktop?.logoImage;
|
|
244
|
+
}
|
|
245
|
+
return model.pages?.[0]?.contents?.find(isLogoContent)?.logoImage;
|
|
246
|
+
};
|
|
228
247
|
export const recalculateLogoContentDimensions = async (pageData, editableLogoVariations, logoImage, isPrePurchase) => {
|
|
229
248
|
try {
|
|
230
249
|
let logoData;
|
|
@@ -20,7 +20,6 @@ import { migration14 } from './migration/migration-14';
|
|
|
20
20
|
import { migration15 } from './migration/migration-15';
|
|
21
21
|
import { migration16 } from './migration/migration-16';
|
|
22
22
|
import { migration17 } from './migration/migration-17';
|
|
23
|
-
import { migration18 } from './migration/migration-18';
|
|
24
23
|
const MIGRATION_TABLE = [
|
|
25
24
|
{
|
|
26
25
|
version: 1,
|
|
@@ -133,16 +132,6 @@ const MIGRATION_TABLE = [
|
|
|
133
132
|
runAlways: true,
|
|
134
133
|
description: 'Padding Control backfill (BP-5699 Tier 2 + BP-5700 Store): backfill existing top/bottom spacing as explicit padding for text (12px), images/social links/shapes/booking (32px), store (16px), contact form (per layout), banner and about (per display style)',
|
|
135
134
|
},
|
|
136
|
-
{
|
|
137
|
-
version: 18,
|
|
138
|
-
migrateFn: migration18,
|
|
139
|
-
// runAlways: normalise RTE to JSON on every load. Idempotent (only HTML
|
|
140
|
-
// strings are converted; JSON is skipped), so it also catches content the
|
|
141
|
-
// AI section builders still emit as HTML — converting it on the next read
|
|
142
|
-
// without a new migration or changes to those builders.
|
|
143
|
-
runAlways: true,
|
|
144
|
-
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)',
|
|
145
|
-
},
|
|
146
135
|
];
|
|
147
136
|
export const GetLatestModelVersion = () => Math.max(...MIGRATION_TABLE.map((x) => x.version));
|
|
148
137
|
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:
|
|
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(
|
|
154
|
-
const title = sanitizeForVCard(
|
|
155
|
-
const description = sanitizeForVCard(
|
|
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(
|
|
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
|
|
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 (
|
|
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
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
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
|
|
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:
|
|
98
|
-
description:
|
|
97
|
+
title: string;
|
|
98
|
+
description: string;
|
|
99
99
|
displayStyle: ImagesSectionContentDisplayStyle;
|
|
100
100
|
aspectRatio: AspectRatio;
|
|
101
101
|
areImagesFullWidth: boolean;
|
|
@@ -118,7 +118,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
118
118
|
content: TContent;
|
|
119
119
|
}>(payload: P): Promise<void>;
|
|
120
120
|
_captureTemplateSwitchIfEnabled(): void;
|
|
121
|
-
applyHistorySnapshot(snapshot: import("@brand-page/models").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
|
|
121
|
+
applyHistorySnapshot(snapshot: import("@brand-page/models").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
|
|
122
122
|
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page/models").BrandPageModel, logoEditsStr?: string): Promise<void>;
|
|
123
123
|
_navigateToActivePage(activePageId?: string): void;
|
|
124
124
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page/models").BrandPageModel): void;
|
|
@@ -163,7 +163,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
163
163
|
content: TContent;
|
|
164
164
|
}>(payload: P): Promise<void>;
|
|
165
165
|
_captureTemplateSwitchIfEnabled(): void;
|
|
166
|
-
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
|
|
166
|
+
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
|
|
167
167
|
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
|
|
168
168
|
_navigateToActivePage(activePageId?: string): void;
|
|
169
169
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
@@ -196,7 +196,7 @@ export default defineComponent({
|
|
|
196
196
|
this.brandPageMakerStore.setIsBrandPageLoaded(true);
|
|
197
197
|
// Capture baseline for undo/redo when the feature is active for this
|
|
198
198
|
// session — see useUndoRedoFlag.ts for the gate (LaunchDarkly flag +
|
|
199
|
-
//
|
|
199
|
+
// non-admin maker; all three brands).
|
|
200
200
|
if (useUndoRedoFlag().value) {
|
|
201
201
|
useHistoryStore().captureBaseline();
|
|
202
202
|
}
|
|
@@ -107,7 +107,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
107
107
|
content: TContent;
|
|
108
108
|
}>(payload: P): Promise<void>;
|
|
109
109
|
_captureTemplateSwitchIfEnabled(): void;
|
|
110
|
-
applyHistorySnapshot(snapshot: import("../../../lib").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
|
|
110
|
+
applyHistorySnapshot(snapshot: import("../../../lib").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
|
|
111
111
|
_syncLogoSettingsFromSnapshot(snapshot: import("../../../lib").BrandPageModel, logoEditsStr?: string): Promise<void>;
|
|
112
112
|
_navigateToActivePage(activePageId?: string): void;
|
|
113
113
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../lib").BrandPageModel): void;
|
package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts
CHANGED
|
@@ -626,7 +626,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
626
626
|
content: TContent;
|
|
627
627
|
}>(payload: P): Promise<void>;
|
|
628
628
|
_captureTemplateSwitchIfEnabled(): void;
|
|
629
|
-
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
|
|
629
|
+
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
|
|
630
630
|
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
|
|
631
631
|
_navigateToActivePage(activePageId?: string): void;
|
|
632
632
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
@@ -113,7 +113,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
113
113
|
content: TContent;
|
|
114
114
|
}>(payload: P): Promise<void>;
|
|
115
115
|
_captureTemplateSwitchIfEnabled(): void;
|
|
116
|
-
applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
|
|
116
|
+
applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
|
|
117
117
|
_syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
|
|
118
118
|
_navigateToActivePage(activePageId?: string): void;
|
|
119
119
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
|