@ethlete/contentful 3.6.3 → 3.7.0

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 (30) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/fesm2022/ethlete-contentful.mjs +61 -47
  3. package/fesm2022/ethlete-contentful.mjs.map +1 -1
  4. package/lib/components/rich-text-renderer/rich-text-renderer.component.d.ts +9 -5
  5. package/package.json +5 -7
  6. package/esm2022/ethlete-contentful.mjs +0 -5
  7. package/esm2022/index.mjs +0 -12
  8. package/esm2022/lib/components/audio/contentful-audio.component.mjs +0 -56
  9. package/esm2022/lib/components/audio/index.mjs +0 -2
  10. package/esm2022/lib/components/file/contentful-file.component.mjs +0 -56
  11. package/esm2022/lib/components/file/index.mjs +0 -2
  12. package/esm2022/lib/components/image/contentful-image.component.mjs +0 -107
  13. package/esm2022/lib/components/image/contentful-image.component.utils.mjs +0 -88
  14. package/esm2022/lib/components/image/index.mjs +0 -3
  15. package/esm2022/lib/components/rich-text-renderer/index.mjs +0 -3
  16. package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.component.mjs +0 -715
  17. package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.errors.mjs +0 -21
  18. package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.util.mjs +0 -61
  19. package/esm2022/lib/components/video/contentful-video.component.mjs +0 -52
  20. package/esm2022/lib/components/video/index.mjs +0 -2
  21. package/esm2022/lib/constants/contentful.constants.mjs +0 -3
  22. package/esm2022/lib/constants/index.mjs +0 -2
  23. package/esm2022/lib/contentful.imports.mjs +0 -13
  24. package/esm2022/lib/gql/asset.fragments.mjs +0 -20
  25. package/esm2022/lib/gql/index.mjs +0 -2
  26. package/esm2022/lib/types/contentful.types.mjs +0 -2
  27. package/esm2022/lib/types/index.mjs +0 -2
  28. package/esm2022/lib/utils/contentful-config.mjs +0 -24
  29. package/esm2022/lib/utils/contentful.util.mjs +0 -7
  30. package/esm2022/lib/utils/index.mjs +0 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @ethlete/contentful
2
2
 
3
+ ## 3.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`1dd18fb`](https://github.com/ethlete-io/ethdk/commit/1dd18fb077b9b377384daac8eacae5732d7e7a3a) Thanks [@TomTomB](https://github.com/TomTomB)! - Update angular 19
8
+
9
+ ## 3.6.4
10
+
11
+ ### Patch Changes
12
+
13
+ - [`df7b967`](https://github.com/ethlete-io/ethdk/commit/df7b9670a1f53d5ea7f331ea4c47be253f36ddc0) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix contentful renderer breaking after auto removal of empty tags
14
+
15
+ - [`df7b967`](https://github.com/ethlete-io/ethdk/commit/df7b9670a1f53d5ea7f331ea4c47be253f36ddc0) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix contentful renderer not rendering br tags
16
+
17
+ - [`df7b967`](https://github.com/ethlete-io/ethdk/commit/df7b9670a1f53d5ea7f331ea4c47be253f36ddc0) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix contentful renderer not rendering self closing elements such as hr
18
+
3
19
  ## 3.6.3
4
20
 
5
21
  ### Patch Changes
@@ -50,8 +50,8 @@ class ContentfulAudioComponent {
50
50
  };
51
51
  });
52
52
  }
53
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulAudioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
54
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.1", type: ContentfulAudioComponent, isStandalone: true, selector: "et-contentful-audio", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, audioClass: { classPropertyName: "audioClass", publicName: "audioClass", isSignal: true, isRequired: false, transformFunction: null }, figureClass: { classPropertyName: "figureClass", publicName: "figureClass", isSignal: true, isRequired: false, transformFunction: null }, figcaptionClass: { classPropertyName: "figcaptionClass", publicName: "figcaptionClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
53
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulAudioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
54
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: ContentfulAudioComponent, isStandalone: true, selector: "et-contentful-audio", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, audioClass: { classPropertyName: "audioClass", publicName: "audioClass", isSignal: true, isRequired: false, transformFunction: null }, figureClass: { classPropertyName: "figureClass", publicName: "figureClass", isSignal: true, isRequired: false, transformFunction: null }, figcaptionClass: { classPropertyName: "figcaptionClass", publicName: "figcaptionClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
55
55
  @if (data(); as data) {
56
56
  <figure [ngClass]="figureClass()">
57
57
  <figcaption [ngClass]="figcaptionClass()">{{ data.title }}</figcaption>
@@ -60,7 +60,7 @@ class ContentfulAudioComponent {
60
60
  }
61
61
  `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
62
62
  }
63
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulAudioComponent, decorators: [{
63
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulAudioComponent, decorators: [{
64
64
  type: Component,
65
65
  args: [{
66
66
  selector: 'et-contentful-audio',
@@ -74,7 +74,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImpor
74
74
  `,
75
75
  changeDetection: ChangeDetectionStrategy.OnPush,
76
76
  encapsulation: ViewEncapsulation.None,
77
- standalone: true,
78
77
  imports: [NgClass],
79
78
  }]
80
79
  }] });
@@ -104,8 +103,8 @@ class ContentfulFileComponent {
104
103
  };
105
104
  });
106
105
  }
107
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
108
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.1", type: ContentfulFileComponent, isStandalone: true, selector: "et-contentful-file", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, fileClass: { classPropertyName: "fileClass", publicName: "fileClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
106
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
107
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: ContentfulFileComponent, isStandalone: true, selector: "et-contentful-file", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, fileClass: { classPropertyName: "fileClass", publicName: "fileClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
109
108
  @if (data(); as data) {
110
109
  <a [href]="data.url" [ngClass]="fileClass()" class="underline" target="_blank">
111
110
  {{ data.title }} ({{ data.size }} Bytes)
@@ -113,7 +112,7 @@ class ContentfulFileComponent {
113
112
  }
114
113
  `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
115
114
  }
116
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulFileComponent, decorators: [{
115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulFileComponent, decorators: [{
117
116
  type: Component,
118
117
  args: [{
119
118
  selector: 'et-contentful-file',
@@ -126,7 +125,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImpor
126
125
  `,
127
126
  changeDetection: ChangeDetectionStrategy.OnPush,
128
127
  encapsulation: ViewEncapsulation.None,
129
- standalone: true,
130
128
  imports: [NgClass],
131
129
  }]
132
130
  }] });
@@ -273,8 +271,8 @@ class ContentfulImageComponent {
273
271
  return asset ? generateDefaultContentfulImageSource(asset) : null;
274
272
  });
275
273
  }
276
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
277
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.1.1", type: ContentfulImageComponent, isStandalone: true, selector: "et-contentful-image", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, srcsetSizes: { classPropertyName: "srcsetSizes", publicName: "srcsetSizes", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, focusArea: { classPropertyName: "focusArea", publicName: "focusArea", isSignal: true, isRequired: false, transformFunction: null }, resizeBehavior: { classPropertyName: "resizeBehavior", publicName: "resizeBehavior", isSignal: true, isRequired: false, transformFunction: null }, hasPriority: { classPropertyName: "hasPriority", publicName: "hasPriority", isSignal: true, isRequired: false, transformFunction: null }, imgClass: { classPropertyName: "imgClass", publicName: "imgClass", isSignal: true, isRequired: false, transformFunction: null }, figureClass: { classPropertyName: "figureClass", publicName: "figureClass", isSignal: true, isRequired: false, transformFunction: null }, figcaptionClass: { classPropertyName: "figcaptionClass", publicName: "figcaptionClass", isSignal: true, isRequired: false, transformFunction: null }, pictureClass: { classPropertyName: "pictureClass", publicName: "pictureClass", isSignal: true, isRequired: false, transformFunction: null }, sizes: { classPropertyName: "sizes", publicName: "sizes", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "et-contentful-image" }, ngImport: i0, template: `
274
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
275
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.3", type: ContentfulImageComponent, isStandalone: true, selector: "et-contentful-image", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, srcsetSizes: { classPropertyName: "srcsetSizes", publicName: "srcsetSizes", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, focusArea: { classPropertyName: "focusArea", publicName: "focusArea", isSignal: true, isRequired: false, transformFunction: null }, resizeBehavior: { classPropertyName: "resizeBehavior", publicName: "resizeBehavior", isSignal: true, isRequired: false, transformFunction: null }, hasPriority: { classPropertyName: "hasPriority", publicName: "hasPriority", isSignal: true, isRequired: false, transformFunction: null }, imgClass: { classPropertyName: "imgClass", publicName: "imgClass", isSignal: true, isRequired: false, transformFunction: null }, figureClass: { classPropertyName: "figureClass", publicName: "figureClass", isSignal: true, isRequired: false, transformFunction: null }, figcaptionClass: { classPropertyName: "figcaptionClass", publicName: "figcaptionClass", isSignal: true, isRequired: false, transformFunction: null }, pictureClass: { classPropertyName: "pictureClass", publicName: "pictureClass", isSignal: true, isRequired: false, transformFunction: null }, sizes: { classPropertyName: "sizes", publicName: "sizes", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "et-contentful-image" }, ngImport: i0, template: `
278
276
  <et-picture
279
277
  [imgClass]="imgClass()"
280
278
  [hasPriority]="hasPriority()"
@@ -291,7 +289,7 @@ class ContentfulImageComponent {
291
289
  />
292
290
  `, isInline: true, dependencies: [{ kind: "component", type: PictureComponent, selector: "et-picture", inputs: ["sources", "hasPriority", "imgClass", "figureClass", "figcaptionClass", "pictureClass", "defaultSrc", "alt", "figcaption", "width", "height", "sizes"], outputs: ["imgLoaded", "imgError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
293
291
  }
294
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulImageComponent, decorators: [{
292
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulImageComponent, decorators: [{
295
293
  type: Component,
296
294
  args: [{
297
295
  selector: 'et-contentful-image',
@@ -313,7 +311,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImpor
313
311
  `,
314
312
  changeDetection: ChangeDetectionStrategy.OnPush,
315
313
  encapsulation: ViewEncapsulation.None,
316
- standalone: true,
317
314
  imports: [PictureComponent],
318
315
  host: {
319
316
  class: 'et-contentful-image',
@@ -342,8 +339,8 @@ class ContentfulVideoComponent {
342
339
  };
343
340
  });
344
341
  }
345
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
346
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.1", type: ContentfulVideoComponent, isStandalone: true, selector: "et-contentful-video", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, videoClass: { classPropertyName: "videoClass", publicName: "videoClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
342
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
343
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: ContentfulVideoComponent, isStandalone: true, selector: "et-contentful-video", inputs: { asset: { classPropertyName: "asset", publicName: "asset", isSignal: true, isRequired: true, transformFunction: null }, videoClass: { classPropertyName: "videoClass", publicName: "videoClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
347
344
  @if (data(); as data) {
348
345
  <video [ngClass]="videoClass()" controls>
349
346
  <source src="{{ data.url }}" type="{{ data.contentType }}" />
@@ -351,7 +348,7 @@ class ContentfulVideoComponent {
351
348
  }
352
349
  `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
353
350
  }
354
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulVideoComponent, decorators: [{
351
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulVideoComponent, decorators: [{
355
352
  type: Component,
356
353
  args: [{
357
354
  selector: 'et-contentful-video',
@@ -364,7 +361,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImpor
364
361
  `,
365
362
  changeDetection: ChangeDetectionStrategy.OnPush,
366
363
  encapsulation: ViewEncapsulation.None,
367
- standalone: true,
368
364
  imports: [NgClass],
369
365
  }]
370
366
  }] });
@@ -490,13 +486,15 @@ const HTML_CLOSE_RENDER_COMMAND_POSITION = {
490
486
  ELEMENT_ID: 5,
491
487
  };
492
488
  const TEXT_RENDER_COMMAND_POSITION = {
493
- TEXT: 4,
489
+ ATTRIBUTES: 4,
490
+ TEXT: 5,
491
+ TEXT_ID: 6,
494
492
  };
495
493
  const COMPONENT_RENDER_COMMAND_POSITION = {
496
494
  ATTRIBUTES: 4,
497
495
  COMPONENT: 5,
498
496
  INPUTS: 6,
499
- COMPONENT_TYPE: 7,
497
+ COMPONENT_ID: 7,
500
498
  };
501
499
  const RENDER_INSTRUCTION_POSITION = {
502
500
  TYPE: 0,
@@ -546,10 +544,10 @@ const getRenderCommandId = (command) => {
546
544
  return command[HTML_CLOSE_RENDER_COMMAND_POSITION.ELEMENT_ID];
547
545
  }
548
546
  else if (isTextRenderCommand(command)) {
549
- return command[TEXT_RENDER_COMMAND_POSITION.TEXT];
547
+ return command[TEXT_RENDER_COMMAND_POSITION.TEXT_ID];
550
548
  }
551
549
  else {
552
- return command[COMPONENT_RENDER_COMMAND_POSITION.COMPONENT_TYPE];
550
+ return command[COMPONENT_RENDER_COMMAND_POSITION.COMPONENT_ID];
553
551
  }
554
552
  };
555
553
  const CLASS_ATTR = 'class';
@@ -763,15 +761,18 @@ class ContentfulRichTextRendererComponent {
763
761
  /** List of all render commands */
764
762
  const rootCommands = [];
765
763
  /** Counter for generating unique html element IDs. */
766
- let elementId = 0;
764
+ let elementOpenId = 0;
765
+ /** Counter for generating unique html element IDs. */
766
+ let elementCloseId = 0;
767
767
  /** Counter for generating unique component IDs. */
768
768
  const componentIdMap = new Map();
769
769
  /** The nesting level of the current node. */
770
770
  let nestingLevel = 0;
771
771
  /** The position (index) of the current node inside the parent node. */
772
772
  let domPosition = 0;
773
+ let textId = 0;
773
774
  let commandIndex = 0;
774
- const traverse = (node, parent = null) => {
775
+ const traverse = (node) => {
775
776
  switch (node.nodeType) {
776
777
  case 'text': {
777
778
  // Render media
@@ -779,19 +780,7 @@ class ContentfulRichTextRendererComponent {
779
780
  const text = node.value;
780
781
  if (!text)
781
782
  break;
782
- const command = [type, nestingLevel, domPosition, commandIndex++, text];
783
- rootCommands.push(command);
784
- domPosition++;
785
- if (!parent) {
786
- throw richTextRendererError('text_parent_not_found', false, { node });
787
- }
788
- if (!isHtmlOpenRenderCommand(parent) && !isComponentRenderCommand(parent)) {
789
- throw richTextRendererError('text_parent_wrong_type', false, { node, parent });
790
- }
791
- const attributesPosition = parent[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.HTML_OPEN
792
- ? HTML_OPEN_RENDER_COMMAND_POSITION.ATTRIBUTES
793
- : COMPONENT_RENDER_COMMAND_POSITION.ATTRIBUTES;
794
- const attributes = parent[attributesPosition];
783
+ const attributes = {};
795
784
  if (node.marks.length) {
796
785
  const markClasses = marksToClass(node.marks);
797
786
  if (CLASS_ATTR in attributes) {
@@ -801,6 +790,10 @@ class ContentfulRichTextRendererComponent {
801
790
  attributes[CLASS_ATTR] = markClasses;
802
791
  }
803
792
  }
793
+ const id = 't' + textId++;
794
+ const command = [type, nestingLevel, domPosition, commandIndex++, attributes, text, id];
795
+ rootCommands.push(command);
796
+ domPosition++;
804
797
  break;
805
798
  }
806
799
  case BLOCKS.EMBEDDED_ASSET: {
@@ -903,7 +896,7 @@ class ContentfulRichTextRendererComponent {
903
896
  const type = RENDER_COMMAND_TYPE.HTML_OPEN;
904
897
  const tag = translateContentfulNodeTypeToHtmlTag(node.nodeType);
905
898
  const attributes = {};
906
- const id = 'e' + elementId++;
899
+ const id = 'e-o' + elementOpenId++;
907
900
  const command = [type, nestingLevel, domPosition, commandIndex++, attributes, tag, id];
908
901
  rootCommands.push(command);
909
902
  const domPositionAtThisLevel = domPosition;
@@ -911,17 +904,21 @@ class ContentfulRichTextRendererComponent {
911
904
  for (const child of node.content) {
912
905
  domPosition = 0;
913
906
  nestingLevel++;
914
- traverse(child, command);
907
+ traverse(child);
915
908
  nestingLevel--;
916
909
  domPosition = domPositionAtThisLevel;
917
910
  }
918
911
  const lastCommand = rootCommands[rootCommands.length - 1];
919
- if (lastCommand?.[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.HTML_OPEN) {
912
+ if (lastCommand?.[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.HTML_OPEN &&
913
+ lastCommand[HTML_OPEN_RENDER_COMMAND_POSITION.TAG_NAME] !== 'td' &&
914
+ lastCommand[HTML_OPEN_RENDER_COMMAND_POSITION.TAG_NAME] !== 'hr') {
920
915
  // If the last command is an open command, we can remove it since it's empty
921
916
  rootCommands.pop();
917
+ elementOpenId--;
918
+ commandIndex--;
922
919
  }
923
920
  else {
924
- const closeId = 'e' + elementId++;
921
+ const closeId = 'e-c' + elementCloseId++;
925
922
  const closeCommand = [
926
923
  RENDER_COMMAND_TYPE.HTML_CLOSE,
927
924
  nestingLevel,
@@ -947,7 +944,7 @@ class ContentfulRichTextRendererComponent {
947
944
  }
948
945
  };
949
946
  for (const node of richTextData.content) {
950
- traverse(node, null);
947
+ traverse(node);
951
948
  }
952
949
  return rootCommands;
953
950
  }
@@ -988,14 +985,31 @@ class ContentfulRichTextRendererComponent {
988
985
  }
989
986
  else if (isTextRenderCommand(command)) {
990
987
  const text = command[TEXT_RENDER_COMMAND_POSITION.TEXT];
991
- const textNode = this._renderer.createText(text);
992
988
  const span = this._renderer.createElement('span');
993
- this._renderer.appendChild(span, textNode);
989
+ const attributes = command[TEXT_RENDER_COMMAND_POSITION.ATTRIBUTES];
990
+ const textSplitInLineBreaks = text.split('\n').filter((t) => t.trim().length > 0);
991
+ const textNodes = [];
992
+ for (const [key, value] of Object.entries(attributes)) {
993
+ this._renderer.setAttribute(span, key, value);
994
+ }
995
+ if (text.startsWith('\n')) {
996
+ const brNode = this._renderer.createElement('br');
997
+ this._renderer.appendChild(parentElement, brNode);
998
+ }
999
+ for (const [textPartIndex, textPart] of textSplitInLineBreaks.entries()) {
1000
+ if (textPartIndex > 0) {
1001
+ const brNode = this._renderer.createElement('br');
1002
+ this._renderer.appendChild(span, brNode);
1003
+ }
1004
+ const textNode = this._renderer.createText(textPart);
1005
+ this._renderer.appendChild(span, textNode);
1006
+ textNodes.push(textNode);
1007
+ }
994
1008
  this._renderInsertOrAppend(span, parentElement, nextElement);
995
1009
  this._executedCommandsCache.set(id, {
996
1010
  command,
997
1011
  element: span,
998
- textNode,
1012
+ textNode: textNodes,
999
1013
  });
1000
1014
  }
1001
1015
  else if (isHtmlOpenRenderCommand(command)) {
@@ -1112,7 +1126,7 @@ class ContentfulRichTextRendererComponent {
1112
1126
  if (!cmd) {
1113
1127
  throw new Error('Command not found!');
1114
1128
  }
1115
- if (cmd[RENDER_COMMAND_POSITION.NESTING_LEVEL] === nestingLevel - 1) {
1129
+ if (cmd[RENDER_COMMAND_POSITION.NESTING_LEVEL] === nestingLevel - 1 && isHtmlOpenRenderCommand(cmd)) {
1116
1130
  parentCommand = cmd;
1117
1131
  break;
1118
1132
  }
@@ -1155,10 +1169,10 @@ class ContentfulRichTextRendererComponent {
1155
1169
  this._renderer.appendChild(parentElement, nodeToRender);
1156
1170
  }
1157
1171
  }
1158
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulRichTextRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1159
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.1.1", type: ContentfulRichTextRendererComponent, isStandalone: true, selector: "et-contentful-rich-text-renderer", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, richTextPath: { classPropertyName: "richTextPath", publicName: "richTextPath", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "et-contentful-rich-text-renderer" }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1172
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulRichTextRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1173
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.3", type: ContentfulRichTextRendererComponent, isStandalone: true, selector: "et-contentful-rich-text-renderer", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, richTextPath: { classPropertyName: "richTextPath", publicName: "richTextPath", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "et-contentful-rich-text-renderer" }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1160
1174
  }
1161
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: ContentfulRichTextRendererComponent, decorators: [{
1175
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulRichTextRendererComponent, decorators: [{
1162
1176
  type: Component,
1163
1177
  args: [{
1164
1178
  selector: 'et-contentful-rich-text-renderer',