Skip to content

feat: add ClipSet to schema #90

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 65 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ type BodyBlock =
| Tweet
| Video
| YoutubeVideo
| ClipSet
```

`BodyBlock` nodes are the only things that are valid as the top level of a `Body`.
Expand Down Expand Up @@ -543,8 +544,6 @@ interface Video extends Node {

The `title` can be obtained by fetching the Video from the content API.

TODO: Figure out how Clips work, how they are different?

### `YoutubeVideo`

```ts
Expand All @@ -554,8 +553,72 @@ interface YoutubeVideo extends Node {
}
```


**YoutubeVideo** represents a video referenced by a Youtube URL.

### `ClipSet`

```ts
interface ClipSet extends Node {
type: "clip-set"
id: string
autoplay: boolean
loop: boolean
muted: boolean
layoutWidth: 'in-line' | 'mid-grid' | 'full-grid'
external noAudio: boolean
external caption: string
external credits: string
external description: string
external displayTitle: string
external systemTitle: string
external source: string
external contentWarning: string[]
external publishedDate: string
external subtitle: string
external clips: Clip[]
external accessibility: ClipAccessibility
}
```

```ts
type Clip = {
id: string
format: 'standard-inline' | 'mobile'
dataSource: ClipSource[]
poster: string
}
```

```ts
type ClipSource = {
audioCodec: string
binaryUrl: string
duration: number
mediaType: string
pixelHeight: number
pixelWidth: number
videoCodec: string
}
```

```ts
type ClipCaption = {
mediaType?: string
url?: string
}
```
```ts
type ClipAccessibility = {
captions?: ClipCaption[]
transcript?: Body
}
```

**ClipSet** represents a short piece of possibly-looping video content for an article.

The external fields are derived from the separately published [ClipSet](https://api.ft.com/schemas/clip-set.json) and [Clip](https://api.ft.com/schemas/clip.json) objects in the Content API.

### `ScrollyBlock`

```ts
Expand Down
168 changes: 164 additions & 4 deletions content-tree.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export declare namespace ContentTree {
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo;
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo | ClipSet;
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
interface Node {
Expand Down Expand Up @@ -171,6 +171,49 @@ export declare namespace ContentTree {
type: "youtube-video";
url: string;
}
interface ClipSet extends Node {
type: "clip-set";
id: string;
autoplay: boolean;
loop: boolean;
muted: boolean;
layoutWidth: 'in-line' | 'mid-grid' | 'full-grid';
noAudio: boolean;
caption: string;
credits: string;
description: string;
displayTitle: string;
systemTitle: string;
source: string;
contentWarning: string[];
publishedDate: string;
subtitle: string;
clips: Clip[];
accessibility: ClipAccessibility;
}
type Clip = {
id: string;
format: 'standard-inline' | 'mobile';
dataSource: ClipSource[];
poster: string;
};
type ClipSource = {
audioCodec: string;
binaryUrl: string;
duration: number;
mediaType: string;
pixelHeight: number;
pixelWidth: number;
videoCodec: string;
};
type ClipCaption = {
mediaType?: string;
url?: string;
};
type ClipAccessibility = {
captions?: ClipCaption[];
transcript?: Body;
};
interface ScrollyBlock extends Parent {
type: "scrolly-block";
theme: "sans" | "serif";
Expand Down Expand Up @@ -272,7 +315,7 @@ export declare namespace ContentTree {
attributes: CustomCodeComponentAttributes;
}
namespace full {
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo;
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo | ClipSet;
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
interface Node {
Expand Down Expand Up @@ -444,6 +487,49 @@ export declare namespace ContentTree {
type: "youtube-video";
url: string;
}
interface ClipSet extends Node {
type: "clip-set";
id: string;
autoplay: boolean;
loop: boolean;
muted: boolean;
layoutWidth: 'in-line' | 'mid-grid' | 'full-grid';
noAudio: boolean;
caption: string;
credits: string;
description: string;
displayTitle: string;
systemTitle: string;
source: string;
contentWarning: string[];
publishedDate: string;
subtitle: string;
clips: Clip[];
accessibility: ClipAccessibility;
}
type Clip = {
id: string;
format: 'standard-inline' | 'mobile';
dataSource: ClipSource[];
poster: string;
};
type ClipSource = {
audioCodec: string;
binaryUrl: string;
duration: number;
mediaType: string;
pixelHeight: number;
pixelWidth: number;
videoCodec: string;
};
type ClipCaption = {
mediaType?: string;
url?: string;
};
type ClipAccessibility = {
captions?: ClipCaption[];
transcript?: Body;
};
interface ScrollyBlock extends Parent {
type: "scrolly-block";
theme: "sans" | "serif";
Expand Down Expand Up @@ -546,7 +632,7 @@ export declare namespace ContentTree {
}
}
namespace transit {
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo;
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo | ClipSet;
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
interface Node {
Expand Down Expand Up @@ -713,6 +799,37 @@ export declare namespace ContentTree {
type: "youtube-video";
url: string;
}
interface ClipSet extends Node {
type: "clip-set";
id: string;
autoplay: boolean;
loop: boolean;
muted: boolean;
layoutWidth: 'in-line' | 'mid-grid' | 'full-grid';
}
type Clip = {
id: string;
format: 'standard-inline' | 'mobile';
dataSource: ClipSource[];
poster: string;
};
type ClipSource = {
audioCodec: string;
binaryUrl: string;
duration: number;
mediaType: string;
pixelHeight: number;
pixelWidth: number;
videoCodec: string;
};
type ClipCaption = {
mediaType?: string;
url?: string;
};
type ClipAccessibility = {
captions?: ClipCaption[];
transcript?: Body;
};
interface ScrollyBlock extends Parent {
type: "scrolly-block";
theme: "sans" | "serif";
Expand Down Expand Up @@ -805,7 +922,7 @@ export declare namespace ContentTree {
}
}
namespace loose {
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo;
type BodyBlock = Paragraph | Heading | ImageSet | Flourish | BigNumber | CustomCodeComponent | Layout | List | Blockquote | Pullquote | ScrollyBlock | ThematicBreak | Table | Recommended | Tweet | Video | YoutubeVideo | ClipSet;
type LayoutWidth = "auto" | "in-line" | "inset-left" | "inset-right" | "full-bleed" | "full-grid" | "mid-grid" | "full-width";
type Phrasing = Text | Break | Strong | Emphasis | Strikethrough | Link;
interface Node {
Expand Down Expand Up @@ -977,6 +1094,49 @@ export declare namespace ContentTree {
type: "youtube-video";
url: string;
}
interface ClipSet extends Node {
type: "clip-set";
id: string;
autoplay: boolean;
loop: boolean;
muted: boolean;
layoutWidth: 'in-line' | 'mid-grid' | 'full-grid';
noAudio?: boolean;
caption?: string;
credits?: string;
description?: string;
displayTitle?: string;
systemTitle?: string;
source?: string;
contentWarning?: string[];
publishedDate?: string;
subtitle?: string;
clips?: Clip[];
accessibility?: ClipAccessibility;
}
type Clip = {
id: string;
format: 'standard-inline' | 'mobile';
dataSource: ClipSource[];
poster: string;
};
type ClipSource = {
audioCodec: string;
binaryUrl: string;
duration: number;
mediaType: string;
pixelHeight: number;
pixelWidth: number;
videoCodec: string;
};
type ClipCaption = {
mediaType?: string;
url?: string;
};
type ClipAccessibility = {
captions?: ClipCaption[];
transcript?: Body;
};
interface ScrollyBlock extends Parent {
type: "scrolly-block";
theme: "sans" | "serif";
Expand Down
42 changes: 42 additions & 0 deletions schemas/body-tree.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@
},
{
"$ref": "#/definitions/ContentTree.transit.YoutubeVideo"
},
{
"$ref": "#/definitions/ContentTree.transit.ClipSet"
}
]
},
Expand All @@ -136,6 +139,45 @@
],
"type": "object"
},
"ContentTree.transit.ClipSet": {
"additionalProperties": false,
"properties": {
"autoplay": {
"type": "boolean"
},
"data": {},
"id": {
"type": "string"
},
"layoutWidth": {
"enum": [
"full-grid",
"in-line",
"mid-grid"
],
"type": "string"
},
"loop": {
"type": "boolean"
},
"muted": {
"type": "boolean"
},
"type": {
"const": "clip-set",
"type": "string"
}
},
"required": [
"autoplay",
"id",
"layoutWidth",
"loop",
"muted",
"type"
],
"type": "object"
},
"ContentTree.transit.CustomCodeComponent": {
"additionalProperties": false,
"properties": {
Expand Down
Loading
Loading