@designcrowd/library.brand-page 6.0.26-json-prereq-2 → 6.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-CKBqjDH3.js → CreatedOnBrandCrowd-de-de-DU6YEVcW.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-CRXiimvT.js → CreatedOnBrandCrowd-en-us-DNWWK6Tj.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-DCYdY6sj.js → CreatedOnBrandCrowd-es-es-DVFvV9Qp.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-Dk7LOhxE.js → CreatedOnBrandCrowd-fr-ca-B4ZkjNdw.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-Dk7LOhxE.js → CreatedOnBrandCrowd-fr-fr-B4ZkjNdw.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-Cp4ufHJP.js → CreatedOnBrandCrowd-pt-br-DP7AQGgW.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-Cp4ufHJP.js → CreatedOnBrandCrowd-pt-pt-DP7AQGgW.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-ZSLkWMwM.js → CreatedOnDcom-de-de-CaC3GtG9.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-BgdIGfT3.js → CreatedOnDcom-en-us-D16yT0-P.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-D0KemkCZ.js → CreatedOnDcom-es-es-DA5sHgD_.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-BuwNjNbC.js → CreatedOnDcom-fr-ca-CDv2SG1-.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-DCQcsFPf.js → CreatedOnDcom-fr-fr-Cygc7c5d.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-DD-oLAS1.js → CreatedOnDcom-pt-br-B_3RIzgF.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-D8qLq2wW.js → CreatedOnDcom-pt-pt-Bz5w-rrD.js} +1 -1
  15. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +2 -5
  16. package/lib/src/brand-page/models/index.d.ts +26 -34
  17. package/lib/src/brand-page/utils/migration.util.js +0 -11
  18. package/lib/src/brand-page/utils/text.util.d.ts +1 -1
  19. package/lib/src/brand-page/utils/text.util.js +0 -32
  20. package/lib/src/brand-page/utils/vcard.util.js +4 -4
  21. package/lib/src/brand-page/utils/view-model.util.d.ts +0 -1
  22. package/lib/src/brand-page/utils/view-model.util.js +20 -68
  23. package/lib/src/brand-page/view-models.d.ts +3 -3
  24. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +1 -0
  25. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.d.ts +9 -2
  26. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.js +10 -6
  27. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontSize.d.ts +20 -0
  28. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontSize.js +44 -0
  29. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/LineHeight.d.ts +27 -0
  30. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/LineHeight.js +44 -0
  31. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +1 -1
  32. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +103 -24
  33. package/lib/src/brand-page-maker/utils/index.d.ts +0 -2
  34. package/lib/src/brand-page-maker/utils/index.js +0 -2
  35. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +5 -28
  36. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +5 -48
  37. package/lib/src/brand-page-maker/validators/field.validator.js +2 -10
  38. package/lib/src/css/library.brand-page-brandCrowd.min.css +39 -39
  39. package/lib/src/css/library.brand-page-brandPage.min.css +39 -39
  40. package/lib/src/css/library.brand-page-designCom.min.css +39 -39
  41. package/lib/src/css/library.brand-page-preview.min.css +39 -39
  42. package/lib/src/index.d.ts +0 -1
  43. package/lib/src/index.mjs +138 -143
  44. package/lib/src/{lib-Db6j9fQZ.js → lib-6_P6kXPu.js} +51709 -55194
  45. package/lib/src/lib.js +0 -2
  46. package/lib/src/metadata-builder/ai-metadata-executor.d.ts +1 -0
  47. package/lib/src/metadata-builder/ai-metadata-executor.js +19 -0
  48. package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +3 -2
  49. package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +3 -2
  50. package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.js +3 -2
  51. package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +4 -3
  52. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +3 -2
  53. package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +2 -1
  54. package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +2 -1
  55. package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +4 -3
  56. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +3 -2
  57. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +2 -1
  58. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +11 -15
  59. package/lib/src/metadata-builder/builders/update-content-text-builder.d.ts +17 -0
  60. package/lib/src/metadata-builder/builders/update-content-text-builder.js +103 -0
  61. package/lib/src/metadata-builder/builders/update-content-text-style-builder.d.ts +16 -0
  62. package/lib/src/metadata-builder/builders/update-content-text-style-builder.js +216 -0
  63. package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +13 -11
  64. package/lib/src/metadata-builder/helpers/rte.helpers.js +73 -14
  65. package/lib/src/metadata-builder/metadata-executor.js +4 -0
  66. package/lib/src/metadata-builder/models.d.ts +2 -0
  67. package/lib/src/metadata-builder/models.js +2 -0
  68. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +19 -0
  69. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.js +4 -0
  70. package/lib/src/metadata-builder/sanitizers/rte-schema-check.d.ts +8 -7
  71. package/lib/src/metadata-builder/sanitizers/rte-schema-check.js +52 -21
  72. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.js +1 -14
  73. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +3 -12
  74. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +2 -3
  75. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.js +3 -10
  76. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +1 -2
  77. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +1 -4
  78. package/lib/src/utils/minify-brand-page-metadata.js +1 -4
  79. package/package.json +15 -17
  80. package/src/brand-page/components/contact-form/ContactForm.mixin.ts +2 -5
  81. package/src/brand-page/components/text-wrapper/TextWrapper.vue +6 -17
  82. package/src/brand-page/models/index.ts +26 -35
  83. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -3
  84. package/src/brand-page/utils/migration.util.ts +0 -12
  85. package/src/brand-page/utils/style.util.test.ts +0 -51
  86. package/src/brand-page/utils/text.util.ts +4 -43
  87. package/src/brand-page/utils/vcard.util.ts +4 -6
  88. package/src/brand-page/utils/view-model.util.ts +26 -94
  89. package/src/brand-page/view-models.ts +2 -3
  90. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +3 -4
  91. package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +1 -0
  92. package/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.ts +10 -6
  93. package/src/brand-page-maker/composables/rich-text-editor/extensions/FontSize.ts +73 -0
  94. package/src/brand-page-maker/composables/rich-text-editor/extensions/LineHeight.ts +85 -0
  95. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +111 -27
  96. package/src/brand-page-maker/utils/index.ts +0 -2
  97. package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +3 -37
  98. package/src/brand-page-maker/utils/rich-text-editor.util.ts +11 -66
  99. package/src/brand-page-maker/validators/field.validator.ts +2 -10
  100. package/src/lib.ts +0 -9
  101. package/src/metadata-builder/ai-metadata-executor.ts +26 -0
  102. package/src/metadata-builder/builders/section-builders/about-section-builder.ts +3 -2
  103. package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +3 -2
  104. package/src/metadata-builder/builders/section-builders/booking-section-builder.ts +5 -2
  105. package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +4 -3
  106. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +3 -2
  107. package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +2 -1
  108. package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +2 -1
  109. package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +6 -3
  110. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +3 -2
  111. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +2 -1
  112. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +13 -19
  113. package/src/metadata-builder/builders/update-content-text-builder.ts +148 -0
  114. package/src/metadata-builder/builders/update-content-text-style-builder.ts +352 -0
  115. package/src/metadata-builder/helpers/rte.helpers.ts +101 -15
  116. package/src/metadata-builder/metadata-executor.ts +5 -0
  117. package/src/metadata-builder/models.ts +3 -0
  118. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +27 -0
  119. package/src/metadata-builder/sanitizers/rte-schema-check.ts +53 -24
  120. package/src/shared/content-settings/components/GenericTextInput.mixin.ts +1 -17
  121. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +3 -16
  122. package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.ts +4 -13
  123. package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.vue +4 -6
  124. package/src/shared/content-settings/components/text-image-field/TextImageField.vue +3 -6
  125. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +1 -6
  126. package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +1 -1
  127. package/src/utils/minify-brand-page-metadata.ts +1 -4
  128. package/lib/src/brand-page/utils/migration/migration-20.d.ts +0 -2
  129. package/lib/src/brand-page/utils/migration/migration-20.js +0 -66
  130. package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.d.ts +0 -22
  131. package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.js +0 -22
  132. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.d.ts +0 -14
  133. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.js +0 -39
  134. package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
  135. package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.js +0 -90
  136. package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -63
  137. package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -95
  138. package/lib/src/brand-page-maker/utils/rte-sanitize.util.d.ts +0 -6
  139. package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +0 -158
  140. package/src/brand-page/utils/migration/migration-20.server.test.ts +0 -125
  141. package/src/brand-page/utils/migration/migration-20.test.ts +0 -72
  142. package/src/brand-page/utils/migration/migration-20.ts +0 -87
  143. package/src/brand-page/utils/text.util.test.ts +0 -47
  144. package/src/brand-page/utils/view-model.pageid-rte.test.ts +0 -104
  145. package/src/brand-page-maker/__fixtures__/complex-rte.fixture.ts +0 -23
  146. package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +0 -52
  147. package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.ts +0 -42
  148. package/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.ts +0 -137
  149. package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +0 -202
  150. package/src/brand-page-maker/utils/rte-features.test.ts +0 -351
  151. package/src/brand-page-maker/utils/rte-render-parity.test.ts +0 -157
  152. package/src/brand-page-maker/utils/rte-render.util.ts +0 -165
  153. package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +0 -158
  154. package/src/brand-page-maker/utils/rte-sanitize.util.ts +0 -195
  155. package/src/brand-page-maker/validators/field.validator.test.ts +0 -55
package/lib/src/lib.js CHANGED
@@ -30,8 +30,6 @@ export { minifyBrandPageMetadata, } from './utils/minify-brand-page-metadata';
30
30
  export * as brandPageUtils from './brand-page/utils';
31
31
  export { getOptimalLogoSize, calculateOptimizedLogoDimensions, applyLogoImageBase64UrlToBrandPageTemplateModel, recalculateLogoContentDimensions, recalculateHeaderLogoSizes, } from './brand-page/utils/logo.util';
32
32
  export { sanitizeRTEHtml } from './brand-page-maker/utils';
33
- // BP-5787: RTE JSON storage boundary helpers (render/normalise/sanitise/extract).
34
- export { renderRteToHtml, toRteJson, isTiptapDocument, sanitizeRteJson, getRteJsonPlainText, } from './brand-page-maker/utils';
35
33
  export { getPageSlugFromPageTitle } from './brand-page-maker/utils/slug.util';
36
34
  // AI-pipeline preview (longclaw per-turn snapshots): web-renderer's
37
35
  // /preview/ai-pipeline render page + manifest server route apply the agent's
@@ -6,6 +6,7 @@ import { type MetadataExecutorResult } from './models';
6
6
  import { type ParsedToolCall } from './parsers/ai-toolcall-parser';
7
7
  export declare const executeToolCallsAsync: (metadata: BrandPageModel, toolcalls: ParsedToolCall[], options: {
8
8
  logger?: Logger;
9
+ maxCharacters?: number;
9
10
  /**
10
11
  * Callback invoked by the UndoBuilder at execution time to resolve the
11
12
  * pre-prompt snapshot to restore to. The library is agnostic about where
@@ -1,4 +1,6 @@
1
1
  import {} from '../brand-page/models';
2
+ import { buildUpdateTextRequest } from './builders/update-content-text-builder';
3
+ import { buildUpdateTextStyleRequest } from './builders/update-content-text-style-builder';
2
4
  import { MetadataExecutor } from './metadata-executor';
3
5
  import { BUILDER_TYPES, } from './models';
4
6
  import { AI_ASSISTANT_TOOL_NAMES, SECTION_TOOL_MAP,
@@ -9,6 +11,23 @@ export const executeToolCallsAsync = async (metadata, toolcalls, options) => {
9
11
  const requests = toolcalls
10
12
  .map((toolcall) => {
11
13
  switch (toolcall.function) {
14
+ case AI_ASSISTANT_TOOL_NAMES.UPDATE_TEXT: {
15
+ const arg = toolcall.arguments;
16
+ return buildUpdateTextRequest(toolcall.toolId, {
17
+ contentId: arg.contentId,
18
+ fieldName: arg.fieldName,
19
+ newText: arg.metadata.text,
20
+ maxCharacters: options.maxCharacters,
21
+ });
22
+ }
23
+ case AI_ASSISTANT_TOOL_NAMES.UPDATE_STYLE: {
24
+ const arg = toolcall.arguments;
25
+ return buildUpdateTextStyleRequest(toolcall.toolId, {
26
+ contentId: arg.contentId,
27
+ fieldName: arg.fieldName,
28
+ newStyles: arg.metadata.style,
29
+ });
30
+ }
12
31
  case AI_ASSISTANT_TOOL_NAMES.DELETE_SECTION: {
13
32
  const arg = toolcall.arguments;
14
33
  return {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { applyColorThemeToReplacements, resolveShapeColorReplacementsAsync, } from '../shape-color-utils';
@@ -23,7 +24,7 @@ export class AboutSectionBuilder extends BaseSectionBuilder {
23
24
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
24
25
  if (aboutArgs.title !== undefined) {
25
26
  if (isTiptapDocument(aboutArgs.title)) {
26
- resolved.content.title = aboutArgs.title;
27
+ resolved.content.title = tiptapJsonToHtml(aboutArgs.title);
27
28
  resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
28
29
  }
29
30
  else {
@@ -32,7 +33,7 @@ export class AboutSectionBuilder extends BaseSectionBuilder {
32
33
  }
33
34
  if (aboutArgs.paragraph !== undefined) {
34
35
  if (isTiptapDocument(aboutArgs.paragraph)) {
35
- resolved.content.paragraph = aboutArgs.paragraph;
36
+ resolved.content.paragraph = tiptapJsonToHtml(aboutArgs.paragraph);
36
37
  resolved.content.paragraphStyle = resolveGlobalPresetIntoStyle(resolved.content.paragraphStyle, textStyleOptions);
37
38
  }
38
39
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyButtonLink, applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { applyColorThemeToReplacements, resolveShapeColorReplacementsAsync, } from '../shape-color-utils';
@@ -43,7 +44,7 @@ export class BannerSectionBuilder extends BaseSectionBuilder {
43
44
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
44
45
  if (bannerArgs.title !== undefined) {
45
46
  if (isTiptapDocument(bannerArgs.title)) {
46
- resolved.content.title = bannerArgs.title;
47
+ resolved.content.title = tiptapJsonToHtml(bannerArgs.title);
47
48
  resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
48
49
  }
49
50
  else {
@@ -52,7 +53,7 @@ export class BannerSectionBuilder extends BaseSectionBuilder {
52
53
  }
53
54
  if (bannerArgs.description !== undefined) {
54
55
  if (isTiptapDocument(bannerArgs.description)) {
55
- resolved.content.description = bannerArgs.description;
56
+ resolved.content.description = tiptapJsonToHtml(bannerArgs.description);
56
57
  resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(resolved.content.descriptionStyle, textStyleOptions);
57
58
  }
58
59
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyButtonLink, applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
@@ -22,7 +23,7 @@ export class BookingSectionBuilder extends BaseSectionBuilder {
22
23
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
23
24
  if (bookingArgs.title !== undefined) {
24
25
  if (isTiptapDocument(bookingArgs.title)) {
25
- resolved.content.title = bookingArgs.title;
26
+ resolved.content.title = tiptapJsonToHtml(bookingArgs.title);
26
27
  resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
27
28
  }
28
29
  else {
@@ -31,7 +32,7 @@ export class BookingSectionBuilder extends BaseSectionBuilder {
31
32
  }
32
33
  if (bookingArgs.description !== undefined) {
33
34
  if (isTiptapDocument(bookingArgs.description)) {
34
- resolved.content.description = bookingArgs.description;
35
+ resolved.content.description = tiptapJsonToHtml(bookingArgs.description);
35
36
  resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(resolved.content.descriptionStyle, textStyleOptions);
36
37
  }
37
38
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
@@ -22,7 +23,7 @@ export class ContactFormBuilder extends BaseSectionBuilder {
22
23
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
23
24
  if (args.title !== undefined) {
24
25
  if (isTiptapDocument(args.title)) {
25
- content.title = args.title;
26
+ content.title = tiptapJsonToHtml(args.title);
26
27
  content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
27
28
  }
28
29
  else {
@@ -31,7 +32,7 @@ export class ContactFormBuilder extends BaseSectionBuilder {
31
32
  }
32
33
  if (args.description !== undefined) {
33
34
  if (isTiptapDocument(args.description)) {
34
- content.description = args.description;
35
+ content.description = tiptapJsonToHtml(args.description);
35
36
  content.descriptionStyle = resolveGlobalPresetIntoStyle(content.descriptionStyle, textStyleOptions);
36
37
  }
37
38
  else {
@@ -40,7 +41,7 @@ export class ContactFormBuilder extends BaseSectionBuilder {
40
41
  }
41
42
  if (args.success_message !== undefined) {
42
43
  if (isTiptapDocument(args.success_message)) {
43
- content.successMessage = args.success_message;
44
+ content.successMessage = tiptapJsonToHtml(args.success_message);
44
45
  content.successMessageStyle = resolveGlobalPresetIntoStyle(content.successMessageStyle, textStyleOptions);
45
46
  }
46
47
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, isValidUrl, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
@@ -95,7 +96,7 @@ export class ImagesSectionBuilder extends BaseSectionBuilder {
95
96
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
96
97
  if (args.title !== undefined) {
97
98
  if (isTiptapDocument(args.title)) {
98
- content.title = args.title;
99
+ content.title = tiptapJsonToHtml(args.title);
99
100
  content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
100
101
  }
101
102
  else {
@@ -104,7 +105,7 @@ export class ImagesSectionBuilder extends BaseSectionBuilder {
104
105
  }
105
106
  if (args.description !== undefined) {
106
107
  if (isTiptapDocument(args.description)) {
107
- content.description = args.description;
108
+ content.description = tiptapJsonToHtml(args.description);
108
109
  content.descriptionStyle = resolveGlobalPresetIntoStyle(content.descriptionStyle, textStyleOptions);
109
110
  }
110
111
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
@@ -22,7 +23,7 @@ export class MailingListBuilder extends BaseSectionBuilder {
22
23
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
23
24
  if (mailingListArgs.title !== undefined) {
24
25
  if (isTiptapDocument(mailingListArgs.title)) {
25
- content.title = mailingListArgs.title;
26
+ content.title = tiptapJsonToHtml(mailingListArgs.title);
26
27
  content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
27
28
  }
28
29
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
@@ -21,7 +22,7 @@ export class MailingListSectionBuilder extends BaseSectionBuilder {
21
22
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
22
23
  if (mailingListArgs.title !== undefined) {
23
24
  if (isTiptapDocument(mailingListArgs.title)) {
24
- resolved.content.title = mailingListArgs.title;
25
+ resolved.content.title = tiptapJsonToHtml(mailingListArgs.title);
25
26
  resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
26
27
  }
27
28
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
@@ -20,7 +21,7 @@ export class ProfileSectionBuilder extends BaseSectionBuilder {
20
21
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
21
22
  if (profileArgs.name !== undefined) {
22
23
  if (isTiptapDocument(profileArgs.name)) {
23
- resolved.content.name = profileArgs.name;
24
+ resolved.content.name = tiptapJsonToHtml(profileArgs.name);
24
25
  resolved.content.nameStyle = resolveGlobalPresetIntoStyle(resolved.content.nameStyle, textStyleOptions);
25
26
  }
26
27
  else {
@@ -29,7 +30,7 @@ export class ProfileSectionBuilder extends BaseSectionBuilder {
29
30
  }
30
31
  if (profileArgs.title !== undefined) {
31
32
  if (isTiptapDocument(profileArgs.title)) {
32
- resolved.content.title = profileArgs.title;
33
+ resolved.content.title = tiptapJsonToHtml(profileArgs.title);
33
34
  resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
34
35
  }
35
36
  else {
@@ -38,7 +39,7 @@ export class ProfileSectionBuilder extends BaseSectionBuilder {
38
39
  }
39
40
  if (profileArgs.description !== undefined) {
40
41
  if (isTiptapDocument(profileArgs.description)) {
41
- resolved.content.description = profileArgs.description;
42
+ resolved.content.description = tiptapJsonToHtml(profileArgs.description);
42
43
  resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(resolved.content.descriptionStyle, textStyleOptions);
43
44
  }
44
45
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { applyColorThemeToReplacements, resolveShapeColorReplacementsAsync, } from '../shape-color-utils';
@@ -116,7 +117,7 @@ export class ShapesSectionBuilder extends BaseSectionBuilder {
116
117
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
117
118
  if (args.title !== undefined) {
118
119
  if (isTiptapDocument(args.title)) {
119
- content.title = args.title;
120
+ content.title = tiptapJsonToHtml(args.title);
120
121
  content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
121
122
  }
122
123
  else {
@@ -125,7 +126,7 @@ export class ShapesSectionBuilder extends BaseSectionBuilder {
125
126
  }
126
127
  if (args.description !== undefined) {
127
128
  if (isTiptapDocument(args.description)) {
128
- content.description = args.description;
129
+ content.description = tiptapJsonToHtml(args.description);
129
130
  content.descriptionStyle = resolveGlobalPresetIntoStyle(content.descriptionStyle, textStyleOptions);
130
131
  }
131
132
  else {
@@ -1,3 +1,4 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { applyColorThemeToReplacements, resolveShapeColorReplacementsAsync, } from '../shape-color-utils';
@@ -102,7 +103,7 @@ export class TestimonialSectionBuilder extends BaseSectionBuilder {
102
103
  const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
103
104
  if (args.title !== undefined) {
104
105
  if (isTiptapDocument(args.title)) {
105
- content.title = args.title;
106
+ content.title = tiptapJsonToHtml(args.title);
106
107
  content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
107
108
  }
108
109
  else {
@@ -1,28 +1,24 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
1
2
  import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
2
3
  import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
4
5
  import { validateTextSection } from '../section-rules/text-section.rules';
5
6
  import { ensureItemIds, generateItemId, removeItemsByIds, repositionItemByAnchor, } from '../item-id-utils';
6
- /**
7
- * Resolve a RichTextField to its stored RTE value. BP-5787: Tiptap JSON is
8
- * stored as-is (no JSON→HTML round-trip — migration-20 is now a one-time
9
- * legacy conversion), plain strings pass through. `wasTiptap` drives the
10
- * text-style preset resolution for rich content.
11
- */
7
+ /** Resolve a RichTextField (string or TiptapDocument) to a plain HTML string. */
12
8
  const resolveText = (value) => {
13
9
  if (isTiptapDocument(value))
14
- return { value, wasTiptap: true };
15
- return { value: typeof value === 'string' ? value : '', wasTiptap: false };
10
+ return { html: tiptapJsonToHtml(value), wasTiptap: true };
11
+ return { html: typeof value === 'string' ? value : '', wasTiptap: false };
16
12
  };
17
13
  const clearTextStyleTypeIfTiptap = (style, wasTiptap, textStyleOptions) => wasTiptap
18
14
  ? resolveGlobalPresetIntoStyle(style, textStyleOptions)
19
15
  : style;
20
16
  const createTextItem = (item, baseStyle, textStyleOptions) => {
21
17
  const textStyle = (item.text_style ? { ...baseStyle, ...item.text_style } : { ...baseStyle });
22
- const { value, wasTiptap } = resolveText(item.text);
18
+ const { html, wasTiptap } = resolveText(item.text);
23
19
  return {
24
20
  id: item.item_id || generateItemId(),
25
- text: value,
21
+ text: html,
26
22
  textStyle: clearTextStyleTypeIfTiptap(textStyle, wasTiptap, textStyleOptions),
27
23
  };
28
24
  };
@@ -55,8 +51,8 @@ const mergeTextItems = (content, items, removeIds, textStyleOptions) => {
55
51
  if (!existing)
56
52
  continue;
57
53
  if (item.text !== undefined) {
58
- const { value, wasTiptap } = resolveText(item.text);
59
- existing.text = value;
54
+ const { html, wasTiptap } = resolveText(item.text);
55
+ existing.text = html;
60
56
  existing.textStyle = clearTextStyleTypeIfTiptap(existing.textStyle || {}, wasTiptap, textStyleOptions);
61
57
  }
62
58
  if (item.text_style && typeof item.text_style === 'object') {
@@ -80,11 +76,11 @@ const mergeTextItems = (content, items, removeIds, textStyleOptions) => {
80
76
  */
81
77
  const applySingleTextField = (content, args, textStyleOptions) => {
82
78
  if (args.text !== undefined) {
83
- const { value, wasTiptap } = resolveText(args.text);
79
+ const { html, wasTiptap } = resolveText(args.text);
84
80
  if (Array.isArray(content.textItems) && content.textItems.length > 0) {
85
81
  content.textItems[0] = {
86
82
  ...content.textItems[0],
87
- text: value,
83
+ text: html,
88
84
  textStyle: clearTextStyleTypeIfTiptap(content.textItems[0].textStyle || {}, wasTiptap, textStyleOptions),
89
85
  };
90
86
  }
@@ -92,7 +88,7 @@ const applySingleTextField = (content, args, textStyleOptions) => {
92
88
  content.textItems = [
93
89
  {
94
90
  id: generateItemId(),
95
- text: value,
91
+ text: html,
96
92
  textStyle: clearTextStyleTypeIfTiptap({ ...(content.textStyle || {}) }, wasTiptap, textStyleOptions),
97
93
  },
98
94
  ];
@@ -0,0 +1,17 @@
1
+ import { type BrandPageModel } from '../../brand-page/models';
2
+ import type { Logger } from '../logger';
3
+ import { BaseMetadataBuilder, type BuilderResult, type MetadataBuilderRequest } from '../models';
4
+ export interface UpdateTextPayload {
5
+ contentId: string;
6
+ fieldName: string;
7
+ newText: string;
8
+ maxCharacters?: number;
9
+ }
10
+ export declare const buildUpdateTextRequest: (id: string, payload: UpdateTextPayload) => MetadataBuilderRequest<UpdateTextPayload>;
11
+ export declare class UpdateContentTextBuilder extends BaseMetadataBuilder<UpdateTextPayload> {
12
+ constructor(request: MetadataBuilderRequest<UpdateTextPayload>, logger?: Logger);
13
+ validateAsync(): Promise<{
14
+ errors: string[];
15
+ }>;
16
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
17
+ }
@@ -0,0 +1,103 @@
1
+ import {} from '../../brand-page/models';
2
+ import { BaseMetadataBuilder, BUILDER_TYPES, } from '../models';
3
+ import { hasRTEContent, replaceTextInRTE } from '../../brand-page-maker/utils';
4
+ export const buildUpdateTextRequest = (id, payload) => {
5
+ return {
6
+ id,
7
+ type: BUILDER_TYPES.UPDATE_CONTENT_TEXT,
8
+ payload,
9
+ };
10
+ };
11
+ const updateTextField = (target, fieldName, newText) => {
12
+ // Check if this is an array item path like "textItems.0.text"
13
+ const match = fieldName.match(/^(\w+)\.(\d+)\.(\w+)$/);
14
+ if (match) {
15
+ const [, arrayName, index, property] = match;
16
+ const array = target[arrayName];
17
+ if (Array.isArray(array) && array[+index]) {
18
+ const existingText = array[+index][property];
19
+ const updatedValue = existingText &&
20
+ typeof existingText === 'string' &&
21
+ hasRTEContent(existingText)
22
+ ? replaceTextInRTE(existingText, newText)
23
+ : newText;
24
+ // Create a new array with the updated item to trigger reactivity
25
+ const newArray = [...array];
26
+ newArray[+index] = {
27
+ ...newArray[+index],
28
+ [property]: updatedValue,
29
+ };
30
+ target[arrayName] = newArray;
31
+ }
32
+ }
33
+ else {
34
+ // Simple field
35
+ const existingText = target[fieldName];
36
+ if (existingText &&
37
+ typeof existingText === 'string' &&
38
+ hasRTEContent(existingText)) {
39
+ target[fieldName] = replaceTextInRTE(existingText, newText);
40
+ }
41
+ else {
42
+ target[fieldName] = newText;
43
+ }
44
+ }
45
+ };
46
+ export class UpdateContentTextBuilder extends BaseMetadataBuilder {
47
+ constructor(request, logger) {
48
+ super(request, logger);
49
+ }
50
+ validateAsync() {
51
+ const newText = this.request.payload?.newText ?? '';
52
+ const errors = [];
53
+ const maxChars = this.request.payload?.maxCharacters ?? 2000;
54
+ if (newText.length > maxChars) {
55
+ errors.push(`Text exceeds maximum allowed length of ${maxChars}`);
56
+ }
57
+ this.log({
58
+ message: `Validation called`,
59
+ errors,
60
+ });
61
+ return Promise.resolve({ errors: errors });
62
+ }
63
+ async buildAsync(model) {
64
+ this.log(`Build called`);
65
+ const { contentId, fieldName, newText } = this.request.payload;
66
+ const validation = await this.validateAsync();
67
+ if (validation.errors.length) {
68
+ return {
69
+ request: this.request,
70
+ model,
71
+ errors: validation.errors,
72
+ };
73
+ }
74
+ let updated = false;
75
+ for (const page of model.pages) {
76
+ for (const content of page.contents) {
77
+ // Use includes to handle potential ID format differences
78
+ if (content.id.includes(contentId) || contentId.includes(content.id)) {
79
+ this.log({
80
+ message: `Content found`,
81
+ model,
82
+ });
83
+ updateTextField(content, fieldName, newText);
84
+ this.log({
85
+ message: `Successfully updated text content.`,
86
+ model,
87
+ });
88
+ updated = true;
89
+ break;
90
+ }
91
+ }
92
+ }
93
+ return {
94
+ request: this.request,
95
+ model,
96
+ errors: updated
97
+ ? undefined
98
+ : [
99
+ `Could not update the text because content with ID "${contentId}" not found.`,
100
+ ],
101
+ };
102
+ }
103
+ }
@@ -0,0 +1,16 @@
1
+ import { type BrandPageModel, type TextStyleDeclaration } from '../../brand-page/models';
2
+ import { BaseMetadataBuilder, type BuilderResult, type MetadataBuilderRequest } from '../models';
3
+ import type { Logger } from '../logger';
4
+ export interface UpdateTextStylePayload {
5
+ contentId: string;
6
+ fieldName: string;
7
+ newStyles: TextStyleDeclaration;
8
+ }
9
+ export declare const buildUpdateTextStyleRequest: (id: string, payload: UpdateTextStylePayload) => MetadataBuilderRequest<UpdateTextStylePayload>;
10
+ export declare class UpdateContentTextStyleBuilder extends BaseMetadataBuilder<UpdateTextStylePayload> {
11
+ constructor(request: MetadataBuilderRequest<UpdateTextStylePayload>, logger?: Logger);
12
+ validateAsync(): Promise<{
13
+ errors: string[];
14
+ }>;
15
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
16
+ }