@ethlete/contentful 3.2.1 → 3.3.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.
- package/CHANGELOG.md +8 -0
- package/esm2022/lib/components/audio/contentful-audio.component.mjs +25 -8
- package/esm2022/lib/components/file/contentful-file.component.mjs +29 -8
- package/esm2022/lib/components/image/contentful-image.component.mjs +29 -9
- package/esm2022/lib/components/image/contentful-image.component.utils.mjs +11 -5
- package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.component.mjs +1 -1
- package/esm2022/lib/components/video/contentful-video.component.mjs +23 -6
- package/esm2022/lib/gql/asset.fragments.mjs +5 -1
- package/esm2022/lib/types/contentful.types.mjs +1 -1
- package/fesm2022/ethlete-contentful.mjs +126 -46
- package/fesm2022/ethlete-contentful.mjs.map +1 -1
- package/lib/components/audio/contentful-audio.component.d.ts +7 -2
- package/lib/components/file/contentful-file.component.d.ts +9 -2
- package/lib/components/image/contentful-image.component.d.ts +9 -2
- package/lib/components/image/contentful-image.component.utils.d.ts +4 -3
- package/lib/components/rich-text-renderer/rich-text-renderer.component.d.ts +3 -3
- package/lib/components/video/contentful-video.component.d.ts +7 -2
- package/lib/gql/asset.fragments.d.ts +1 -0
- package/lib/types/contentful.types.d.ts +4 -3
- package/package.json +1 -1
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
import { NgClass, DOCUMENT } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { input, Component, ChangeDetectionStrategy, ViewEncapsulation, InjectionToken, inject, numberAttribute, booleanAttribute,
|
|
3
|
+
import { input, computed, Component, ChangeDetectionStrategy, ViewEncapsulation, InjectionToken, inject, numberAttribute, booleanAttribute, ViewContainerRef, Renderer2, ElementRef, isDevMode } from '@angular/core';
|
|
4
|
+
import { gql } from '@ethlete/query';
|
|
4
5
|
import { normalizePictureSizes, PictureComponent } from '@ethlete/cdk';
|
|
5
6
|
import { toSignal, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
7
|
import { INLINES, BLOCKS } from '@contentful/rich-text-types';
|
|
7
8
|
import { RuntimeError, isObject, getObjectProperty } from '@ethlete/core';
|
|
8
9
|
import { startWith, pairwise, tap } from 'rxjs';
|
|
9
|
-
|
|
10
|
+
|
|
11
|
+
const GQL_FRAGMENT_CONTENTFUL_ASSET = gql `
|
|
12
|
+
fragment AssetData on Asset {
|
|
13
|
+
sys {
|
|
14
|
+
id
|
|
15
|
+
}
|
|
16
|
+
url
|
|
17
|
+
title
|
|
18
|
+
width
|
|
19
|
+
height
|
|
20
|
+
description
|
|
21
|
+
contentType
|
|
22
|
+
size
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
const isContentfulGqlAsset = (asset) => {
|
|
27
|
+
return asset?.sys?.id && asset?.url && typeof asset?.size === 'number';
|
|
28
|
+
};
|
|
10
29
|
|
|
11
30
|
class ContentfulAudioComponent {
|
|
12
31
|
constructor() {
|
|
@@ -14,13 +33,29 @@ class ContentfulAudioComponent {
|
|
|
14
33
|
this.audioClass = input(null);
|
|
15
34
|
this.figureClass = input(null);
|
|
16
35
|
this.figcaptionClass = input(null);
|
|
36
|
+
this.data = computed(() => {
|
|
37
|
+
const asset = this.asset();
|
|
38
|
+
if (!asset) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (isContentfulGqlAsset(asset)) {
|
|
42
|
+
return {
|
|
43
|
+
url: asset.url,
|
|
44
|
+
title: asset.title,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
url: asset.fields.file.url,
|
|
49
|
+
title: asset.fields.title,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
17
52
|
}
|
|
18
53
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulAudioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
19
54
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.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: `
|
|
20
|
-
@if (
|
|
55
|
+
@if (data(); as data) {
|
|
21
56
|
<figure [ngClass]="figureClass()">
|
|
22
|
-
<figcaption [ngClass]="figcaptionClass()">{{ data.
|
|
23
|
-
<audio [ngClass]="audioClass()" controls src="{{ data.
|
|
57
|
+
<figcaption [ngClass]="figcaptionClass()">{{ data.title }}</figcaption>
|
|
58
|
+
<audio [ngClass]="audioClass()" controls src="{{ data.url }}"></audio>
|
|
24
59
|
</figure>
|
|
25
60
|
}
|
|
26
61
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
@@ -30,10 +65,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
|
|
|
30
65
|
args: [{
|
|
31
66
|
selector: 'et-contentful-audio',
|
|
32
67
|
template: `
|
|
33
|
-
@if (
|
|
68
|
+
@if (data(); as data) {
|
|
34
69
|
<figure [ngClass]="figureClass()">
|
|
35
|
-
<figcaption [ngClass]="figcaptionClass()">{{ data.
|
|
36
|
-
<audio [ngClass]="audioClass()" controls src="{{ data.
|
|
70
|
+
<figcaption [ngClass]="figcaptionClass()">{{ data.title }}</figcaption>
|
|
71
|
+
<audio [ngClass]="audioClass()" controls src="{{ data.url }}"></audio>
|
|
37
72
|
</figure>
|
|
38
73
|
}
|
|
39
74
|
`,
|
|
@@ -48,12 +83,32 @@ class ContentfulFileComponent {
|
|
|
48
83
|
constructor() {
|
|
49
84
|
this.asset = input.required();
|
|
50
85
|
this.fileClass = input(null);
|
|
86
|
+
this.data = computed(() => {
|
|
87
|
+
const asset = this.asset();
|
|
88
|
+
if (!asset) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
if (isContentfulGqlAsset(asset)) {
|
|
92
|
+
return {
|
|
93
|
+
url: asset.url,
|
|
94
|
+
contentType: asset.contentType,
|
|
95
|
+
size: asset.size,
|
|
96
|
+
title: asset.title,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
url: asset.fields.file.url,
|
|
101
|
+
contentType: asset.fields.file.contentType,
|
|
102
|
+
size: asset.fields.file.details.size,
|
|
103
|
+
title: asset.fields.title,
|
|
104
|
+
};
|
|
105
|
+
});
|
|
51
106
|
}
|
|
52
107
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
53
108
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.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: `
|
|
54
|
-
@if (
|
|
55
|
-
<a [href]="data.
|
|
56
|
-
{{ data.
|
|
109
|
+
@if (data(); as data) {
|
|
110
|
+
<a [href]="data.url" [ngClass]="fileClass()" class="underline" target="_blank">
|
|
111
|
+
{{ data.title }} ({{ data.size }} Bytes)
|
|
57
112
|
</a>
|
|
58
113
|
}
|
|
59
114
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
@@ -63,9 +118,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
|
|
|
63
118
|
args: [{
|
|
64
119
|
selector: 'et-contentful-file',
|
|
65
120
|
template: `
|
|
66
|
-
@if (
|
|
67
|
-
<a [href]="data.
|
|
68
|
-
{{ data.
|
|
121
|
+
@if (data(); as data) {
|
|
122
|
+
<a [href]="data.url" [ngClass]="fileClass()" class="underline" target="_blank">
|
|
123
|
+
{{ data.title }} ({{ data.size }} Bytes)
|
|
69
124
|
</a>
|
|
70
125
|
}
|
|
71
126
|
`,
|
|
@@ -79,10 +134,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
|
|
|
79
134
|
const CONTENTFUL_CONFIG = new InjectionToken('ContentfulConfig');
|
|
80
135
|
|
|
81
136
|
const generateDefaultContentfulImageSource = (data) => {
|
|
82
|
-
|
|
137
|
+
if (isContentfulGqlAsset(data)) {
|
|
138
|
+
return {
|
|
139
|
+
type: data.contentType,
|
|
140
|
+
srcset: data.url,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
83
143
|
return {
|
|
84
|
-
type: file.contentType,
|
|
85
|
-
srcset: file.url,
|
|
144
|
+
type: data.fields.file.contentType,
|
|
145
|
+
srcset: data.fields.file.url,
|
|
86
146
|
};
|
|
87
147
|
};
|
|
88
148
|
/**
|
|
@@ -120,7 +180,7 @@ const generateContentfulImageSources = (data, srcsetSizes, backgroundColor, qual
|
|
|
120
180
|
const sources = [];
|
|
121
181
|
const SOURCE_TYPES = ['image/avif', 'image/webp', 'image/png', 'image/jpg'];
|
|
122
182
|
for (const type of SOURCE_TYPES) {
|
|
123
|
-
const baseUrl = assetData.fields.file.url;
|
|
183
|
+
const baseUrl = isContentfulGqlAsset(assetData) ? assetData.url : assetData.fields.file.url;
|
|
124
184
|
const sourceSets = [];
|
|
125
185
|
const queryParams = [];
|
|
126
186
|
// Set the format (e.g. 'fm=webp')
|
|
@@ -177,6 +237,25 @@ class ContentfulImageComponent {
|
|
|
177
237
|
this.sizes = input(normalizePictureSizes(this._contentfulConfig.imageOptions.sizes), {
|
|
178
238
|
transform: (v) => normalizePictureSizes(v),
|
|
179
239
|
});
|
|
240
|
+
this.normalizedAsset = computed(() => {
|
|
241
|
+
const asset = this.asset();
|
|
242
|
+
if (isContentfulGqlAsset(asset)) {
|
|
243
|
+
return {
|
|
244
|
+
alt: asset.title || null,
|
|
245
|
+
figcaption: asset.description || null,
|
|
246
|
+
width: asset.width,
|
|
247
|
+
height: asset.height,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
return {
|
|
252
|
+
alt: asset?.fields?.title || null,
|
|
253
|
+
figcaption: asset?.fields?.description || null,
|
|
254
|
+
width: asset?.fields?.file?.details?.image?.width ?? null,
|
|
255
|
+
height: asset?.fields?.file?.details?.image?.height ?? null,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
});
|
|
180
259
|
this._sources = computed(() => {
|
|
181
260
|
const asset = this.asset();
|
|
182
261
|
const backgroundColor = this.backgroundColor();
|
|
@@ -203,10 +282,10 @@ class ContentfulImageComponent {
|
|
|
203
282
|
[pictureClass]="pictureClass()"
|
|
204
283
|
[figcaptionClass]="figcaptionClass()"
|
|
205
284
|
[defaultSrc]="_defaultSrc()"
|
|
206
|
-
[alt]="
|
|
207
|
-
[figcaption]="
|
|
208
|
-
[width]="
|
|
209
|
-
[height]="
|
|
285
|
+
[alt]="normalizedAsset().alt ?? null"
|
|
286
|
+
[figcaption]="normalizedAsset().figcaption ?? null"
|
|
287
|
+
[width]="normalizedAsset().width ?? null"
|
|
288
|
+
[height]="normalizedAsset().height ?? null"
|
|
210
289
|
[sizes]="sizes()"
|
|
211
290
|
[sources]="_sources()"
|
|
212
291
|
/>
|
|
@@ -224,10 +303,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
|
|
|
224
303
|
[pictureClass]="pictureClass()"
|
|
225
304
|
[figcaptionClass]="figcaptionClass()"
|
|
226
305
|
[defaultSrc]="_defaultSrc()"
|
|
227
|
-
[alt]="
|
|
228
|
-
[figcaption]="
|
|
229
|
-
[width]="
|
|
230
|
-
[height]="
|
|
306
|
+
[alt]="normalizedAsset().alt ?? null"
|
|
307
|
+
[figcaption]="normalizedAsset().figcaption ?? null"
|
|
308
|
+
[width]="normalizedAsset().width ?? null"
|
|
309
|
+
[height]="normalizedAsset().height ?? null"
|
|
231
310
|
[sizes]="sizes()"
|
|
232
311
|
[sources]="_sources()"
|
|
233
312
|
/>
|
|
@@ -246,12 +325,28 @@ class ContentfulVideoComponent {
|
|
|
246
325
|
constructor() {
|
|
247
326
|
this.asset = input.required();
|
|
248
327
|
this.videoClass = input(null);
|
|
328
|
+
this.data = computed(() => {
|
|
329
|
+
const asset = this.asset();
|
|
330
|
+
if (!asset) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
if (isContentfulGqlAsset(asset)) {
|
|
334
|
+
return {
|
|
335
|
+
url: asset.url,
|
|
336
|
+
contentType: asset.contentType,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
url: asset.fields.file.url,
|
|
341
|
+
contentType: asset.fields.file.contentType,
|
|
342
|
+
};
|
|
343
|
+
});
|
|
249
344
|
}
|
|
250
345
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
251
346
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.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: `
|
|
252
|
-
@if (
|
|
347
|
+
@if (data(); as data) {
|
|
253
348
|
<video [ngClass]="videoClass()" controls>
|
|
254
|
-
<source src="{{ data.
|
|
349
|
+
<source src="{{ data.url }}" type="{{ data.contentType }}" />
|
|
255
350
|
</video>
|
|
256
351
|
}
|
|
257
352
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
@@ -261,9 +356,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImpor
|
|
|
261
356
|
args: [{
|
|
262
357
|
selector: 'et-contentful-video',
|
|
263
358
|
template: `
|
|
264
|
-
@if (
|
|
359
|
+
@if (data(); as data) {
|
|
265
360
|
<video [ngClass]="videoClass()" controls>
|
|
266
|
-
<source src="{{ data.
|
|
361
|
+
<source src="{{ data.url }}" type="{{ data.contentType }}" />
|
|
267
362
|
</video>
|
|
268
363
|
}
|
|
269
364
|
`,
|
|
@@ -1123,21 +1218,6 @@ const ContentfulImports = [
|
|
|
1123
1218
|
ContentfulRichTextRendererComponent,
|
|
1124
1219
|
];
|
|
1125
1220
|
|
|
1126
|
-
const GQL_FRAGMENT_CONTENTFUL_ASSET = gql `
|
|
1127
|
-
fragment AssetData on Asset {
|
|
1128
|
-
sys {
|
|
1129
|
-
id
|
|
1130
|
-
}
|
|
1131
|
-
url
|
|
1132
|
-
title
|
|
1133
|
-
width
|
|
1134
|
-
height
|
|
1135
|
-
description
|
|
1136
|
-
contentType
|
|
1137
|
-
size
|
|
1138
|
-
}
|
|
1139
|
-
`;
|
|
1140
|
-
|
|
1141
1221
|
const provideContentfulConfig = (contentfulConfig = {}) => {
|
|
1142
1222
|
return { provide: CONTENTFUL_CONFIG, useValue: createContentfulConfig(contentfulConfig) };
|
|
1143
1223
|
};
|
|
@@ -1148,5 +1228,5 @@ const provideContentfulConfig = (contentfulConfig = {}) => {
|
|
|
1148
1228
|
* Generated bundle index. Do not edit.
|
|
1149
1229
|
*/
|
|
1150
1230
|
|
|
1151
|
-
export { COMPONENT_RENDER_COMMAND_POSITION, CONTENTFUL_CONFIG, ContentfulAudioComponent, ContentfulFileComponent, ContentfulImageComponent, ContentfulImports, ContentfulRichTextRendererComponent, ContentfulVideoComponent, ET_CONTENTFUL_ANY_ENTRY_CONTENT_TYPE_SYS_ID, GQL_FRAGMENT_CONTENTFUL_ASSET, HTML_CLOSE_RENDER_COMMAND_POSITION, HTML_OPEN_RENDER_COMMAND_POSITION, RENDER_COMMAND_POSITION, RENDER_COMMAND_TYPE, RENDER_INSTRUCTION_POSITION, RENDER_INSTRUCTION_TYPE, TEXT_RENDER_COMMAND_POSITION, createContentfulConfig, generateContentfulImageSources, generateDefaultContentfulImageSource, getRenderCommandId, isComponentRenderCommand, isExecutedComponentCommandCacheItem, isExecutedHtmlOrTextCommandCacheItem, isExecutedTextCommandCacheItem, isHtmlCloseRenderCommand, isHtmlOpenRenderCommand, isRichTextRootNode, isTextRenderCommand, marksToClass, parseContentfulImageSize, provideContentfulConfig, translateContentfulNodeTypeToHtmlTag };
|
|
1231
|
+
export { COMPONENT_RENDER_COMMAND_POSITION, CONTENTFUL_CONFIG, ContentfulAudioComponent, ContentfulFileComponent, ContentfulImageComponent, ContentfulImports, ContentfulRichTextRendererComponent, ContentfulVideoComponent, ET_CONTENTFUL_ANY_ENTRY_CONTENT_TYPE_SYS_ID, GQL_FRAGMENT_CONTENTFUL_ASSET, HTML_CLOSE_RENDER_COMMAND_POSITION, HTML_OPEN_RENDER_COMMAND_POSITION, RENDER_COMMAND_POSITION, RENDER_COMMAND_TYPE, RENDER_INSTRUCTION_POSITION, RENDER_INSTRUCTION_TYPE, TEXT_RENDER_COMMAND_POSITION, createContentfulConfig, generateContentfulImageSources, generateDefaultContentfulImageSource, getRenderCommandId, isComponentRenderCommand, isContentfulGqlAsset, isExecutedComponentCommandCacheItem, isExecutedHtmlOrTextCommandCacheItem, isExecutedTextCommandCacheItem, isHtmlCloseRenderCommand, isHtmlOpenRenderCommand, isRichTextRootNode, isTextRenderCommand, marksToClass, parseContentfulImageSize, provideContentfulConfig, translateContentfulNodeTypeToHtmlTag };
|
|
1152
1232
|
//# sourceMappingURL=ethlete-contentful.mjs.map
|