@designcrowd/library.brand-page 6.2.11 → 6.2.12
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-DDcraD5S.js → CreatedOnBrandCrowd-de-de-BtVKllNQ.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-DtOeaisf.js → CreatedOnBrandCrowd-en-us-CX5V0v8u.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-BZpmJPew.js → CreatedOnBrandCrowd-es-es-CbA02PCL.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-CqRwC4e7.js → CreatedOnBrandCrowd-fr-ca-BQAKruBF.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-CqRwC4e7.js → CreatedOnBrandCrowd-fr-fr-BQAKruBF.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-DId9Dfjh.js → CreatedOnBrandCrowd-pt-br-Yk_yzB3s.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-DId9Dfjh.js → CreatedOnBrandCrowd-pt-pt-Yk_yzB3s.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-BTDfmOcm.js → CreatedOnDcom-de-de-DJZQbPSD.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-CeAu9Ayx.js → CreatedOnDcom-en-us-BJvNAa4l.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-WCv0K41H.js → CreatedOnDcom-es-es-CUwB1FRY.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-BlfevQDY.js → CreatedOnDcom-fr-ca-CK54U4oh.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-Cvt7MHPZ.js → CreatedOnDcom-fr-fr-DuUNBGrM.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-DipZuylv.js → CreatedOnDcom-pt-br-BfODpFNV.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-BCw4lcKN.js → CreatedOnDcom-pt-pt-Cf6u2GCg.js} +1 -1
- package/lib/src/brand-page/__fixtures__/production-text-style-resolver.fixture.d.ts +16 -0
- package/lib/src/brand-page/__fixtures__/production-text-style-resolver.fixture.js +35 -0
- package/lib/src/brand-page/components/contact-form/ContactForm.mixin.d.ts +3 -0
- package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +19 -13
- package/lib/src/brand-page/components/mailing-list/MailingList.mixin.d.ts +3 -1
- package/lib/src/brand-page/components/mailing-list/MailingList.mixin.js +17 -2
- package/lib/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.d.ts +11 -3
- package/lib/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.js +35 -1
- package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.d.ts +8 -2
- package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.js +27 -3
- package/lib/src/brand-page/components/page/Page.mixin.d.ts +5 -2
- package/lib/src/brand-page/components/page/Page.mixin.js +33 -27
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.d.ts +7 -2
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.js +21 -1
- package/lib/src/brand-page/components/payment/Payment.mixin.d.ts +5 -2
- package/lib/src/brand-page/components/payment/Payment.mixin.js +22 -2
- package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.d.ts +6 -2
- package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.js +32 -1
- package/lib/src/brand-page/components/social-links/SocialLinks.stories.js +0 -3
- package/lib/src/brand-page/components/testimonial-section/__fixtures__/data.js +0 -3
- package/lib/src/brand-page/components/text/Text.stories.js +0 -17
- package/lib/src/brand-page/constants/font.constants.d.ts +62 -0
- package/lib/src/brand-page/constants/font.constants.js +35 -0
- package/lib/src/brand-page/models/index.d.ts +23 -24
- package/lib/src/brand-page/models/index.js +20 -7
- package/lib/src/brand-page/models/navigation-styles.model.d.ts +1 -1
- package/lib/src/brand-page/models/navigation-styles.model.js +17 -8
- package/lib/src/brand-page/models/payment.model.d.ts +11 -6
- package/lib/src/brand-page/models/styles.model.d.ts +53 -7
- package/lib/src/brand-page/models/styles.model.js +115 -27
- package/lib/src/brand-page/utils/color-palette.util.d.ts +43 -23
- package/lib/src/brand-page/utils/color-palette.util.js +65 -27
- package/lib/src/brand-page/utils/color.util.d.ts +13 -9
- package/lib/src/brand-page/utils/color.util.js +56 -15
- package/lib/src/brand-page/utils/container-text-color.util.d.ts +46 -13
- package/lib/src/brand-page/utils/container-text-color.util.js +321 -41
- package/lib/src/brand-page/utils/index.d.ts +1 -0
- package/lib/src/brand-page/utils/index.js +1 -0
- package/lib/src/brand-page/utils/migration/migration-20.js +6 -2
- package/lib/src/brand-page/utils/migration/migration-21.js +34 -6
- package/lib/src/brand-page/utils/migration/migration-22.d.ts +99 -0
- package/lib/src/brand-page/utils/migration/migration-22.js +909 -0
- package/lib/src/brand-page/utils/migration.util.js +17 -0
- package/lib/src/brand-page/utils/model.util.d.ts +4 -0
- package/lib/src/brand-page/utils/model.util.js +4 -0
- package/lib/src/brand-page/utils/personalisation.util.js +9 -1
- package/lib/src/brand-page/utils/rte-role-lift.util.d.ts +72 -0
- package/lib/src/brand-page/utils/rte-role-lift.util.js +275 -0
- package/lib/src/brand-page/utils/style.util.d.ts +5 -1
- package/lib/src/brand-page/utils/style.util.js +34 -11
- package/lib/src/brand-page/utils/text-role-css.util.d.ts +19 -0
- package/lib/src/brand-page/utils/text-role-css.util.js +186 -0
- package/lib/src/brand-page/utils/text-role-reconnect.util.d.ts +90 -0
- package/lib/src/brand-page/utils/text-role-reconnect.util.js +434 -0
- package/lib/src/brand-page/utils/text-style.util.d.ts +53 -23
- package/lib/src/brand-page/utils/text-style.util.js +122 -22
- package/lib/src/brand-page/utils/view-model.util.d.ts +9 -1
- package/lib/src/brand-page/utils/view-model.util.js +124 -111
- package/lib/src/brand-page/view-models.d.ts +1 -0
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +13 -2
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +4 -4
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +0 -10
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +0 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +23 -138
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +0 -28
- package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +5 -2
- package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +1 -0
- package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.js +1 -0
- package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +1 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.d.ts +16 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.js +61 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.d.ts +11 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.js +236 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +2 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +25 -6
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +17 -4
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +204 -17
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +29 -31
- package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.d.ts +20 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.js +60 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +2 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +22 -6
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +10 -4
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +319 -275
- package/lib/src/brand-page-maker/constants/config-settings-constant.js +1 -5
- package/lib/src/brand-page-maker/convertors/text-css-style-options.convertor.js +6 -2
- package/lib/src/brand-page-maker/convertors/text-size-value.convertor.d.ts +1 -1
- package/lib/src/brand-page-maker/convertors/text-size-value.convertor.js +3 -1
- package/lib/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.js +7 -14
- package/lib/src/brand-page-maker/default-getters/text-color.default-getter.js +6 -13
- package/lib/src/brand-page-maker/models/content-settings.d.ts +8 -0
- package/lib/src/brand-page-maker/models/content-settings.js +112 -81
- package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.d.ts +2 -2
- package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.js +5 -2
- package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.js +4 -3
- package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +1257 -117
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +6 -1
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +17 -9
- package/lib/src/brand-page-maker/stores/history/history-store.d.ts +59 -5
- package/lib/src/brand-page-maker/stores/history/history-store.js +22 -2
- package/lib/src/brand-page-maker/utils/apply-color-strategy.js +26 -8
- package/lib/src/brand-page-maker/utils/index.d.ts +2 -1
- package/lib/src/brand-page-maker/utils/index.js +2 -1
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +117 -15
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +435 -281
- package/lib/src/brand-page-maker/utils/rte-authoring.util.d.ts +4 -0
- package/lib/src/brand-page-maker/utils/rte-authoring.util.js +101 -0
- package/lib/src/brand-page-maker/utils/rte-clipboard.util.d.ts +126 -0
- package/lib/src/brand-page-maker/utils/rte-clipboard.util.js +307 -0
- package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +13 -3
- package/lib/src/{bundled-translations-zfiA5Tsw.js → bundled-translations-yGrvPE5i.js} +17 -17
- package/lib/src/{bundled-translations.de-DE-ChsdSyAP.js → bundled-translations.de-DE-L4Znf8Hs.js} +17 -17
- package/lib/src/{bundled-translations.es-ES-DflsWQK0.js → bundled-translations.es-ES-D6iticrK.js} +15 -15
- package/lib/src/{bundled-translations.fr-CA-fpDRuZ52.js → bundled-translations.fr-CA-BgAVE-9k.js} +25 -25
- package/lib/src/{bundled-translations.fr-FR-Bub73Zt-.js → bundled-translations.fr-FR-B8GbyqxQ.js} +17 -17
- package/lib/src/{bundled-translations.pt-BR-BlnWE9TB.js → bundled-translations.pt-BR-DjPU3Db7.js} +25 -25
- package/lib/src/{bundled-translations.pt-PT-DmzXlnaS.js → bundled-translations.pt-PT-BaepaDpr.js} +23 -23
- package/lib/src/bundles/bundled-translations.de-DE.json +21 -2
- package/lib/src/bundles/bundled-translations.es-ES.json +21 -2
- package/lib/src/bundles/bundled-translations.fr-CA.json +21 -2
- package/lib/src/bundles/bundled-translations.fr-FR.json +21 -2
- package/lib/src/bundles/bundled-translations.json +21 -2
- package/lib/src/bundles/bundled-translations.pt-BR.json +21 -2
- package/lib/src/bundles/bundled-translations.pt-PT.json +21 -2
- package/lib/src/clients/ai-assistant-client.d.ts +1 -0
- package/lib/src/composables/useTranslate.d.ts +1 -1
- package/lib/src/composables/useTranslate.js +1 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +303 -207
- package/lib/src/css/library.brand-page-brandPage.min.css +303 -207
- package/lib/src/css/library.brand-page-designCom.min.css +303 -207
- package/lib/src/css/library.brand-page-preview.min.css +303 -207
- package/lib/src/index.d.ts +2 -1
- package/lib/src/index.mjs +195 -191
- package/lib/src/{lib-1AqtEmvQ.js → lib-kGRlD3_P.js} +36855 -33893
- package/lib/src/lib.js +2 -1
- package/lib/src/metadata-builder/builders/footer-builder.js +4 -5
- package/lib/src/metadata-builder/builders/global-role-propagation.d.ts +58 -0
- package/lib/src/metadata-builder/builders/global-role-propagation.js +246 -0
- package/lib/src/metadata-builder/builders/global-styles-builder.d.ts +1 -0
- package/lib/src/metadata-builder/builders/global-styles-builder.js +116 -45
- package/lib/src/metadata-builder/builders/header-builder.js +13 -4
- package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +4 -4
- package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +2 -2
- package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +2 -2
- package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +4 -4
- package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +8 -2
- package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +2 -2
- package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +60 -29
- package/lib/src/metadata-builder/builders/section-field-maps.js +1 -0
- package/lib/src/metadata-builder/builders/section-field-utils.d.ts +48 -19
- package/lib/src/metadata-builder/builders/section-field-utils.js +128 -52
- package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.d.ts +4 -2
- package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.js +28 -12
- package/lib/src/metadata-builder/builders/section-rules/social-links.rules.js +5 -1
- package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +1 -1
- package/lib/src/metadata-builder/helpers/rte.helpers.js +97 -40
- package/lib/src/metadata-builder/metadata-executor.js +23 -1
- package/lib/src/metadata-builder/models.d.ts +2 -0
- package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +18 -19
- package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +18 -1
- package/lib/src/metadata-builder/sanitizers/rte-schema-check.js +1 -1
- package/lib/src/metadata-builder/sanitizers/sanitizer-rules.d.ts +0 -1
- package/lib/src/metadata-builder/sanitizers/sanitizer-rules.js +5 -8
- package/lib/src/metadata-builder/sanitizers/section-args-validator.d.ts +7 -16
- package/lib/src/metadata-builder/sanitizers/section-args-validator.js +95 -22
- package/lib/src/shared/color-palette/section-color-matches.js +9 -25
- package/lib/src/shared/color-strategies/color-strategies.d.ts +15 -0
- package/lib/src/shared/color-strategies/color-strategies.js +31 -0
- package/lib/src/shared/color-strategies/rte-color.d.ts +8 -0
- package/lib/src/shared/color-strategies/rte-color.js +16 -0
- package/lib/src/shared/color-strategies/rte-field-pairs.d.ts +23 -0
- package/lib/src/shared/color-strategies/rte-field-pairs.js +28 -0
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +9 -135
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +1 -27
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +12 -2
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +7 -0
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +75 -6
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +18 -7
- package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +6 -1
- package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +0 -7
- package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +1 -0
- package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +8 -4
- package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +1255 -26
- package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.js +203 -59
- package/lib/src/shared/content-settings/store/content-settings-store.d.ts +6 -0
- package/lib/src/shared/content-settings/store/content-settings-store.js +105 -8
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +5 -1
- package/lib/src/shared/navigation-style-settings/store/index.d.ts +7 -3
- package/lib/src/shared/navigation-style-settings/store/index.js +40 -15
- package/lib/src/shared/page-settings/components/delete-page-modal/DeletePageModal.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +1 -0
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +17 -5
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +70 -13
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.js +10 -2
- package/lib/src/shared/page-settings/store/page-settings-store.d.ts +2 -1
- package/lib/src/shared/page-settings/store/page-settings-store.js +17 -0
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +4 -1
- package/lib/src/shared/rte-extensions/AutoLink.d.ts +17 -0
- package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.js +67 -51
- package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.js +4 -1
- package/lib/src/shared/rte-extensions/TextEffects.d.ts +28 -0
- package/lib/src/shared/rte-extensions/TextEffects.js +96 -0
- package/lib/src/shared/rte-extensions/ViewDomParser.d.ts +2 -0
- package/lib/src/shared/rte-extensions/ViewDomParser.js +21 -0
- package/lib/src/shared/rte-extensions.util.d.ts +25 -0
- package/lib/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.js → shared/rte-extensions.util.js} +62 -7
- package/lib/src/shared/rte-link.util.d.ts +1 -0
- package/lib/src/shared/rte-link.util.js +1 -0
- package/lib/src/shared/rte-render.util.d.ts +112 -0
- package/lib/src/shared/rte-render.util.js +255 -0
- package/lib/src/shared/rte-shape.util.d.ts +6 -0
- package/lib/src/shared/rte-shape.util.js +18 -0
- package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +2 -1
- package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
- package/lib/src/shared/side-bar/store/side-bar-store.d.ts +2 -0
- package/lib/src/shared/side-bar/store/side-bar-store.js +9 -0
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +155 -15
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.js +7 -1
- package/lib/src/shared/style-settings/store/style-settings-store.d.ts +1 -9
- package/lib/src/shared/style-settings/store/style-settings-store.js +3 -33
- package/lib/src/shared/style-settings/text-style-size-order.d.ts +2 -0
- package/lib/src/shared/style-settings/text-style-size-order.js +13 -0
- package/lib/src/shared/text-role-typography.util.d.ts +64 -0
- package/lib/src/shared/text-role-typography.util.js +183 -0
- package/lib/src/utils/minify-brand-page-metadata.d.ts +16 -1
- package/lib/src/utils/minify-brand-page-metadata.js +31 -9
- package/package.json +1 -1
- package/src/brand-page/__fixtures__/migration-22-v21/edited-brandsite-sections.v21.json +982 -0
- package/src/brand-page/__fixtures__/migration-22-v21/new-brandcontact-every-section.v21.json +1231 -0
- package/src/brand-page/__fixtures__/migration-22-v21/new-brandpage-every-section.v21.json +1231 -0
- package/src/brand-page/__fixtures__/migration-22-v21/new-brandsite-every-section.v21.json +1243 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandcontact.v21.json +755 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-general-link.v21.json +527 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-links.v21.json +755 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-social-links.v21.json +514 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-about.v21.json +459 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-footer.v21.json +469 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-header-banner.v21.json +481 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-sections.v21.json +800 -0
- package/src/brand-page/__fixtures__/production-text-style-resolver.fixture.ts +52 -0
- package/src/brand-page/components/about-section/AboutSection.vue.test.ts +0 -10
- package/src/brand-page/components/contact-form/ContactForm.mixin.test.ts +127 -0
- package/src/brand-page/components/contact-form/ContactForm.mixin.ts +31 -14
- package/src/brand-page/components/contact-form/ContactForm.vue +26 -12
- package/src/brand-page/components/contact-form/ContactForm.vue.test.ts +60 -0
- package/src/brand-page/components/mailing-list/MailingList.mixin.test.ts +92 -0
- package/src/brand-page/components/mailing-list/MailingList.mixin.ts +28 -3
- package/src/brand-page/components/mailing-list/MailingList.vue +9 -4
- package/src/brand-page/components/mailing-list/MailingList.vue.test.ts +63 -0
- package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.ts +51 -1
- package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.test.ts +114 -0
- package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.vue +8 -2
- package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.test.ts +182 -0
- package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.vue +59 -12
- package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.ts +40 -3
- package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue +15 -7
- package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue.test.ts +133 -3
- package/src/brand-page/components/page/Page.mixin.ts +41 -34
- package/src/brand-page/components/page/Page.vue +17 -6
- package/src/brand-page/components/page/Page.vue.test.ts +91 -1
- package/src/brand-page/components/page-footer/PageFooter.mixin.ts +32 -2
- package/src/brand-page/components/page-footer/PageFooter.test.ts +79 -0
- package/src/brand-page/components/page-footer/PageFooter.vue +12 -4
- package/src/brand-page/components/payment/Payment.mixin.ts +34 -2
- package/src/brand-page/components/payment/Payment.test.ts +188 -0
- package/src/brand-page/components/payment/Payment.vue +12 -5
- package/src/brand-page/components/payment/RequestPaymentStripe.vue +1 -0
- package/src/brand-page/components/payment/support-me/SupportMe.mixin.ts +49 -2
- package/src/brand-page/components/payment/support-me/SupportMe.test.ts +100 -0
- package/src/brand-page/components/payment/support-me/SupportMe.vue +7 -1
- package/src/brand-page/components/payment/support-me/SupportMe.vue.test.ts +66 -0
- package/src/brand-page/components/save-contact/SaveContactWidget.test.ts +100 -0
- package/src/brand-page/components/save-contact/SaveContactWidget.vue +6 -3
- package/src/brand-page/components/shop/PaymentModal.vue +2 -6
- package/src/brand-page/components/shop/PaymentShippingAddress.vue +6 -0
- package/src/brand-page/components/shop/Shop.vue +15 -2
- package/src/brand-page/components/shop/Shop.vue.test.ts +74 -2
- package/src/brand-page/components/social-links/SocialLinks.stories.ts +0 -3
- package/src/brand-page/components/social-links/SocialLinks.vue.test.ts +0 -3
- package/src/brand-page/components/testimonial-section/__fixtures__/data.ts +0 -3
- package/src/brand-page/components/text/Text.stories.ts +0 -17
- package/src/brand-page/components/text-wrapper/TextWrapper.parity.test.ts +136 -0
- package/src/brand-page/components/text-wrapper/TextWrapper.test.ts +358 -0
- package/src/brand-page/components/text-wrapper/TextWrapper.vue +82 -22
- package/src/brand-page/constants/font.constants.ts +37 -0
- package/src/brand-page/models/footer-icon-color.test.ts +22 -0
- package/src/brand-page/models/index.ts +50 -28
- package/src/brand-page/models/navigation-styles.model.test.ts +77 -1
- package/src/brand-page/models/navigation-styles.model.ts +26 -9
- package/src/brand-page/models/payment.model.ts +15 -6
- package/src/brand-page/models/styles.model.test.ts +104 -0
- package/src/brand-page/models/styles.model.ts +181 -47
- package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +619 -115
- package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +150 -9
- package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +300 -18
- package/src/brand-page/utils/color-palette.util.test.ts +126 -1
- package/src/brand-page/utils/color-palette.util.ts +92 -26
- package/src/brand-page/utils/color.util.test.ts +62 -29
- package/src/brand-page/utils/color.util.ts +77 -14
- package/src/brand-page/utils/container-text-color.util.test.ts +672 -26
- package/src/brand-page/utils/container-text-color.util.ts +472 -46
- package/src/brand-page/utils/index.ts +1 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/edited-brandsite-sections.v22.json +1191 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandcontact-every-section.v22.json +2026 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandpage-every-section.v22.json +2017 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandsite-every-section.v22.json +2031 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandcontact.v22.json +1145 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-general-link.v22.json +645 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-links.v22.json +1136 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-social-links.v22.json +662 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-about.v22.json +638 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-footer.v22.json +610 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-header-banner.v22.json +660 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-sections.v22.json +1132 -0
- package/src/brand-page/utils/migration/migration-01.ts +293 -237
- package/src/brand-page/utils/migration/migration-02.ts +8 -1
- package/src/brand-page/utils/migration/migration-20.ts +6 -3
- package/src/brand-page/utils/migration/migration-20_5.test.ts +5 -2
- package/src/brand-page/utils/migration/migration-21.test.ts +34 -0
- package/src/brand-page/utils/migration/migration-21.ts +46 -10
- package/src/brand-page/utils/migration/migration-22.fixed-input.test.ts +43 -0
- package/src/brand-page/utils/migration/migration-22.test.ts +4103 -0
- package/src/brand-page/utils/migration/migration-22.text-font-family.test.ts +72 -0
- package/src/brand-page/utils/migration/migration-22.ts +1336 -0
- package/src/brand-page/utils/migration.util.test.ts +146 -32
- package/src/brand-page/utils/migration.util.ts +18 -0
- package/src/brand-page/utils/model.util.ts +4 -0
- package/src/brand-page/utils/personalisation.util.test.ts +148 -3
- package/src/brand-page/utils/personalisation.util.ts +9 -1
- package/src/brand-page/utils/rte-role-lift.util.ts +409 -0
- package/src/brand-page/utils/style.util.test.ts +35 -2
- package/src/brand-page/utils/style.util.ts +45 -11
- package/src/brand-page/utils/text-role-css.util.test.ts +525 -0
- package/src/brand-page/utils/text-role-css.util.ts +321 -0
- package/src/brand-page/utils/text-role-reconnect.util.test.ts +604 -0
- package/src/brand-page/utils/text-role-reconnect.util.ts +727 -0
- package/src/brand-page/utils/text-style.util.test.ts +305 -0
- package/src/brand-page/utils/text-style.util.ts +198 -24
- package/src/brand-page/utils/view-model.page-data.test.ts +232 -0
- package/src/brand-page/utils/view-model.util.test.ts +954 -133
- package/src/brand-page/utils/view-model.util.ts +187 -139
- package/src/brand-page/view-models.ts +4 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.blank-site.test.ts +57 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +9 -5
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -10
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +0 -1
- package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +0 -44
- package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +253 -200
- package/src/brand-page-maker/components/shop/AddOrEditProductContainer.vue +1 -0
- package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +1 -0
- package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +2 -0
- package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +1 -0
- package/src/brand-page-maker/composables/rich-text-editor/block-typography.test.ts +519 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +26 -1
- package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.test.ts +110 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.ts +99 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.ts +397 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/ViewDomParser.test.ts +139 -0
- package/src/brand-page-maker/composables/rich-text-editor/font.ts +36 -5
- package/src/brand-page-maker/composables/rich-text-editor/formatting.test.ts +375 -1
- package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +301 -17
- package/src/brand-page-maker/composables/rich-text-editor/hyperlink.test.ts +82 -1
- package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +28 -34
- package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.test.ts +80 -0
- package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.ts +75 -0
- package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +31 -6
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.test.ts +2485 -0
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +435 -337
- package/src/brand-page-maker/constants/config-settings-constant.ts +0 -6
- package/src/brand-page-maker/convertors/text-css-style-options.convertor.test.ts +43 -0
- package/src/brand-page-maker/convertors/text-css-style-options.convertor.ts +6 -2
- package/src/brand-page-maker/convertors/text-size-value.convertor.test.ts +24 -0
- package/src/brand-page-maker/convertors/text-size-value.convertor.ts +17 -13
- package/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.ts +7 -22
- package/src/brand-page-maker/default-getters/text-color.default-getter.ts +5 -21
- package/src/brand-page-maker/models/content-settings.test.ts +708 -0
- package/src/brand-page-maker/models/content-settings.ts +133 -82
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.test.ts +63 -1
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.ts +16 -3
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.test.ts +34 -0
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.ts +4 -2
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +185 -1
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +22 -34
- package/src/brand-page-maker/stores/history/history-store.ts +35 -2
- package/src/brand-page-maker/utils/__snapshots__/apply-color-strategy.golden.test.ts.snap +528 -0
- package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +12 -0
- package/src/brand-page-maker/utils/apply-color-strategy.golden.test.ts +2 -0
- package/src/brand-page-maker/utils/apply-color-strategy.test.ts +181 -3
- package/src/brand-page-maker/utils/apply-color-strategy.ts +36 -4
- package/src/brand-page-maker/utils/index.ts +2 -1
- package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +447 -410
- package/src/brand-page-maker/utils/rich-text-editor.util.ts +610 -506
- package/src/brand-page-maker/utils/rte-authoring.util.test.ts +244 -0
- package/src/brand-page-maker/utils/rte-authoring.util.ts +175 -0
- package/src/brand-page-maker/utils/rte-clipboard.util.test.ts +558 -0
- package/src/brand-page-maker/utils/rte-clipboard.util.ts +473 -0
- package/src/brand-page-maker/utils/rte-features.test.ts +99 -3
- package/src/brand-page-maker/utils/rte-render-parity.test.ts +1 -1
- package/src/brand-page-maker/utils/rte-render.util.test.ts +230 -0
- package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +1 -1
- package/src/brand-page-maker/utils/rte-sanitize.util.ts +14 -3
- package/src/brand-page-maker/utils/rte-schema-version.test.ts +102 -0
- package/src/bundles/bundled-translations.de-DE.json +21 -2
- package/src/bundles/bundled-translations.es-ES.json +21 -2
- package/src/bundles/bundled-translations.fr-CA.json +21 -2
- package/src/bundles/bundled-translations.fr-FR.json +21 -2
- package/src/bundles/bundled-translations.json +21 -2
- package/src/bundles/bundled-translations.pt-BR.json +21 -2
- package/src/bundles/bundled-translations.pt-PT.json +21 -2
- package/src/clients/ai-assistant-client.ts +1 -0
- package/src/composables/useTranslate.ts +2 -1
- package/src/lib.ts +2 -2
- package/src/metadata-builder/builders/footer-builder.test.ts +70 -45
- package/src/metadata-builder/builders/footer-builder.ts +4 -8
- package/src/metadata-builder/builders/global-role-propagation.test.ts +907 -0
- package/src/metadata-builder/builders/global-role-propagation.ts +430 -0
- package/src/metadata-builder/builders/global-styles-builder.test.ts +1020 -0
- package/src/metadata-builder/builders/global-styles-builder.ts +194 -48
- package/src/metadata-builder/builders/header-builder.test.ts +112 -40
- package/src/metadata-builder/builders/header-builder.ts +18 -8
- package/src/metadata-builder/builders/section-builders/about-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/booking-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +7 -4
- package/src/metadata-builder/builders/section-builders/images-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +7 -7
- package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/social-links-builder.test.ts +2 -2
- package/src/metadata-builder/builders/section-builders/social-links-builder.ts +21 -10
- package/src/metadata-builder/builders/section-builders/support-me-builder.test.ts +10 -0
- package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/text-section-builder.ts +111 -61
- package/src/metadata-builder/builders/section-field-maps.ts +1 -0
- package/src/metadata-builder/builders/section-field-utils.test.ts +545 -2
- package/src/metadata-builder/builders/section-field-utils.ts +202 -69
- package/src/metadata-builder/builders/section-rules/global-styles.rules.ts +38 -13
- package/src/metadata-builder/builders/section-rules/social-links.rules.ts +5 -0
- package/src/metadata-builder/helpers/rte.helpers.test.ts +101 -0
- package/src/metadata-builder/helpers/rte.helpers.ts +129 -43
- package/src/metadata-builder/metadata-executor.test.ts +167 -0
- package/src/metadata-builder/metadata-executor.ts +34 -1
- package/src/metadata-builder/models.ts +2 -0
- package/src/metadata-builder/parsers/ai-toolcall-parser.ts +23 -7
- package/src/metadata-builder/parsers/section-tool-arguments.ts +21 -1
- package/src/metadata-builder/sanitizers/__tests__/section-args-validator.test.ts +215 -0
- package/src/metadata-builder/sanitizers/rte-schema-check.ts +1 -1
- package/src/metadata-builder/sanitizers/sanitizer-rules.ts +4 -8
- package/src/metadata-builder/sanitizers/section-args-validator.ts +136 -53
- package/src/shared/color-palette/section-color-matches.test.ts +15 -11
- package/src/shared/color-palette/section-color-matches.ts +9 -28
- package/src/shared/color-strategies/color-strategies.ts +35 -0
- package/src/shared/color-strategies/rte-color.test.ts +1 -1
- package/src/shared/color-strategies/rte-color.ts +19 -0
- package/src/shared/color-strategies/rte-field-pairs.test.ts +26 -5
- package/src/shared/color-strategies/rte-field-pairs.ts +33 -0
- package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.test.ts +43 -66
- package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.vue +7 -1
- package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +1 -48
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +33 -7
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.test.ts +128 -1
- package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.vue +1 -0
- package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +0 -6
- package/src/shared/content-settings/components/logo-selection-field/LogoSelection.vue +3 -0
- package/src/shared/content-settings/components/logo-size-field/LogoSizeSlider.vue +3 -0
- package/src/shared/content-settings/components/logo-size-field/LogoSizeSliderField.vue +1 -0
- package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.vue +1 -0
- package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.test.ts +56 -3
- package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +11 -4
- package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.test.ts +335 -25
- package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.ts +248 -70
- package/src/shared/content-settings/components/text-style-field/TextStyleField.vue +113 -25
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.de-DE.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.es-ES.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-CA.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-FR.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.json +8 -1
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-BR.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-PT.json +17 -10
- package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.test.ts +141 -0
- package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.vue +136 -0
- package/src/shared/content-settings/store/content-settings-store.test.ts +491 -6
- package/src/shared/content-settings/store/content-settings-store.ts +159 -17
- package/src/shared/logo-settings/components/EditLogoSettings.vue +1 -0
- package/src/shared/logo-settings/components/LogoVariations.vue +1 -0
- package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.vue +1 -0
- package/src/shared/navigation-style-settings/store/index.test.ts +295 -0
- package/src/shared/navigation-style-settings/store/index.ts +65 -15
- package/src/shared/page-settings/components/header-settings-panel/HeaderSettingsPanel.vue +2 -0
- package/src/shared/page-settings/components/page-settings/PageElement.vue +1 -0
- package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.test.ts +44 -4
- package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.vue +13 -4
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.navigation.test.ts +89 -0
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.text-style.test.ts +91 -0
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.ts +14 -2
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.vue +2 -0
- package/src/shared/page-settings/store/page-settings-store.text-style.test.ts +84 -0
- package/src/shared/page-settings/store/page-settings-store.ts +30 -1
- package/src/shared/rte-extensions/AutoLink.test.ts +98 -0
- package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.ts +87 -58
- package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.ts +4 -1
- package/src/shared/rte-extensions/TextEffects.ts +151 -0
- package/src/shared/rte-extensions/ViewDomParser.ts +27 -0
- package/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.ts → shared/rte-extensions.util.ts} +66 -9
- package/src/shared/rte-link.util.ts +2 -0
- package/src/shared/rte-render.util.ts +385 -0
- package/src/shared/rte-shape.util.ts +29 -0
- package/src/shared/side-bar/store/side-bar-store.test.ts +27 -1
- package/src/shared/side-bar/store/side-bar-store.ts +11 -0
- package/src/shared/style-settings/components/StyleSettings.mixin.ts +7 -3
- package/src/shared/style-settings/components/StyleSettings.test.ts +116 -0
- package/src/shared/style-settings/components/StyleSettings.vue +75 -25
- package/src/shared/style-settings/components/i18n/style-settings.de-DE.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.es-ES.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.fr-CA.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.fr-FR.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.json +13 -3
- package/src/shared/style-settings/components/i18n/style-settings.pt-BR.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.pt-PT.json +32 -20
- package/src/shared/style-settings/components/text-style-options-settings-with-state/TextStyleOptionsSettingsWithState.vue +14 -34
- package/src/shared/style-settings/store/style-settings-store.ts +3 -49
- package/src/shared/style-settings/text-style-size-order.test.ts +76 -0
- package/src/shared/style-settings/text-style-size-order.ts +28 -0
- package/src/shared/template-settings/components/TemplatesSettings.vue +4 -0
- package/src/shared/text-role-typography.util.ts +277 -0
- package/src/utils/minify-brand-page-metadata.test.ts +102 -7
- package/src/utils/minify-brand-page-metadata.ts +62 -8
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +0 -2
- package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
- package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -63
- package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -106
- package/lib/src/brand-page-maker/utils/rte-shape.d.ts +0 -18
- package/lib/src/brand-page-maker/utils/rte-shape.js +0 -21
- package/lib/src/metadata-builder/builders/global-font-propagation.d.ts +0 -41
- package/lib/src/metadata-builder/builders/global-font-propagation.js +0 -146
- package/src/brand-page-maker/utils/rte-render.util.ts +0 -179
- package/src/brand-page-maker/utils/rte-shape.ts +0 -29
- package/src/metadata-builder/builders/global-font-propagation.test.ts +0 -401
- package/src/metadata-builder/builders/global-font-propagation.ts +0 -238
- package/src/shared/style-settings/components/StyleSettingsSection.vue +0 -8
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.d.ts +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.js +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.d.ts +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.js +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.d.ts +0 -0
- /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.ts +0 -0
- /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.ts +0 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { JSONContent } from '@tiptap/vue-3';
|
|
2
|
+
import type { Content, TextStyleOptions } from '@brand-page';
|
|
3
|
+
export declare const docHasTextRun: (doc: JSONContent) => boolean;
|
|
4
|
+
export declare const authorContentRteFields: (content: Content, textStyleOptions?: TextStyleOptions) => void;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { rteStyleFieldsFor, pairedRteTextField, } from '@shared/color-strategies/rte-field-pairs';
|
|
2
|
+
import { setRteTextColor } from '@shared/color-strategies/rte-color';
|
|
3
|
+
import { plainTextToRteJson, isTiptapDocument, } from '@shared/rte-render.util';
|
|
4
|
+
import { isCanonicalLinked } from './rich-text-editor.util';
|
|
5
|
+
import { roleVarRef, ROLE_VAR_ATTRS } from '@shared/text-role-typography.util';
|
|
6
|
+
/** The linked role's style for a field's `textStyleType`, for the defined-attr check below. */
|
|
7
|
+
const roleStyleFor = (options, textStyleType) => textStyleType && options
|
|
8
|
+
? options[textStyleType]?.style
|
|
9
|
+
: undefined;
|
|
10
|
+
/**
|
|
11
|
+
* BP-5969 — reference the role's typography on every run of a canonical-linked authored doc, so
|
|
12
|
+
* new content matches migration output: the mark names the reference (self-describing, and the
|
|
13
|
+
* editor reads it without reaching into the store), and it follows role edits via the cascade.
|
|
14
|
+
* A ref is emitted ONLY for an attr the role actually defines — mirroring `buildInitialMarks` and
|
|
15
|
+
* migration `stripLiftRteDoc`, so authored and migrated runs share one shape (no reference to a
|
|
16
|
+
* `--role-*` var the role class never emits). No role style (options absent) → no refs.
|
|
17
|
+
*/
|
|
18
|
+
const applyRoleTypographyVars = (doc, roleStyle) => {
|
|
19
|
+
const refs = ROLE_VAR_ATTRS.flatMap(({ markAttr }) => {
|
|
20
|
+
const ref = roleVarRef(markAttr);
|
|
21
|
+
return ref && roleStyle?.[markAttr]
|
|
22
|
+
? [[markAttr, ref]]
|
|
23
|
+
: [];
|
|
24
|
+
});
|
|
25
|
+
if (!refs.length)
|
|
26
|
+
return;
|
|
27
|
+
const walk = (node) => {
|
|
28
|
+
if (node.type === 'text') {
|
|
29
|
+
const marks = (node.marks ??= []);
|
|
30
|
+
let textStyle = marks.find((mark) => mark.type === 'textStyle');
|
|
31
|
+
if (!textStyle) {
|
|
32
|
+
textStyle = { type: 'textStyle', attrs: {} };
|
|
33
|
+
marks.push(textStyle);
|
|
34
|
+
}
|
|
35
|
+
textStyle.attrs = { ...(textStyle.attrs ?? {}) };
|
|
36
|
+
for (const [attr, ref] of refs)
|
|
37
|
+
textStyle.attrs[attr] = ref;
|
|
38
|
+
}
|
|
39
|
+
node.content?.forEach(walk);
|
|
40
|
+
};
|
|
41
|
+
walk(doc);
|
|
42
|
+
};
|
|
43
|
+
// True when the doc has at least one text run — i.e. somewhere for a run mark (colour) to live.
|
|
44
|
+
export const docHasTextRun = (doc) => {
|
|
45
|
+
const walk = (node) => node.type === 'text' ? true : (node.content ?? []).some(walk);
|
|
46
|
+
return walk(doc);
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Author (or enrich) one RTE field into its final doc: bake the resolved element colour into the run
|
|
50
|
+
* mark and reference the role's typography on every run, matching migration output.
|
|
51
|
+
*
|
|
52
|
+
* The field's value is either an already-authored doc — the BP-5969 factory source (`rteDoc`) — or a
|
|
53
|
+
* plain string (legacy / AI callers); both normalise to a doc here. `undefined` for empty/absent
|
|
54
|
+
* input so callers can leave the field alone.
|
|
55
|
+
*/
|
|
56
|
+
const authorRteDoc = (value, style, roleStyle) => {
|
|
57
|
+
let doc = isTiptapDocument(value)
|
|
58
|
+
? value
|
|
59
|
+
: plainTextToRteJson(value);
|
|
60
|
+
if (!doc)
|
|
61
|
+
return undefined;
|
|
62
|
+
// Colour rides the run mark — but ONLY when there is a run. An empty doc (empty field) has no text
|
|
63
|
+
// node to hold a mark, so its colour stays on `style.color` until the user types (the editor's
|
|
64
|
+
// `buildInitialMarks` seeds the first run from it); stripping it here would strand it.
|
|
65
|
+
if (style?.color && docHasTextRun(doc)) {
|
|
66
|
+
doc = setRteTextColor(doc, style.color) ?? doc;
|
|
67
|
+
delete style.color; // colour now lives in the mark (matches migration step G)
|
|
68
|
+
}
|
|
69
|
+
if (style?.textAlign) {
|
|
70
|
+
for (const block of doc.content ?? []) {
|
|
71
|
+
block.attrs = { ...(block.attrs ?? {}), textAlign: style.textAlign };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Canonical-linked: reference the role's (defined) typography on every run.
|
|
75
|
+
if (isCanonicalLinked(style))
|
|
76
|
+
applyRoleTypographyVars(doc, roleStyle);
|
|
77
|
+
return doc;
|
|
78
|
+
};
|
|
79
|
+
export const authorContentRteFields = (content,
|
|
80
|
+
// Role definitions, so a run references only the attrs its role actually defines (matches
|
|
81
|
+
// migration output). Absent → no typography refs (colour/textAlign still authored).
|
|
82
|
+
textStyleOptions) => {
|
|
83
|
+
const fields = content;
|
|
84
|
+
for (const styleField of rteStyleFieldsFor(content.type)) {
|
|
85
|
+
const textField = pairedRteTextField(content.type, styleField);
|
|
86
|
+
if (!textField)
|
|
87
|
+
continue;
|
|
88
|
+
const style = fields[styleField];
|
|
89
|
+
const doc = authorRteDoc(fields[textField], style, roleStyleFor(textStyleOptions, style?.textStyleType));
|
|
90
|
+
if (doc)
|
|
91
|
+
fields[textField] = doc;
|
|
92
|
+
}
|
|
93
|
+
const textItems = fields.textItems;
|
|
94
|
+
if (Array.isArray(textItems)) {
|
|
95
|
+
for (const item of textItems) {
|
|
96
|
+
const doc = authorRteDoc(item.text, item.textStyle, roleStyleFor(textStyleOptions, item.textStyle?.textStyleType));
|
|
97
|
+
if (doc)
|
|
98
|
+
item.text = doc;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { JSONContent } from '@tiptap/vue-3';
|
|
2
|
+
import type { ColorItem, GlobalTextStyleDeclaration, TextStyleDeclaration } from '@brand-page';
|
|
3
|
+
import { type RoleVarMarkAttr } from '@shared/text-role-typography.util';
|
|
4
|
+
/**
|
|
5
|
+
* Pure transforms for the maker RTE's copy, cut and paste. No editor, no DOM: every
|
|
6
|
+
* function here takes and returns Tiptap JSON (or a bare value), so `RteClipboard.ts`
|
|
7
|
+
* can call them from real clipboard events without this module knowing ProseMirror's
|
|
8
|
+
* live `Node`/`Mark` instances exist. Kept off the `brand-page-maker/utils` barrel
|
|
9
|
+
* (imported by path) — see `rich-text-editor.md` *Entry points* for why it stays out
|
|
10
|
+
* of `getRteExtensions`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const RTE_CLIPBOARD_MIME_TYPE = "application/x-rte-slice";
|
|
13
|
+
export declare const RTE_CLIPBOARD_VERSION: 1;
|
|
14
|
+
export interface RteClipboardContext {
|
|
15
|
+
/** The field's canonical role style, or undefined for a legacy/unlinked field. */
|
|
16
|
+
role: GlobalTextStyleDeclaration | undefined;
|
|
17
|
+
/** The field's own style object (whole-field overrides, colour, alignment). */
|
|
18
|
+
block: TextStyleDeclaration | undefined;
|
|
19
|
+
/** The site palette, for resolving and relinking colour references. */
|
|
20
|
+
colors: ColorItem[];
|
|
21
|
+
}
|
|
22
|
+
export type ResolvedRunStyle = Partial<Record<RoleVarMarkAttr, string>> & {
|
|
23
|
+
color?: string;
|
|
24
|
+
};
|
|
25
|
+
export interface RteClipboardSliceJSON {
|
|
26
|
+
content: JSONContent[];
|
|
27
|
+
openStart?: number;
|
|
28
|
+
openEnd?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface RteClipboardPayload {
|
|
31
|
+
v: typeof RTE_CLIPBOARD_VERSION;
|
|
32
|
+
slice: RteClipboardSliceJSON;
|
|
33
|
+
}
|
|
34
|
+
type RteRunMark = {
|
|
35
|
+
type: string;
|
|
36
|
+
attrs?: Record<string, unknown>;
|
|
37
|
+
};
|
|
38
|
+
type RteRunNode = {
|
|
39
|
+
marks?: RteRunMark[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Resolve a colour value (text or highlight) to what the canvas shows, in one
|
|
43
|
+
* normalised form: a legacy `logo-*` token maps to its palette role first; a
|
|
44
|
+
* `var(--id)` reference resolves against `colors` (a blank role reads as its default);
|
|
45
|
+
* a resolvable solid canonicalises to lowercase `#rrggbb`/`#rrggbbaa`. A reference the
|
|
46
|
+
* palette doesn't hold stays exactly as written (D3) — copy never invents a look the
|
|
47
|
+
* canvas doesn't have.
|
|
48
|
+
*/
|
|
49
|
+
export declare const resolveRunColorForCopy: (value: string | undefined, colors: ColorItem[]) => string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* A run's typography and colour, resolved to what the canvas shows (A5): every role
|
|
52
|
+
* reference becomes a literal value, so the slice carries "what it looks like" rather
|
|
53
|
+
* than "what it's linked to" — the destination decides what re-links (see
|
|
54
|
+
* `relinkRunTypographyToRole`). An uncoloured run stays uncoloured (ADR-0020: no base
|
|
55
|
+
* coat) — colour has no whole-field fallback, unlike typography.
|
|
56
|
+
*/
|
|
57
|
+
export declare const resolveRunStyleForCopy: (node: RteRunNode, context: RteClipboardContext) => ResolvedRunStyle;
|
|
58
|
+
/**
|
|
59
|
+
* The external (`text/html`, other apps) reading of a run: the same resolved look, with
|
|
60
|
+
* `fontSize` converted from em to px at the 16px root (the toolbar's own readout) so an
|
|
61
|
+
* app with no `--role-*`/em context still shows the right size, and the run's link href
|
|
62
|
+
* (if any) carried through untouched.
|
|
63
|
+
*/
|
|
64
|
+
export declare const resolveRunStyleForExternal: (node: RteRunNode, context: RteClipboardContext) => ResolvedRunStyle & {
|
|
65
|
+
href?: string;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* "Same value written differently" (A6): family ignores quoting, weight/style/
|
|
69
|
+
* decoration/spacing treat their CSS-neutral keyword as equal to unset, and — local to
|
|
70
|
+
* this comparator, so the asterisk and relink paths don't widen — `fontSize` compares
|
|
71
|
+
* as px at the 16px root, so `1.375em` and `22px` are one size.
|
|
72
|
+
*/
|
|
73
|
+
export declare const isSameTypographyValue: (attr: RoleVarMarkAttr, a: string | undefined, b: string | undefined) => boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Relink a resolved run to the destination role (A5 step 2, R2): a value equal to the
|
|
76
|
+
* destination's (or its neutral) becomes the role var, so it keeps following that role;
|
|
77
|
+
* any other value stays the run's own literal. With no canonical role at the
|
|
78
|
+
* destination, every value stays literal — `roleVarOrLiteral`'s rule, applied per run
|
|
79
|
+
* instead of at the mutation point. An attr the copy left absent stays absent.
|
|
80
|
+
*/
|
|
81
|
+
export declare const relinkRunTypographyToRole: (resolved: ResolvedRunStyle, destinationRole: GlobalTextStyleDeclaration | undefined) => ResolvedRunStyle;
|
|
82
|
+
/**
|
|
83
|
+
* Relink a resolved colour to the destination palette (A5 step 3, R3, D3). On a link
|
|
84
|
+
* run, the fixed link colour is never remapped, so a coincidental match doesn't mint a
|
|
85
|
+
* spurious reference. Otherwise (including a non-link run that happens to equal the
|
|
86
|
+
* fixed link colour): a destination palette ROLE holding the same canonical value wins
|
|
87
|
+
* first (lowest index — `roleIdsByCanonicalValue`'s tie-break), then a custom in stored
|
|
88
|
+
* order (blanks skipped); with no match, the canonical hex stays fixed and nothing is
|
|
89
|
+
* added to the palette.
|
|
90
|
+
*/
|
|
91
|
+
export declare const relinkColorToPalette: (canonicalHex: string, colors: ColorItem[], isLinkColor?: boolean) => string;
|
|
92
|
+
/**
|
|
93
|
+
* Every paragraph/heading a paste touches takes the destination's alignment (Reading
|
|
94
|
+
* 14) — overriding whatever the source paragraphs carried. With no destination
|
|
95
|
+
* alignment resolved, the source's own alignment is cleared rather than left in place:
|
|
96
|
+
* an open-ended LAST paragraph merges into the following text using the SLICE's own
|
|
97
|
+
* attrs, so a leftover source alignment would repaint the destination's own trailing
|
|
98
|
+
* text — the open-ended FIRST paragraph merges the other way, keeping the destination
|
|
99
|
+
* paragraph's own attrs untouched.
|
|
100
|
+
*/
|
|
101
|
+
export declare const alignPastedParagraphs: (content: JSONContent[], destinationAlign: string | undefined) => JSONContent[];
|
|
102
|
+
/**
|
|
103
|
+
* A plain-text (no valid own-editor form) paste's paragraphs (Approach step 4): split on
|
|
104
|
+
* runs of line breaks — prosemirror-view's own rule — dropping empty pieces, each line
|
|
105
|
+
* becomes a paragraph carrying the caller's marks (the seed a first type, or the
|
|
106
|
+
* paste-point's marks, would take) and the destination's alignment. Open at both ends,
|
|
107
|
+
* so the first and last line join the surrounding text. `null` for text with no visible
|
|
108
|
+
* line (nothing to insert).
|
|
109
|
+
*/
|
|
110
|
+
export declare const plainTextToParagraphSlice: (text: string, marks: RteRunMark[], textAlign: string | undefined) => RteClipboardSliceJSON | null;
|
|
111
|
+
/**
|
|
112
|
+
* Validate a clipboard string as our own, un-tampered `x-rte-slice` payload (R13): it
|
|
113
|
+
* parses, its version is ours, and it is byte-for-byte its own `sanitizeRteJson` form —
|
|
114
|
+
* an unsafe link or CSS value, an unknown mark, or even a key reordered from the
|
|
115
|
+
* sanitised form changes it and fails this. It must also build against the live editor
|
|
116
|
+
* schema — catching a node/mark `sanitizeRteJson`'s broader allowlist accepts but this
|
|
117
|
+
* editor's restricted schema doesn't (lists, code). `Slice.fromJSON` alone only checks
|
|
118
|
+
* that node/mark types exist; it neither validates a node's content against its type's
|
|
119
|
+
* content expression nor its mark set, and it accepts any `openStart`/`openEnd` number —
|
|
120
|
+
* fractional included — regardless of the content's actual depth — so every top-level node
|
|
121
|
+
* is also `check()`ed, and the open depths must be integers bounded by `Slice.maxOpen`. Any
|
|
122
|
+
* failure returns `null`, so the caller falls back to the text-only path instead of
|
|
123
|
+
* inserting a malformed slice.
|
|
124
|
+
*/
|
|
125
|
+
export declare const parseOwnRteClipboardPayload: (raw: string) => RteClipboardPayload | null;
|
|
126
|
+
export {};
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { getSchema } from '@tiptap/core';
|
|
2
|
+
import { Slice } from 'prosemirror-model';
|
|
3
|
+
import { canonicalSolidHex, isBlankColorValue, isPaletteRoleId, paletteRoleIdForToken, resolveColorReference, roleIdsByCanonicalValue, toColorVarReference, } from '@brand-page/utils/color-palette.util';
|
|
4
|
+
import { ROLE_VAR_ATTRS, roleVarRef, runTypographyFillValue, NEUTRAL_TYPOGRAPHY_VALUE, } from '@shared/text-role-typography.util';
|
|
5
|
+
import { DEFAULT_LINK_COLOR } from '@src/constants/rich-text-editor.constants';
|
|
6
|
+
import { isRoleVarRef, normTypographyValue } from './rich-text-editor.util';
|
|
7
|
+
import { sanitizeRteJson } from './rte-sanitize.util';
|
|
8
|
+
import { emToPx } from './text.util';
|
|
9
|
+
import { getRteExtensions } from '@shared/rte-extensions.util';
|
|
10
|
+
/**
|
|
11
|
+
* Pure transforms for the maker RTE's copy, cut and paste. No editor, no DOM: every
|
|
12
|
+
* function here takes and returns Tiptap JSON (or a bare value), so `RteClipboard.ts`
|
|
13
|
+
* can call them from real clipboard events without this module knowing ProseMirror's
|
|
14
|
+
* live `Node`/`Mark` instances exist. Kept off the `brand-page-maker/utils` barrel
|
|
15
|
+
* (imported by path) — see `rich-text-editor.md` *Entry points* for why it stays out
|
|
16
|
+
* of `getRteExtensions`.
|
|
17
|
+
*/
|
|
18
|
+
export const RTE_CLIPBOARD_MIME_TYPE = 'application/x-rte-slice';
|
|
19
|
+
export const RTE_CLIPBOARD_VERSION = 1;
|
|
20
|
+
/**
|
|
21
|
+
* The JSON-node twin of `runTypography` (`rich-text-editor.util.ts`): a run's own
|
|
22
|
+
* typography, falling back to a legacy semantic mark for un-migrated/pasted runs. Works
|
|
23
|
+
* on a Tiptap JSON node directly (no schema needed), because a copy/paste payload is
|
|
24
|
+
* JSON — never a live ProseMirror `Node` — end to end.
|
|
25
|
+
*/
|
|
26
|
+
const runTypographyFromJson = (node) => {
|
|
27
|
+
const marks = node.marks ?? [];
|
|
28
|
+
const textStyle = marks.find((mark) => mark.type === 'textStyle');
|
|
29
|
+
const attrOf = (attr) => {
|
|
30
|
+
const value = textStyle?.attrs?.[attr];
|
|
31
|
+
return typeof value === 'string' && value !== '' ? value : undefined;
|
|
32
|
+
};
|
|
33
|
+
const has = (markType) => marks.some((mark) => mark.type === markType);
|
|
34
|
+
const legacyDecoration = [has('underline') && 'underline', has('strike') && 'line-through']
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join(' ') || undefined;
|
|
37
|
+
return {
|
|
38
|
+
fontFamily: attrOf('fontFamily'),
|
|
39
|
+
fontSize: attrOf('fontSize'),
|
|
40
|
+
lineHeight: attrOf('lineHeight'),
|
|
41
|
+
letterSpacing: attrOf('letterSpacing'),
|
|
42
|
+
fontWeight: attrOf('fontWeight') ?? (has('bold') ? 'bold' : undefined),
|
|
43
|
+
fontStyle: attrOf('fontStyle') ?? (has('italic') ? 'italic' : undefined),
|
|
44
|
+
textDecoration: attrOf('textDecoration') ?? legacyDecoration,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Resolve one typography attr the way the canvas renders it: the run's own value
|
|
49
|
+
* (a role ref resolved to the source role's value, or its neutral; a literal — including
|
|
50
|
+
* a legacy bold/italic/underline/strike mark — kept as written), else, for an attr the
|
|
51
|
+
* run doesn't carry, `runTypographyFillValue`'s whole-field fill, resolved the same way.
|
|
52
|
+
* Never invents a value the canvas wouldn't show (D2).
|
|
53
|
+
*/
|
|
54
|
+
const resolveTypographyAttrForCopy = (attr, own, role, block) => {
|
|
55
|
+
const value = own !== undefined
|
|
56
|
+
? own
|
|
57
|
+
: runTypographyFillValue(attr, role, block);
|
|
58
|
+
if (value === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
const resolved = isRoleVarRef(value)
|
|
61
|
+
? (role?.[attr] ?? NEUTRAL_TYPOGRAPHY_VALUE[attr])
|
|
62
|
+
: value;
|
|
63
|
+
// A quoted family (`"Playfair Display"`, or a stack like `"Playfair Display", serif`)
|
|
64
|
+
// fails sanitizeRteJson's safe-CSS-value check and is dropped outright, not kept
|
|
65
|
+
// quoted — so strip every quote, not just an outer pair, rather than lose it.
|
|
66
|
+
return attr === 'fontFamily' ? resolved?.replace(/['"]+/g, '') : resolved;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Resolve a colour value (text or highlight) to what the canvas shows, in one
|
|
70
|
+
* normalised form: a legacy `logo-*` token maps to its palette role first; a
|
|
71
|
+
* `var(--id)` reference resolves against `colors` (a blank role reads as its default);
|
|
72
|
+
* a resolvable solid canonicalises to lowercase `#rrggbb`/`#rrggbbaa`. A reference the
|
|
73
|
+
* palette doesn't hold stays exactly as written (D3) — copy never invents a look the
|
|
74
|
+
* canvas doesn't have.
|
|
75
|
+
*/
|
|
76
|
+
export const resolveRunColorForCopy = (value, colors) => {
|
|
77
|
+
if (!value)
|
|
78
|
+
return undefined;
|
|
79
|
+
const roleId = paletteRoleIdForToken(value);
|
|
80
|
+
const ref = roleId ? toColorVarReference(roleId) : value;
|
|
81
|
+
const resolved = resolveColorReference(ref, colors, {
|
|
82
|
+
withRoleDefaults: true,
|
|
83
|
+
});
|
|
84
|
+
return canonicalSolidHex(resolved) ?? resolved;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* A run's typography and colour, resolved to what the canvas shows (A5): every role
|
|
88
|
+
* reference becomes a literal value, so the slice carries "what it looks like" rather
|
|
89
|
+
* than "what it's linked to" — the destination decides what re-links (see
|
|
90
|
+
* `relinkRunTypographyToRole`). An uncoloured run stays uncoloured (ADR-0020: no base
|
|
91
|
+
* coat) — colour has no whole-field fallback, unlike typography.
|
|
92
|
+
*/
|
|
93
|
+
export const resolveRunStyleForCopy = (node, context) => {
|
|
94
|
+
const own = runTypographyFromJson(node);
|
|
95
|
+
const style = {};
|
|
96
|
+
for (const { markAttr } of ROLE_VAR_ATTRS) {
|
|
97
|
+
const value = resolveTypographyAttrForCopy(markAttr, own[markAttr], context.role, context.block);
|
|
98
|
+
if (value !== undefined)
|
|
99
|
+
style[markAttr] = value;
|
|
100
|
+
}
|
|
101
|
+
const textStyle = node.marks?.find((mark) => mark.type === 'textStyle');
|
|
102
|
+
const color = resolveRunColorForCopy(textStyle?.attrs?.color, context.colors);
|
|
103
|
+
if (color !== undefined)
|
|
104
|
+
style.color = color;
|
|
105
|
+
return style;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* The external (`text/html`, other apps) reading of a run: the same resolved look, with
|
|
109
|
+
* `fontSize` converted from em to px at the 16px root (the toolbar's own readout) so an
|
|
110
|
+
* app with no `--role-*`/em context still shows the right size, and the run's link href
|
|
111
|
+
* (if any) carried through untouched.
|
|
112
|
+
*/
|
|
113
|
+
export const resolveRunStyleForExternal = (node, context) => {
|
|
114
|
+
const style = resolveRunStyleForCopy(node, context);
|
|
115
|
+
const link = (node.marks ?? []).find((mark) => mark.type === 'link');
|
|
116
|
+
const href = link?.attrs?.href;
|
|
117
|
+
const fontSizePx = sizeToPx(style.fontSize);
|
|
118
|
+
return {
|
|
119
|
+
...style,
|
|
120
|
+
...(fontSizePx !== undefined ? { fontSize: `${fontSizePx}px` } : {}),
|
|
121
|
+
...(href ? { href } : {}),
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
const SIZE_UNIT = /^(-?[\d.]+)(px|em)$/;
|
|
125
|
+
/** A typography value's px size at the 16px root, or undefined for anything else. */
|
|
126
|
+
const sizeToPx = (value) => {
|
|
127
|
+
const match = value?.trim().match(SIZE_UNIT);
|
|
128
|
+
if (!match)
|
|
129
|
+
return undefined;
|
|
130
|
+
const [, amount, unit] = match;
|
|
131
|
+
return unit === 'px' ? parseFloat(amount) : parseFloat(emToPx(`${amount}em`));
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* "Same value written differently" (A6): family ignores quoting, weight/style/
|
|
135
|
+
* decoration/spacing treat their CSS-neutral keyword as equal to unset, and — local to
|
|
136
|
+
* this comparator, so the asterisk and relink paths don't widen — `fontSize` compares
|
|
137
|
+
* as px at the 16px root, so `1.375em` and `22px` are one size.
|
|
138
|
+
*/
|
|
139
|
+
export const isSameTypographyValue = (attr, a, b) => {
|
|
140
|
+
if (attr === 'fontSize') {
|
|
141
|
+
const pxA = sizeToPx(a);
|
|
142
|
+
return pxA !== undefined && pxA === sizeToPx(b);
|
|
143
|
+
}
|
|
144
|
+
return normTypographyValue(attr, a) === normTypographyValue(attr, b);
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Relink a resolved run to the destination role (A5 step 2, R2): a value equal to the
|
|
148
|
+
* destination's (or its neutral) becomes the role var, so it keeps following that role;
|
|
149
|
+
* any other value stays the run's own literal. With no canonical role at the
|
|
150
|
+
* destination, every value stays literal — `roleVarOrLiteral`'s rule, applied per run
|
|
151
|
+
* instead of at the mutation point. An attr the copy left absent stays absent.
|
|
152
|
+
*/
|
|
153
|
+
export const relinkRunTypographyToRole = (resolved, destinationRole) => {
|
|
154
|
+
const relinked = { ...resolved };
|
|
155
|
+
if (!destinationRole)
|
|
156
|
+
return relinked;
|
|
157
|
+
for (const { markAttr } of ROLE_VAR_ATTRS) {
|
|
158
|
+
const value = resolved[markAttr];
|
|
159
|
+
if (value === undefined)
|
|
160
|
+
continue;
|
|
161
|
+
relinked[markAttr] = isSameTypographyValue(markAttr, value, destinationRole[markAttr])
|
|
162
|
+
? roleVarRef(markAttr)
|
|
163
|
+
: value;
|
|
164
|
+
}
|
|
165
|
+
return relinked;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Relink a resolved colour to the destination palette (A5 step 3, R3, D3). On a link
|
|
169
|
+
* run, the fixed link colour is never remapped, so a coincidental match doesn't mint a
|
|
170
|
+
* spurious reference. Otherwise (including a non-link run that happens to equal the
|
|
171
|
+
* fixed link colour): a destination palette ROLE holding the same canonical value wins
|
|
172
|
+
* first (lowest index — `roleIdsByCanonicalValue`'s tie-break), then a custom in stored
|
|
173
|
+
* order (blanks skipped); with no match, the canonical hex stays fixed and nothing is
|
|
174
|
+
* added to the palette.
|
|
175
|
+
*/
|
|
176
|
+
export const relinkColorToPalette = (canonicalHex, colors, isLinkColor = false) => {
|
|
177
|
+
if (isLinkColor && canonicalHex === DEFAULT_LINK_COLOR)
|
|
178
|
+
return canonicalHex;
|
|
179
|
+
const roleId = roleIdsByCanonicalValue(colors).get(canonicalHex);
|
|
180
|
+
if (roleId)
|
|
181
|
+
return toColorVarReference(roleId);
|
|
182
|
+
const custom = colors.find((color) => !isPaletteRoleId(color.id) &&
|
|
183
|
+
!isBlankColorValue(color.value) &&
|
|
184
|
+
canonicalSolidHex(color.value) === canonicalHex);
|
|
185
|
+
return custom ? toColorVarReference(custom.id) : canonicalHex;
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Every paragraph/heading a paste touches takes the destination's alignment (Reading
|
|
189
|
+
* 14) — overriding whatever the source paragraphs carried. With no destination
|
|
190
|
+
* alignment resolved, the source's own alignment is cleared rather than left in place:
|
|
191
|
+
* an open-ended LAST paragraph merges into the following text using the SLICE's own
|
|
192
|
+
* attrs, so a leftover source alignment would repaint the destination's own trailing
|
|
193
|
+
* text — the open-ended FIRST paragraph merges the other way, keeping the destination
|
|
194
|
+
* paragraph's own attrs untouched.
|
|
195
|
+
*/
|
|
196
|
+
export const alignPastedParagraphs = (content, destinationAlign) => content.map((node) => {
|
|
197
|
+
if (node.type !== 'paragraph' && node.type !== 'heading')
|
|
198
|
+
return node;
|
|
199
|
+
const { textAlign: _sourceAlign, ...attrs } = (node.attrs ?? {});
|
|
200
|
+
return {
|
|
201
|
+
...node,
|
|
202
|
+
attrs: destinationAlign
|
|
203
|
+
? { ...attrs, textAlign: destinationAlign }
|
|
204
|
+
: attrs,
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
const LINE_BREAK_RUN = /(?:\r\n?|\n)+/;
|
|
208
|
+
/**
|
|
209
|
+
* A plain-text (no valid own-editor form) paste's paragraphs (Approach step 4): split on
|
|
210
|
+
* runs of line breaks — prosemirror-view's own rule — dropping empty pieces, each line
|
|
211
|
+
* becomes a paragraph carrying the caller's marks (the seed a first type, or the
|
|
212
|
+
* paste-point's marks, would take) and the destination's alignment. Open at both ends,
|
|
213
|
+
* so the first and last line join the surrounding text. `null` for text with no visible
|
|
214
|
+
* line (nothing to insert).
|
|
215
|
+
*/
|
|
216
|
+
export const plainTextToParagraphSlice = (text, marks, textAlign) => {
|
|
217
|
+
const lines = text.split(LINE_BREAK_RUN).filter((line) => line !== '');
|
|
218
|
+
if (!lines.length)
|
|
219
|
+
return null;
|
|
220
|
+
return {
|
|
221
|
+
content: lines.map((line) => ({
|
|
222
|
+
type: 'paragraph',
|
|
223
|
+
...(textAlign ? { attrs: { textAlign } } : {}),
|
|
224
|
+
content: [
|
|
225
|
+
{
|
|
226
|
+
type: 'text',
|
|
227
|
+
text: line,
|
|
228
|
+
...(marks.length ? { marks } : {}),
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
})),
|
|
232
|
+
openStart: 1,
|
|
233
|
+
openEnd: 1,
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
// The ProseMirror schema a paste is validated against: the SAME extension set the live
|
|
237
|
+
// maker editor mounts (`restrictStarterKit`), so a node/mark the editor lacks — lists,
|
|
238
|
+
// code — fails here exactly as it would fail reaching the real editor. `getSchema` is
|
|
239
|
+
// DOM-less (mirrors `rte-schema-check.ts`), so this stays a pure check; built once and
|
|
240
|
+
// cached.
|
|
241
|
+
let cachedRteClipboardSchema;
|
|
242
|
+
const getRteClipboardSchema = () => (cachedRteClipboardSchema ??= getSchema(getRteExtensions({ restrictStarterKit: true })));
|
|
243
|
+
const canonicalSliceJSON = (sliceJson) => {
|
|
244
|
+
const sanitized = sanitizeRteJson({
|
|
245
|
+
type: 'doc',
|
|
246
|
+
content: sliceJson.content,
|
|
247
|
+
});
|
|
248
|
+
return {
|
|
249
|
+
content: sanitized.content ?? [],
|
|
250
|
+
...(sliceJson.openStart ? { openStart: sliceJson.openStart } : {}),
|
|
251
|
+
...(sliceJson.openEnd ? { openEnd: sliceJson.openEnd } : {}),
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* Validate a clipboard string as our own, un-tampered `x-rte-slice` payload (R13): it
|
|
256
|
+
* parses, its version is ours, and it is byte-for-byte its own `sanitizeRteJson` form —
|
|
257
|
+
* an unsafe link or CSS value, an unknown mark, or even a key reordered from the
|
|
258
|
+
* sanitised form changes it and fails this. It must also build against the live editor
|
|
259
|
+
* schema — catching a node/mark `sanitizeRteJson`'s broader allowlist accepts but this
|
|
260
|
+
* editor's restricted schema doesn't (lists, code). `Slice.fromJSON` alone only checks
|
|
261
|
+
* that node/mark types exist; it neither validates a node's content against its type's
|
|
262
|
+
* content expression nor its mark set, and it accepts any `openStart`/`openEnd` number —
|
|
263
|
+
* fractional included — regardless of the content's actual depth — so every top-level node
|
|
264
|
+
* is also `check()`ed, and the open depths must be integers bounded by `Slice.maxOpen`. Any
|
|
265
|
+
* failure returns `null`, so the caller falls back to the text-only path instead of
|
|
266
|
+
* inserting a malformed slice.
|
|
267
|
+
*/
|
|
268
|
+
export const parseOwnRteClipboardPayload = (raw) => {
|
|
269
|
+
let candidate;
|
|
270
|
+
try {
|
|
271
|
+
candidate = JSON.parse(raw);
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
if (!candidate ||
|
|
277
|
+
typeof candidate !== 'object' ||
|
|
278
|
+
candidate.v !== RTE_CLIPBOARD_VERSION) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
const slice = candidate.slice;
|
|
282
|
+
if (!slice || typeof slice !== 'object')
|
|
283
|
+
return null;
|
|
284
|
+
const canonical = {
|
|
285
|
+
v: RTE_CLIPBOARD_VERSION,
|
|
286
|
+
slice: canonicalSliceJSON(slice),
|
|
287
|
+
};
|
|
288
|
+
if (JSON.stringify(candidate) !== JSON.stringify(canonical))
|
|
289
|
+
return null;
|
|
290
|
+
try {
|
|
291
|
+
const parsed = Slice.fromJSON(getRteClipboardSchema(), slice);
|
|
292
|
+
parsed.content.forEach((node) => node.check());
|
|
293
|
+
const maxOpen = Slice.maxOpen(parsed.content);
|
|
294
|
+
if (!Number.isInteger(parsed.openStart) ||
|
|
295
|
+
!Number.isInteger(parsed.openEnd) ||
|
|
296
|
+
parsed.openStart < 0 ||
|
|
297
|
+
parsed.openEnd < 0 ||
|
|
298
|
+
parsed.openStart > maxOpen.openStart ||
|
|
299
|
+
parsed.openEnd > maxOpen.openEnd) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
return canonical;
|
|
307
|
+
};
|
|
@@ -42,15 +42,20 @@ const ALLOWED_MARK_TYPES = new Set([
|
|
|
42
42
|
'highlight',
|
|
43
43
|
'link',
|
|
44
44
|
]);
|
|
45
|
-
// textStyle attrs map to the allow-listed CSS properties
|
|
46
|
-
//
|
|
47
|
-
//
|
|
45
|
+
// textStyle attrs map to the allow-listed CSS properties. BP-5969: font-weight / font-style /
|
|
46
|
+
// text-decoration are now textStyle attrs (role var or literal), NOT semantic <strong>/<u>/<s>
|
|
47
|
+
// marks, so a role edit propagates via the cascade. text-align → node attr and background-color →
|
|
48
|
+
// highlight are still intentionally not here.
|
|
48
49
|
const ALLOWED_TEXT_STYLE_ATTRS = new Set([
|
|
49
50
|
'color',
|
|
50
51
|
'fontFamily',
|
|
51
52
|
'fontSize',
|
|
52
53
|
'letterSpacing',
|
|
53
54
|
'lineHeight',
|
|
55
|
+
'fontWeight',
|
|
56
|
+
'fontStyle',
|
|
57
|
+
'textDecoration',
|
|
58
|
+
'textDecorationReset',
|
|
54
59
|
]);
|
|
55
60
|
/**
|
|
56
61
|
* A safe CSS value is a short string free of characters that could inject an
|
|
@@ -70,6 +75,11 @@ const sanitizeTextStyleAttrs = (attrs) => {
|
|
|
70
75
|
if (!ALLOWED_TEXT_STYLE_ATTRS.has(key))
|
|
71
76
|
continue;
|
|
72
77
|
const value = attrs[key];
|
|
78
|
+
if (key === 'textDecorationReset') {
|
|
79
|
+
if (value === true)
|
|
80
|
+
clean[key] = true;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
73
83
|
// Tiptap emits '' for unset textStyle slots — preserve them.
|
|
74
84
|
if (value === '' || value == null) {
|
|
75
85
|
clean[key] = '';
|