@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
|
@@ -727,6 +727,59 @@ describe('brand page maker store module', () => {
|
|
|
727
727
|
expect(pageNavigationStore.activePageId).toBe(expectedFirstId);
|
|
728
728
|
});
|
|
729
729
|
|
|
730
|
+
// BP-5813: the templates sidebar highlight binds to `selectedTemplateId`,
|
|
731
|
+
// which isn't part of `brandPageData`. It rides along as a history-entry
|
|
732
|
+
// sidecar; applyHistorySnapshot restores it so the highlight reverts in
|
|
733
|
+
// lock-step with the canvas.
|
|
734
|
+
test('applyHistorySnapshot restores selectedTemplateId from the sidecar', async () => {
|
|
735
|
+
const makerStore = useBrandPageMakerStore();
|
|
736
|
+
|
|
737
|
+
await makerStore.initialise(INITIALISE_PAYLOAD);
|
|
738
|
+
|
|
739
|
+
makerStore.setSelectedTemplateId({ templateId: 'template-current' });
|
|
740
|
+
|
|
741
|
+
// Undo lands on an entry captured while 'template-previous' was selected.
|
|
742
|
+
await makerStore.applyHistorySnapshot(
|
|
743
|
+
makerStore.brandPageData,
|
|
744
|
+
undefined,
|
|
745
|
+
undefined,
|
|
746
|
+
'template-previous',
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
expect(makerStore.selectedTemplateId).toBe('template-previous');
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
test('applyHistorySnapshot restores a cleared (false) selectedTemplateId', async () => {
|
|
753
|
+
const makerStore = useBrandPageMakerStore();
|
|
754
|
+
|
|
755
|
+
await makerStore.initialise(INITIALISE_PAYLOAD);
|
|
756
|
+
|
|
757
|
+
makerStore.setSelectedTemplateId({ templateId: 'template-current' });
|
|
758
|
+
|
|
759
|
+
await makerStore.applyHistorySnapshot(
|
|
760
|
+
makerStore.brandPageData,
|
|
761
|
+
undefined,
|
|
762
|
+
undefined,
|
|
763
|
+
false,
|
|
764
|
+
);
|
|
765
|
+
|
|
766
|
+
expect(makerStore.selectedTemplateId).toBe(false);
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
test('applyHistorySnapshot leaves selectedTemplateId untouched when the sidecar is undefined', async () => {
|
|
770
|
+
const makerStore = useBrandPageMakerStore();
|
|
771
|
+
|
|
772
|
+
await makerStore.initialise(INITIALISE_PAYLOAD);
|
|
773
|
+
|
|
774
|
+
makerStore.setSelectedTemplateId({ templateId: 'template-current' });
|
|
775
|
+
|
|
776
|
+
// An entry with no sidecar (e.g. captured before the field existed) must
|
|
777
|
+
// not clobber the current selection.
|
|
778
|
+
await makerStore.applyHistorySnapshot(makerStore.brandPageData);
|
|
779
|
+
|
|
780
|
+
expect(makerStore.selectedTemplateId).toBe('template-current');
|
|
781
|
+
});
|
|
782
|
+
|
|
730
783
|
// BP-5506 follow-up: undoing a non-page-structural edit (e.g. a title
|
|
731
784
|
// change) must NOT push a new route. The router push fires
|
|
732
785
|
// `router.afterEach`, and BrandPageMaker.mixin's afterEach hook resets
|
|
@@ -793,6 +793,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
793
793
|
snapshot: BrandPageModel,
|
|
794
794
|
activePageId?: string,
|
|
795
795
|
logoEditsStr?: string,
|
|
796
|
+
selectedTemplateId?: string | false,
|
|
796
797
|
): Promise<void> {
|
|
797
798
|
const styleSettingsStore = useUiStyleSettingsStore();
|
|
798
799
|
const navigationStyleSettingsStore = useUiNavigationStyleSettingsStore();
|
|
@@ -883,6 +884,16 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
883
884
|
this.cookieOptions = snapshot.cookieOptions;
|
|
884
885
|
this.saveContactSettings = snapshot.saveContactSettings;
|
|
885
886
|
|
|
887
|
+
// 7b. Restore the selected-template pointer that drives the templates
|
|
888
|
+
// sidebar highlight. It's a UI pointer, not part of the persisted
|
|
889
|
+
// model, so it rides along as a history-entry sidecar (like
|
|
890
|
+
// `activePageId`). Its watchers only reset scroll position (no
|
|
891
|
+
// template re-application), so setting it here is safe during apply.
|
|
892
|
+
// (BP-5813)
|
|
893
|
+
if (selectedTemplateId !== undefined) {
|
|
894
|
+
this.setSelectedTemplateId({ templateId: selectedTemplateId });
|
|
895
|
+
}
|
|
896
|
+
|
|
886
897
|
// 8. Re-sync the logo-settings sidebar's `selectedLogoImage` from the
|
|
887
898
|
// restored header logo. The preview rehydrates via the page contents,
|
|
888
899
|
// but `uiLogoSettings` holds its own copy that drives the sidebar
|
|
@@ -945,14 +956,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
945
956
|
}
|
|
946
957
|
}
|
|
947
958
|
|
|
948
|
-
const logoImage =
|
|
949
|
-
snapshot.brandPageType === BRAND_PAGE_TYPES.default
|
|
950
|
-
? (
|
|
951
|
-
snapshot.pages?.[0]?.contents?.find(
|
|
952
|
-
(c) => c.type === 'logo',
|
|
953
|
-
) as any
|
|
954
|
-
)?.logoImage
|
|
955
|
-
: snapshot.pageHeaderDesktop?.logoImage;
|
|
959
|
+
const logoImage = logoUtil.getLogoImageFromModel(snapshot);
|
|
956
960
|
|
|
957
961
|
if (!logoImage) return;
|
|
958
962
|
|
|
@@ -1273,14 +1277,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
1273
1277
|
brandPageType: _brandPageType,
|
|
1274
1278
|
});
|
|
1275
1279
|
|
|
1276
|
-
let logoImage =
|
|
1277
|
-
brandPageModel.brandPageType === BRAND_PAGE_TYPES.default
|
|
1278
|
-
? (
|
|
1279
|
-
brandPageModel.pages?.[0].contents.find(
|
|
1280
|
-
(c) => c.type === 'logo',
|
|
1281
|
-
) as any
|
|
1282
|
-
)?.logoImage
|
|
1283
|
-
: brandPageModel.pageHeaderDesktop?.logoImage;
|
|
1280
|
+
let logoImage = logoUtil.getLogoImageFromModel(brandPageModel);
|
|
1284
1281
|
|
|
1285
1282
|
if (!logoImage?.logoDraftToken) {
|
|
1286
1283
|
logoImage = logoUtil.safeGetLogoImageFromLogoImageUrl(
|
|
@@ -16,6 +16,8 @@ const mockMakerStore = {
|
|
|
16
16
|
isBrandPageLoaded: false,
|
|
17
17
|
applyHistorySnapshot: vi.fn(async () => undefined),
|
|
18
18
|
setIsBrandPageLoaded: vi.fn(),
|
|
19
|
+
selectedTemplateId: false as string | false,
|
|
20
|
+
setSelectedTemplateId: vi.fn(),
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
const mockPageNavigationStore = {
|
|
@@ -64,6 +66,8 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
64
66
|
beforeEach(() => {
|
|
65
67
|
setActivePinia(createPinia());
|
|
66
68
|
mockMakerStore.applyHistorySnapshot.mockClear();
|
|
69
|
+
mockMakerStore.setSelectedTemplateId.mockClear();
|
|
70
|
+
mockMakerStore.selectedTemplateId = false;
|
|
67
71
|
mutationCounter = 0;
|
|
68
72
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
73
|
(mockMakerStore.brandPageData as any).v = 1;
|
|
@@ -443,6 +447,46 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
443
447
|
});
|
|
444
448
|
});
|
|
445
449
|
|
|
450
|
+
// BP-5813: the templates sidebar highlight binds to
|
|
451
|
+
// `brandPageMakerStore.selectedTemplateId`, which is NOT part of
|
|
452
|
+
// `brandPageData`. It rides along as a per-entry sidecar so undo/redo can
|
|
453
|
+
// restore the highlight in lock-step with the canvas.
|
|
454
|
+
describe('selectedTemplateId sidecar (BP-5813 — template sidebar highlight)', () => {
|
|
455
|
+
it('captures the current selectedTemplateId on each entry', async () => {
|
|
456
|
+
const store = useHistoryStore();
|
|
457
|
+
|
|
458
|
+
mockMakerStore.selectedTemplateId = 'template-a';
|
|
459
|
+
await store.captureBaseline();
|
|
460
|
+
|
|
461
|
+
expect(store.entries[0].selectedTemplateId).toBe('template-a');
|
|
462
|
+
|
|
463
|
+
mockMakerStore.selectedTemplateId = 'template-b';
|
|
464
|
+
captureMutated(store);
|
|
465
|
+
|
|
466
|
+
expect(store.entries[1].selectedTemplateId).toBe('template-b');
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
it('passes the target entry selectedTemplateId to applyHistorySnapshot on undo', async () => {
|
|
470
|
+
const store = useHistoryStore();
|
|
471
|
+
|
|
472
|
+
mockMakerStore.selectedTemplateId = 'template-a';
|
|
473
|
+
await store.captureBaseline();
|
|
474
|
+
|
|
475
|
+
mockMakerStore.selectedTemplateId = 'template-b';
|
|
476
|
+
captureMutated(store);
|
|
477
|
+
|
|
478
|
+
await store.undo();
|
|
479
|
+
|
|
480
|
+
// 4th arg is the baseline entry's template id — the sidebar reverts
|
|
481
|
+
// with the canvas instead of lagging on the undone template.
|
|
482
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
483
|
+
const callArgs = mockMakerStore.applyHistorySnapshot.mock
|
|
484
|
+
.calls[0] as any[];
|
|
485
|
+
|
|
486
|
+
expect(callArgs[3]).toBe('template-a');
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
|
|
446
490
|
it('reentrancy guard: capture no-ops when isApplyingSnapshot is true', async () => {
|
|
447
491
|
const store = useHistoryStore();
|
|
448
492
|
|
|
@@ -505,6 +549,7 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
505
549
|
expect.objectContaining(baselineBrandPageData),
|
|
506
550
|
undefined,
|
|
507
551
|
expect.any(String),
|
|
552
|
+
false,
|
|
508
553
|
);
|
|
509
554
|
});
|
|
510
555
|
|
|
@@ -767,6 +812,7 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
767
812
|
expect.anything(),
|
|
768
813
|
'page-home',
|
|
769
814
|
expect.any(String),
|
|
815
|
+
false,
|
|
770
816
|
);
|
|
771
817
|
});
|
|
772
818
|
|
|
@@ -801,6 +847,7 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
801
847
|
expect.anything(),
|
|
802
848
|
'page-home',
|
|
803
849
|
expect.any(String),
|
|
850
|
+
false,
|
|
804
851
|
);
|
|
805
852
|
});
|
|
806
853
|
|
|
@@ -842,6 +889,7 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
842
889
|
expect.anything(),
|
|
843
890
|
'page-about',
|
|
844
891
|
expect.any(String),
|
|
892
|
+
false,
|
|
845
893
|
);
|
|
846
894
|
});
|
|
847
895
|
|
|
@@ -879,6 +927,7 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
879
927
|
expect.anything(),
|
|
880
928
|
'page-new',
|
|
881
929
|
expect.any(String),
|
|
930
|
+
false,
|
|
882
931
|
);
|
|
883
932
|
});
|
|
884
933
|
|
|
@@ -912,6 +961,7 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
912
961
|
expect.anything(),
|
|
913
962
|
'page-home',
|
|
914
963
|
expect.any(String),
|
|
964
|
+
false,
|
|
915
965
|
);
|
|
916
966
|
|
|
917
967
|
// Now redo. Pointer moves forward to entry 1 (page-x captured),
|
|
@@ -922,6 +972,7 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
922
972
|
expect.anything(),
|
|
923
973
|
'page-x',
|
|
924
974
|
expect.any(String),
|
|
975
|
+
false,
|
|
925
976
|
);
|
|
926
977
|
});
|
|
927
978
|
});
|
|
@@ -26,6 +26,12 @@ export interface HistoryEntry {
|
|
|
26
26
|
activePageId: string;
|
|
27
27
|
/** JSON-stringified `editableLogoStore.logoEdits`. Undefined if logo tab never opened. */
|
|
28
28
|
logoEdits?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Selected template id at capture time — drives the templates sidebar
|
|
31
|
+
* highlight. `false` when no template is selected. Sidecar to
|
|
32
|
+
* `brandPageData` (not part of the persisted model), like `activePageId`.
|
|
33
|
+
*/
|
|
34
|
+
selectedTemplateId?: string | false;
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
// Monotonic burst — first mutation starts the timer, subsequent mutations
|
|
@@ -150,6 +156,10 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
150
156
|
return usePageNavigationStore().activePageId ?? '';
|
|
151
157
|
}
|
|
152
158
|
|
|
159
|
+
function getCurrentSelectedTemplateId(): string | false {
|
|
160
|
+
return useBrandPageMakerStore().selectedTemplateId;
|
|
161
|
+
}
|
|
162
|
+
|
|
153
163
|
function serializeCurrentLogoEdits(): string | undefined {
|
|
154
164
|
try {
|
|
155
165
|
const editableLogoStore = useUiEditableLogoStore();
|
|
@@ -187,6 +197,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
187
197
|
label?: string;
|
|
188
198
|
activePageId: string;
|
|
189
199
|
logoEdits?: string;
|
|
200
|
+
selectedTemplateId?: string | false;
|
|
190
201
|
}): 'committed' | 'oversized' | 'noop' {
|
|
191
202
|
const current = entries.value[currentIndex.value];
|
|
192
203
|
|
|
@@ -219,6 +230,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
219
230
|
sizeBytes: args.snapshot.length,
|
|
220
231
|
activePageId: args.activePageId,
|
|
221
232
|
logoEdits: args.logoEdits,
|
|
233
|
+
selectedTemplateId: args.selectedTemplateId,
|
|
222
234
|
};
|
|
223
235
|
|
|
224
236
|
// FR-11: truncate redo tail, then append.
|
|
@@ -293,6 +305,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
293
305
|
|
|
294
306
|
const activePageId = getCurrentActivePageId();
|
|
295
307
|
const logoEdits = serializeCurrentLogoEdits();
|
|
308
|
+
const selectedTemplateId = getCurrentSelectedTemplateId();
|
|
296
309
|
|
|
297
310
|
// Settle window: fold post-init reactive cascades back into the
|
|
298
311
|
// baseline so undo doesn't light up before the user has done
|
|
@@ -317,6 +330,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
317
330
|
sizeBytes: snapshot.length,
|
|
318
331
|
activePageId,
|
|
319
332
|
logoEdits,
|
|
333
|
+
selectedTemplateId,
|
|
320
334
|
},
|
|
321
335
|
];
|
|
322
336
|
|
|
@@ -333,6 +347,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
333
347
|
sizeBytes: snapshot.length,
|
|
334
348
|
activePageId,
|
|
335
349
|
logoEdits,
|
|
350
|
+
selectedTemplateId,
|
|
336
351
|
};
|
|
337
352
|
entries.value = next;
|
|
338
353
|
|
|
@@ -345,6 +360,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
345
360
|
actor: 'user',
|
|
346
361
|
activePageId,
|
|
347
362
|
logoEdits,
|
|
363
|
+
selectedTemplateId,
|
|
348
364
|
});
|
|
349
365
|
};
|
|
350
366
|
|
|
@@ -402,6 +418,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
402
418
|
sizeBytes: snapshot.length,
|
|
403
419
|
activePageId: getCurrentActivePageId(),
|
|
404
420
|
logoEdits: serializeCurrentLogoEdits(),
|
|
421
|
+
selectedTemplateId: getCurrentSelectedTemplateId(),
|
|
405
422
|
},
|
|
406
423
|
];
|
|
407
424
|
currentIndex.value = 0;
|
|
@@ -427,6 +444,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
427
444
|
snapshot,
|
|
428
445
|
activePageId: getCurrentActivePageId(),
|
|
429
446
|
logoEdits: serializeCurrentLogoEdits(),
|
|
447
|
+
selectedTemplateId: getCurrentSelectedTemplateId(),
|
|
430
448
|
...args,
|
|
431
449
|
});
|
|
432
450
|
}
|
|
@@ -531,6 +549,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
531
549
|
snapshot,
|
|
532
550
|
resolvedActivePageId,
|
|
533
551
|
targetEntry?.logoEdits,
|
|
552
|
+
targetEntry?.selectedTemplateId,
|
|
534
553
|
);
|
|
535
554
|
} finally {
|
|
536
555
|
isApplyingSnapshot.value = false;
|
|
@@ -7,8 +7,6 @@ export * from './url.util';
|
|
|
7
7
|
export * from './slug.util';
|
|
8
8
|
export * from './text.util';
|
|
9
9
|
export * from './rich-text-editor.util';
|
|
10
|
-
export * from './rte-render.util';
|
|
11
|
-
export * from './rte-sanitize.util';
|
|
12
10
|
|
|
13
11
|
export const isColorMatched = (color: string | null | undefined): boolean => {
|
|
14
12
|
if (!color) return false;
|
|
@@ -76,7 +76,7 @@ describe('hasHTML', () => {
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
describe('getUpdatedHTMLFromEditor', () => {
|
|
79
|
-
it('applies style commands and returns updated
|
|
79
|
+
it('applies style commands and returns updated HTML', () => {
|
|
80
80
|
// Mock editor
|
|
81
81
|
const runMock = vi.fn();
|
|
82
82
|
const chain = {
|
|
@@ -119,7 +119,7 @@ describe('getUpdatedHTMLFromEditor', () => {
|
|
|
119
119
|
},
|
|
120
120
|
},
|
|
121
121
|
chain: () => chain as any,
|
|
122
|
-
|
|
122
|
+
getHTML: () => '<div>styled</div>',
|
|
123
123
|
} as unknown as Editor;
|
|
124
124
|
|
|
125
125
|
const newStyle = {
|
|
@@ -137,8 +137,7 @@ describe('getUpdatedHTMLFromEditor', () => {
|
|
|
137
137
|
|
|
138
138
|
expect(externalEditor.commands.setContent).toHaveBeenCalledWith('foo');
|
|
139
139
|
expect(runMock).toHaveBeenCalled();
|
|
140
|
-
|
|
141
|
-
expect(result).toEqual({ type: 'doc', content: [{ type: 'paragraph' }] });
|
|
140
|
+
expect(result).toBe('<div>styled</div>');
|
|
142
141
|
});
|
|
143
142
|
});
|
|
144
143
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChainedCommands, Editor
|
|
1
|
+
import type { ChainedCommands, Editor } from '@tiptap/vue-3';
|
|
2
2
|
import type { EditorState, Transaction, Selection } from 'prosemirror-state';
|
|
3
3
|
import {
|
|
4
4
|
STYLE_THEME_KEYS,
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
type RequestPaymentContent,
|
|
20
20
|
type SupportMeContent,
|
|
21
21
|
type ShopContent,
|
|
22
|
-
type RichTextValue,
|
|
23
22
|
} from '@brand-page';
|
|
24
23
|
import type { PageSettingsState } from '@shared/page-settings/store';
|
|
25
24
|
import type { StyleSettingsState } from '@shared/style-settings/store';
|
|
@@ -244,38 +243,8 @@ export const skipStyleDetection = (chain: ChainedCommands, marks?: Mark[]) =>
|
|
|
244
243
|
return true;
|
|
245
244
|
});
|
|
246
245
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
* document is an object with `type: 'doc'`.
|
|
250
|
-
*/
|
|
251
|
-
export const isTiptapDocument = (value: unknown): value is JSONContent =>
|
|
252
|
-
typeof value === 'object' &&
|
|
253
|
-
value !== null &&
|
|
254
|
-
(value as JSONContent).type === 'doc';
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Extract visible plain text from a Tiptap JSON document (concatenated text
|
|
258
|
-
* nodes). Dependency-free — no editor instantiation.
|
|
259
|
-
*/
|
|
260
|
-
export const getRteJsonPlainText = (doc: JSONContent): string => {
|
|
261
|
-
const parts: string[] = [];
|
|
262
|
-
|
|
263
|
-
const walk = (node: JSONContent): void => {
|
|
264
|
-
if (typeof node.text === 'string') parts.push(node.text);
|
|
265
|
-
|
|
266
|
-
node.content?.forEach(walk);
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
walk(doc);
|
|
270
|
-
|
|
271
|
-
return parts.join(' ').replace(/\s+/g, ' ').trim();
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
// Accepts a legacy inline-HTML string or a Tiptap JSON document (BP-5787).
|
|
275
|
-
export const hasRTEContent = (content: unknown): boolean => {
|
|
276
|
-
if (isTiptapDocument(content)) return true;
|
|
277
|
-
|
|
278
|
-
if (typeof content !== 'string' || content.length === 0) return false;
|
|
246
|
+
export const hasRTEContent = (content: string): boolean => {
|
|
247
|
+
if (!content || content.length === 0) return false;
|
|
279
248
|
|
|
280
249
|
const trimmed = content.trim();
|
|
281
250
|
const tagWrapRegex = /^<([A-Za-z][A-Za-z0-9-]*)\b[^>]*>[\s\S]*<\/\1>$/;
|
|
@@ -283,11 +252,7 @@ export const hasRTEContent = (content: unknown): boolean => {
|
|
|
283
252
|
return tagWrapRegex.test(trimmed);
|
|
284
253
|
};
|
|
285
254
|
|
|
286
|
-
export const getPlainTextFromRTE = (content:
|
|
287
|
-
if (isTiptapDocument(content)) {
|
|
288
|
-
return getRteJsonPlainText(content);
|
|
289
|
-
}
|
|
290
|
-
|
|
255
|
+
export const getPlainTextFromRTE = (content: string): string => {
|
|
291
256
|
if (typeof content !== 'string') {
|
|
292
257
|
return '';
|
|
293
258
|
}
|
|
@@ -756,20 +721,16 @@ export const switchAllContentToRTE = (
|
|
|
756
721
|
|
|
757
722
|
export const getUpdatedHTMLFromEditor = (
|
|
758
723
|
externalEditor: Editor,
|
|
759
|
-
contentText:
|
|
724
|
+
contentText: string,
|
|
760
725
|
newContentStyle: TextStyleDeclaration,
|
|
761
726
|
) => {
|
|
762
727
|
if (!contentText) {
|
|
763
728
|
return contentText;
|
|
764
729
|
}
|
|
765
730
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
typeof contentText === 'string' &&
|
|
770
|
-
contentText.includes(ESCAPED_NEWLINE_CHARACTER)
|
|
771
|
-
? getRenderText(contentText)
|
|
772
|
-
: contentText;
|
|
731
|
+
const content = contentText.includes(ESCAPED_NEWLINE_CHARACTER)
|
|
732
|
+
? getRenderText(contentText)
|
|
733
|
+
: contentText;
|
|
773
734
|
|
|
774
735
|
externalEditor.commands.setContent(content);
|
|
775
736
|
|
|
@@ -827,9 +788,9 @@ export const getUpdatedHTMLFromEditor = (
|
|
|
827
788
|
chain = newContentStyle?.fontStyle ? chain.setItalic() : chain.unsetItalic();
|
|
828
789
|
|
|
829
790
|
chain.run();
|
|
791
|
+
const html = externalEditor.getHTML();
|
|
830
792
|
|
|
831
|
-
|
|
832
|
-
return externalEditor.getJSON();
|
|
793
|
+
return html;
|
|
833
794
|
};
|
|
834
795
|
|
|
835
796
|
// Helper to build stored marks from a style declaration
|
|
@@ -953,7 +914,7 @@ export const sanitiseClientSideRTE = (html: string): SanitizationResult => {
|
|
|
953
914
|
/**
|
|
954
915
|
* Validates if an href value is safe and returns a sanitized version
|
|
955
916
|
*/
|
|
956
|
-
|
|
917
|
+
const validateAndSanitizeHref = (href: string): string | null => {
|
|
957
918
|
if (!href || typeof href !== 'string') return null;
|
|
958
919
|
|
|
959
920
|
// Trim whitespace and decode entities
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isURL, isEmail, isTel } from '@utils/validator.util';
|
|
2
2
|
import type { ItemFieldType, Validator } from '@brand-page-maker/models';
|
|
3
|
-
import { YOUTUBE_URL_RE
|
|
3
|
+
import { YOUTUBE_URL_RE } from '@brand-page-maker/utils';
|
|
4
4
|
import { validatorTr } from '@src/composables/useTranslate';
|
|
5
5
|
|
|
6
6
|
const addressValueValidator: Validator = {
|
|
@@ -76,15 +76,7 @@ export const dummyValidator: Validator = {
|
|
|
76
76
|
|
|
77
77
|
const nonEmptyStringValidator: Validator = {
|
|
78
78
|
validate: (name, value: any) => {
|
|
79
|
-
|
|
80
|
-
// An RTE field's stored value used to be inline HTML — an empty editor was
|
|
81
|
-
// "<p></p>", a NON-empty string, so the required check always passed for RTE
|
|
82
|
-
// fields (it only ever failed for genuinely empty PLAIN inputs). Now RTE
|
|
83
|
-
// fields are Tiptap JSON docs; treat any doc as "present" so behaviour
|
|
84
|
-
// stays identical. A plain string is still required to be non-empty.
|
|
85
|
-
const isValid = isTiptapDocument(value)
|
|
86
|
-
? true
|
|
87
|
-
: typeof value === 'string' && value.length > 0;
|
|
79
|
+
const isValid = typeof value === 'string' && value.length > 0;
|
|
88
80
|
|
|
89
81
|
return {
|
|
90
82
|
isValid,
|
package/src/lib.ts
CHANGED
|
@@ -85,15 +85,6 @@ export {
|
|
|
85
85
|
recalculateHeaderLogoSizes,
|
|
86
86
|
} from './brand-page/utils/logo.util';
|
|
87
87
|
export { sanitizeRTEHtml } from './brand-page-maker/utils';
|
|
88
|
-
// BP-5787: RTE JSON storage boundary helpers (render/normalise/sanitise/extract).
|
|
89
|
-
export {
|
|
90
|
-
renderRteToHtml,
|
|
91
|
-
toRteJson,
|
|
92
|
-
isTiptapDocument,
|
|
93
|
-
sanitizeRteJson,
|
|
94
|
-
getRteJsonPlainText,
|
|
95
|
-
type RichTextValue,
|
|
96
|
-
} from './brand-page-maker/utils';
|
|
97
88
|
export { getPageSlugFromPageTitle } from './brand-page-maker/utils/slug.util';
|
|
98
89
|
|
|
99
90
|
// AI-pipeline preview (longclaw per-turn snapshots): web-renderer's
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { BrandPageModel, NavOrder } from '../../brand-page/models';
|
|
2
|
+
import {
|
|
3
|
+
BaseMetadataBuilder,
|
|
4
|
+
type BuilderResult,
|
|
5
|
+
type MetadataBuilderRequest,
|
|
6
|
+
} from '../models';
|
|
7
|
+
import type { Logger } from '../logger';
|
|
8
|
+
|
|
9
|
+
export interface ReorderPagesPayload {
|
|
10
|
+
pageOrder: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class ReorderPagesBuilder extends BaseMetadataBuilder<ReorderPagesPayload> {
|
|
14
|
+
constructor(
|
|
15
|
+
request: MetadataBuilderRequest<ReorderPagesPayload>,
|
|
16
|
+
logger?: Logger,
|
|
17
|
+
) {
|
|
18
|
+
super(request, logger);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async validateAsync(): Promise<{ errors: string[] }> {
|
|
22
|
+
const errors: string[] = [];
|
|
23
|
+
const payload = this.request.payload;
|
|
24
|
+
|
|
25
|
+
if (!payload?.pageOrder?.length) {
|
|
26
|
+
errors.push('page_order is required for reorder_pages');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return { errors };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async buildAsync(model: BrandPageModel): Promise<BuilderResult> {
|
|
33
|
+
this.log('Build called');
|
|
34
|
+
|
|
35
|
+
const validation = await this.validateAsync();
|
|
36
|
+
|
|
37
|
+
if (validation.errors.length) {
|
|
38
|
+
return { request: this.request, model, errors: validation.errors };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const { pageOrder } = this.request.payload!;
|
|
42
|
+
|
|
43
|
+
// Build pageId → routeId lookup from nav.routes
|
|
44
|
+
const pageIdToRouteId = new Map<string, string>();
|
|
45
|
+
|
|
46
|
+
for (const route of model.nav.routes) {
|
|
47
|
+
pageIdToRouteId.set(route.pageId, route.id);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Build new nav.orders from the flat page_order (array of pageIds)
|
|
51
|
+
const newOrders: NavOrder[] = [];
|
|
52
|
+
const seenRouteIds = new Set<string>();
|
|
53
|
+
|
|
54
|
+
for (const pageId of pageOrder) {
|
|
55
|
+
const routeId = pageIdToRouteId.get(pageId);
|
|
56
|
+
|
|
57
|
+
if (!routeId) continue;
|
|
58
|
+
|
|
59
|
+
newOrders.push({ routeId, subRoutes: [] });
|
|
60
|
+
seenRouteIds.add(routeId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Safety: append any routes not mentioned (don't lose pages)
|
|
64
|
+
for (const route of model.nav.routes) {
|
|
65
|
+
const routeId = pageIdToRouteId.get(route.pageId);
|
|
66
|
+
|
|
67
|
+
if (routeId && !seenRouteIds.has(routeId)) {
|
|
68
|
+
newOrders.push({ routeId, subRoutes: [] });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
model.nav.orders = newOrders;
|
|
73
|
+
|
|
74
|
+
this.log({
|
|
75
|
+
message: `Reordered pages: ${pageOrder.join(', ')}`,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return { request: this.request, model };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -6,36 +6,7 @@ import {
|
|
|
6
6
|
type BuilderResult,
|
|
7
7
|
type MetadataBuilderRequest,
|
|
8
8
|
} from '../models';
|
|
9
|
-
import {
|
|
10
|
-
hasRTEContent,
|
|
11
|
-
replaceTextInRTE,
|
|
12
|
-
isTiptapDocument,
|
|
13
|
-
renderRteToHtml,
|
|
14
|
-
toRteJson,
|
|
15
|
-
} from '../../brand-page-maker/utils';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* BP-5787 — replace the text of an RTE field while preserving formatting, for
|
|
19
|
-
* either storage form. JSON is rendered to HTML, edited via the existing
|
|
20
|
-
* HTML-preserving replace, then converted back to JSON; plain/legacy strings
|
|
21
|
-
* keep the original behaviour.
|
|
22
|
-
*/
|
|
23
|
-
const updateRteFieldValue = (existing: unknown, newText: string): unknown => {
|
|
24
|
-
const wasJson = isTiptapDocument(existing);
|
|
25
|
-
const existingHtml = wasJson ? renderRteToHtml(existing) : existing;
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
existingHtml &&
|
|
29
|
-
typeof existingHtml === 'string' &&
|
|
30
|
-
hasRTEContent(existingHtml)
|
|
31
|
-
) {
|
|
32
|
-
const updatedHtml = replaceTextInRTE(existingHtml, newText);
|
|
33
|
-
|
|
34
|
-
return wasJson ? toRteJson(updatedHtml) : updatedHtml;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return newText;
|
|
38
|
-
};
|
|
9
|
+
import { hasRTEContent, replaceTextInRTE } from '../../brand-page-maker/utils';
|
|
39
10
|
|
|
40
11
|
export interface UpdateTextPayload {
|
|
41
12
|
contentId: string;
|
|
@@ -65,7 +36,12 @@ const updateTextField = (target: any, fieldName: string, newText: string) => {
|
|
|
65
36
|
|
|
66
37
|
if (Array.isArray(array) && array[+index]) {
|
|
67
38
|
const existingText = array[+index][property];
|
|
68
|
-
const updatedValue =
|
|
39
|
+
const updatedValue =
|
|
40
|
+
existingText &&
|
|
41
|
+
typeof existingText === 'string' &&
|
|
42
|
+
hasRTEContent(existingText)
|
|
43
|
+
? replaceTextInRTE(existingText, newText)
|
|
44
|
+
: newText;
|
|
69
45
|
|
|
70
46
|
// Create a new array with the updated item to trigger reactivity
|
|
71
47
|
const newArray = [...array];
|
|
@@ -78,7 +54,17 @@ const updateTextField = (target: any, fieldName: string, newText: string) => {
|
|
|
78
54
|
}
|
|
79
55
|
} else {
|
|
80
56
|
// Simple field
|
|
81
|
-
|
|
57
|
+
const existingText = target[fieldName];
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
existingText &&
|
|
61
|
+
typeof existingText === 'string' &&
|
|
62
|
+
hasRTEContent(existingText)
|
|
63
|
+
) {
|
|
64
|
+
target[fieldName] = replaceTextInRTE(existingText, newText);
|
|
65
|
+
} else {
|
|
66
|
+
target[fieldName] = newText;
|
|
67
|
+
}
|
|
82
68
|
}
|
|
83
69
|
};
|
|
84
70
|
|