@financial-times/cp-content-pipeline-schema 0.2.1 → 0.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 +22 -0
- package/README.md +57 -0
- package/lib/concept.d.ts +3 -5
- package/lib/concept.js +8 -21
- package/lib/concept.js.map +1 -1
- package/lib/content.d.ts +3 -54
- package/lib/content.js +18 -95
- package/lib/content.js.map +1 -1
- package/lib/datasources/capi.d.ts +4 -2
- package/lib/datasources/capi.js +2 -1
- package/lib/datasources/capi.js.map +1 -1
- package/lib/fixtures/capiObject.d.ts +2 -0
- package/lib/fixtures/capiObject.js +60 -0
- package/lib/fixtures/capiObject.js.map +1 -0
- package/lib/fixtures/capiPerson.d.ts +2 -0
- package/lib/fixtures/capiPerson.js +54 -0
- package/lib/fixtures/capiPerson.js.map +1 -0
- package/lib/helpers/metadata.d.ts +0 -11
- package/lib/helpers/metadata.js +0 -52
- package/lib/helpers/metadata.js.map +1 -1
- package/lib/image.d.ts +2 -23
- package/lib/image.js +10 -82
- package/lib/image.js.map +1 -1
- package/lib/index.d.ts +5 -3
- package/lib/index.js +4 -11
- package/lib/index.js.map +1 -1
- package/lib/model/Byline.d.ts +29 -0
- package/lib/model/Byline.js +45 -0
- package/lib/model/Byline.js.map +1 -0
- package/lib/{content.test.d.ts → model/Byline.test.d.ts} +0 -0
- package/lib/model/Byline.test.js +60 -0
- package/lib/model/Byline.test.js.map +1 -0
- package/lib/model/CapiResponse.d.ts +48 -0
- package/lib/model/CapiResponse.js +159 -0
- package/lib/model/CapiResponse.js.map +1 -0
- package/lib/model/Concept.d.ts +36 -0
- package/lib/model/Concept.js +109 -0
- package/lib/model/Concept.js.map +1 -0
- package/lib/{image.test.d.ts → model/Concept.test.d.ts} +0 -0
- package/lib/model/Concept.test.js +96 -0
- package/lib/model/Concept.test.js.map +1 -0
- package/lib/model/Image.d.ts +34 -0
- package/lib/model/Image.js +101 -0
- package/lib/model/Image.js.map +1 -0
- package/lib/model/Image.test.d.ts +1 -0
- package/lib/{image.test.js → model/Image.test.js} +71 -74
- package/lib/model/Image.test.js.map +1 -0
- package/lib/model/Topper.d.ts +26 -0
- package/lib/model/Topper.js +93 -0
- package/lib/model/Topper.js.map +1 -0
- package/lib/model/Topper.test.d.ts +1 -0
- package/lib/model/Topper.test.js +283 -0
- package/lib/model/Topper.test.js.map +1 -0
- package/lib/picture.d.ts +7 -8
- package/lib/picture.js +15 -8
- package/lib/picture.js.map +1 -1
- package/lib/richText.d.ts +2 -2
- package/lib/richText.js.map +1 -1
- package/lib/tags.d.ts +3 -3
- package/lib/tags.js +48 -24
- package/lib/tags.js.map +1 -1
- package/lib/teaser.d.ts +4 -0
- package/lib/teaser.js +56 -0
- package/lib/teaser.js.map +1 -0
- package/lib/topper.d.ts +2 -5
- package/lib/topper.js +27 -101
- package/lib/topper.js.map +1 -1
- package/lib/unified-plugins/extract-references.d.ts +2 -2
- package/lib/unified-plugins/extract-references.js.map +1 -1
- package/package.json +3 -1
- package/src/concept.ts +12 -39
- package/src/content.ts +25 -109
- package/src/datasources/capi.ts +4 -2
- package/src/fixtures/capiObject.ts +61 -0
- package/src/fixtures/capiPerson.ts +59 -0
- package/src/helpers/metadata.ts +0 -79
- package/src/image.ts +15 -112
- package/src/index.ts +17 -13
- package/src/model/Byline.test.ts +67 -0
- package/src/model/Byline.ts +39 -0
- package/src/model/CapiResponse.ts +182 -0
- package/src/model/Concept.test.ts +124 -0
- package/src/model/Concept.ts +143 -0
- package/src/{image.test.ts → model/Image.test.ts} +84 -134
- package/src/model/Image.ts +116 -0
- package/src/model/Topper.test.ts +354 -0
- package/src/model/Topper.ts +120 -0
- package/src/model/__snapshots__/Byline.test.ts.snap +126 -0
- package/src/picture.ts +16 -15
- package/src/richText.ts +3 -3
- package/src/tags.ts +55 -18
- package/src/teaser.ts +63 -0
- package/src/topper.ts +30 -124
- package/src/types/internal-content.d.ts +29 -4
- package/src/unified-plugins/extract-references.ts +6 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/content.test.js +0 -149
- package/lib/content.test.js.map +0 -1
- package/lib/helpers/byline.d.ts +0 -1
- package/lib/helpers/byline.js +0 -5
- package/lib/helpers/byline.js.map +0 -1
- package/lib/helpers/syntaxTree.d.ts +0 -23
- package/lib/helpers/syntaxTree.js +0 -23
- package/lib/helpers/syntaxTree.js.map +0 -1
- package/lib/image.test.js.map +0 -1
- package/src/__snapshots__/content.test.ts.snap +0 -118
- package/src/content.test.ts +0 -163
- package/src/helpers/byline.ts +0 -4
- package/src/helpers/syntaxTree.ts +0 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v0.2.1...cp-content-pipeline-schema-v0.3.0) (2022-10-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* render byline as part of a new ArticleInfo component
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* add pull-quotes ([b4cd5d6](https://github.com/Financial-Times/cp-content-pipeline/commit/b4cd5d65b8ae50c64e774ae55049e1d43c7b1c7e))
|
|
13
|
+
* render byline as part of a new ArticleInfo component ([de58076](https://github.com/Financial-Times/cp-content-pipeline/commit/de580765ec5094252b23132b6b457003ca66c4fb))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* implement min/max width resolvers ([8140aa2](https://github.com/Financial-Times/cp-content-pipeline/commit/8140aa27b39dbe89970a5f52a5c500546ec6d587))
|
|
19
|
+
* show brand as displayConcept for opinion articles ([c86060e](https://github.com/Financial-Times/cp-content-pipeline/commit/c86060eea95d8ef632105e9a10deff16aab9ee0f))
|
|
20
|
+
* show brand tags on fancy toppers with brands ([b3d4748](https://github.com/Financial-Times/cp-content-pipeline/commit/b3d4748c518e96200369abf5a8e9068e68580fc0))
|
|
21
|
+
* support articles without bylines ([0996c75](https://github.com/Financial-Times/cp-content-pipeline/commit/0996c75f0452aa2fec8b4b1e5617f3246e16c915))
|
|
22
|
+
* use image model for teaser image ([0eae6f8](https://github.com/Financial-Times/cp-content-pipeline/commit/0eae6f82f508369dd4384d24b2fc25cbd417af0e))
|
|
23
|
+
* use wheat as 'auto' colour for fancy toppers ([dfb1eac](https://github.com/Financial-Times/cp-content-pipeline/commit/dfb1eac6b0948199d0cb41d71a05b857a4456dec))
|
|
24
|
+
|
|
3
25
|
## [0.2.1](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v0.2.0...cp-content-pipeline-schema-v0.2.1) (2022-09-27)
|
|
4
26
|
|
|
5
27
|
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Schema
|
|
2
|
+
|
|
3
|
+
## What is this?
|
|
4
|
+
|
|
5
|
+
The GraphQL schema, data sources, and business logic for the content pipeline API. It is consumed by the
|
|
6
|
+
[api package](../api) and not intended for use outside this project.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import { ApolloServer } from 'apollo-server'
|
|
12
|
+
import {
|
|
13
|
+
resolvers,
|
|
14
|
+
typeDefs,
|
|
15
|
+
dataSources,
|
|
16
|
+
} from '@financial-times/cp-content-pipeline-schema'
|
|
17
|
+
|
|
18
|
+
const server = new ApolloServer({
|
|
19
|
+
typeDefs,
|
|
20
|
+
resolvers,
|
|
21
|
+
dataSources,
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
See the [api package entry point](../api/src/index.ts) for a more complex example.
|
|
26
|
+
|
|
27
|
+
## How does it work?
|
|
28
|
+
|
|
29
|
+
This package's exports are shown below. They are consumed by a GraphQL server framework:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import {
|
|
33
|
+
resolvers,
|
|
34
|
+
typeDefs,
|
|
35
|
+
dataSources,
|
|
36
|
+
DataSources,
|
|
37
|
+
QueryContext,
|
|
38
|
+
} from '@financial-times/cp-content-pipeline-schema'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The schema is a collection of type definitions that is exported as `typeDefs`. It defines the 'shape' of queries that
|
|
42
|
+
are executed against our data.
|
|
43
|
+
|
|
44
|
+
The schema is split into files at the root of the `src` directory and brought together in `src/index.ts` for export.
|
|
45
|
+
|
|
46
|
+
Resolvers define the technique for fetching the types defined in the schema. The resolvers for each part of the schema
|
|
47
|
+
are defined in the
|
|
48
|
+
same file the schema definition is in. They are exported as `resolvers`.
|
|
49
|
+
|
|
50
|
+
Data sources are used to fetch data from external sources, such as the content API. These are defined in the
|
|
51
|
+
[data sources directory](src/datasources). Its type is exported as `DataSources`, its factory function is exported as
|
|
52
|
+
`dataSources`.
|
|
53
|
+
|
|
54
|
+
The `QueryContext` type defines the context object sent to each resolver function.
|
|
55
|
+
|
|
56
|
+
The model contains the business logic gluing the data sources and resolvers together. It is defined in the
|
|
57
|
+
[model](src/model) directory and consumed by the resolvers.
|
package/lib/concept.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { IResolvers } from '@graphql-tools/utils';
|
|
2
|
-
import {
|
|
2
|
+
import type { QueryContext } from './index.js';
|
|
3
|
+
import { Concept } from './model/Concept.js';
|
|
3
4
|
export declare const typeDef: import("graphql").DocumentNode;
|
|
4
|
-
export declare const resolvers: IResolvers<
|
|
5
|
-
systemCode: string;
|
|
6
|
-
dataSources: DataSources;
|
|
7
|
-
}, never>;
|
|
5
|
+
export declare const resolvers: IResolvers<Concept, QueryContext, never>;
|
package/lib/concept.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { gql } from 'graphql-tag';
|
|
2
|
-
const CAPI_ID_PREFIX = /^https?:\/\/(?:www|api)\.ft\.com\/things?\//;
|
|
3
|
-
const BASE_URL = 'https://www.ft.com/stream/';
|
|
4
|
-
const FT_URL = 'https://www.ft.com';
|
|
5
2
|
export const typeDef = gql `
|
|
6
3
|
type Concept {
|
|
7
4
|
apiUrl: String!
|
|
@@ -16,24 +13,14 @@ export const typeDef = gql `
|
|
|
16
13
|
`;
|
|
17
14
|
export const resolvers = {
|
|
18
15
|
Concept: {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
//TODO:AG:26-09-2022 log error here, but fail gracefully to use non-vanity
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (args.relative) {
|
|
33
|
-
url = url.replace(FT_URL, '');
|
|
34
|
-
}
|
|
35
|
-
return url;
|
|
36
|
-
},
|
|
16
|
+
apiUrl: (parent) => parent.apiUrl(),
|
|
17
|
+
directType: (parent) => parent.directType(),
|
|
18
|
+
id: (parent) => parent.id(),
|
|
19
|
+
predicate: (parent) => parent.predicate(),
|
|
20
|
+
prefLabel: (parent) => parent.prefLabel(),
|
|
21
|
+
type: (parent) => parent.type(),
|
|
22
|
+
types: (parent) => parent.types(),
|
|
23
|
+
url: async (parent, args, context) => parent.url(args),
|
|
37
24
|
},
|
|
38
25
|
};
|
|
39
26
|
//# sourceMappingURL=concept.js.map
|
package/lib/concept.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concept.js","sourceRoot":"","sources":["../src/concept.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"concept.js","sourceRoot":"","sources":["../src/concept.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAIjC,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,CAAA;;;;;;;;;;;CAWzB,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAA6C;IACjE,OAAO,EAAE;QACP,MAAM,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE;QAC5C,UAAU,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE;QACpD,EAAE,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE;QACpC,SAAS,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;QAClD,SAAS,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;QAClD,IAAI,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;QACxC,KAAK,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;QAC1C,GAAG,EAAE,KAAK,EAAE,MAAe,EAAE,IAAkB,EAAE,OAAO,EAAE,EAAE,CAC1D,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;KACnB;CACF,CAAA"}
|
package/lib/content.d.ts
CHANGED
|
@@ -1,55 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { IResolvers } from '@graphql-tools/utils';
|
|
2
|
+
import type { QueryContext } from './index.js';
|
|
2
3
|
export declare const typeDef: import("graphql").DocumentNode[];
|
|
3
|
-
export declare const resolvers:
|
|
4
|
-
Content: {
|
|
5
|
-
body(parent: InternalContent): {
|
|
6
|
-
source: string;
|
|
7
|
-
value: string;
|
|
8
|
-
contentApiData: InternalContent;
|
|
9
|
-
};
|
|
10
|
-
topper(parent: InternalContent): InternalContent;
|
|
11
|
-
byline(parent: InternalContent): {
|
|
12
|
-
tree: {
|
|
13
|
-
type: string;
|
|
14
|
-
children: ({
|
|
15
|
-
type: string;
|
|
16
|
-
tagName: string;
|
|
17
|
-
properties: {
|
|
18
|
-
href: string;
|
|
19
|
-
};
|
|
20
|
-
children: {
|
|
21
|
-
type: string;
|
|
22
|
-
value: string;
|
|
23
|
-
}[];
|
|
24
|
-
value?: undefined;
|
|
25
|
-
} | {
|
|
26
|
-
type: string;
|
|
27
|
-
value: string;
|
|
28
|
-
tagName?: undefined;
|
|
29
|
-
properties?: undefined;
|
|
30
|
-
children?: undefined;
|
|
31
|
-
})[];
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
metaLink(parent: InternalContent): any;
|
|
35
|
-
metaAltLink(parent: InternalContent): any;
|
|
36
|
-
metaPrefixText(parent: InternalContent): any;
|
|
37
|
-
metaSuffixText(parent: InternalContent): any;
|
|
38
|
-
url(parent: InternalContent, args: {
|
|
39
|
-
relative: boolean;
|
|
40
|
-
}): string;
|
|
41
|
-
type(parent: InternalContent): string;
|
|
42
|
-
mainImage(parent: InternalContent): import("./types/internal-content.js").Image | undefined;
|
|
43
|
-
altTitle(parent: InternalContent): string | undefined;
|
|
44
|
-
altStandfirst(parent: InternalContent): string | undefined;
|
|
45
|
-
indicators(parent: InternalContent): {
|
|
46
|
-
accessLevel: import("./types/internal-content.js").AccessLevel;
|
|
47
|
-
isOpinion: boolean;
|
|
48
|
-
isColumn: boolean;
|
|
49
|
-
isPodcast: boolean;
|
|
50
|
-
isEditorsChoice: boolean;
|
|
51
|
-
isExclusive: boolean;
|
|
52
|
-
isScoop: boolean;
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
};
|
|
4
|
+
export declare const resolvers: IResolvers<unknown, QueryContext, never>;
|
package/lib/content.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { gql } from 'graphql-tag';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { buildUrlTree } from './helpers/syntaxTree.js';
|
|
5
|
-
import { splitBylineByName } from './helpers/byline.js';
|
|
2
|
+
import { Topper } from './model/Topper.js';
|
|
3
|
+
import { Byline } from './model/Byline.js';
|
|
6
4
|
export const typeDef = [
|
|
7
5
|
gql `
|
|
8
6
|
type Content {
|
|
@@ -16,30 +14,11 @@ export const typeDef = [
|
|
|
16
14
|
url(relative: Boolean): String!
|
|
17
15
|
publishedDate: String!
|
|
18
16
|
firstPublishedDate: String!
|
|
19
|
-
metaLink: Concept
|
|
20
|
-
metaAltLink: Concept
|
|
21
|
-
metaPrefixText: String
|
|
22
|
-
metaSuffixText: String
|
|
23
17
|
mainImage: Image
|
|
24
|
-
indicators: Indicators!
|
|
25
18
|
altTitle: AltTitle
|
|
26
19
|
altStandfirst: AltStandfirst
|
|
27
|
-
byline: StructuredContent
|
|
28
|
-
|
|
29
|
-
type Indicators {
|
|
30
|
-
accessLevel: AccessLevel
|
|
31
|
-
isOpinion: Boolean
|
|
32
|
-
isColumn: Boolean
|
|
33
|
-
isPodcast: Boolean
|
|
34
|
-
isEditorsChoice: Boolean
|
|
35
|
-
isExclusive: Boolean
|
|
36
|
-
isScoop: Boolean
|
|
37
|
-
}
|
|
38
|
-
enum AccessLevel {
|
|
39
|
-
premium
|
|
40
|
-
subscribed
|
|
41
|
-
registered
|
|
42
|
-
free
|
|
20
|
+
byline: StructuredContent
|
|
21
|
+
teaser: Teaser
|
|
43
22
|
}
|
|
44
23
|
type AltTitle {
|
|
45
24
|
promotionalTitle: String
|
|
@@ -49,85 +28,29 @@ export const typeDef = [
|
|
|
49
28
|
}
|
|
50
29
|
`,
|
|
51
30
|
];
|
|
52
|
-
function getTeaserMetadata(annotations, field) {
|
|
53
|
-
const meta = metadata.teaser({
|
|
54
|
-
annotations,
|
|
55
|
-
});
|
|
56
|
-
return meta[field];
|
|
57
|
-
}
|
|
58
31
|
export const resolvers = {
|
|
59
32
|
Content: {
|
|
60
33
|
body(parent) {
|
|
61
34
|
return {
|
|
62
35
|
source: 'bodyXML',
|
|
63
|
-
value: parent.bodyXML,
|
|
36
|
+
value: parent.bodyXML(),
|
|
64
37
|
contentApiData: parent,
|
|
65
38
|
};
|
|
66
39
|
},
|
|
67
|
-
topper(parent)
|
|
68
|
-
return parent;
|
|
69
|
-
},
|
|
40
|
+
topper: (parent, args, context) => new Topper(parent, context),
|
|
70
41
|
byline(parent) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
metaPrefixText(parent) {
|
|
85
|
-
return getTeaserMetadata(parent.annotations, 'prefixText');
|
|
86
|
-
},
|
|
87
|
-
metaSuffixText(parent) {
|
|
88
|
-
return getTeaserMetadata(parent.annotations, 'suffixText');
|
|
89
|
-
},
|
|
90
|
-
url(parent, args) {
|
|
91
|
-
const RELATIVE_URL_REGEX = /https?:\/\/www.ft.com/;
|
|
92
|
-
if (args.relative) {
|
|
93
|
-
return parent.webUrl.replace(RELATIVE_URL_REGEX, '');
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
return parent.webUrl;
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
type(parent) {
|
|
100
|
-
const TYPE_REGEX = /https?:\/\/www.ft.com\/ontology\/content\//;
|
|
101
|
-
return parent.types[0].replace(TYPE_REGEX, '').toLowerCase();
|
|
102
|
-
},
|
|
103
|
-
mainImage(parent) {
|
|
104
|
-
var _a, _b;
|
|
105
|
-
if (((_a = parent.mainImage) === null || _a === void 0 ? void 0 : _a.type) === 'http://www.ft.com/ontology/content/Image') {
|
|
106
|
-
return parent.mainImage;
|
|
107
|
-
}
|
|
108
|
-
else if (((_b = parent.mainImage) === null || _b === void 0 ? void 0 : _b.type) === 'http://www.ft.com/ontology/content/ImageSet') {
|
|
109
|
-
return parent.mainImage.members[0];
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
altTitle(parent) {
|
|
113
|
-
var _a;
|
|
114
|
-
return (_a = parent.alternativeTitles) === null || _a === void 0 ? void 0 : _a.promotionalTitle;
|
|
115
|
-
},
|
|
116
|
-
altStandfirst(parent) {
|
|
117
|
-
var _a;
|
|
118
|
-
return (_a = parent.alternativeStandfirsts) === null || _a === void 0 ? void 0 : _a.promotionalStandfirst;
|
|
119
|
-
},
|
|
120
|
-
indicators(parent) {
|
|
121
|
-
return {
|
|
122
|
-
accessLevel: parent.accessLevel,
|
|
123
|
-
isOpinion: isOpinion(parent),
|
|
124
|
-
isColumn: isColumn(parent),
|
|
125
|
-
isPodcast: isPodcast(parent),
|
|
126
|
-
isEditorsChoice: isEditorsChoice(parent),
|
|
127
|
-
isExclusive: isExclusive(parent),
|
|
128
|
-
isScoop: isScoop(parent),
|
|
129
|
-
};
|
|
130
|
-
},
|
|
42
|
+
const bylineText = parent.byline();
|
|
43
|
+
if (!bylineText)
|
|
44
|
+
return null;
|
|
45
|
+
const authorUrlMapping = parent.getAuthorUrlMapping();
|
|
46
|
+
return new Byline(bylineText, authorUrlMapping).buildBylineTree();
|
|
47
|
+
},
|
|
48
|
+
url: (parent, args) => args.relative ? parent.relativeUrl() : parent.url(),
|
|
49
|
+
type: (parent) => parent.type(),
|
|
50
|
+
mainImage: (parent) => parent.mainImage(),
|
|
51
|
+
altTitle: (parent) => parent.alternativeTitle(),
|
|
52
|
+
altStandfirst: (parent) => parent.alternativeStandfirst(),
|
|
53
|
+
publishedDate: (parent) => parent.publishedDate(),
|
|
131
54
|
},
|
|
132
55
|
};
|
|
133
56
|
//# sourceMappingURL=content.js.map
|
package/lib/content.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAIjC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBF;CACF,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAA6C;IACjE,OAAO,EAAE;QACP,IAAI,CAAC,MAAoB;YACvB,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;gBACvB,cAAc,EAAE,MAAM;aACvB,CAAA;QACH,CAAC;QACD,MAAM,EAAE,CAAC,MAAoB,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAC9C,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QAC7B,MAAM,CAAC,MAAoB;YACzB,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;YAClC,IAAI,CAAC,UAAU;gBAAE,OAAO,IAAI,CAAA;YAC5B,MAAM,gBAAgB,GAAG,MAAM,CAAC,mBAAmB,EAAE,CAAA;YACrD,OAAO,IAAI,MAAM,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,eAAe,EAAE,CAAA;QACnE,CAAC;QACD,GAAG,EAAE,CAAC,MAAoB,EAAE,IAA2B,EAAE,EAAE,CACzD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE;QACrD,IAAI,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;QAC7C,SAAS,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;QACvD,QAAQ,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAC7D,aAAa,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,qBAAqB,EAAE;QACvE,aAAa,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE;KAChE;CACF,CAAA"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { RESTDataSource, RequestOptions } from 'apollo-datasource-rest';
|
|
2
|
+
import { CapiResponse } from '../model/CapiResponse.js';
|
|
3
|
+
import { CapiPerson } from '../types/internal-content.js';
|
|
2
4
|
export declare class CapiDataSource extends RESTDataSource {
|
|
3
5
|
baseURL: string;
|
|
4
6
|
capiKey: string;
|
|
5
7
|
articleCacheTTL: number;
|
|
6
8
|
peopleCacheTTL: number;
|
|
7
9
|
willSendRequest(request: RequestOptions): void;
|
|
8
|
-
getContent(uuid: string): Promise<
|
|
9
|
-
getPerson(uuid: string): Promise<
|
|
10
|
+
getContent(uuid: string): Promise<CapiResponse>;
|
|
11
|
+
getPerson(uuid: string): Promise<CapiPerson>;
|
|
10
12
|
}
|
package/lib/datasources/capi.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RESTDataSource } from 'apollo-datasource-rest';
|
|
2
|
+
import { CapiResponse } from '../model/CapiResponse.js';
|
|
2
3
|
export class CapiDataSource extends RESTDataSource {
|
|
3
4
|
constructor() {
|
|
4
5
|
super(...arguments);
|
|
@@ -17,7 +18,7 @@ export class CapiDataSource extends RESTDataSource {
|
|
|
17
18
|
async getContent(uuid) {
|
|
18
19
|
return this.get(`internalcontent/${uuid}`, undefined, {
|
|
19
20
|
cacheOptions: { ttl: this.articleCacheTTL },
|
|
20
|
-
});
|
|
21
|
+
}).then((response) => new CapiResponse(response, this.context));
|
|
21
22
|
}
|
|
22
23
|
async getPerson(uuid) {
|
|
23
24
|
return this.get(`people/${uuid}`, undefined, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capi.js","sourceRoot":"","sources":["../../src/datasources/capi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"capi.js","sourceRoot":"","sources":["../../src/datasources/capi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,MAAM,wBAAwB,CAAA;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAGvD,MAAM,OAAO,cAAe,SAAQ,cAAc;IAAlD;;QACE,YAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,uBAAuB,CAAA;QACzD,YAAO,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAA;QACxC,oBAAe,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAC7C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;YACzC,CAAC,CAAC,EAAE,CAAA,CAAC,aAAa;QACpB,mBAAc,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB;YAC3C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACxC,CAAC,CAAC,GAAG,CAAA,CAAC,aAAa;IAiBvB,CAAC;IAfC,eAAe,CAAC,OAAuB;QACrC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,EAAE,SAAS,EAAE;YACpD,YAAY,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE;SAC5C,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;IACjE,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,EAAE,SAAS,EAAE;YAC3C,YAAY,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE;SAC3C,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const baseCapiObject = {
|
|
2
|
+
id: '',
|
|
3
|
+
type: '',
|
|
4
|
+
types: [],
|
|
5
|
+
webUrl: '',
|
|
6
|
+
title: 'Kwarteng faces test persuading UK watchdog of fiscal plans',
|
|
7
|
+
standfirst: '',
|
|
8
|
+
byline: 'Chris Giles in London',
|
|
9
|
+
bodyXML: '',
|
|
10
|
+
annotations: [
|
|
11
|
+
{
|
|
12
|
+
apiUrl: 'http://api.ft.com/things/9bfe954c-e0ec-4716-ae91-24bd0f7860c9',
|
|
13
|
+
directType: 'http://www.ft.com/ontology/Topic',
|
|
14
|
+
id: 'http://api.ft.com/things/9bfe954c-e0ec-4716-ae91-24bd0f7860c9',
|
|
15
|
+
predicate: 'http://www.ft.com/ontology/annotation/about',
|
|
16
|
+
prefLabel: 'UK financial crisis',
|
|
17
|
+
type: 'TOPIC',
|
|
18
|
+
types: [
|
|
19
|
+
'http://www.ft.com/ontology/core/Thing',
|
|
20
|
+
'http://www.ft.com/ontology/concept/Concept',
|
|
21
|
+
'http://www.ft.com/ontology/Topic',
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
apiUrl: 'http://api.ft.com/things/9c0f3107-a34f-4319-a6a6-3101ac88b50d',
|
|
26
|
+
directType: 'http://www.ft.com/ontology/Topic',
|
|
27
|
+
id: 'http://api.ft.com/things/9c0f3107-a34f-4319-a6a6-3101ac88b50d',
|
|
28
|
+
predicate: 'http://www.ft.com/ontology/hasDisplayTag',
|
|
29
|
+
prefLabel: 'UK politics & policy',
|
|
30
|
+
type: 'TOPIC',
|
|
31
|
+
types: [
|
|
32
|
+
'http://www.ft.com/ontology/core/Thing',
|
|
33
|
+
'http://www.ft.com/ontology/concept/Concept',
|
|
34
|
+
'http://www.ft.com/ontology/Topic',
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'http://api.ft.com/things/1d556016-ad16-4fe7-8724-42b3fb15ad28',
|
|
39
|
+
predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
|
|
40
|
+
prefLabel: 'Chris Giles',
|
|
41
|
+
apiUrl: '',
|
|
42
|
+
directType: '',
|
|
43
|
+
type: '',
|
|
44
|
+
types: [],
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
mainImage: {
|
|
48
|
+
id: '',
|
|
49
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
50
|
+
title: '',
|
|
51
|
+
description: '',
|
|
52
|
+
binaryUrl: 'https://cloudfront.com/main-image.png',
|
|
53
|
+
},
|
|
54
|
+
leadImages: [],
|
|
55
|
+
accessLevel: 'premium',
|
|
56
|
+
embeds: [],
|
|
57
|
+
publishedDate: '',
|
|
58
|
+
firstPublishedDate: '',
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=capiObject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capiObject.js","sourceRoot":"","sources":["../../src/fixtures/capiObject.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,EAAE,EAAE,EAAE;IACN,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,4DAA4D;IACnE,UAAU,EAAE,EAAE;IACd,MAAM,EAAE,uBAAuB;IAC/B,OAAO,EAAE,EAAE;IACX,WAAW,EAAE;QACX;YACE,MAAM,EAAE,+DAA+D;YACvE,UAAU,EAAE,kCAAkC;YAC9C,EAAE,EAAE,+DAA+D;YACnE,SAAS,EAAE,6CAA6C;YACxD,SAAS,EAAE,qBAAqB;YAChC,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,uCAAuC;gBACvC,4CAA4C;gBAC5C,kCAAkC;aACnC;SACF;QACD;YACE,MAAM,EAAE,+DAA+D;YACvE,UAAU,EAAE,kCAAkC;YAC9C,EAAE,EAAE,+DAA+D;YACnE,SAAS,EAAE,0CAA0C;YACrD,SAAS,EAAE,sBAAsB;YACjC,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,uCAAuC;gBACvC,4CAA4C;gBAC5C,kCAAkC;aACnC;SACF;QACD;YACE,EAAE,EAAE,+DAA+D;YACnE,SAAS,EAAE,iDAAiD;YAC5D,SAAS,EAAE,aAAa;YACxB,MAAM,EAAE,EAAE;YACV,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,EAAE;SACV;KACF;IACD,SAAS,EAAE;QACT,EAAE,EAAE,EAAE;QACN,IAAI,EAAE,0CAAmD;QACzD,KAAK,EAAE,EAAE;QACT,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,uCAAuC;KACnD;IACD,UAAU,EAAE,EAAE;IACd,WAAW,EAAE,SAAkB;IAC/B,MAAM,EAAE,EAAE;IACV,aAAa,EAAE,EAAE;IACjB,kBAAkB,EAAE,EAAE;CACvB,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const capiPerson =
|
|
2
|
+
// http://api.ft.com/people/4076f4fd-723b-4ce5-9934-fb29416554fa
|
|
3
|
+
{
|
|
4
|
+
id: 'http://api.ft.com/things/4076f4fd-723b-4ce5-9934-fb29416554fa',
|
|
5
|
+
apiUrl: 'http://api.ft.com/people/4076f4fd-723b-4ce5-9934-fb29416554fa',
|
|
6
|
+
prefLabel: 'Robert Shrimsley',
|
|
7
|
+
types: [
|
|
8
|
+
'http://www.ft.com/ontology/core/Thing',
|
|
9
|
+
'http://www.ft.com/ontology/concept/Concept',
|
|
10
|
+
'http://www.ft.com/ontology/person/Person',
|
|
11
|
+
],
|
|
12
|
+
directType: 'http://www.ft.com/ontology/person/Person',
|
|
13
|
+
labels: ['Robert Shrimsley', "Robert Shrimsley's Notebook"],
|
|
14
|
+
memberships: [
|
|
15
|
+
{
|
|
16
|
+
title: 'UK chief political commentator and UK editor at large',
|
|
17
|
+
types: [
|
|
18
|
+
'http://www.ft.com/ontology/core/Thing',
|
|
19
|
+
'http://www.ft.com/ontology/concept/Concept',
|
|
20
|
+
'http://www.ft.com/ontology/organisation/Membership',
|
|
21
|
+
],
|
|
22
|
+
directType: 'http://www.ft.com/ontology/organisation/Membership',
|
|
23
|
+
organisation: {
|
|
24
|
+
id: 'http://api.ft.com/things/7bcfe07b-0fb1-49ce-a5fa-e51d5c01c3e0',
|
|
25
|
+
apiUrl: 'http://api.ft.com/organisations/7bcfe07b-0fb1-49ce-a5fa-e51d5c01c3e0',
|
|
26
|
+
prefLabel: 'Financial Times',
|
|
27
|
+
types: [
|
|
28
|
+
'http://www.ft.com/ontology/core/Thing',
|
|
29
|
+
'http://www.ft.com/ontology/concept/Concept',
|
|
30
|
+
'http://www.ft.com/ontology/organisation/Organisation',
|
|
31
|
+
],
|
|
32
|
+
directType: 'http://www.ft.com/ontology/organisation/Organisation',
|
|
33
|
+
},
|
|
34
|
+
roles: [
|
|
35
|
+
{
|
|
36
|
+
id: 'http://api.ft.com/things/7ef75a6a-b6bf-4eb7-a1da-03e0acabef1b',
|
|
37
|
+
apiUrl: 'http://api.ft.com/things/7ef75a6a-b6bf-4eb7-a1da-03e0acabef1b',
|
|
38
|
+
prefLabel: 'Columnist',
|
|
39
|
+
types: [
|
|
40
|
+
'http://www.ft.com/ontology/core/Thing',
|
|
41
|
+
'http://www.ft.com/ontology/concept/Concept',
|
|
42
|
+
'http://www.ft.com/ontology/MembershipRole',
|
|
43
|
+
],
|
|
44
|
+
directType: 'http://www.ft.com/ontology/MembershipRole',
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
emailAddress: 'robert.shrimsley@ft.com',
|
|
50
|
+
twitterHandle: '@robertshrimsley',
|
|
51
|
+
descriptionXML: '<p>Robert Shrimsley is UK chief political commentator and UK editor at large of the Financial Times. He writes a weekly column on British politics and for the FT weekend magazine. Before this, he served as the FT’s chief political correspondent, news editor, managing editor of FT.com and <!--StartFragment--><span style="color: rgb(0, 0, 0);background-color: rgb(255, 255, 255);float: none;">editorial director</span><!--EndFragment-->.</p>',
|
|
52
|
+
_imageUrl: 'https://d1e00ek4ebabms.cloudfront.net/production/uploaded-files/fthead-v1_robert-shrimsley-cc467908-15d6-474d-94d8-171594ceabb9.png',
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=capiPerson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capiPerson.js","sourceRoot":"","sources":["../../src/fixtures/capiPerson.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU;AACrB,gEAAgE;AAChE;IACE,EAAE,EAAE,+DAA+D;IACnE,MAAM,EAAE,+DAA+D;IACvE,SAAS,EAAE,kBAAkB;IAC7B,KAAK,EAAE;QACL,uCAAuC;QACvC,4CAA4C;QAC5C,0CAA0C;KAC3C;IACD,UAAU,EAAE,0CAA0C;IACtD,MAAM,EAAE,CAAC,kBAAkB,EAAE,6BAA6B,CAAC;IAC3D,WAAW,EAAE;QACX;YACE,KAAK,EAAE,uDAAuD;YAC9D,KAAK,EAAE;gBACL,uCAAuC;gBACvC,4CAA4C;gBAC5C,oDAAoD;aACrD;YACD,UAAU,EAAE,oDAAoD;YAChE,YAAY,EAAE;gBACZ,EAAE,EAAE,+DAA+D;gBACnE,MAAM,EACJ,sEAAsE;gBACxE,SAAS,EAAE,iBAAiB;gBAC5B,KAAK,EAAE;oBACL,uCAAuC;oBACvC,4CAA4C;oBAC5C,sDAAsD;iBACvD;gBACD,UAAU,EAAE,sDAAsD;aACnE;YACD,KAAK,EAAE;gBACL;oBACE,EAAE,EAAE,+DAA+D;oBACnE,MAAM,EACJ,+DAA+D;oBACjE,SAAS,EAAE,WAAW;oBACtB,KAAK,EAAE;wBACL,uCAAuC;wBACvC,4CAA4C;wBAC5C,2CAA2C;qBAC5C;oBACD,UAAU,EAAE,2CAA2C;iBACxD;aACF;SACF;KACF;IACD,YAAY,EAAE,yBAAyB;IACvC,aAAa,EAAE,kBAAkB;IACjC,cAAc,EACZ,2bAA2b;IAC7b,SAAS,EACP,qIAAqI;CACxI,CAAA"}
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
import type { InternalContent, Annotation } from '../types/internal-content.js';
|
|
2
1
|
export declare function uuidFromUrl(url: string): string;
|
|
3
|
-
export declare function isOpinion(content: InternalContent): boolean;
|
|
4
|
-
export declare function getAuthorUrlMapping(annotations: Annotation[]): Map<string, string>;
|
|
5
|
-
export declare function getAuthor(content: InternalContent): Annotation | undefined;
|
|
6
|
-
export declare function isColumn(content: InternalContent): boolean;
|
|
7
|
-
export declare function getDisplayConcept(content: InternalContent): Annotation | undefined;
|
|
8
|
-
export declare function getBrandConcept(content: InternalContent): Annotation | undefined;
|
|
9
|
-
export declare function isPodcast(content: InternalContent): boolean;
|
|
10
|
-
export declare function isEditorsChoice(content: InternalContent): boolean;
|
|
11
|
-
export declare function isExclusive(content: InternalContent): boolean;
|
|
12
|
-
export declare function isScoop(content: InternalContent): boolean;
|
package/lib/helpers/metadata.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import conceptIds from '@financial-times/n-concept-ids';
|
|
2
1
|
export function uuidFromUrl(url) {
|
|
3
2
|
const match = url.match(/(........-....-....-....-............)/);
|
|
4
3
|
if (match === null) {
|
|
@@ -6,55 +5,4 @@ export function uuidFromUrl(url) {
|
|
|
6
5
|
}
|
|
7
6
|
return match[1] || '';
|
|
8
7
|
}
|
|
9
|
-
export function isOpinion(content) {
|
|
10
|
-
return content.annotations.some((annotation) => annotation.id.endsWith(conceptIds.genre.opinion));
|
|
11
|
-
}
|
|
12
|
-
function isAuthor(annotation) {
|
|
13
|
-
return (annotation.predicate === 'http://www.ft.com/ontology/annotation/hasAuthor');
|
|
14
|
-
}
|
|
15
|
-
function createStreamLink(streamUuid) {
|
|
16
|
-
return `https://www.ft.com/stream/uuid/${streamUuid}`;
|
|
17
|
-
}
|
|
18
|
-
export function getAuthorUrlMapping(annotations) {
|
|
19
|
-
const authorAnnotations = getAuthorAnnotations(annotations);
|
|
20
|
-
return authorAnnotations.reduce((mapping, author) => {
|
|
21
|
-
if (author.prefLabel) {
|
|
22
|
-
const uuid = uuidFromUrl(author.id);
|
|
23
|
-
mapping.set(author.prefLabel, createStreamLink(uuid));
|
|
24
|
-
}
|
|
25
|
-
return mapping;
|
|
26
|
-
}, new Map);
|
|
27
|
-
}
|
|
28
|
-
function getAuthorAnnotations(annotations) {
|
|
29
|
-
return annotations.filter(isAuthor);
|
|
30
|
-
}
|
|
31
|
-
export function getAuthor(content) {
|
|
32
|
-
return content.annotations.find((annotation) => isAuthor(annotation));
|
|
33
|
-
}
|
|
34
|
-
export function isColumn(content) {
|
|
35
|
-
return isOpinion(content) && !!getAuthor(content);
|
|
36
|
-
}
|
|
37
|
-
export function getDisplayConcept(content) {
|
|
38
|
-
return content.annotations.find((annotation) => annotation.predicate === 'http://www.ft.com/ontology/hasDisplayTag');
|
|
39
|
-
}
|
|
40
|
-
export function getBrandConcept(content) {
|
|
41
|
-
return content.annotations.find((annotation) => annotation.predicate ===
|
|
42
|
-
'http://www.ft.com/ontology/classification/isClassifiedBy' &&
|
|
43
|
-
annotation.directType === 'http://www.ft.com/ontology/product/Brand');
|
|
44
|
-
}
|
|
45
|
-
export function isPodcast(content) {
|
|
46
|
-
return content.types.includes('http://www.ft.com/ontology/content/Audio');
|
|
47
|
-
}
|
|
48
|
-
export function isEditorsChoice(content) {
|
|
49
|
-
var _a;
|
|
50
|
-
return !!((_a = content.standout) === null || _a === void 0 ? void 0 : _a.editorsChoice);
|
|
51
|
-
}
|
|
52
|
-
export function isExclusive(content) {
|
|
53
|
-
var _a;
|
|
54
|
-
return !!((_a = content.standout) === null || _a === void 0 ? void 0 : _a.exclusive);
|
|
55
|
-
}
|
|
56
|
-
export function isScoop(content) {
|
|
57
|
-
var _a;
|
|
58
|
-
return !!((_a = content.standout) === null || _a === void 0 ? void 0 : _a.scoop);
|
|
59
|
-
}
|
|
60
8
|
//# sourceMappingURL=metadata.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/helpers/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/helpers/metadata.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAA;IAEjE,IAAI,KAAK,KAAK,IAAI,EAAE;QAClB,OAAO,EAAE,CAAA;KACV;IAED,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;AACvB,CAAC"}
|