@financial-times/cp-content-pipeline-schema 0.2.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 (100) hide show
  1. package/.toolkitrc.yml +12 -0
  2. package/CHANGELOG.md +72 -0
  3. package/jest.config.js +3 -0
  4. package/lib/concept.d.ts +7 -0
  5. package/lib/concept.js +39 -0
  6. package/lib/concept.js.map +1 -0
  7. package/lib/constants/contentTypes.d.ts +2 -0
  8. package/lib/constants/contentTypes.js +3 -0
  9. package/lib/constants/contentTypes.js.map +1 -0
  10. package/lib/content.d.ts +55 -0
  11. package/lib/content.js +133 -0
  12. package/lib/content.js.map +1 -0
  13. package/lib/content.test.d.ts +1 -0
  14. package/lib/content.test.js +149 -0
  15. package/lib/content.test.js.map +1 -0
  16. package/lib/datasources/capi.d.ts +10 -0
  17. package/lib/datasources/capi.js +28 -0
  18. package/lib/datasources/capi.js.map +1 -0
  19. package/lib/datasources/index.d.ts +9 -0
  20. package/lib/datasources/index.js +9 -0
  21. package/lib/datasources/index.js.map +1 -0
  22. package/lib/datasources/origami-image.d.ts +8 -0
  23. package/lib/datasources/origami-image.js +11 -0
  24. package/lib/datasources/origami-image.js.map +1 -0
  25. package/lib/datasources/url-management.d.ts +11 -0
  26. package/lib/datasources/url-management.js +40 -0
  27. package/lib/datasources/url-management.js.map +1 -0
  28. package/lib/datasources/url-management.test.d.ts +1 -0
  29. package/lib/datasources/url-management.test.js +69 -0
  30. package/lib/datasources/url-management.test.js.map +1 -0
  31. package/lib/helpers/byline.d.ts +1 -0
  32. package/lib/helpers/byline.js +5 -0
  33. package/lib/helpers/byline.js.map +1 -0
  34. package/lib/helpers/imageService.d.ts +8 -0
  35. package/lib/helpers/imageService.js +13 -0
  36. package/lib/helpers/imageService.js.map +1 -0
  37. package/lib/helpers/metadata.d.ts +12 -0
  38. package/lib/helpers/metadata.js +60 -0
  39. package/lib/helpers/metadata.js.map +1 -0
  40. package/lib/helpers/syntaxTree.d.ts +23 -0
  41. package/lib/helpers/syntaxTree.js +23 -0
  42. package/lib/helpers/syntaxTree.js.map +1 -0
  43. package/lib/image.d.ts +25 -0
  44. package/lib/image.js +123 -0
  45. package/lib/image.js.map +1 -0
  46. package/lib/image.test.d.ts +1 -0
  47. package/lib/image.test.js +235 -0
  48. package/lib/image.test.js.map +1 -0
  49. package/lib/index.d.ts +8 -0
  50. package/lib/index.js +69 -0
  51. package/lib/index.js.map +1 -0
  52. package/lib/picture.d.ts +22 -0
  53. package/lib/picture.js +80 -0
  54. package/lib/picture.js.map +1 -0
  55. package/lib/richText.d.ts +14 -0
  56. package/lib/richText.js +48 -0
  57. package/lib/richText.js.map +1 -0
  58. package/lib/tags.d.ts +13 -0
  59. package/lib/tags.js +178 -0
  60. package/lib/tags.js.map +1 -0
  61. package/lib/topper.d.ts +7 -0
  62. package/lib/topper.js +196 -0
  63. package/lib/topper.js.map +1 -0
  64. package/lib/unified-plugins/extract-references.d.ts +7 -0
  65. package/lib/unified-plugins/extract-references.js +36 -0
  66. package/lib/unified-plugins/extract-references.js.map +1 -0
  67. package/lib/unified-plugins/map-to-abstract-types.d.ts +4 -0
  68. package/lib/unified-plugins/map-to-abstract-types.js +17 -0
  69. package/lib/unified-plugins/map-to-abstract-types.js.map +1 -0
  70. package/package.json +43 -0
  71. package/src/__snapshots__/content.test.ts.snap +118 -0
  72. package/src/concept.ts +58 -0
  73. package/src/constants/contentTypes.ts +4 -0
  74. package/src/content.test.ts +163 -0
  75. package/src/content.ts +146 -0
  76. package/src/datasources/capi.ts +28 -0
  77. package/src/datasources/index.ts +11 -0
  78. package/src/datasources/origami-image.ts +10 -0
  79. package/src/datasources/url-management.test.ts +92 -0
  80. package/src/datasources/url-management.ts +65 -0
  81. package/src/helpers/byline.ts +4 -0
  82. package/src/helpers/imageService.ts +31 -0
  83. package/src/helpers/metadata.ts +88 -0
  84. package/src/helpers/syntaxTree.ts +26 -0
  85. package/src/image.test.ts +339 -0
  86. package/src/image.ts +154 -0
  87. package/src/index.ts +87 -0
  88. package/src/picture.ts +98 -0
  89. package/src/richText.ts +62 -0
  90. package/src/tags.ts +237 -0
  91. package/src/topper.ts +228 -0
  92. package/src/types/internal-content.d.ts +78 -0
  93. package/src/types/n-concept-ids.d.ts +16 -0
  94. package/src/types/n-display-metadata.d.ts +1 -0
  95. package/src/types/n-url-management-api-read-client.d.ts +11 -0
  96. package/src/types/next-metrics.d.ts +1 -0
  97. package/src/unified-plugins/extract-references.ts +50 -0
  98. package/src/unified-plugins/map-to-abstract-types.ts +21 -0
  99. package/tsconfig.json +10 -0
  100. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,40 @@
1
+ import { DataSource } from 'apollo-datasource';
2
+ import { InMemoryLRUCache, PrefixingKeyValueCache, } from 'apollo-server-caching';
3
+ import * as nUrlManagementApiReadClient from '@financial-times/n-url-management-api-read-client';
4
+ import metrics from 'next-metrics';
5
+ const CACHE_PREFIX = 'nurlmgmtapi';
6
+ const DEFAULT_TTL_IN_SECONDS = 60 * 60; // one hour
7
+ export class URLManagementDataSource extends DataSource {
8
+ constructor() {
9
+ super();
10
+ this.memoizedResults = new Map();
11
+ if (!URLManagementDataSource.clientInitialised) {
12
+ nUrlManagementApiReadClient.init({ metrics });
13
+ URLManagementDataSource.clientInitialised = true;
14
+ }
15
+ }
16
+ initialize({ context, cache = new InMemoryLRUCache(), }) {
17
+ this.context = context;
18
+ this.cache = new PrefixingKeyValueCache(cache, CACHE_PREFIX);
19
+ }
20
+ async get(fromURL, ttl = DEFAULT_TTL_IN_SECONDS) {
21
+ const getVanity = async () => {
22
+ const fromCache = await this.cache.get(fromURL);
23
+ if (fromCache) {
24
+ return fromCache;
25
+ }
26
+ const fromDynamoDB = await nUrlManagementApiReadClient.get(fromURL);
27
+ await this.cache.set(fromURL, fromDynamoDB.toURL, { ttl });
28
+ return fromDynamoDB.toURL;
29
+ };
30
+ let promise = this.memoizedResults.get(fromURL);
31
+ if (promise) {
32
+ return promise;
33
+ }
34
+ promise = getVanity();
35
+ this.memoizedResults.set(fromURL, promise);
36
+ return promise;
37
+ }
38
+ }
39
+ URLManagementDataSource.clientInitialised = false;
40
+ //# sourceMappingURL=url-management.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-management.js","sourceRoot":"","sources":["../../src/datasources/url-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAoB,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAEL,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,2BAA2B,MAAM,mDAAmD,CAAA;AAEhG,OAAO,OAAO,MAAM,cAAc,CAAA;AAElC,MAAM,YAAY,GAAG,aAAa,CAAA;AAClC,MAAM,sBAAsB,GAAG,EAAE,GAAG,EAAE,CAAA,CAAC,WAAW;AAElD,MAAM,OAAO,uBAAwB,SAAQ,UAAU;IAMrD;QACE,KAAK,EAAE,CAAA;QAJT,oBAAe,GAAG,IAAI,GAAG,EAA2B,CAAA;QAMlD,IAAI,CAAC,uBAAuB,CAAC,iBAAiB,EAAE;YAC9C,2BAA2B,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;YAC7C,uBAAuB,CAAC,iBAAiB,GAAG,IAAI,CAAA;SACjD;IACH,CAAC;IAEQ,UAAU,CAAC,EAClB,OAAO,EACP,KAAK,GAAG,IAAI,gBAAgB,EAAE,GACJ;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,sBAAsB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IAC9D,CAAC;IAED,KAAK,CAAC,GAAG,CACP,OAAe,EACf,MAAc,sBAAsB;QAEpC,MAAM,SAAS,GAAG,KAAK,IAAqB,EAAE;YAC5C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC/C,IAAI,SAAS,EAAE;gBACb,OAAO,SAAS,CAAA;aACjB;YAED,MAAM,YAAY,GAChB,MAAM,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAChD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1D,OAAO,YAAY,CAAC,KAAK,CAAA;QAC3B,CAAC,CAAA;QAED,IAAI,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAE/C,IAAI,OAAO,EAAE;YACX,OAAO,OAAO,CAAA;SACf;QAED,OAAO,GAAG,SAAS,EAAE,CAAA;QACrB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAE1C,OAAO,OAAO,CAAA;IAChB,CAAC;;AA5CM,yCAAiB,GAAG,KAAK,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,69 @@
1
+ // HACK:AG:26-09-2022 hack for jest to support non-ESM module
2
+ // see https://github.com/facebook/jest/issues/10025
3
+ jest.unstable_mockModule('@financial-times/n-url-management-api-read-client', () => ({
4
+ get: jest.fn(),
5
+ init: jest.fn(),
6
+ }));
7
+ const urlmgmtimport = await import('./url-management.js');
8
+ const URLManagementDataSource = urlmgmtimport.URLManagementDataSource;
9
+ const nUrlManagementApiReadClient = await import('@financial-times/n-url-management-api-read-client');
10
+ import { InMemoryLRUCache } from 'apollo-server-caching';
11
+ import { jest } from '@jest/globals';
12
+ const getMock = nUrlManagementApiReadClient.get;
13
+ describe('URL management data source', () => {
14
+ beforeEach(() => {
15
+ jest.resetAllMocks();
16
+ });
17
+ it('only initialises the client library once', async () => {
18
+ new URLManagementDataSource();
19
+ expect(nUrlManagementApiReadClient.init).toHaveBeenCalledTimes(1);
20
+ new URLManagementDataSource();
21
+ expect(nUrlManagementApiReadClient.init).toHaveBeenCalledTimes(1);
22
+ });
23
+ it('gets a vanity URL from the dynamodb database', async () => {
24
+ getMock.mockResolvedValue({
25
+ toURL: 'vanity.url',
26
+ });
27
+ const dataSource = new URLManagementDataSource();
28
+ dataSource.initialize({ context: null, cache: new InMemoryLRUCache() });
29
+ const vanity = await dataSource.get('original.url');
30
+ expect(vanity).toEqual('vanity.url');
31
+ expect(nUrlManagementApiReadClient.get).toHaveBeenCalled();
32
+ });
33
+ it('gets subsequent requests from the cache', async () => {
34
+ getMock.mockImplementation((fromUrl) => Promise.resolve({ toURL: `${fromUrl}.vanity` }));
35
+ const dataSource = new URLManagementDataSource();
36
+ const cache = new InMemoryLRUCache();
37
+ dataSource.initialize({ context: null, cache });
38
+ const firstRequest = await dataSource.get('original.url');
39
+ expect(firstRequest).toEqual('original.url.vanity');
40
+ expect(await cache.getTotalSize()).toEqual(19); // string length of original.url.vanity
41
+ const secondRequest = await dataSource.get('original.url');
42
+ expect(secondRequest).toEqual('original.url.vanity');
43
+ expect(nUrlManagementApiReadClient.get).toHaveBeenCalledTimes(1);
44
+ expect(await cache.getTotalSize()).toEqual(19);
45
+ const differentRequest = await dataSource.get('different.url');
46
+ expect(differentRequest).toEqual('different.url.vanity');
47
+ expect(nUrlManagementApiReadClient.get).toHaveBeenCalledTimes(2);
48
+ expect(await cache.getTotalSize()).toEqual(39);
49
+ });
50
+ it('memoizes requests made in the same query', async () => {
51
+ getMock.mockImplementation((fromUrl) => Promise.resolve({ toURL: `${fromUrl}.vanity` }));
52
+ const dataSource = new URLManagementDataSource();
53
+ const cache = new InMemoryLRUCache();
54
+ dataSource.initialize({ context: null, cache });
55
+ const firstRequest = dataSource.get('original.url');
56
+ const secondRequest = dataSource.get('original.url');
57
+ const differentRequest = dataSource.get('different.url');
58
+ const [first, second, different] = await Promise.all([
59
+ firstRequest,
60
+ secondRequest,
61
+ differentRequest,
62
+ ]);
63
+ expect(first).toEqual('original.url.vanity');
64
+ expect(second).toEqual('original.url.vanity');
65
+ expect(different).toEqual('different.url.vanity');
66
+ expect(nUrlManagementApiReadClient.get).toHaveBeenCalledTimes(2);
67
+ });
68
+ });
69
+ //# sourceMappingURL=url-management.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-management.test.js","sourceRoot":"","sources":["../../src/datasources/url-management.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function splitBylineByName(byline: string, names: string[]): string[];
@@ -0,0 +1,5 @@
1
+ export function splitBylineByName(byline, names) {
2
+ const regex = new RegExp(`(${names.join('|')})`, 'ig');
3
+ return byline.split(regex).filter((string) => string !== '');
4
+ }
5
+ //# sourceMappingURL=byline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byline.js","sourceRoot":"","sources":["../../src/helpers/byline.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,KAAe;IAC/D,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACtD,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,CAAA;AAC9D,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare type ImageServiceUrlArguments = {
2
+ url: string;
3
+ systemCode: string;
4
+ width?: number;
5
+ id?: string;
6
+ dpr?: number;
7
+ };
8
+ export default function imageServiceUrl({ url, id, systemCode, width, dpr, }: ImageServiceUrlArguments): string;
@@ -0,0 +1,13 @@
1
+ const DEFAULT_IMAGE_SERVICE_WIDTH = 700;
2
+ const DEFAULT_IMAGE_SERVICE_DPR = 1;
3
+ export default function imageServiceUrl({ url, id, systemCode, width = DEFAULT_IMAGE_SERVICE_WIDTH, dpr = DEFAULT_IMAGE_SERVICE_DPR, }) {
4
+ const imageSource = encodeURIComponent(id ? `ftcms:${id}` : url);
5
+ const imageServiceUrl = new URL(`https://www.ft.com/__origami/service/image/v2/images/raw/${imageSource}`);
6
+ imageServiceUrl.searchParams.set('source', systemCode);
7
+ imageServiceUrl.searchParams.set('fit', 'scale-down');
8
+ imageServiceUrl.searchParams.set('quality', 'highest');
9
+ imageServiceUrl.searchParams.set('width', width.toString());
10
+ imageServiceUrl.searchParams.set('dpr', dpr.toString());
11
+ return imageServiceUrl.href;
12
+ }
13
+ //# sourceMappingURL=imageService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageService.js","sourceRoot":"","sources":["../../src/helpers/imageService.ts"],"names":[],"mappings":"AAAA,MAAM,2BAA2B,GAAG,GAAG,CAAA;AACvC,MAAM,yBAAyB,GAAG,CAAC,CAAA;AAUnC,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,GAAG,EACH,EAAE,EACF,UAAU,EACV,KAAK,GAAG,2BAA2B,EACnC,GAAG,GAAG,yBAAyB,GACN;IACzB,MAAM,WAAW,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAChE,MAAM,eAAe,GAAG,IAAI,GAAG,CAC7B,4DAA4D,WAAW,EAAE,CAC1E,CAAA;IAED,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACtD,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IACrD,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IACtD,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC3D,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEvD,OAAO,eAAe,CAAC,IAAI,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { InternalContent, Annotation } from '../types/internal-content.js';
2
+ 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;
@@ -0,0 +1,60 @@
1
+ import conceptIds from '@financial-times/n-concept-ids';
2
+ export function uuidFromUrl(url) {
3
+ const match = url.match(/(........-....-....-....-............)/);
4
+ if (match === null) {
5
+ return '';
6
+ }
7
+ return match[1] || '';
8
+ }
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
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/helpers/metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export declare function buildUrlTree(urlMapping: Map<string, string>, parts: string[]): {
2
+ tree: {
3
+ type: string;
4
+ children: ({
5
+ type: string;
6
+ tagName: string;
7
+ properties: {
8
+ href: string;
9
+ };
10
+ children: {
11
+ type: string;
12
+ value: string;
13
+ }[];
14
+ value?: undefined;
15
+ } | {
16
+ type: string;
17
+ value: string;
18
+ tagName?: undefined;
19
+ properties?: undefined;
20
+ children?: undefined;
21
+ })[];
22
+ };
23
+ };
@@ -0,0 +1,23 @@
1
+ export function buildUrlTree(urlMapping, parts) {
2
+ const children = parts.map((part) => {
3
+ const url = urlMapping.get(part);
4
+ if (url) {
5
+ return {
6
+ type: 'element',
7
+ tagName: 'Link',
8
+ properties: { href: url },
9
+ children: [{ type: 'text', value: part }],
10
+ };
11
+ }
12
+ else {
13
+ return {
14
+ type: 'text',
15
+ value: part,
16
+ };
17
+ }
18
+ });
19
+ return {
20
+ tree: { type: 'root', children },
21
+ };
22
+ }
23
+ //# sourceMappingURL=syntaxTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syntaxTree.js","sourceRoot":"","sources":["../../src/helpers/syntaxTree.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAC1B,UAA+B,EAC/B,KAAe;IAEf,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAClC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEhC,IAAI,GAAG,EAAE;YACP,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE;gBACzB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;aAC1C,CAAA;SACF;aAAM;YACL,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,IAAI;aACZ,CAAA;SACF;IACH,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;KACjC,CAAA;AACH,CAAC"}
package/lib/image.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { IResolvers } from '@graphql-tools/utils';
2
+ import type { DataSources } from './datasources/index.js';
3
+ import type { Image } from './types/internal-content.js';
4
+ declare type ImageDimensions = {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ export declare type ImageSourceArgs = {
9
+ width: number;
10
+ maxDpr?: number;
11
+ };
12
+ export declare type DisplayWidthArgs = {
13
+ width?: number;
14
+ };
15
+ export declare const ImageType: {
16
+ readonly Image: "http://www.ft.com/ontology/content/Image";
17
+ readonly Graphic: "http://www.ft.com/ontology/content/Graphic";
18
+ };
19
+ export declare const typeDef: import("graphql").DocumentNode;
20
+ export declare function getImageDimensions(image: Image, dataSources: DataSources): Promise<ImageDimensions>;
21
+ export declare const resolvers: IResolvers<unknown, {
22
+ systemCode: string;
23
+ dataSources: DataSources;
24
+ }, never>;
25
+ export {};
package/lib/image.js ADDED
@@ -0,0 +1,123 @@
1
+ import { gql } from 'graphql-tag';
2
+ import imageServiceUrl from './helpers/imageService.js';
3
+ import { uuidFromUrl } from './helpers/metadata.js';
4
+ export const ImageType = {
5
+ Image: 'http://www.ft.com/ontology/content/Image',
6
+ Graphic: 'http://www.ft.com/ontology/content/Graphic',
7
+ };
8
+ export const typeDef = gql `
9
+ enum ImageType {
10
+ Image
11
+ Graphic
12
+ }
13
+
14
+ type ImageSource {
15
+ url: String!
16
+ width: Int
17
+ dpr: Int
18
+ }
19
+
20
+ type Image {
21
+ type: ImageType
22
+ sources(width: Int, maxDpr: Int): [ImageSource!]!
23
+ binaryUrl: String
24
+ originalWidth: Int
25
+ originalHeight: Int
26
+ copyright: String
27
+ minDisplayWidth(
28
+ """
29
+ min-width (in pixels) for this image to be displayed.
30
+ Overrides any value coming from the Content API
31
+ """
32
+ width: Int
33
+ ): String
34
+ maxDisplayWidth(width: Int): String
35
+ caption: String!
36
+ alt: String!
37
+ }
38
+ `;
39
+ export async function getImageDimensions(image, dataSources) {
40
+ if (image.pixelWidth && image.pixelHeight) {
41
+ return { width: image.pixelWidth, height: image.pixelHeight };
42
+ }
43
+ const binaryUrl = image.binaryUrl;
44
+ const imageMetadata = await dataSources.origami.getImageMetadata(binaryUrl);
45
+ return imageMetadata;
46
+ }
47
+ export const resolvers = {
48
+ Image: {
49
+ async sources(parent, args, context) {
50
+ const id = uuidFromUrl(parent.id);
51
+ if (!id) {
52
+ throw new Error(`${parent.id} is not a valid Content API Image ID`);
53
+ }
54
+ const requestedWidth = args.width || 700;
55
+ let maxAllowedWidth = requestedWidth;
56
+ let maxDpr = 1;
57
+ try {
58
+ const dimensions = await getImageDimensions(parent, context.dataSources);
59
+ maxAllowedWidth = Math.min(requestedWidth, dimensions.width);
60
+ maxDpr = Math.min(args.maxDpr || Infinity, Math.floor(dimensions.width / maxAllowedWidth));
61
+ }
62
+ catch (err) {
63
+ //TODO: log error
64
+ }
65
+ const resolutions = [...Array(maxDpr + 1).keys()].slice(1);
66
+ return resolutions.map((dpr) => ({
67
+ url: imageServiceUrl({
68
+ id,
69
+ url: parent.binaryUrl,
70
+ systemCode: context.systemCode,
71
+ width: maxAllowedWidth,
72
+ dpr,
73
+ }),
74
+ width: maxAllowedWidth,
75
+ dpr,
76
+ }));
77
+ },
78
+ async originalWidth(parent, args, context) {
79
+ try {
80
+ const dimensions = await getImageDimensions(parent, context.dataSources);
81
+ return dimensions.width;
82
+ }
83
+ catch (err) {
84
+ //TODO: log error
85
+ return null;
86
+ }
87
+ },
88
+ async originalHeight(parent, args, context) {
89
+ try {
90
+ const dimensions = await getImageDimensions(parent, context.dataSources);
91
+ return dimensions.height;
92
+ }
93
+ catch (err) {
94
+ //TODO: log error
95
+ return null;
96
+ }
97
+ },
98
+ copyright(parent) {
99
+ var _a;
100
+ return (_a = parent.copyright) === null || _a === void 0 ? void 0 : _a.notice;
101
+ },
102
+ minDisplayWidth(parent, args) {
103
+ return args.width ? `${args.width}px` : parent.minDisplayWidth;
104
+ },
105
+ maxDisplayWidth(parent, args) {
106
+ return args.width ? `${args.width}px` : parent.maxDisplayWidth;
107
+ },
108
+ caption(parent) {
109
+ var _a;
110
+ const elements = [parent.title, (_a = parent.copyright) === null || _a === void 0 ? void 0 : _a.notice].filter(Boolean);
111
+ return elements.length && elements.join(' ');
112
+ },
113
+ alt(parent) {
114
+ const fallback = parent.type === ImageType.Graphic ? 'A graphic with no description' : '';
115
+ return (parent.description || fallback).replace(/"/g, '&quot;');
116
+ },
117
+ },
118
+ ImageType: {
119
+ Image: ImageType.Image,
120
+ Graphic: ImageType.Graphic,
121
+ },
122
+ };
123
+ //# sourceMappingURL=image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};