@ethlete/contentful 3.6.4 → 3.7.1

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 (34) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/fesm2022/ethlete-contentful.mjs +39 -22
  3. package/fesm2022/ethlete-contentful.mjs.map +1 -1
  4. package/lib/components/audio/contentful-audio.component.d.ts +2 -2
  5. package/lib/components/file/contentful-file.component.d.ts +4 -4
  6. package/lib/components/video/contentful-video.component.d.ts +2 -2
  7. package/lib/gql/asset.fragments.d.ts +4 -4
  8. package/lib/types/contentful.types.d.ts +4 -4
  9. package/package.json +5 -7
  10. package/esm2022/ethlete-contentful.mjs +0 -5
  11. package/esm2022/index.mjs +0 -12
  12. package/esm2022/lib/components/audio/contentful-audio.component.mjs +0 -56
  13. package/esm2022/lib/components/audio/index.mjs +0 -2
  14. package/esm2022/lib/components/file/contentful-file.component.mjs +0 -56
  15. package/esm2022/lib/components/file/index.mjs +0 -2
  16. package/esm2022/lib/components/image/contentful-image.component.mjs +0 -107
  17. package/esm2022/lib/components/image/contentful-image.component.utils.mjs +0 -88
  18. package/esm2022/lib/components/image/index.mjs +0 -3
  19. package/esm2022/lib/components/rich-text-renderer/index.mjs +0 -3
  20. package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.component.mjs +0 -733
  21. package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.errors.mjs +0 -21
  22. package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.util.mjs +0 -61
  23. package/esm2022/lib/components/video/contentful-video.component.mjs +0 -52
  24. package/esm2022/lib/components/video/index.mjs +0 -2
  25. package/esm2022/lib/constants/contentful.constants.mjs +0 -3
  26. package/esm2022/lib/constants/index.mjs +0 -2
  27. package/esm2022/lib/contentful.imports.mjs +0 -13
  28. package/esm2022/lib/gql/asset.fragments.mjs +0 -20
  29. package/esm2022/lib/gql/index.mjs +0 -2
  30. package/esm2022/lib/types/contentful.types.mjs +0 -2
  31. package/esm2022/lib/types/index.mjs +0 -2
  32. package/esm2022/lib/utils/contentful-config.mjs +0 -24
  33. package/esm2022/lib/utils/contentful.util.mjs +0 -7
  34. package/esm2022/lib/utils/index.mjs +0 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ethlete/contentful
2
2
 
3
+ ## 3.7.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`e34e60b`](https://github.com/ethlete-io/ethdk/commit/e34e60b26df11baf7d9c8dd305f91b60902294cc) Thanks [@TomTomB](https://github.com/TomTomB)! - Gracefully handle contentful assets where the file is missing (e.g. when no file is uploaded to the asset in Contentful for the current locale).
8
+
9
+ ## 3.7.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [`1dd18fb`](https://github.com/ethlete-io/ethdk/commit/1dd18fb077b9b377384daac8eacae5732d7e7a3a) Thanks [@TomTomB](https://github.com/TomTomB)! - Update angular 19
14
+
3
15
  ## 3.6.4
4
16
 
5
17
  ### 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.2", ngImport: i0, type: ContentfulAudioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
54
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.2", 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.2", 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.2", 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.2", ngImport: i0, type: ContentfulFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
108
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.2", 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.2", 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.2", ngImpor
126
125
  `,
127
126
  changeDetection: ChangeDetectionStrategy.OnPush,
128
127
  encapsulation: ViewEncapsulation.None,
129
- standalone: true,
130
128
  imports: [NgClass],
131
129
  }]
132
130
  }] });
@@ -135,11 +133,23 @@ const CONTENTFUL_CONFIG = new InjectionToken('ContentfulConfig');
135
133
 
136
134
  const generateDefaultContentfulImageSource = (data) => {
137
135
  if (isContentfulGqlAsset(data)) {
136
+ if (!data.contentType || !data.url) {
137
+ return {
138
+ type: '',
139
+ srcset: '',
140
+ };
141
+ }
138
142
  return {
139
143
  type: data.contentType,
140
144
  srcset: data.url,
141
145
  };
142
146
  }
147
+ if (!data.fields.file.contentType || !data.fields.file.url) {
148
+ return {
149
+ type: '',
150
+ srcset: '',
151
+ };
152
+ }
143
153
  return {
144
154
  type: data.fields.file.contentType,
145
155
  srcset: data.fields.file.url,
@@ -273,8 +283,8 @@ class ContentfulImageComponent {
273
283
  return asset ? generateDefaultContentfulImageSource(asset) : null;
274
284
  });
275
285
  }
276
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: ContentfulImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
277
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.1.2", 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: `
286
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
287
+ 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
288
  <et-picture
279
289
  [imgClass]="imgClass()"
280
290
  [hasPriority]="hasPriority()"
@@ -291,7 +301,7 @@ class ContentfulImageComponent {
291
301
  />
292
302
  `, 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
303
  }
294
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: ContentfulImageComponent, decorators: [{
304
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulImageComponent, decorators: [{
295
305
  type: Component,
296
306
  args: [{
297
307
  selector: 'et-contentful-image',
@@ -313,7 +323,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImpor
313
323
  `,
314
324
  changeDetection: ChangeDetectionStrategy.OnPush,
315
325
  encapsulation: ViewEncapsulation.None,
316
- standalone: true,
317
326
  imports: [PictureComponent],
318
327
  host: {
319
328
  class: 'et-contentful-image',
@@ -342,8 +351,8 @@ class ContentfulVideoComponent {
342
351
  };
343
352
  });
344
353
  }
345
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: ContentfulVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
346
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.2", 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: `
354
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
355
+ 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
356
  @if (data(); as data) {
348
357
  <video [ngClass]="videoClass()" controls>
349
358
  <source src="{{ data.url }}" type="{{ data.contentType }}" />
@@ -351,7 +360,7 @@ class ContentfulVideoComponent {
351
360
  }
352
361
  `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
353
362
  }
354
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: ContentfulVideoComponent, decorators: [{
363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulVideoComponent, decorators: [{
355
364
  type: Component,
356
365
  args: [{
357
366
  selector: 'et-contentful-video',
@@ -364,7 +373,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImpor
364
373
  `,
365
374
  changeDetection: ChangeDetectionStrategy.OnPush,
366
375
  encapsulation: ViewEncapsulation.None,
367
- standalone: true,
368
376
  imports: [NgClass],
369
377
  }]
370
378
  }] });
@@ -813,9 +821,18 @@ class ContentfulRichTextRendererComponent {
813
821
  }
814
822
  const contentType = asset.fields.file.contentType;
815
823
  const assetComponents = this._config.components;
816
- const isImage = contentType.startsWith('image/');
817
- const isVideo = contentType.startsWith('video/');
818
- const isAudio = contentType.startsWith('audio/');
824
+ // Every property inside the asset will be null if no file was provided for a translation.
825
+ // In this case, we can assume that the asset is missing due to user error.
826
+ const isMissing = !contentType && !asset.fields.file.url;
827
+ if (isMissing) {
828
+ if (isDevMode()) {
829
+ console.warn('Asset is missing file data! Asset will be skipped. Did you forget to upload a file for the current translation in Contentful?', { asset });
830
+ }
831
+ break;
832
+ }
833
+ const isImage = contentType?.startsWith('image/');
834
+ const isVideo = contentType?.startsWith('video/');
835
+ const isAudio = contentType?.startsWith('audio/');
819
836
  const component = isImage
820
837
  ? assetComponents.image
821
838
  : isVideo
@@ -1173,10 +1190,10 @@ class ContentfulRichTextRendererComponent {
1173
1190
  this._renderer.appendChild(parentElement, nodeToRender);
1174
1191
  }
1175
1192
  }
1176
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: ContentfulRichTextRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1177
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.1.2", 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 }); }
1193
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulRichTextRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1194
+ 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 }); }
1178
1195
  }
1179
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: ContentfulRichTextRendererComponent, decorators: [{
1196
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ContentfulRichTextRendererComponent, decorators: [{
1180
1197
  type: Component,
1181
1198
  args: [{
1182
1199
  selector: 'et-contentful-rich-text-renderer',