Skip to content

Commit 252e107

Browse files
committed
add schemas for trail type
1 parent ee336a4 commit 252e107

File tree

7 files changed

+226
-151
lines changed

7 files changed

+226
-151
lines changed

dotcom-rendering/src/frontend/feArticle.ts

Lines changed: 52 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type CrosswordProps } from '@guardian/react-crossword';
2+
import { literal, object, type Output, union } from 'valibot';
23
import type { EditionId } from '../lib/edition';
34
import type { FEArticleBadgeType } from '../types/badge';
45
import type { Block } from '../types/blocks';
@@ -135,65 +136,70 @@ type PageType = {
135136
isSensitive: boolean;
136137
};
137138

138-
type ThemePillar =
139-
| 'NewsPillar'
140-
| 'OpinionPillar'
141-
| 'SportPillar'
142-
| 'CulturePillar'
143-
| 'LifestylePillar';
144-
145-
type ThemeSpecial = 'SpecialReportTheme' | 'Labs' | 'SpecialReportAltTheme';
146-
type FETheme = ThemePillar | ThemeSpecial;
139+
const FEThemeSchema = union([
140+
literal('NewsPillar'),
141+
literal('OpinionPillar'),
142+
literal('SportPillar'),
143+
literal('CulturePillar'),
144+
literal('LifestylePillar'),
145+
literal('SpecialReportTheme'),
146+
literal('Labs'),
147+
literal('SpecialReportAltTheme'),
148+
]);
147149

148150
/**
149151
* FEDesign is what frontend gives (originating in the capi scala client) us on the Format field
150152
* https://github.com/guardian/content-api-scala-client/blob/master/client/src/main/scala/com.gu.contentapi.client/utils/format/Design.scala
151153
*/
152-
type FEDesign =
153-
| 'ArticleDesign'
154-
| 'PictureDesign'
155-
| 'GalleryDesign'
156-
| 'AudioDesign'
157-
| 'VideoDesign'
158-
| 'CrosswordDesign'
159-
| 'ReviewDesign'
160-
| 'AnalysisDesign'
161-
| 'CommentDesign'
162-
| 'ExplainerDesign'
163-
| 'LetterDesign'
164-
| 'FeatureDesign'
165-
| 'LiveBlogDesign'
166-
| 'DeadBlogDesign'
167-
| 'RecipeDesign'
168-
| 'MatchReportDesign'
169-
| 'InterviewDesign'
170-
| 'EditorialDesign'
171-
| 'QuizDesign'
172-
| 'InteractiveDesign'
173-
| 'PhotoEssayDesign'
174-
| 'ObituaryDesign'
175-
| 'FullPageInteractiveDesign'
176-
| 'NewsletterSignupDesign'
177-
| 'TimelineDesign'
178-
| 'ProfileDesign';
154+
const FEDesignSchema = union([
155+
literal('ArticleDesign'),
156+
literal('PictureDesign'),
157+
literal('GalleryDesign'),
158+
literal('AudioDesign'),
159+
literal('VideoDesign'),
160+
literal('CrosswordDesign'),
161+
literal('ReviewDesign'),
162+
literal('AnalysisDesign'),
163+
literal('CommentDesign'),
164+
literal('ExplainerDesign'),
165+
literal('LetterDesign'),
166+
literal('FeatureDesign'),
167+
literal('LiveBlogDesign'),
168+
literal('DeadBlogDesign'),
169+
literal('RecipeDesign'),
170+
literal('MatchReportDesign'),
171+
literal('InterviewDesign'),
172+
literal('EditorialDesign'),
173+
literal('QuizDesign'),
174+
literal('InteractiveDesign'),
175+
literal('PhotoEssayDesign'),
176+
literal('ObituaryDesign'),
177+
literal('FullPageInteractiveDesign'),
178+
literal('NewsletterSignupDesign'),
179+
literal('TimelineDesign'),
180+
literal('ProfileDesign'),
181+
]);
179182

180183
/** FEDisplay is the display information passed through from frontend (originating in the capi scala client) and dictates the display style of the content e.g. Immersive
181184
https://github.com/guardian/content-api-scala-client/blob/master/client/src/main/scala/com.gu.contentapi.client/utils/format/Display.scala */
182-
type FEDisplay =
183-
| 'StandardDisplay'
184-
| 'ImmersiveDisplay'
185-
| 'ShowcaseDisplay'
186-
| 'NumberedListDisplay';
185+
const FEDisplaySchema = union([
186+
literal('StandardDisplay'),
187+
literal('ImmersiveDisplay'),
188+
literal('ShowcaseDisplay'),
189+
literal('NumberedListDisplay'),
190+
]);
187191

188192
/**
189193
* FEFormat is the stringified version of Format passed through from Frontend.
190194
* It gets converted to the `@guardian/libs` format on platform
191195
*/
192-
export type FEFormat = {
193-
design: FEDesign;
194-
theme: FETheme;
195-
display: FEDisplay;
196-
};
196+
export type FEFormat = Output<typeof FEFormatSchema>;
197+
198+
export const FEFormatSchema = object({
199+
design: FEDesignSchema,
200+
theme: FEThemeSchema,
201+
display: FEDisplaySchema,
202+
});
197203

198204
export type FEStoryPackage = {
199205
heading: string;

dotcom-rendering/src/types/branding.ts

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,46 @@
1+
import {
2+
literal,
3+
number,
4+
object,
5+
optional,
6+
type Output,
7+
string,
8+
union,
9+
} from 'valibot';
110
import type { EditionId } from '../lib/edition';
211

3-
type BrandingLogo = {
4-
src: string;
5-
link: string;
6-
label: string;
7-
dimensions: { width: number; height: number };
8-
};
12+
export type BrandingLogo = Output<typeof BrandingLogoSchema>;
13+
14+
export const BrandingLogoSchema = object({
15+
src: string(),
16+
link: string(),
17+
label: string(),
18+
dimensions: object({
19+
width: number(),
20+
height: number(),
21+
}),
22+
});
923

1024
/**
1125
* @see https://github.com/guardian/commercial-shared/blob/35cdf4e1/src/main/scala/com/gu/commercial/branding/BrandingType.scala
1226
*/
13-
export type BrandingType =
14-
| { name: 'paid-content' }
15-
| { name: 'foundation' }
16-
| { name: 'sponsored' };
17-
18-
export interface Branding {
19-
brandingType?: BrandingType;
20-
sponsorName: string;
21-
logo: BrandingLogo;
22-
aboutThisLink: string;
23-
logoForDarkBackground?: BrandingLogo;
24-
}
27+
export type BrandingType = Output<typeof BrandingTypeSchema>;
28+
29+
export const BrandingTypeSchema = union([
30+
object({ name: literal('paid-content') }),
31+
object({ name: literal('foundation') }),
32+
object({ name: literal('sponsored') }),
33+
]);
34+
35+
export type Branding = Output<typeof BrandingSchema>;
36+
37+
export const BrandingSchema = object({
38+
brandingType: optional(BrandingTypeSchema),
39+
sponsorName: string(),
40+
logo: BrandingLogoSchema,
41+
aboutThisLink: string(),
42+
logoForDarkBackground: optional(BrandingLogoSchema),
43+
});
2544

2645
export interface EditionBranding {
2746
edition: {

dotcom-rendering/src/types/content.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
import { type CrosswordProps } from '@guardian/react-crossword';
2+
import { literal, type Output, union } from 'valibot';
23
import type { ArticleFormat } from '../lib/articleFormat';
34

4-
export type StarRating = 0 | 1 | 2 | 3 | 4 | 5;
5+
export const StarRatingSchema = union([
6+
literal(0),
7+
literal(1),
8+
literal(2),
9+
literal(3),
10+
literal(4),
11+
literal(5),
12+
]);
13+
14+
export type StarRating = Output<typeof StarRatingSchema>;
515

616
export type BoostLevel = 'default' | 'boost' | 'megaboost' | 'gigaboost';
717

dotcom-rendering/src/types/front.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { object, optional, type Output, string } from 'valibot';
12
import type {
23
FEAspectRatio,
34
FEContainer,
@@ -109,11 +110,13 @@ export type DCRSlideshowImage = {
109110
imageCaption?: string;
110111
};
111112

112-
export type DCRSnapType = {
113-
embedHtml?: string;
114-
embedCss?: string;
115-
embedJs?: string;
116-
};
113+
export type DCRSnapType = Output<typeof DCRSnapTypeSchema>;
114+
115+
export const DCRSnapTypeSchema = object({
116+
embedHtml: optional(string()),
117+
embedCss: optional(string()),
118+
embedJs: optional(string()),
119+
});
117120

118121
export type AspectRatio = FEAspectRatio;
119122

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,55 @@
1-
import type { PodcastSeriesImage } from './tag';
2-
3-
type Media = {
4-
type: 'Video' | 'LoopVideo' | 'Audio' | 'Gallery';
5-
};
6-
1+
import {
2+
boolean,
3+
literal,
4+
number,
5+
object,
6+
optional,
7+
type Output,
8+
string,
9+
union,
10+
} from 'valibot';
11+
import { PodcastSeriesImageSchema } from './tag';
712
/** For displaying embedded, playable videos directly in cards */
8-
type Video = Media & {
9-
type: 'Video';
13+
const VideoSchema = object({
14+
type: literal('Video'),
1015
/** @see https://github.com/guardian/frontend/blob/8e7e4d0e/common/app/model/content/Atom.scala#L159 */
11-
id: string;
12-
videoId: string;
13-
height: number;
14-
width: number;
15-
origin: string;
16-
title: string;
17-
duration: number;
18-
expired: boolean;
19-
image?: string;
20-
};
16+
id: string(),
17+
videoId: string(),
18+
height: number(),
19+
width: number(),
20+
origin: string(),
21+
title: string(),
22+
duration: number(),
23+
expired: boolean(),
24+
image: optional(string()),
25+
});
26+
27+
const LoopVideoSchema = object({
28+
type: literal('LoopVideo'),
29+
atomId: string(),
30+
videoId: string(),
31+
height: number(),
32+
width: number(),
33+
duration: number(),
34+
image: optional(string()),
35+
});
2136

22-
type LoopVideo = Media & {
23-
type: 'LoopVideo';
24-
atomId: string;
25-
videoId: string;
26-
height: number;
27-
width: number;
28-
duration: number;
29-
image?: string;
30-
};
37+
const AudioSchema = object({
38+
type: literal('Audio'),
39+
duration: string(),
40+
podcastImage: optional(PodcastSeriesImageSchema),
41+
});
3142

32-
type Audio = Media & {
33-
type: 'Audio';
34-
duration: string;
35-
podcastImage?: PodcastSeriesImage;
36-
};
43+
const GallerySchema = object({
44+
type: literal('Gallery'),
45+
count: string(),
46+
});
3747

38-
type Gallery = Media & {
39-
type: 'Gallery';
40-
count: string;
41-
};
48+
export type MainMedia = Output<typeof MainMediaSchema>;
4249

43-
export type MainMedia = Video | LoopVideo | Audio | Gallery;
50+
export const MainMediaSchema = union([
51+
VideoSchema,
52+
LoopVideoSchema,
53+
AudioSchema,
54+
GallerySchema,
55+
]);

dotcom-rendering/src/types/tag.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { object, optional, type Output, string } from 'valibot';
12
/**
23
* This type comes from `frontend`, hence the FE prefix.
34
*
@@ -43,10 +44,12 @@ export type Podcast = {
4344
image?: string;
4445
};
4546

46-
export type PodcastSeriesImage = {
47-
src?: string;
48-
altText?: string;
49-
};
47+
export type PodcastSeriesImage = Output<typeof PodcastSeriesImageSchema>;
48+
49+
export const PodcastSeriesImageSchema = object({
50+
src: optional(string()),
51+
altText: optional(string()),
52+
});
5053

5154
export type TagType = {
5255
id: string;

0 commit comments

Comments
 (0)