@financial-times/cp-content-pipeline-schema 1.8.6 → 2.0.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.
- package/CHANGELOG.md +18 -0
- package/lib/generated/index.d.ts +10 -6
- package/lib/model/Clip.d.ts +2 -1
- package/lib/model/Clip.js +17 -2
- package/lib/model/Clip.js.map +1 -1
- package/lib/model/Clip.test.d.ts +1 -0
- package/lib/model/Clip.test.js +156 -0
- package/lib/model/Clip.test.js.map +1 -0
- package/lib/resolvers/content-tree/references/ClipSet.d.ts +2 -1
- package/lib/resolvers/content-tree/references/ClipSet.js +14 -2
- package/lib/resolvers/content-tree/references/ClipSet.js.map +1 -1
- package/lib/resolvers/index.d.ts +1 -1
- package/lib/resolvers/scalars.d.ts +2 -2
- package/lib/resolvers/scalars.js +1 -1
- package/lib/resolvers/scalars.js.map +1 -1
- package/package.json +1 -1
- package/queries/article.graphql +10 -1
- package/src/generated/index.ts +5 -5
- package/src/model/Clip.test.ts +154 -0
- package/src/model/Clip.ts +16 -2
- package/src/resolvers/content-tree/references/ClipSet.ts +14 -2
- package/src/resolvers/scalars.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/typedefs/clip.graphql +1 -2
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Clip } from './Clip';
|
|
2
|
+
|
|
3
|
+
describe('Clip', () => {
|
|
4
|
+
describe('poster', () => {
|
|
5
|
+
it('uses the Origami Image Service when a url is provided', () => {
|
|
6
|
+
const clip = new Clip({
|
|
7
|
+
id: 'http://api.ft.com/things/1234',
|
|
8
|
+
type: "http://www.ft.com/ontology/content/Clip",
|
|
9
|
+
dataSource: [
|
|
10
|
+
{},
|
|
11
|
+
],
|
|
12
|
+
poster: {
|
|
13
|
+
id: 'http://api.ft.com/things/1234',
|
|
14
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
15
|
+
members: [
|
|
16
|
+
{
|
|
17
|
+
id: 'http://api.ft.com/things/1234',
|
|
18
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
19
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
expect(clip.poster()).toContain('https://www.ft.com/__origami/service/image/v2/images/raw/');
|
|
25
|
+
expect(clip.poster()).toContain('source=cp-content-pipeline&fit=scale-down&quality=highest');
|
|
26
|
+
});
|
|
27
|
+
it('returns an empty string if an image url is not provided', () => {
|
|
28
|
+
const clip = new Clip({
|
|
29
|
+
id: 'http://api.ft.com/things/1234',
|
|
30
|
+
type: "http://www.ft.com/ontology/content/Clip",
|
|
31
|
+
dataSource: [
|
|
32
|
+
{},
|
|
33
|
+
],
|
|
34
|
+
poster: {
|
|
35
|
+
id: 'http://api.ft.com/things/1234',
|
|
36
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
37
|
+
members: [
|
|
38
|
+
{
|
|
39
|
+
id: 'http://api.ft.com/things/1234',
|
|
40
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
41
|
+
binaryUrl: '',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
expect(clip.poster()).toEqual('');
|
|
47
|
+
});
|
|
48
|
+
it('uses a default width if a layout is not provided', () => {
|
|
49
|
+
const clip = new Clip({
|
|
50
|
+
id: 'http://api.ft.com/things/1234',
|
|
51
|
+
type: "http://www.ft.com/ontology/content/Clip",
|
|
52
|
+
dataSource: [
|
|
53
|
+
{},
|
|
54
|
+
],
|
|
55
|
+
poster: {
|
|
56
|
+
id: 'http://api.ft.com/things/1234',
|
|
57
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
58
|
+
members: [
|
|
59
|
+
{
|
|
60
|
+
id: 'http://api.ft.com/things/1234',
|
|
61
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
62
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
expect(clip.poster()).toContain('width=700');
|
|
68
|
+
});
|
|
69
|
+
it('uses a default width if a layout is not supported', () => {
|
|
70
|
+
const clip = new Clip({
|
|
71
|
+
id: 'http://api.ft.com/things/1234',
|
|
72
|
+
type: "http://www.ft.com/ontology/content/Clip",
|
|
73
|
+
dataSource: [
|
|
74
|
+
{},
|
|
75
|
+
],
|
|
76
|
+
poster: {
|
|
77
|
+
id: 'http://api.ft.com/things/1234',
|
|
78
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
79
|
+
members: [
|
|
80
|
+
{
|
|
81
|
+
id: 'http://api.ft.com/things/1234',
|
|
82
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
83
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
}, 'I-dont-exist');
|
|
88
|
+
expect(clip.poster()).toEqual('https://www.ft.com/__origami/service/image/v2/images/raw/http%3A%2F%2Fvideo.ft.com%2F1234.jpg?source=cp-content-pipeline&fit=scale-down&quality=highest&width=700&dpr=1');
|
|
89
|
+
});
|
|
90
|
+
it('generates an image with the appropriate width for a `in-line` layout', () => {
|
|
91
|
+
const clip = new Clip({
|
|
92
|
+
id: 'http://api.ft.com/things/1234',
|
|
93
|
+
type: "http://www.ft.com/ontology/content/Clip",
|
|
94
|
+
dataSource: [
|
|
95
|
+
{},
|
|
96
|
+
],
|
|
97
|
+
poster: {
|
|
98
|
+
id: 'http://api.ft.com/things/1234',
|
|
99
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
100
|
+
members: [
|
|
101
|
+
{
|
|
102
|
+
id: 'http://api.ft.com/things/1234',
|
|
103
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
104
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
}, 'in-line');
|
|
109
|
+
expect(clip.poster()).toContain('width=700');
|
|
110
|
+
});
|
|
111
|
+
it('generates an image with the appropriate width for a `mid-grid` layout', () => {
|
|
112
|
+
const clip = new Clip({
|
|
113
|
+
id: 'http://api.ft.com/things/1234',
|
|
114
|
+
type: "http://www.ft.com/ontology/content/Clip",
|
|
115
|
+
dataSource: [
|
|
116
|
+
{},
|
|
117
|
+
],
|
|
118
|
+
poster: {
|
|
119
|
+
id: 'http://api.ft.com/things/1234',
|
|
120
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
121
|
+
members: [
|
|
122
|
+
{
|
|
123
|
+
id: 'http://api.ft.com/things/1234',
|
|
124
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
125
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
}, 'mid-grid');
|
|
130
|
+
expect(clip.poster()).toContain('width=900');
|
|
131
|
+
});
|
|
132
|
+
it('generates an image with the appropriate width for a `full-grid` layout', () => {
|
|
133
|
+
const clip = new Clip({
|
|
134
|
+
id: 'http://api.ft.com/things/1234',
|
|
135
|
+
type: "http://www.ft.com/ontology/content/Clip",
|
|
136
|
+
dataSource: [
|
|
137
|
+
{},
|
|
138
|
+
],
|
|
139
|
+
poster: {
|
|
140
|
+
id: 'http://api.ft.com/things/1234',
|
|
141
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
142
|
+
members: [
|
|
143
|
+
{
|
|
144
|
+
id: 'http://api.ft.com/things/1234',
|
|
145
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
146
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
}, 'full-grid');
|
|
151
|
+
expect(clip.poster()).toContain('width=1200');
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
package/src/model/Clip.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
validLiteralUnionValue,
|
|
6
6
|
} from '../resolvers/literal-union'
|
|
7
7
|
import { ClipFormat } from '../resolvers/scalars'
|
|
8
|
+
import imageServiceUrl from '../helpers/imageService'
|
|
8
9
|
|
|
9
10
|
export type ClipSource = {
|
|
10
11
|
binaryUrl: string
|
|
@@ -25,7 +26,7 @@ export interface ClipVideo {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export class Clip implements ClipVideo {
|
|
28
|
-
constructor(private clip: ClipMetadata) {}
|
|
29
|
+
constructor(private clip: ClipMetadata, private layout?: string) {}
|
|
29
30
|
|
|
30
31
|
type() {
|
|
31
32
|
return 'clip'
|
|
@@ -70,6 +71,19 @@ export class Clip implements ClipVideo {
|
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
poster() {
|
|
73
|
-
|
|
74
|
+
const mapSizes: {
|
|
75
|
+
[key: string]: number
|
|
76
|
+
} = {
|
|
77
|
+
'in-line': 700,
|
|
78
|
+
'mid-grid': 900,
|
|
79
|
+
'full-grid': 1200,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const url = this.clip.poster?.members[0].binaryUrl;
|
|
83
|
+
return url ? imageServiceUrl({
|
|
84
|
+
url,
|
|
85
|
+
systemCode: 'cp-content-pipeline',
|
|
86
|
+
width: this.layout && mapSizes[this.layout] ? mapSizes[this.layout] : 700,
|
|
87
|
+
}) : ''
|
|
74
88
|
}
|
|
75
89
|
}
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
} from '../Workarounds'
|
|
6
6
|
import { uuidFromUrl } from '../../../helpers/metadata'
|
|
7
7
|
import { Clip } from '../../../model/Clip'
|
|
8
|
+
import { RichText } from '../../../model/RichText'
|
|
8
9
|
import { ClipSetResolvers } from '../../../generated'
|
|
9
10
|
import { ReferenceWithCAPIData } from '.'
|
|
10
11
|
|
|
@@ -45,7 +46,18 @@ export const ClipSet = {
|
|
|
45
46
|
caption: (parent) =>
|
|
46
47
|
(parent.reference as OldClipContentTree).caption ??
|
|
47
48
|
getClipSet(parent)?.caption,
|
|
48
|
-
accessibility: (parent) =>
|
|
49
|
+
accessibility: (parent) => {
|
|
50
|
+
const accessibility = getClipSet(parent)?.accessibility
|
|
51
|
+
if (accessibility) {
|
|
52
|
+
return {
|
|
53
|
+
...accessibility,
|
|
54
|
+
transcript: accessibility.transcript
|
|
55
|
+
? new RichText('transcript', accessibility.transcript)
|
|
56
|
+
: null,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null
|
|
60
|
+
},
|
|
49
61
|
description: (parent) =>
|
|
50
62
|
(parent.reference as OldClipContentTree).description ??
|
|
51
63
|
getClipSet(parent)?.description,
|
|
@@ -61,7 +73,7 @@ export const ClipSet = {
|
|
|
61
73
|
const clipSet = getClipSet(parent)
|
|
62
74
|
|
|
63
75
|
return clipSet && clipSet.members && clipSet.members.length > 0
|
|
64
|
-
? clipSet.members.map((clip) => new Clip(clip))
|
|
76
|
+
? clipSet.members.map((clip) => new Clip(clip, parent.reference.dataLayout))
|
|
65
77
|
: null
|
|
66
78
|
},
|
|
67
79
|
} satisfies ClipSetResolvers
|
package/src/resolvers/scalars.ts
CHANGED
|
@@ -111,10 +111,10 @@ export const ClipFormat = new LiteralUnionScalar<['standard-inline', 'mobile']>(
|
|
|
111
111
|
)
|
|
112
112
|
|
|
113
113
|
export const RichTextSource = new LiteralUnionScalar<
|
|
114
|
-
['standfirst', 'summary', 'bodyXML']
|
|
114
|
+
['standfirst', 'summary', 'bodyXML', 'transcript']
|
|
115
115
|
>({
|
|
116
116
|
name: 'RichTextSource',
|
|
117
|
-
values: ['standfirst', 'summary', 'bodyXML'],
|
|
117
|
+
values: ['standfirst', 'summary', 'bodyXML', 'transcript'],
|
|
118
118
|
})
|
|
119
119
|
|
|
120
120
|
export const ContentType = new LiteralUnionScalar<
|