├── .editorconfig
├── .git-blame-ignore-revs
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug.yml
│ └── request-for-change.yml
├── PULL_REQUEST_TEMPLATE.md
├── actions
│ └── setup-node-env
│ │ └── action.yml
├── dependabot.yml
├── labeler.yml
└── workflows
│ ├── ar-chromatic.yml
│ ├── ar-ci.yml
│ ├── ar-nodejs.yml
│ ├── build-check.yml
│ ├── bundle-analyser.yml
│ ├── chromatic-label-helper.yml
│ ├── cicd.yml
│ ├── compress.yml
│ ├── container.yml
│ ├── dcr-chromatic.yml
│ ├── delete-old-packages.yml
│ ├── deno.yml
│ ├── jest.yml
│ ├── labeler.yml
│ ├── lighthouse.yml
│ ├── lint.yml
│ ├── permissions-advisor.yml
│ ├── playwright.yml
│ ├── prettier.yml
│ ├── publish.yml
│ ├── scheduled.yml
│ ├── schema-check.yml
│ ├── stale.yml
│ ├── stories-check.yml
│ └── typescript.yml
├── .gitignore
├── .husky
├── post-merge
├── pre-commit
└── pre-push
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .prettierrc.json
├── .vscode
├── dcr.code-snippets
├── extensions.json
├── settings.json.recommended
└── settings.json.required
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps-rendering
├── .editorconfig
├── .eslintignore
├── .gitignore
├── .storybook
│ ├── fonts-css.ts
│ ├── main.js
│ ├── mocks
│ │ └── jsdom.js
│ ├── preview-head.html
│ └── preview.js
├── README.md
├── artifact.json
├── assets
│ └── fonts
│ │ ├── GHGuardianHeadline-Bold.ttf
│ │ ├── GHGuardianHeadline-BoldItalic.ttf
│ │ ├── GHGuardianHeadline-Light.ttf
│ │ ├── GHGuardianHeadline-LightItalic.ttf
│ │ ├── GHGuardianHeadline-Medium.ttf
│ │ ├── GHGuardianHeadline-MediumItalic.ttf
│ │ ├── GHGuardianHeadline-Regular.ttf
│ │ ├── GHGuardianHeadline-RegularItalic.ttf
│ │ ├── GHGuardianHeadline-Semibold.ttf
│ │ ├── GHGuardianHeadline-SemiboldItalic.ttf
│ │ ├── GuardianTextEgyptian-Bold.ttf
│ │ ├── GuardianTextEgyptian-BoldItalic.ttf
│ │ ├── GuardianTextEgyptian-Reg.ttf
│ │ ├── GuardianTextEgyptian-RegItalic.ttf
│ │ ├── GuardianTextSans-Bold.ttf
│ │ ├── GuardianTextSans-BoldItalic.ttf
│ │ ├── GuardianTextSans-Regular.ttf
│ │ └── GuardianTextSans-RegularItalic.ttf
├── cdk.json
├── cdk
│ ├── README.md
│ ├── bin
│ │ └── cdk.ts
│ └── lib
│ │ ├── __snapshots__
│ │ └── mobile-apps-rendering.test.ts.snap
│ │ ├── mobile-apps-rendering.test.ts
│ │ └── mobile-apps-rendering.ts
├── config
│ ├── .eslintrc.js
│ ├── jest.config.js
│ ├── jestSetup.js
│ ├── jestglobalSetup.js
│ ├── rendered-items-assets-styles.ts
│ ├── rendered-items-assets-template.html
│ ├── tsconfig.cdk.json
│ ├── tsconfig.client.json
│ ├── tsconfig.server.json
│ └── tsconfig.test.json
├── package.json
├── pull_request_template.md
├── riff-raff.yaml
├── src
│ ├── adSlot.stories.tsx
│ ├── adSlot.tsx
│ ├── ads.test.ts
│ ├── ads.ts
│ ├── articleFormat.test.ts
│ ├── articleFormat.ts
│ ├── atoms.test.ts
│ ├── atoms.ts
│ ├── bodyElement.test.ts
│ ├── bodyElement.ts
│ ├── bodyElementKind.ts
│ ├── campaign.test.ts
│ ├── campaign.ts
│ ├── capi.test.ts
│ ├── capi.ts
│ ├── cartoon.test.ts
│ ├── cartoon.ts
│ ├── client
│ │ ├── article.ts
│ │ ├── bridgetVersion.ts
│ │ ├── callouts.ts
│ │ ├── editions.ts
│ │ ├── interactives.ts
│ │ ├── liveblog.ts
│ │ ├── nativeCommunication.ts
│ │ ├── newsletterEmbeds.ts
│ │ ├── newsletterSignupForm.ts
│ │ ├── parser.ts
│ │ └── setup.ts
│ ├── components
│ │ ├── Accordion
│ │ │ ├── Accordion.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Anchor
│ │ │ ├── Anchor.stories.tsx
│ │ │ └── index.tsx
│ │ ├── ArticleBody
│ │ │ └── index.tsx
│ │ ├── Audio
│ │ │ └── index.tsx
│ │ ├── Avatar
│ │ │ └── index.tsx
│ │ ├── Blockquote
│ │ │ ├── Blockquote.stories.tsx
│ │ │ └── index.tsx
│ │ ├── BodyImage
│ │ │ ├── BodyImage.defaults.tsx
│ │ │ ├── BodyImage.stories.tsx
│ │ │ ├── GalleryBodyImage.tsx
│ │ │ └── index.tsx
│ │ ├── Bullet
│ │ │ ├── Bullet.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Byline
│ │ │ ├── AnalysisByline.tsx
│ │ │ ├── Byline.defaults.tsx
│ │ │ ├── Byline.stories.tsx
│ │ │ ├── CommentByline.tsx
│ │ │ ├── DeadBlogByline.tsx
│ │ │ ├── GalleryByline.tsx
│ │ │ ├── LabsByline.tsx
│ │ │ ├── LiveBlogByline.tsx
│ │ │ └── index.tsx
│ │ ├── BylineCard
│ │ │ └── index.tsx
│ │ ├── Callout
│ │ │ ├── Callout.stories.tsx
│ │ │ ├── callout.test.ts
│ │ │ ├── calloutBlock.tsx
│ │ │ ├── calloutComponents.tsx
│ │ │ ├── calloutContact.tsx
│ │ │ ├── calloutForm.tsx
│ │ │ ├── formFields.tsx
│ │ │ ├── index.tsx
│ │ │ ├── shareLink.tsx
│ │ │ ├── styles.ts
│ │ │ └── theme.ts
│ │ ├── CaptionIcon
│ │ │ ├── CaptionIcon.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Card
│ │ │ └── index.tsx
│ │ ├── CheckboxInput
│ │ │ └── index.tsx
│ │ ├── ClickToView
│ │ │ ├── ClickToView.test.tsx
│ │ │ └── index.tsx
│ │ ├── CommentCount
│ │ │ ├── CommentCount.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Credit
│ │ │ └── index.tsx
│ │ ├── Cutout
│ │ │ └── index.tsx
│ │ ├── Dateline
│ │ │ ├── Dateline.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Deadline
│ │ │ ├── index.test.ts
│ │ │ ├── index.tsx
│ │ │ └── styles.ts
│ │ ├── DesignTag
│ │ │ ├── DesignTag.stories.tsx
│ │ │ └── index.tsx
│ │ ├── EmailSignup
│ │ │ └── index.tsx
│ │ ├── EmailSignupForm
│ │ │ └── index.tsx
│ │ ├── Embed
│ │ │ └── index.tsx
│ │ ├── EmbedWrapper
│ │ │ ├── EmbedWrapper.stories.tsx
│ │ │ ├── EmbedWrapper.test.tsx
│ │ │ └── index.tsx
│ │ ├── Epic
│ │ │ └── index.tsx
│ │ ├── EpicContent
│ │ │ └── index.tsx
│ │ ├── FigCaption
│ │ │ ├── FigCaption.stories.tsx
│ │ │ └── index.tsx
│ │ ├── FirstPublished
│ │ │ ├── FirstPublished.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Follow
│ │ │ ├── Follow.stories.tsx
│ │ │ ├── Follow.test.tsx
│ │ │ └── index.tsx
│ │ ├── FollowStatus
│ │ │ └── index.tsx
│ │ ├── FootballScores
│ │ │ ├── FootballScores.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Footer
│ │ │ ├── Footer.defaults.tsx
│ │ │ ├── Footer.stories.tsx
│ │ │ ├── GalleryFooter.tsx
│ │ │ ├── ImmersiveFooter.tsx
│ │ │ └── index.tsx
│ │ ├── FooterContent
│ │ │ └── index.tsx
│ │ ├── GenericEmbed
│ │ │ └── index.tsx
│ │ ├── GridItem
│ │ │ └── index.tsx
│ │ ├── HeadingTwo
│ │ │ ├── HeadingTwo.defaults.tsx
│ │ │ ├── ImmersiveHeadingTwo.tsx
│ │ │ ├── LabsHeadingTwo.tsx
│ │ │ └── index.tsx
│ │ ├── Headline
│ │ │ ├── BlogHeadline.tsx
│ │ │ ├── CommentHeadline.tsx
│ │ │ ├── FeatureHeadline.tsx
│ │ │ ├── GalleryHeadline.tsx
│ │ │ ├── Headline.defaults.tsx
│ │ │ ├── Headline.stories.tsx
│ │ │ ├── ImmersiveHeadline.tsx
│ │ │ ├── InterviewHeadline.tsx
│ │ │ ├── LabsHeadline.tsx
│ │ │ ├── MediaHeadline.tsx
│ │ │ ├── ReviewHeadline.tsx
│ │ │ └── index.tsx
│ │ ├── HeadlineByline
│ │ │ ├── HeadlineByline.stories.tsx
│ │ │ └── index.tsx
│ │ ├── HorizontalRule
│ │ │ ├── HorizontalRule.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Img
│ │ │ └── index.tsx
│ │ ├── ImgAlt
│ │ │ ├── ImgAlt.stories.tsx
│ │ │ └── index.tsx
│ │ ├── InPageNewsletterSignup
│ │ │ ├── InPageNewsletterSignup.stories.tsx
│ │ │ ├── NotSupportedMessage.tsx
│ │ │ └── index.tsx
│ │ ├── InlineSkipToWrapper
│ │ │ └── index.tsx
│ │ ├── Instagram
│ │ │ └── index.tsx
│ │ ├── Interactive
│ │ │ └── index.tsx
│ │ ├── InteractiveAtom
│ │ │ └── index.tsx
│ │ ├── KeyEvents
│ │ │ ├── KeyEvents.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Kicker
│ │ │ └── index.tsx
│ │ ├── LabsLogo
│ │ │ └── index.tsx
│ │ ├── LastUpdated
│ │ │ ├── LastUpdated.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Layout
│ │ │ ├── AnalysisLayout.tsx
│ │ │ ├── CommentLayout.tsx
│ │ │ ├── GalleryLayout.tsx
│ │ │ ├── ImmersiveLayout.tsx
│ │ │ ├── InteractiveLayout.tsx
│ │ │ ├── LabsLayout.tsx
│ │ │ ├── Layout.stories.tsx
│ │ │ ├── LetterLayout.tsx
│ │ │ ├── LiveLayout.tsx
│ │ │ ├── NewsletterSignUpLayout.tsx
│ │ │ ├── StandardLayout.tsx
│ │ │ └── index.tsx
│ │ ├── List
│ │ │ ├── List.stories.tsx
│ │ │ └── index.tsx
│ │ ├── ListItem
│ │ │ ├── ListItem.stories.tsx
│ │ │ └── index.tsx
│ │ ├── LiveBlock
│ │ │ └── index.tsx
│ │ ├── LiveBlockContainer
│ │ │ └── index.tsx
│ │ ├── LiveBlocks
│ │ │ └── index.tsx
│ │ ├── LiveDateline
│ │ │ └── index.tsx
│ │ ├── LiveEventLink
│ │ │ └── index.tsx
│ │ ├── LiveblogHeader
│ │ │ └── index.tsx
│ │ ├── LiveblogMetadataLines
│ │ │ └── index.tsx
│ │ ├── Logo
│ │ │ ├── Logo.stories.tsx
│ │ │ ├── Logo.test.tsx
│ │ │ └── index.tsx
│ │ ├── MainMedia
│ │ │ ├── GalleryCaption.tsx
│ │ │ ├── ImmersiveCaption.tsx
│ │ │ ├── MainMedia.defaults.ts
│ │ │ ├── MainMediaImage
│ │ │ │ ├── BlogMainMediaImage.tsx
│ │ │ │ ├── CommentMainMediaImage.tsx
│ │ │ │ ├── GalleryMainMediaImage.tsx
│ │ │ │ ├── ImmersiveMainMediaImage.tsx
│ │ │ │ ├── InterviewMainMediaImage.tsx
│ │ │ │ ├── MainMediaImage.defaults.tsx
│ │ │ │ ├── NewsletterSignupMainMediaImage.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── MainMediaVideo
│ │ │ │ └── index.tsx
│ │ │ └── index.tsx
│ │ ├── MainMediaCaption
│ │ │ ├── Caption.tsx
│ │ │ ├── MainMediaCaption.defaults.tsx
│ │ │ ├── MainMediaCaption.stories.tsx
│ │ │ ├── MainMediaCaption.test.tsx
│ │ │ └── index.tsx
│ │ ├── MatchStatusIcon
│ │ │ └── index.tsx
│ │ ├── Meta
│ │ │ └── index.tsx
│ │ ├── Metadata
│ │ │ ├── ExtendedMetadata.tsx
│ │ │ ├── GalleryMetadata.tsx
│ │ │ ├── ImmersiveMetadata.tsx
│ │ │ ├── LiveBlogMetadata.tsx
│ │ │ ├── Metadata.defaults.tsx
│ │ │ ├── Metadata.stories.tsx
│ │ │ ├── ShortMetadata.tsx
│ │ │ └── index.tsx
│ │ ├── NewsletterSignup
│ │ │ ├── NewsletterSignup.stories.tsx
│ │ │ ├── PrivacyWording.tsx
│ │ │ └── index.tsx
│ │ ├── OrderedList
│ │ │ ├── OrderedList.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Pagination
│ │ │ ├── Pagination.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Paragraph
│ │ │ ├── Paragraph.stories.tsx
│ │ │ └── index.tsx
│ │ ├── PinnedPost
│ │ │ ├── PinnedPost.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Pullquote
│ │ │ ├── Pullquote.stories.tsx
│ │ │ └── index.tsx
│ │ ├── RadioInput
│ │ │ └── index.tsx
│ │ ├── RelatedContent
│ │ │ ├── GalleryRelatedContent.tsx
│ │ │ ├── ImmersiveRelatedContent.tsx
│ │ │ ├── RelatedContent.defaults.tsx
│ │ │ └── index.tsx
│ │ ├── RichLink
│ │ │ ├── RichLink.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Scripts
│ │ │ └── index.tsx
│ │ ├── Series
│ │ │ ├── GallerySeries.tsx
│ │ │ ├── ImmersiveSeries.tsx
│ │ │ ├── Series.stories.tsx
│ │ │ └── index.tsx
│ │ ├── SpecialReportAltAtom
│ │ │ ├── SpecialReportAltAtom.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Standfirst
│ │ │ ├── AnalysisStandfirst.tsx
│ │ │ ├── DeadBlogStandfirst.tsx
│ │ │ ├── ExplainerStandfirst.tsx
│ │ │ ├── GalleryStandfirst.tsx
│ │ │ ├── ImmersiveLabsStandfirst.tsx
│ │ │ ├── ImmersiveStandfirst.tsx
│ │ │ ├── InterviewStandfirst.tsx
│ │ │ ├── LabsStandfirst.tsx
│ │ │ ├── LiveBlogStandfirst.tsx
│ │ │ ├── MediaStandfirst.tsx
│ │ │ ├── NewsletterSignupStandfirst.tsx
│ │ │ ├── ReviewStandfirst.tsx
│ │ │ ├── Standfirst.defaults.tsx
│ │ │ ├── Standfirst.stories.tsx
│ │ │ └── index.tsx
│ │ ├── StarRating
│ │ │ ├── StarRating.stories.tsx
│ │ │ └── index.tsx
│ │ ├── TableOfContents
│ │ │ ├── TableOfContents.stories.tsx
│ │ │ └── index.tsx
│ │ ├── Tags
│ │ │ ├── GalleryTags.tsx
│ │ │ ├── ImmersiveTags.tsx
│ │ │ ├── Tags.defaults.tsx
│ │ │ ├── Tags.stories.tsx
│ │ │ ├── Tags.test.tsx
│ │ │ └── index.tsx
│ │ ├── TeamScore
│ │ │ └── index.tsx
│ │ ├── Video
│ │ │ └── index.tsx
│ │ ├── WithAgeWarning
│ │ │ ├── WithAgeWarning.test.tsx
│ │ │ └── index.tsx
│ │ ├── caption
│ │ │ ├── caption.tsx
│ │ │ └── index.tsx
│ │ ├── editions
│ │ │ ├── avatar
│ │ │ │ ├── avatar.stories.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── byline
│ │ │ │ ├── byline.stories.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── cartoon
│ │ │ │ ├── cartoon.stories.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── footballScores
│ │ │ │ ├── footballScores.stories.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── galleryImage
│ │ │ │ ├── galleryImage.stories.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── header
│ │ │ │ └── index.tsx
│ │ │ ├── headerImageCaption.tsx
│ │ │ ├── headerMedia
│ │ │ │ ├── headerMedia.stories.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── headline
│ │ │ │ ├── headline.stories.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── kickerPicker.ts
│ │ │ ├── layout
│ │ │ │ ├── index.tsx
│ │ │ │ └── layout.stories.tsx
│ │ │ ├── lines.tsx
│ │ │ ├── pullquote
│ │ │ │ ├── index.tsx
│ │ │ │ └── pullquote.stories.tsx
│ │ │ ├── series
│ │ │ │ ├── index.tsx
│ │ │ │ └── series.stories.tsx
│ │ │ ├── shareIcon
│ │ │ │ ├── index.tsx
│ │ │ │ └── shareIcon.stories.tsx
│ │ │ ├── standfirst
│ │ │ │ ├── index.tsx
│ │ │ │ └── standfirst.stories.tsx
│ │ │ ├── starRating
│ │ │ │ ├── index.tsx
│ │ │ │ └── starRating.stories.tsx
│ │ │ ├── styles.ts
│ │ │ ├── teamScore
│ │ │ │ └── index.tsx
│ │ │ ├── utils
│ │ │ │ └── useOnlineStatus.tsx
│ │ │ └── video
│ │ │ │ ├── index.tsx
│ │ │ │ └── video.stories.tsx
│ │ └── media
│ │ │ ├── articleBody.tsx
│ │ │ ├── articleSeries.tsx
│ │ │ ├── byline.tsx
│ │ │ └── tags.tsx
│ ├── contributer.test.ts
│ ├── contributor.ts
│ ├── date.test.ts
│ ├── date.ts
│ ├── datetime.ts
│ ├── embed.ts
│ ├── fixtures
│ │ ├── article.ts
│ │ ├── campaign.ts
│ │ ├── cartoon.ts
│ │ ├── galleryBody.ts
│ │ ├── galleryImage.ts
│ │ ├── image.ts
│ │ ├── item.ts
│ │ ├── live.ts
│ │ ├── newsletterSignUpContent.ts
│ │ └── relatedContent.ts
│ ├── football.ts
│ ├── grid
│ │ ├── LeftCentreBorder.tsx
│ │ └── grid.ts
│ ├── helperTest.ts
│ ├── image.test.ts
│ ├── image.ts
│ ├── image
│ │ ├── __snapshots__
│ │ │ └── sizes.test.tsx.snap
│ │ ├── image.ts
│ │ ├── lightbox.ts
│ │ ├── sizes.test.tsx
│ │ ├── sizes.ts
│ │ ├── srcsets.test.ts
│ │ └── srcsets.ts
│ ├── item.test.ts
│ ├── item.ts
│ ├── lib.test.tsx
│ ├── lib.ts
│ ├── liveBlock.ts
│ ├── logger
│ │ ├── LoggerFunctions.ts
│ │ ├── clientDev
│ │ │ └── index.ts
│ │ ├── clientProd
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── server
│ │ │ └── index.ts
│ ├── mainMedia.ts
│ ├── native
│ │ ├── nativeApi.ts
│ │ └── thrift
│ │ │ ├── nativeConnection.ts
│ │ │ └── protocols.ts
│ ├── newsletter.test.ts
│ ├── newsletter.ts
│ ├── optional.ts
│ ├── outline.test.ts
│ ├── outline.ts
│ ├── pagination.test.ts
│ ├── pagination.ts
│ ├── palette
│ │ ├── background.ts
│ │ ├── border.ts
│ │ ├── colour.ts
│ │ ├── fill.ts
│ │ ├── hover.ts
│ │ ├── index.ts
│ │ └── text.ts
│ ├── parser.md
│ ├── parser.test.ts
│ ├── parser.ts
│ ├── parserContext.ts
│ ├── quizAtom.ts
│ ├── relatedContent.test.ts
│ ├── relatedContent.ts
│ ├── renderer.test.ts
│ ├── renderer.ts
│ ├── result.test.ts
│ ├── result.ts
│ ├── server
│ │ ├── appIdentity.ts
│ │ ├── assets.ts
│ │ ├── aws.ts
│ │ ├── csp.test.ts
│ │ ├── csp.ts
│ │ ├── decoders.ts
│ │ ├── editionsPage.tsx
│ │ ├── footballContent.ts
│ │ ├── page.tsx
│ │ ├── paramParser.ts
│ │ ├── server.ts
│ │ └── ssmConfig.ts
│ ├── span.test.ts
│ ├── span.ts
│ ├── styles.test.ts
│ ├── styles.ts
│ ├── testsHelper.ts
│ ├── video.test.ts
│ └── video.ts
├── tsconfig.json
├── vendor
│ └── @guardian
│ │ └── types
│ │ ├── README.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── option.d.ts
│ │ ├── option.js
│ │ ├── result.d.ts
│ │ └── result.js
└── webpack.config.ts
├── dotcom-rendering
├── .eslintignore
├── .eslintrc.js
├── .fast
├── .gitignore
├── .prout.json
├── .storybook
│ ├── decorators
│ │ ├── configContextDecorator.tsx
│ │ ├── gridDecorators.tsx
│ │ ├── splitThemeDecorator.tsx
│ │ └── themeDecorator.tsx
│ ├── main.ts
│ ├── mocks
│ │ ├── bridgetApi.ts
│ │ ├── jsdom.ts
│ │ ├── log4js.ts
│ │ └── paletteDeclarations.ts
│ ├── modes.ts
│ ├── preview-head.html
│ ├── preview.ts
│ └── toolbar
│ │ └── globalColourScheme.ts
├── Containerfile
├── README.md
├── __mocks__
│ └── svgMock.tsx
├── cdk.json
├── cdk
│ ├── bin
│ │ └── cdk.ts
│ └── lib
│ │ ├── __snapshots__
│ │ └── renderingStack.test.ts.snap
│ │ ├── renderingStack.test.ts
│ │ ├── renderingStack.ts
│ │ └── userData.ts
├── configs
│ └── webpack
│ │ ├── .test.mjs
│ │ ├── README.md
│ │ ├── base.mjs
│ │ ├── client.apps.mjs
│ │ ├── client.web.mjs
│ │ ├── client.web.variant.mjs
│ │ ├── server.dev.mjs
│ │ ├── server.mjs
│ │ └── utils
│ │ └── env.mjs
├── docs
│ ├── ads
│ │ ├── apps-ads.md
│ │ └── web-ads.md
│ ├── architecture
│ │ ├── 000-architecture-decision-records.md
│ │ ├── 001-dotcom-rendering.md
│ │ ├── 002-componentisation.md
│ │ ├── 003-react.md
│ │ ├── 004-emotion.md
│ │ ├── 005-monorepo.md
│ │ ├── 006-support-for-frontend-only.md
│ │ ├── 007-css-in-js.md
│ │ ├── 008-static-types.md
│ │ ├── 009-storybook.md
│ │ ├── 010-capi-elements-as-components.md
│ │ ├── 011-amp.md
│ │ ├── 012-new-elements-models-in-frontend.md
│ │ ├── 013-testing.md
│ │ ├── 014-client-side-computation.md
│ │ ├── 015-javascript-loading.md
│ │ ├── 017-remove-monorepo.md
│ │ ├── 018-react-hooks.md
│ │ ├── 019-react-to-preact.md
│ │ ├── 020-react-portals.md
│ │ ├── 021-NoJS-navigation-and-accessibility.md
│ │ ├── 022-dynamic-imports.md
│ │ ├── 023-script-loading.md
│ │ ├── 024-click-to-view.md
│ │ ├── 025-interactive-pressing.md
│ │ ├── 026-better-partial-hydration.md
│ │ ├── 027-pictures.md
│ │ ├── 028-react-context-api.md
│ │ ├── 029-scaling-policy-decision-record.md
│ │ ├── 3rd-party-technical-review
│ │ │ ├── 000-technical-review-records.md
│ │ │ ├── 001-modi-poc.md
│ │ │ ├── 002-ipsos-mori.md
│ │ │ ├── 003-gracenote.md
│ │ │ └── 004-urlbox.md
│ │ ├── amp
│ │ │ └── 000-structure-for-initial-milestone.md
│ │ ├── historic-adrs
│ │ │ ├── 016-react-context-api.md
│ │ │ ├── dotenv.md
│ │ │ ├── multiple-sites.md
│ │ │ ├── signing-image-urls.md
│ │ │ └── use-percy-for-e2e-visual-regression-testing.md
│ │ └── proposed-adrs
│ │ │ └── rendering-type.md
│ ├── commercial
│ │ ├── liveblog-server-side-ad-slots.md
│ │ └── overview.md
│ ├── contracts
│ │ ├── 000-contracts.md
│ │ ├── 001-commercial-selectors.md
│ │ ├── 002-viewer-body-selector.md
│ │ ├── 003-extra-classes-for-interactives.md
│ │ └── 004-heatphan-selectors.md
│ ├── contributing
│ │ ├── README.md
│ │ ├── code-style.md
│ │ ├── detailed-setup-guide-pics
│ │ │ └── high-level-diagram.png
│ │ ├── detailed-setup-guide.md
│ │ ├── how-to.md
│ │ └── where-should-my-code-live.md
│ ├── development
│ │ ├── ab-testing-in-dcr.md
│ │ ├── apps-testing.md
│ │ ├── assets
│ │ │ ├── android-clear-cache.png
│ │ │ ├── local-ar-android.png
│ │ │ └── local-ar-ios.png
│ │ ├── loadable-components.md
│ │ ├── local-sign-in.md
│ │ ├── run-prod-bundle-locally.md
│ │ ├── storybook.md
│ │ └── track-user-behaviour.md
│ ├── duplication.md
│ ├── elements
│ │ ├── Disclaimer.md
│ │ ├── Embed.md
│ │ ├── Image.md
│ │ ├── Instagram.md
│ │ ├── Richlink.md
│ │ ├── Subheading.md
│ │ ├── Text.md
│ │ └── Tweet.md
│ ├── email-newsletters-page.md
│ ├── images
│ │ ├── logo-ab-testing.png
│ │ ├── logo-chromatic.jpg
│ │ ├── logo-deno.svg
│ │ ├── logo-emotion.png
│ │ ├── logo-express.png
│ │ ├── logo-jest.jpg
│ │ ├── logo-playwright.svg
│ │ ├── logo-preact.jpg
│ │ ├── logo-storybook.jpg
│ │ └── logo-typescript.png
│ ├── incidents
│ │ └── incident-handling.md
│ ├── interactives
│ │ └── working-with-interactives.md
│ ├── lightbox.md
│ ├── logging.md
│ ├── patterns
│ │ ├── decide-layout.md
│ │ ├── enhancers.md
│ │ └── switch-on-display-design.md
│ ├── principles
│ │ ├── browser-support.md
│ │ ├── developer-experience.md
│ │ ├── images
│ │ │ ├── chrome70.png
│ │ │ └── ie8.png
│ │ └── performance-budgets.md
│ ├── resources.md
│ ├── testing.md
│ ├── tracking
│ │ └── 001-sentry.md
│ ├── values
│ │ └── README.md
│ └── youtube
│ │ ├── youtube-variations-2020-06-23.md
│ │ ├── youtube-variations-2021-11-17.md
│ │ ├── youtubeimages-2020
│ │ ├── embedcapijson.png
│ │ ├── embedcomposerscreenshot.png
│ │ ├── embeddcrjson.png
│ │ ├── embedscreenshot.png
│ │ ├── mediaatomcapijson.png
│ │ ├── mediaatomcomposerscreenshot.png
│ │ ├── mediaatomdcrjson.png
│ │ ├── mediaatomscreenshot.png
│ │ ├── structuredataembedscreenshot.png
│ │ ├── structureddataembedcapijson.png
│ │ └── structureddataembedcomposer.png
│ │ └── youtubeimages-2021
│ │ ├── composer-embed-dialog.png
│ │ ├── composer-embed-menu.png
│ │ ├── composer-generic-embed-code.png
│ │ ├── composer-video-menu.png
│ │ ├── composer-youtube-embed-atom.png
│ │ ├── composer-youtube-embed-generic.png
│ │ └── composer-youtube-embed.png
├── fixtures
│ ├── config-overrides.js
│ ├── config.js
│ ├── generated
│ │ ├── cricket-match.ts
│ │ ├── fe-articles
│ │ │ ├── Analysis.ts
│ │ │ ├── Audio.ts
│ │ │ ├── Comment.ts
│ │ │ ├── Dead.ts
│ │ │ ├── Editorial.ts
│ │ │ ├── Explainer.ts
│ │ │ ├── Feature.ts
│ │ │ ├── Gallery.ts
│ │ │ ├── Interview.ts
│ │ │ ├── Labs.ts
│ │ │ ├── Letter.ts
│ │ │ ├── Live.ts
│ │ │ ├── LiveBlogSingleContributor.ts
│ │ │ ├── MatchReport.ts
│ │ │ ├── NewsletterSignup.ts
│ │ │ ├── NumberedList.ts
│ │ │ ├── PhotoEssay.ts
│ │ │ ├── Picture.ts
│ │ │ ├── Quiz.ts
│ │ │ ├── Recipe.ts
│ │ │ ├── Review.ts
│ │ │ ├── SpecialReport.ts
│ │ │ ├── Standard.ts
│ │ │ ├── StandardWithVideo.ts
│ │ │ └── Video.ts
│ │ ├── football-live.ts
│ │ ├── images.ts
│ │ ├── match-report.ts
│ │ ├── series.ts
│ │ └── story-package.ts
│ ├── manual
│ │ ├── InteractiveAtomBlockElement.ts
│ │ ├── InteractiveLayoutAtom.ts
│ │ ├── block-meta-data.ts
│ │ ├── calloutCampaign.ts
│ │ ├── calloutCampaignV2.ts
│ │ ├── chartAtoms.ts
│ │ ├── comment.ts
│ │ ├── contributionsHeader.ts
│ │ ├── cricket-scoreboard.ts
│ │ ├── discussion-no-top-comments.ts
│ │ ├── discussion.ts
│ │ ├── discussionApiUrl.ts
│ │ ├── discussionWithNoComments.ts
│ │ ├── discussionWithTwoComments.ts
│ │ ├── editionsCrossword.ts
│ │ ├── ensure.ts
│ │ ├── footballData.ts
│ │ ├── footballMatches.ts
│ │ ├── frontCollections.ts
│ │ ├── guideAtom.ts
│ │ ├── highlights-trails.ts
│ │ ├── key-events.ts
│ │ ├── knowledgeQuizAtom.ts
│ │ ├── legacyDiscussionWithoutThreading.ts
│ │ ├── live-blog-key-events.ts
│ │ ├── liveBlock.ts
│ │ ├── most-read-geo.ts
│ │ ├── most-read.ts
│ │ ├── nav-international.ts
│ │ ├── nav-world.ts
│ │ ├── noTopPicks.ts
│ │ ├── personalityQuizAtom.ts
│ │ ├── qandaAtom.tsx
│ │ ├── related.ts
│ │ ├── short-discussion.ts
│ │ ├── show-more-trails.ts
│ │ ├── timelineAtom.tsx
│ │ ├── topPicks.ts
│ │ ├── trails-nav.ts
│ │ └── trails.ts
│ └── switch-overrides.js
├── index.d.ts
├── jest.config.js
├── lighthouserc.js
├── makefile
├── package.json
├── playwright.config.ts
├── playwright
│ ├── fixtures
│ │ ├── cricket-match.js
│ │ └── tweet-block.js
│ ├── lib
│ │ ├── cmp.ts
│ │ ├── cookies.ts
│ │ ├── iframe.ts
│ │ ├── islands.ts
│ │ ├── load-page.ts
│ │ ├── locators.ts
│ │ ├── network.ts
│ │ └── ophan.ts
│ └── tests
│ │ ├── article.e2e.spec.ts
│ │ ├── article.embeds.e2e.spec.ts
│ │ ├── article.interactivity.e2e.spec.ts
│ │ ├── article.metaAndOphan.e2e.spec.ts
│ │ ├── atom.interactivity.e2e.spec.ts
│ │ ├── atom.video.e2e.spec.ts
│ │ ├── banner.e2e.spec.ts
│ │ ├── commercial.e2e.spec.ts
│ │ ├── edition-switcher-banner.e2e.spec.ts
│ │ ├── epic.interactivity.e2e.spec.ts
│ │ ├── lightbox.e2e.spec.ts
│ │ ├── liveblog.interactivity.e2e.spec.ts
│ │ ├── ophan.e2e.spec.ts
│ │ ├── paid.content.e2e.spec.ts
│ │ └── signedin.e2e.spec.ts
├── scripts
│ ├── check-node-versions.mjs
│ ├── deploy
│ │ ├── build-riffraff-bundle.mjs
│ │ └── riff-raff.yaml
│ ├── env
│ │ ├── check-deps.js
│ │ └── check-files.js
│ ├── gen-stories
│ │ ├── check-stories.mjs
│ │ ├── gen-stories.mjs
│ │ └── get-stories.mjs
│ ├── islands
│ │ ├── island-descriptions.mjs
│ │ └── islands.html
│ ├── jest
│ │ └── setup.ts
│ ├── jsonSchema
│ │ ├── checkSchemas.mjs
│ │ ├── genSchemas.mjs
│ │ └── schema.mjs
│ ├── lighthouse
│ │ └── puppeteer-script.js
│ ├── nginx
│ │ ├── Brewfile
│ │ ├── nginx-mappings.yaml
│ │ └── setup.sh
│ ├── perf
│ │ ├── gc
│ │ │ └── gc-report.js
│ │ └── k6
│ │ │ ├── README.md
│ │ │ ├── article-nier-automata.json
│ │ │ ├── k6-install.sh
│ │ │ └── k6.mjs
│ ├── test-data
│ │ └── gen-fixtures.js
│ └── test
│ │ ├── amp-validation.js
│ │ └── build-check.js
├── src
│ ├── AMPAttributes.amp.ts
│ ├── client
│ │ ├── adaptiveSite.ts
│ │ ├── atomIframe.ts
│ │ ├── bootCmp.ts
│ │ ├── debug
│ │ │ ├── README.md
│ │ │ ├── debug.css
│ │ │ └── debug.ts
│ │ ├── decidePublicPath.test.ts
│ │ ├── decidePublicPath.ts
│ │ ├── discussion.ts
│ │ ├── dynamicImport.ts
│ │ ├── embedIframe.ts
│ │ ├── islands
│ │ │ ├── doHydration.tsx
│ │ │ ├── emotion.ts
│ │ │ ├── getConfig.ts
│ │ │ ├── getName.ts
│ │ │ ├── getPriority.ts
│ │ │ ├── getProps.ts
│ │ │ ├── initHydration.ts
│ │ │ ├── islands.ts
│ │ │ ├── onInteraction.ts
│ │ │ ├── onNavigation.ts
│ │ │ ├── whenIdle.ts
│ │ │ └── whenVisible.ts
│ │ ├── main.apps.ts
│ │ ├── main.editionsCrossword.tsx
│ │ ├── main.web.ts
│ │ ├── newsletterEmbedIframe.ts
│ │ ├── ophan
│ │ │ ├── ophan.ts
│ │ │ └── recordInitialPageEvents.ts
│ │ ├── poorPerformanceMonitoring.ts
│ │ ├── sIndicator.ts
│ │ ├── sentryLoader
│ │ │ ├── loadSentry.ts
│ │ │ ├── sentry.ts
│ │ │ ├── sentryLoader.test.ts
│ │ │ └── sentryLoader.ts
│ │ ├── startup.ts
│ │ ├── updateIframeHeight.tsx
│ │ ├── userFeatures
│ │ │ ├── cookies
│ │ │ │ ├── adFree.ts
│ │ │ │ ├── allowRejectAll.ts
│ │ │ │ ├── cookieHelpers.ts
│ │ │ │ ├── hideSupportMessaging.ts
│ │ │ │ ├── sIndicatorCapiKey.ts
│ │ │ │ └── userBenefitsExpiry.ts
│ │ │ ├── fetchJson.ts
│ │ │ ├── user-features.test.ts
│ │ │ ├── user-features.ts
│ │ │ └── userBenefitsApi.ts
│ │ └── webpackPublicPath.ts
│ ├── components
│ │ ├── Accessibility.importable.tsx
│ │ ├── Accordion.stories.tsx
│ │ ├── Accordion.tsx
│ │ ├── Ad.amp.tsx
│ │ ├── AdBlockAsk.importable.tsx
│ │ ├── AdBlockAskLeaderboard.stories.tsx
│ │ ├── AdBlockAskMPU.stories.tsx
│ │ ├── AdConsent.amp.tsx
│ │ ├── AdPlaceholder.apps.tsx
│ │ ├── AdPortals.importable.tsx
│ │ ├── AdSlot.apps.stories.tsx
│ │ ├── AdSlot.apps.tsx
│ │ ├── AdSlot.web.stories.tsx
│ │ ├── AdSlot.web.tsx
│ │ ├── AffiliateDisclaimer.tsx
│ │ ├── AgeWarning.stories.tsx
│ │ ├── AgeWarning.tsx
│ │ ├── AllEditorialNewslettersPage.tsx
│ │ ├── AlreadyVisited.importable.tsx
│ │ ├── AmpExperiment.amp.tsx
│ │ ├── Analytics.amp.tsx
│ │ ├── AnalyticsIframe.amp.tsx
│ │ ├── Answers.stories.tsx
│ │ ├── Answers.tsx
│ │ ├── AppsEpic.importable.stories.tsx
│ │ ├── AppsEpic.importable.tsx
│ │ ├── AppsFooter.importable.stories.tsx
│ │ ├── AppsFooter.importable.tsx
│ │ ├── AppsLightboxImage.importable.tsx
│ │ ├── AppsLightboxImageStore.importable.tsx
│ │ ├── ArticleBody.tsx
│ │ ├── ArticleContainer.tsx
│ │ ├── ArticleHeadline.mocks.ts
│ │ ├── ArticleHeadline.stories.tsx
│ │ ├── ArticleHeadline.tsx
│ │ ├── ArticleLastUpdated.stories.tsx
│ │ ├── ArticleLastUpdated.tsx
│ │ ├── ArticleMeta.apps.stories.tsx
│ │ ├── ArticleMeta.apps.tsx
│ │ ├── ArticleMeta.web.stories.tsx
│ │ ├── ArticleMeta.web.test.tsx
│ │ ├── ArticleMeta.web.tsx
│ │ ├── ArticlePage.amp.tsx
│ │ ├── ArticlePage.tsx
│ │ ├── ArticleTitle.stories.tsx
│ │ ├── ArticleTitle.tsx
│ │ ├── AudioAtom
│ │ │ ├── AudioAtom.stories.tsx
│ │ │ ├── AudioAtom.test.tsx
│ │ │ └── AudioAtom.tsx
│ │ ├── AudioAtomBlockComponent.amp.tsx
│ │ ├── AudioAtomWrapper.importable.tsx
│ │ ├── AudioPlayer
│ │ │ ├── AudioPlayer.stories.tsx
│ │ │ ├── AudioPlayer.tsx
│ │ │ ├── components
│ │ │ │ ├── Playback.tsx
│ │ │ │ ├── ProgressBar.tsx
│ │ │ │ ├── Wrapper.tsx
│ │ │ │ └── time.tsx
│ │ │ ├── stories
│ │ │ │ ├── default_audio_test.mp3
│ │ │ │ └── default_audio_test.mp3.d.ts
│ │ │ └── styles.ts
│ │ ├── AudioPlayerWrapper.importable.tsx
│ │ ├── AustralianTerritorySwitcher.importable.stories.tsx
│ │ ├── AustralianTerritorySwitcher.importable.tsx
│ │ ├── Avatar.stories.tsx
│ │ ├── Avatar.tsx
│ │ ├── BackToTop.tsx
│ │ ├── Badge.tsx
│ │ ├── BigNumber.stories.tsx
│ │ ├── BigNumber.tsx
│ │ ├── Bio.tsx
│ │ ├── BlockquoteBlockComponent.stories.tsx
│ │ ├── BlockquoteBlockComponent.tsx
│ │ ├── Blocks.amp.tsx
│ │ ├── BodyArticle.amp.tsx
│ │ ├── BodyLiveblog.amp.tsx
│ │ ├── Border.tsx
│ │ ├── Branding.amp.tsx
│ │ ├── Branding.importable.tsx
│ │ ├── BrazeMessaging.importable.tsx
│ │ ├── Byline.amp.stories.tsx
│ │ ├── Byline.amp.test.tsx
│ │ ├── Byline.amp.tsx
│ │ ├── Byline.tsx
│ │ ├── BylineLink.test.tsx
│ │ ├── BylineLink.tsx
│ │ ├── CPScottHeader.tsx
│ │ ├── Callout
│ │ │ ├── Callout.tsx
│ │ │ ├── CalloutComponents.tsx
│ │ │ ├── Deadline.tsx
│ │ │ ├── Form.tsx
│ │ │ ├── FormField.tsx
│ │ │ ├── MessageUs.tsx
│ │ │ └── callout.test.ts
│ │ ├── CalloutBlockComponent.importable.tsx
│ │ ├── CalloutBlockComponent.stories.tsx
│ │ ├── CalloutEmbed
│ │ │ ├── Form.stories.tsx
│ │ │ ├── Form.test.tsx
│ │ │ ├── Form.tsx
│ │ │ └── FormFields
│ │ │ │ ├── CheckboxSelect.tsx
│ │ │ │ ├── FieldLabel.tsx
│ │ │ │ ├── FileUpload.tsx
│ │ │ │ ├── MultiSelect.tsx
│ │ │ │ ├── RadioSelect.tsx
│ │ │ │ ├── Select.tsx
│ │ │ │ ├── TextArea.tsx
│ │ │ │ └── TextInput.tsx
│ │ ├── CalloutEmbedBlockComponent.importable.tsx
│ │ ├── CalloutEmbedBlockComponent.stories.tsx
│ │ ├── Caption.amp.tsx
│ │ ├── Caption.stories.tsx
│ │ ├── Caption.tsx
│ │ ├── CaptionBlockComponent.stories.tsx
│ │ ├── CaptionBlockComponent.tsx
│ │ ├── Card
│ │ │ ├── Card.stories.tsx
│ │ │ ├── Card.tsx
│ │ │ └── components
│ │ │ │ ├── AvatarContainer.tsx
│ │ │ │ ├── CardAge.tsx
│ │ │ │ ├── CardBranding.tsx
│ │ │ │ ├── CardFooter.stories.tsx
│ │ │ │ ├── CardFooter.tsx
│ │ │ │ ├── CardLayout.tsx
│ │ │ │ ├── CardLink.tsx
│ │ │ │ ├── CardWrapper.tsx
│ │ │ │ ├── ContentWrapper.tsx
│ │ │ │ ├── HeadlineWrapper.tsx
│ │ │ │ ├── ImageWrapper.tsx
│ │ │ │ ├── LI.tsx
│ │ │ │ ├── PlayIcon.tsx
│ │ │ │ ├── SvgWaveform.tsx
│ │ │ │ ├── TrailText.tsx
│ │ │ │ └── UL.tsx
│ │ ├── CardCommentCount.importable.stories.tsx
│ │ ├── CardCommentCount.importable.tsx
│ │ ├── CardHeadline.stories.tsx
│ │ ├── CardHeadline.tsx
│ │ ├── CardPicture.tsx
│ │ ├── Carousel.importable.tsx
│ │ ├── Carousel.stories.tsx
│ │ ├── CarouselForNewsletters.importable.tsx
│ │ ├── CarouselNavigationButtons.tsx
│ │ ├── CartoonComponent.mocks.ts
│ │ ├── CartoonComponent.stories.tsx
│ │ ├── CartoonComponent.tsx
│ │ ├── ChartAtom.importable.tsx
│ │ ├── ChartAtom.stories.tsx
│ │ ├── ChartAtom.test.tsx
│ │ ├── ClickToView.stories.tsx
│ │ ├── ClickToView.test.tsx
│ │ ├── ClickToView.tsx
│ │ ├── CodeBlockComponent.stories.tsx
│ │ ├── CodeBlockComponent.tsx
│ │ ├── CommentBlockComponent.amp.tsx
│ │ ├── CommentBlockComponent.stories.tsx
│ │ ├── CommentBlockComponent.tsx
│ │ ├── CommentCount.importable.tsx
│ │ ├── ConfigContext.test.tsx
│ │ ├── ConfigContext.tsx
│ │ ├── ContainerOverrides.tsx
│ │ ├── ContainerTitle.stories.tsx
│ │ ├── ContainerTitle.tsx
│ │ ├── ContentABTest.amp.test.tsx
│ │ ├── ContentABTest.amp.tsx
│ │ ├── ContentAtomBlockComponent.amp.tsx
│ │ ├── Contributor.test.tsx
│ │ ├── Contributor.tsx
│ │ ├── ContributorAvatar.tsx
│ │ ├── CricketScoreboard.stories.tsx
│ │ ├── CricketScoreboard.test.tsx
│ │ ├── CricketScoreboard.tsx
│ │ ├── CricketScorecard.stories.tsx
│ │ ├── CricketScorecard.tsx
│ │ ├── CricketScorecardPage.tsx
│ │ ├── CrosswordComponent.importable.tsx
│ │ ├── CrosswordInstructions.tsx
│ │ ├── CrosswordLinks.tsx
│ │ ├── CrosswordSelect.editions.stories.tsx
│ │ ├── CrosswordSelect.editions.tsx
│ │ ├── CrosswordSetter.tsx
│ │ ├── Crosswords.editions.stories.tsx
│ │ ├── Crosswords.editions.tsx
│ │ ├── DarkModeMessage.tsx
│ │ ├── DateTime.stories.tsx
│ │ ├── DateTime.tsx
│ │ ├── Dateline.tsx
│ │ ├── DecideContainer.tsx
│ │ ├── DecideContainerByTrails.stories.tsx
│ │ ├── DecideContainerByTrails.tsx
│ │ ├── DecideLines.tsx
│ │ ├── DesignTag.stories.tsx
│ │ ├── DesignTag.tsx
│ │ ├── Details.tsx
│ │ ├── Discussion.stories.tsx
│ │ ├── Discussion.test.tsx
│ │ ├── Discussion.tsx
│ │ ├── Discussion
│ │ │ ├── AbuseReportForm.stories.tsx
│ │ │ ├── AbuseReportForm.test.tsx
│ │ │ ├── AbuseReportForm.tsx
│ │ │ ├── Avatar.stories.tsx
│ │ │ ├── Avatar.tsx
│ │ │ ├── Badges.stories.tsx
│ │ │ ├── Badges.tsx
│ │ │ ├── Column.tsx
│ │ │ ├── Comment.stories.tsx
│ │ │ ├── Comment.tsx
│ │ │ ├── CommentContainer.stories.tsx
│ │ │ ├── CommentContainer.test.tsx
│ │ │ ├── CommentContainer.tsx
│ │ │ ├── CommentForm.stories.tsx
│ │ │ ├── CommentForm.tsx
│ │ │ ├── CommentReplyPreview.stories.tsx
│ │ │ ├── CommentReplyPreview.tsx
│ │ │ ├── Comments.stories.tsx
│ │ │ ├── Comments.tsx
│ │ │ ├── Discussion.test.tsx
│ │ │ ├── Dropdown.stories.tsx
│ │ │ ├── Dropdown.test.tsx
│ │ │ ├── Dropdown.tsx
│ │ │ ├── Filters.stories.tsx
│ │ │ ├── Filters.tsx
│ │ │ ├── FirstCommentWelcome.stories.tsx
│ │ │ ├── FirstCommentWelcome.tsx
│ │ │ ├── LoadingComments.stories.tsx
│ │ │ ├── LoadingComments.tsx
│ │ │ ├── LoadingPicks.stories.tsx
│ │ │ ├── LoadingPicks.tsx
│ │ │ ├── Pagination.stories.tsx
│ │ │ ├── Pagination.test.tsx
│ │ │ ├── Pagination.tsx
│ │ │ ├── PillarButton.stories.tsx
│ │ │ ├── PillarButton.tsx
│ │ │ ├── Preview.stories.tsx
│ │ │ ├── Preview.tsx
│ │ │ ├── RecommendationCount.stories.tsx
│ │ │ ├── RecommendationCount.tsx
│ │ │ ├── Row.tsx
│ │ │ ├── Timestamp.stories.tsx
│ │ │ ├── Timestamp.tsx
│ │ │ ├── TopPick.stories.tsx
│ │ │ ├── TopPick.tsx
│ │ │ ├── TopPicks.stories.tsx
│ │ │ └── TopPicks.tsx
│ │ ├── DiscussionApps.importable.tsx
│ │ ├── DiscussionLayout.tsx
│ │ ├── DiscussionMeta.importable.tsx
│ │ ├── DiscussionWeb.importable.tsx
│ │ ├── DispatchContext.tsx
│ │ ├── Distribution.stories.tsx
│ │ ├── Distribution.tsx
│ │ ├── DividerBlockComponent.stories.tsx
│ │ ├── DividerBlockComponent.tsx
│ │ ├── DocumentBlockComponent.importable.tsx
│ │ ├── DocumentBlockComponent.stories.tsx
│ │ ├── DocumentBlockComponent.test.tsx
│ │ ├── Doughnut.stories.tsx
│ │ ├── Doughnut.test.tsx
│ │ ├── Doughnut.tsx
│ │ ├── DropCap.tsx
│ │ ├── Dropcap.stories.tsx
│ │ ├── Dropdown.importable.tsx
│ │ ├── Dropdown.stories.tsx
│ │ ├── Dropdown.test.tsx
│ │ ├── DynamicFast.stories.tsx
│ │ ├── DynamicFast.tsx
│ │ ├── DynamicPackage.stories.tsx
│ │ ├── DynamicPackage.tsx
│ │ ├── DynamicSlow.stories.tsx
│ │ ├── DynamicSlow.tsx
│ │ ├── DynamicSlowMPU.stories.tsx
│ │ ├── DynamicSlowMPU.tsx
│ │ ├── EditionSwitcherBanner.importable.tsx
│ │ ├── EditionSwitcherBanner.stories.tsx
│ │ ├── EditionSwitcherBanner.test.tsx
│ │ ├── EditionsCrosswordPage.tsx
│ │ ├── EditorialButton
│ │ │ ├── EditorialButton.stories.tsx
│ │ │ ├── EditorialButton.tsx
│ │ │ ├── EditorialLinkButton.stories.tsx
│ │ │ ├── EditorialLinkButton.tsx
│ │ │ └── styles.ts
│ │ ├── ElectionTrackers
│ │ │ ├── ChangeBars.stories.tsx
│ │ │ ├── ChangeBars.tsx
│ │ │ ├── StackedProgress.stories.tsx
│ │ │ ├── StackedProgress.tsx
│ │ │ ├── ValuesWithChange.stories.tsx
│ │ │ ├── ValuesWithChange.tsx
│ │ │ ├── Versus.stories.tsx
│ │ │ └── Versus.tsx
│ │ ├── ElementContainer.tsx
│ │ ├── Elements.amp.tsx
│ │ ├── EmailSignUpWrapper.stories.tsx
│ │ ├── EmailSignUpWrapper.tsx
│ │ ├── EmailSignup.stories.tsx
│ │ ├── EmailSignup.tsx
│ │ ├── EmbedBlockComponent.amp.tsx
│ │ ├── EmbedBlockComponent.importable.tsx
│ │ ├── EndNote.tsx
│ │ ├── EnhancePinnedPost.importable.tsx
│ │ ├── Epic.amp.tsx
│ │ ├── EpicContent.apps.tsx
│ │ ├── Expandable.amp.tsx
│ │ ├── ExpandableAtom
│ │ │ ├── Body.tsx
│ │ │ ├── Container.tsx
│ │ │ ├── Footer.tsx
│ │ │ └── Summary.tsx
│ │ ├── ExplainerAtom.stories.tsx
│ │ ├── ExplainerAtom.test.tsx
│ │ ├── ExplainerAtom.tsx
│ │ ├── FeatureCard.stories.tsx
│ │ ├── FeatureCard.tsx
│ │ ├── FeatureCardCardAge.tsx
│ │ ├── FeatureCardCommentCount.tsx
│ │ ├── FetchOnwardsData.importable.tsx
│ │ ├── Figure.stories.tsx
│ │ ├── Figure.tsx
│ │ ├── FilterKeyEventsToggle.importable.tsx
│ │ ├── FirstPublished.stories.tsx
│ │ ├── FirstPublished.tsx
│ │ ├── FixedLargeSlowXIV.stories.tsx
│ │ ├── FixedLargeSlowXIV.tsx
│ │ ├── FixedMediumFastXI.stories.tsx
│ │ ├── FixedMediumFastXI.tsx
│ │ ├── FixedMediumFastXII.stories.tsx
│ │ ├── FixedMediumFastXII.tsx
│ │ ├── FixedMediumSlowVI.stories.tsx
│ │ ├── FixedMediumSlowVI.tsx
│ │ ├── FixedMediumSlowVII.stories.tsx
│ │ ├── FixedMediumSlowVII.tsx
│ │ ├── FixedMediumSlowXIIMPU.stories.tsx
│ │ ├── FixedMediumSlowXIIMPU.tsx
│ │ ├── FixedSmallFastVIII.stories.tsx
│ │ ├── FixedSmallFastVIII.tsx
│ │ ├── FixedSmallSlowI.stories.tsx
│ │ ├── FixedSmallSlowI.tsx
│ │ ├── FixedSmallSlowIII.stories.tsx
│ │ ├── FixedSmallSlowIII.tsx
│ │ ├── FixedSmallSlowIV.stories.tsx
│ │ ├── FixedSmallSlowIV.tsx
│ │ ├── FixedSmallSlowVHalf.stories.tsx
│ │ ├── FixedSmallSlowVHalf.tsx
│ │ ├── FixedSmallSlowVMPU.stories.tsx
│ │ ├── FixedSmallSlowVMPU.tsx
│ │ ├── FixedSmallSlowVThird.stories.tsx
│ │ ├── FixedSmallSlowVThird.tsx
│ │ ├── Flex.tsx
│ │ ├── FlexibleGeneral.stories.tsx
│ │ ├── FlexibleGeneral.test.tsx
│ │ ├── FlexibleGeneral.tsx
│ │ ├── FlexibleSpecial.stories.tsx
│ │ ├── FlexibleSpecial.tsx
│ │ ├── FocusStyles.importable.tsx
│ │ ├── FollowButtons.stories.tsx
│ │ ├── FollowButtons.test.tsx
│ │ ├── FollowButtons.tsx
│ │ ├── FollowWrapper.importable.tsx
│ │ ├── FootballCompetitionSelect.stories.tsx
│ │ ├── FootballCompetitionSelect.tsx
│ │ ├── FootballMatchList.stories.tsx
│ │ ├── FootballMatchList.test.tsx
│ │ ├── FootballMatchList.tsx
│ │ ├── FootballMatchSummary.stories.tsx
│ │ ├── FootballMatchSummary.tsx
│ │ ├── FootballMatchesPage.stories.tsx
│ │ ├── FootballMatchesPage.tsx
│ │ ├── FootballMatchesPageWrapper.importable.tsx
│ │ ├── FootballTable.stories.tsx
│ │ ├── FootballTable.tsx
│ │ ├── FootballTableForm.stories.tsx
│ │ ├── FootballTableForm.tsx
│ │ ├── FootballTableList.stories.tsx
│ │ ├── FootballTableList.tsx
│ │ ├── FootballTablesCompetitionSelect.importable.tsx
│ │ ├── FootballTablesPage.stories.tsx
│ │ ├── FootballTablesPage.tsx
│ │ ├── Footer.amp.tsx
│ │ ├── Footer.stories.tsx
│ │ ├── Footer.tsx
│ │ ├── FooterLabel.importable.tsx
│ │ ├── FooterReaderRevenueLinks.importable.tsx
│ │ ├── FooterReaderRevenueLinks.stories.tsx
│ │ ├── FooterReaderRevenueLinks.test.tsx
│ │ ├── FormatBoundary.tsx
│ │ ├── FrontCard.tsx
│ │ ├── FrontMostViewed.tsx
│ │ ├── FrontPage.tsx
│ │ ├── FrontPagination.stories.tsx
│ │ ├── FrontPagination.tsx
│ │ ├── FrontSection.stories.tsx
│ │ ├── FrontSection.tsx
│ │ ├── FrontSectionTitle.tsx
│ │ ├── FrontSubNav.importable.tsx
│ │ ├── FrontsAdSlots.test.tsx
│ │ ├── FrontsAdSlots.tsx
│ │ ├── GetCricketScoreboard.importable.tsx
│ │ ├── GetMatchNav.importable.tsx
│ │ ├── GetMatchStats.importable.tsx
│ │ ├── GetMatchTabs.importable.tsx
│ │ ├── GoalAttempts.stories.tsx
│ │ ├── GoalAttempts.tsx
│ │ ├── GridItem.tsx
│ │ ├── GroupedNewsletterList.tsx
│ │ ├── GuVideoBlockComponent.amp.tsx
│ │ ├── GuVideoBlockComponent.tsx
│ │ ├── GuardianLabsLines.tsx
│ │ ├── GuideAtom
│ │ │ ├── GuideAtom.stories.tsx
│ │ │ ├── GuideAtom.test.tsx
│ │ │ └── GuideAtom.tsx
│ │ ├── GuideAtomWrapper.importable.tsx
│ │ ├── Header.amp.tsx
│ │ ├── HeaderAdSlot.tsx
│ │ ├── Heading.tsx
│ │ ├── HeadlineByline.stories.tsx
│ │ ├── HeadlineByline.tsx
│ │ ├── Hide.tsx
│ │ ├── HighlightBlockComponent.stories.tsx
│ │ ├── HighlightBlockComponent.tsx
│ │ ├── ImageBlockComponent.amp.tsx
│ │ ├── ImageBlockComponent.mocks.ts
│ │ ├── ImageBlockComponent.stories.tsx
│ │ ├── ImageBlockComponent.tsx
│ │ ├── ImageComponent.tsx
│ │ ├── InlineAd.amp.test.tsx
│ │ ├── InlineAd.amp.tsx
│ │ ├── InlineSkipToWrapper.tsx
│ │ ├── InstagramBlockComponent.importable.tsx
│ │ ├── InteractiveAtom.stories.tsx
│ │ ├── InteractiveAtom.tsx
│ │ ├── InteractiveAtomBlockComponent.amp.tsx
│ │ ├── InteractiveAtomMessenger.importable.tsx
│ │ ├── InteractiveBlockComponent.amp.tsx
│ │ ├── InteractiveBlockComponent.importable.tsx
│ │ ├── InteractiveBlockComponent.stories.tsx
│ │ ├── InteractiveContentsBlockComponent.importable.tsx
│ │ ├── InteractiveContentsBlockComponent.stories.tsx
│ │ ├── InteractiveLayoutAtom.stories.tsx
│ │ ├── InteractiveLayoutAtom.test.tsx
│ │ ├── InteractiveLayoutAtom.tsx
│ │ ├── InteractivesNativePlatformWrapper.importable.tsx
│ │ ├── Island.test.tsx
│ │ ├── Island.tsx
│ │ ├── ItemLinkBlockElement.stories.tsx
│ │ ├── ItemLinkBlockElement.tsx
│ │ ├── JsonScript.amp.tsx
│ │ ├── KeyEventCard.stories.tsx
│ │ ├── KeyEventCard.tsx
│ │ ├── KeyEvents.amp.tsx
│ │ ├── KeyEventsCarousel.importable.tsx
│ │ ├── KeyEventsCarousel.stories.tsx
│ │ ├── KeyTakeaway.tsx
│ │ ├── KeyTakeaways.stories.tsx
│ │ ├── KeyTakeaways.tsx
│ │ ├── Kicker.stories.tsx
│ │ ├── Kicker.tsx
│ │ ├── KnowledgeQuizAtom.importable.tsx
│ │ ├── KnowledgeQuizAtom.stories.tsx
│ │ ├── KnowledgeQuizAtom.test.tsx
│ │ ├── LabsHeader.stories.tsx
│ │ ├── LabsHeader.tsx
│ │ ├── LabsSection.stories.tsx
│ │ ├── LabsSection.tsx
│ │ ├── LastUpdated.stories.tsx
│ │ ├── LastUpdated.tsx
│ │ ├── LatestLinks.importable.stories.tsx
│ │ ├── LatestLinks.importable.tsx
│ │ ├── Lazy.tsx
│ │ ├── LeftColumn.stories.tsx
│ │ ├── LeftColumn.tsx
│ │ ├── Lightbox.stories.tsx
│ │ ├── Lightbox.tsx
│ │ ├── LightboxCaption.tsx
│ │ ├── LightboxHash.importable.tsx
│ │ ├── LightboxImages.tsx
│ │ ├── LightboxJavascript.tsx
│ │ ├── LightboxLayout.importable.tsx
│ │ ├── LightboxLink.tsx
│ │ ├── LightboxLoader.tsx
│ │ ├── Lineup.stories.tsx
│ │ ├── Lineup.tsx
│ │ ├── LinkHeadline.stories.tsx
│ │ ├── LinkHeadline.tsx
│ │ ├── LiveBlock.stories.tsx
│ │ ├── LiveBlock.tsx
│ │ ├── LiveBlockContainer.tsx
│ │ ├── LiveBlogBlocksAndAdverts.tsx
│ │ ├── LiveBlogEpic.importable.tsx
│ │ ├── LiveBlogRenderer.tsx
│ │ ├── LiveblogGutterAskWrapper.importable.tsx
│ │ ├── LiveblogNotifications.importable.tsx
│ │ ├── Liveness.importable.tsx
│ │ ├── Localisation.ts
│ │ ├── LoopVideo.importable.tsx
│ │ ├── LoopVideo.stories.tsx
│ │ ├── LoopVideoPlayer.tsx
│ │ ├── LoopVideoProgressBar.tsx
│ │ ├── MainMedia.amp.tsx
│ │ ├── MainMedia.tsx
│ │ ├── MainMediaEmbedBlockComponent.tsx
│ │ ├── MainMediaGallery.stories.tsx
│ │ ├── MainMediaGallery.tsx
│ │ ├── MaintainAspectRatio.tsx
│ │ ├── ManyNewsletterSignUp.importable.tsx
│ │ ├── ManyNewsletterSignUp.stories.tsx
│ │ ├── ManyNewslettersForm.tsx
│ │ ├── MapEmbedBlockComponent.importable.tsx
│ │ ├── Masthead
│ │ │ ├── HighlightsCard.stories.tsx
│ │ │ ├── HighlightsCard.tsx
│ │ │ ├── Masthead.stories.tsx
│ │ │ ├── Masthead.tsx
│ │ │ └── Titlepiece
│ │ │ │ ├── EditionDropdown.stories.tsx
│ │ │ │ ├── EditionDropdown.tsx
│ │ │ │ ├── ExpandedNav
│ │ │ │ ├── CollapseSectionButton.tsx
│ │ │ │ ├── ExpandedNav.stories.tsx
│ │ │ │ ├── ExpandedNav.tsx
│ │ │ │ ├── MoreSection.tsx
│ │ │ │ ├── Pillar.tsx
│ │ │ │ ├── ReaderRevenueLinks.tsx
│ │ │ │ ├── SearchBar.tsx
│ │ │ │ └── Sections.tsx
│ │ │ │ ├── Grid.tsx
│ │ │ │ ├── Logo.tsx
│ │ │ │ ├── Nav.mock.tsx
│ │ │ │ ├── Pillars.stories.tsx
│ │ │ │ ├── Pillars.tsx
│ │ │ │ ├── SubNav.tsx
│ │ │ │ ├── VeggieBurger.tsx
│ │ │ │ ├── commonStyles.ts
│ │ │ │ └── constants.ts
│ │ ├── MatchNav.stories.tsx
│ │ ├── MatchNav.tsx
│ │ ├── MatchStats.stories.tsx
│ │ ├── MatchStats.tsx
│ │ ├── MatchTabs.stories.tsx
│ │ ├── MatchTabs.tsx
│ │ ├── MediaDuration.tsx
│ │ ├── MediaMeta.tsx
│ │ ├── Metrics.importable.tsx
│ │ ├── MiniCard.tsx
│ │ ├── MiniProfile.tsx
│ │ ├── MiniProfiles.stories.tsx
│ │ ├── MiniProfiles.tsx
│ │ ├── MostPopularFooterGrid.stories.tsx
│ │ ├── MostPopularFooterGrid.tsx
│ │ ├── MostViewed.mocks.ts
│ │ ├── MostViewedFooter.importable.tsx
│ │ ├── MostViewedFooter.test.tsx
│ │ ├── MostViewedFooterData.importable.tsx
│ │ ├── MostViewedFooterGrid.tsx
│ │ ├── MostViewedFooterItem.tsx
│ │ ├── MostViewedFooterLayout.stories.tsx
│ │ ├── MostViewedFooterLayout.tsx
│ │ ├── MostViewedFooterPlaceholder.stories.tsx
│ │ ├── MostViewedFooterPlaceholder.tsx
│ │ ├── MostViewedRight.stories.tsx
│ │ ├── MostViewedRight.test.tsx
│ │ ├── MostViewedRight.tsx
│ │ ├── MostViewedRightItem.tsx
│ │ ├── MostViewedRightWithAd.importable.tsx
│ │ ├── MostViewedRightWrapper.tsx
│ │ ├── Moustache.amp.tsx
│ │ ├── MultiByline.tsx
│ │ ├── MultiBylines.stories.tsx
│ │ ├── MultiBylines.tsx
│ │ ├── MultiImageBlockComponent.mocks.tsx
│ │ ├── MultiImageBlockComponent.stories.tsx
│ │ ├── MultiImageBlockComponent.tsx
│ │ ├── NavList.stories.tsx
│ │ ├── NavList.tsx
│ │ ├── NewsletterBadge.stories.tsx
│ │ ├── NewsletterBadge.tsx
│ │ ├── NewsletterCard.tsx
│ │ ├── NewsletterDetail.stories.tsx
│ │ ├── NewsletterDetail.tsx
│ │ ├── NewsletterFrequency.stories.tsx
│ │ ├── NewsletterFrequency.tsx
│ │ ├── NewsletterPageHeading.tsx
│ │ ├── NewsletterPrivacyMessage.stories.tsx
│ │ ├── NewsletterPrivacyMessage.tsx
│ │ ├── NumberedTitleBlockComponent.stories.tsx
│ │ ├── NumberedTitleBlockComponent.tsx
│ │ ├── Onward.amp.tsx
│ │ ├── OnwardContainer.amp.tsx
│ │ ├── OnwardsUpper.importable.test.tsx
│ │ ├── OnwardsUpper.importable.tsx
│ │ ├── Pagination.amp.stories.tsx
│ │ ├── Pagination.amp.tsx
│ │ ├── Pagination.stories.tsx
│ │ ├── Pagination.tsx
│ │ ├── PaidForBand.amp.tsx
│ │ ├── Palettes.stories.tsx
│ │ ├── Permutive.amp.tsx
│ │ ├── PersonalityQuizAtom.importable.tsx
│ │ ├── PersonalityQuizAtom.stories.tsx
│ │ ├── PersonalityQuizAtom.test.tsx
│ │ ├── Picture.tsx
│ │ ├── Pill.stories.tsx
│ │ ├── Pill.tsx
│ │ ├── PinnedPost.stories.tsx
│ │ ├── PinnedPost.tsx
│ │ ├── Placeholder.stories.tsx
│ │ ├── Placeholder.tsx
│ │ ├── PodcastCoverImage.tsx
│ │ ├── PodcastMeta.stories.tsx
│ │ ├── PodcastMeta.tsx
│ │ ├── PrivacySettingsLink.importable.tsx
│ │ ├── ProfileAtom.importable.tsx
│ │ ├── ProfileAtom.stories.tsx
│ │ ├── ProfileAtom.test.tsx
│ │ ├── ProfileAtomWrapper.importable.tsx
│ │ ├── PullQuoteBlockComponent.stories.tsx
│ │ ├── PullQuoteBlockComponent.tsx
│ │ ├── PullquoteBlockComponent.amp.tsx
│ │ ├── PulsingDot.importable.tsx
│ │ ├── PulsingDot.test.tsx
│ │ ├── QAndAExplainer.tsx
│ │ ├── QAndAExplainers.stories.tsx
│ │ ├── QAndAExplainers.tsx
│ │ ├── QandaAtom.importable.tsx
│ │ ├── QandaAtom.stories.tsx
│ │ ├── QandaAtom.test.tsx
│ │ ├── QuoteIcon.tsx
│ │ ├── ReaderRevenueButton.amp.tsx
│ │ ├── ReaderRevenueDev.importable.tsx
│ │ ├── RelativeTime.importable.test.tsx
│ │ ├── RelativeTime.importable.tsx
│ │ ├── RewrappedComponent.tsx
│ │ ├── RichLink.stories.tsx
│ │ ├── RichLink.tsx
│ │ ├── RichLinkBlockComponent.amp.tsx
│ │ ├── RichLinkComponent.importable.test.tsx
│ │ ├── RichLinkComponent.importable.tsx
│ │ ├── RightColumn.tsx
│ │ ├── Score.stories.tsx
│ │ ├── Score.tsx
│ │ ├── ScrollableCarousel.tsx
│ │ ├── ScrollableFeature.importable.tsx
│ │ ├── ScrollableFeature.stories.tsx
│ │ ├── ScrollableHighlights.importable.tsx
│ │ ├── ScrollableHighlights.stories.tsx
│ │ ├── ScrollableMedium.importable.tsx
│ │ ├── ScrollableMedium.stories.tsx
│ │ ├── ScrollableSmall.importable.tsx
│ │ ├── ScrollableSmall.stories.tsx
│ │ ├── Section.stories.tsx
│ │ ├── Section.tsx
│ │ ├── SecureSignup.importable.tsx
│ │ ├── SendTargetingParams.importable.tsx
│ │ ├── SeriesLink.amp.tsx
│ │ ├── SeriesSectionLink.tsx
│ │ ├── SetABTests.importable.tsx
│ │ ├── SetAdTargeting.importable.tsx
│ │ ├── ShadyPie.stories.tsx
│ │ ├── ShadyPie.tsx
│ │ ├── ShareButton.importable.tsx
│ │ ├── ShareButton.stories.tsx
│ │ ├── ShareIcons.amp.tsx
│ │ ├── ShowHideButton.tsx
│ │ ├── ShowHideContainers.importable.tsx
│ │ ├── ShowMore.importable.tsx
│ │ ├── ShowMore.stories.tsx
│ │ ├── ShowMoreButton.amp.tsx
│ │ ├── Sidebar.amp.tsx
│ │ ├── SignInGate
│ │ │ ├── README.md
│ │ │ ├── SignInGate.stories.tsx
│ │ │ ├── componentEventTracking.tsx
│ │ │ ├── dismissGate.test.ts
│ │ │ ├── dismissGate.ts
│ │ │ ├── displayRules.test.ts
│ │ │ ├── displayRules.ts
│ │ │ ├── gateDesigns
│ │ │ │ ├── SignInGateAuxia.tsx
│ │ │ │ ├── SignInGateCustomizableText.tsx
│ │ │ │ ├── SignInGateFakeSocial.tsx
│ │ │ │ ├── SignInGateMain.tsx
│ │ │ │ ├── SignInGateMainCheckoutComplete.test.tsx
│ │ │ │ ├── SignInGateMainCheckoutComplete.tsx
│ │ │ │ └── shared.tsx
│ │ │ ├── gates
│ │ │ │ ├── alternative-wording-control.tsx
│ │ │ │ ├── alternative-wording-guardian-live.tsx
│ │ │ │ ├── alternative-wording-saturday-edition.tsx
│ │ │ │ ├── fake-social-variant.tsx
│ │ │ │ ├── main-control.ts
│ │ │ │ ├── main-mandatory-variant.tsx
│ │ │ │ └── main-variant.tsx
│ │ │ ├── signInGateMappings.ts
│ │ │ └── types.ts
│ │ ├── SignInGateSelector.importable.tsx
│ │ ├── SignedInAs.stories.tsx
│ │ ├── SignedInAs.tsx
│ │ ├── SkipTo.tsx
│ │ ├── Slideshow.stories.tsx
│ │ ├── Slideshow.tsx
│ │ ├── SlideshowCarousel.importable.tsx
│ │ ├── SlideshowCarousel.stories.tsx
│ │ ├── SlideshowCarouselScrollingDots.tsx
│ │ ├── SlotBodyEnd.importable.tsx
│ │ ├── SlotBodyEnd
│ │ │ ├── BrazeEpic.stories.tsx
│ │ │ ├── BrazeEpic.tsx
│ │ │ └── ReaderRevenueEpic.tsx
│ │ ├── Snap.stories.tsx
│ │ ├── Snap.tsx
│ │ ├── SnapCssSandbox.tsx
│ │ ├── SoundcloudBlockComponent.amp.tsx
│ │ ├── SoundcloudBlockComponent.tsx
│ │ ├── SportDataPageComponent.tsx
│ │ ├── SpotifyBlockComponent.importable.tsx
│ │ ├── Standfirst.amp.tsx
│ │ ├── Standfirst.stories.tsx
│ │ ├── Standfirst.test.tsx
│ │ ├── Standfirst.tsx
│ │ ├── StarRating.amp.tsx
│ │ ├── StarRating
│ │ │ ├── StarRating.stories.tsx
│ │ │ └── StarRating.tsx
│ │ ├── StarRatingBlockComponent.stories.tsx
│ │ ├── StarRatingBlockComponent.tsx
│ │ ├── StaticFeatureTwo.stories.tsx
│ │ ├── StaticFeatureTwo.tsx
│ │ ├── StaticMediumFour.stories.tsx
│ │ ├── StaticMediumFour.tsx
│ │ ├── StickyAd.amp.tsx
│ │ ├── StickyBottomBanner.importable.tsx
│ │ ├── StickyBottomBanner
│ │ │ ├── BrazeBanner.stories.tsx
│ │ │ ├── BrazeBanner.tsx
│ │ │ └── ReaderRevenueBanner.tsx
│ │ ├── SubMeta.amp.tsx
│ │ ├── SubMeta.stories.tsx
│ │ ├── SubMeta.tsx
│ │ ├── SubNav.importable.tsx
│ │ ├── SubNav.stories.tsx
│ │ ├── Subheading.tsx
│ │ ├── SubheadingBlockComponent.amp.tsx
│ │ ├── SubheadingBlockComponent.stories.tsx
│ │ ├── SubheadingBlockComponent.tsx
│ │ ├── SupportingContent.stories.tsx
│ │ ├── SupportingContent.tsx
│ │ ├── SvgCrossword.tsx
│ │ ├── SvgMediaControlsPlay.tsx
│ │ ├── TableBlockComponent.stories.tsx
│ │ ├── TableBlockComponent.tsx
│ │ ├── TableOfContents.importable.tsx
│ │ ├── TableOfContents.stories.tsx
│ │ ├── TagPage.tsx
│ │ ├── TagPageHeader.stories.tsx
│ │ ├── TagPageHeader.tsx
│ │ ├── TextBlockComponent.amp.tsx
│ │ ├── TextBlockComponent.stories.tsx
│ │ ├── TextBlockComponent.tsx
│ │ ├── Timeline.stories.tsx
│ │ ├── Timeline.tsx
│ │ ├── TimelineAtom.amp.tsx
│ │ ├── TimelineAtom.importable.tsx
│ │ ├── TimelineAtom.stories.tsx
│ │ ├── TimelineAtom.test.tsx
│ │ ├── Titlepiece.importable.tsx
│ │ ├── Titlepiece.stories.tsx
│ │ ├── Toast.stories.tsx
│ │ ├── Toast.tsx
│ │ ├── TopBar.importable.tsx
│ │ ├── TopBar.stories.tsx
│ │ ├── TopBarLink.tsx
│ │ ├── TopBarMyAccount.tsx
│ │ ├── TopBarSupport.importable.tsx
│ │ ├── TopMeta.amp.tsx
│ │ ├── TopMetaAnalysis.amp.tsx
│ │ ├── TopMetaExtras.amp.tsx
│ │ ├── TopMetaLiveblog.amp.tsx
│ │ ├── TopMetaNews.amp.tsx
│ │ ├── TopMetaOpinion.amp.tsx
│ │ ├── TopMetaPaidContent.amp.tsx
│ │ ├── Treats.stories.tsx
│ │ ├── Treats.tsx
│ │ ├── TrendingTopics.tsx
│ │ ├── TweetBlockComponent.importable.tsx
│ │ ├── TwitterBlockComponent.amp.tsx
│ │ ├── UnsafeEmbedBlockComponent.importable.tsx
│ │ ├── UnsafeEmbedBlockComponent.stories.tsx
│ │ ├── VideoAtom.stories.tsx
│ │ ├── VideoAtom.tsx
│ │ ├── VideoFacebookBlockComponent.importable.tsx
│ │ ├── VideoFacebookBlockComponent.stories.tsx
│ │ ├── VideoVimeoBlockComponent.amp.tsx
│ │ ├── VideoYoutubeBlockComponent.amp.tsx
│ │ ├── VimeoBlockComponent.stories.tsx
│ │ ├── VimeoBlockComponent.tsx
│ │ ├── VineBlockComponent.importable.tsx
│ │ ├── WaveForm.stories.tsx
│ │ ├── WaveForm.tsx
│ │ ├── WitnessBlockComponent.stories.tsx
│ │ ├── WitnessBlockComponent.tsx
│ │ ├── YoutubeAtom
│ │ │ ├── YoutubeAtom.stories.tsx
│ │ │ ├── YoutubeAtom.test.tsx
│ │ │ ├── YoutubeAtom.tsx
│ │ │ ├── YoutubeAtomExpiredOverlay.tsx
│ │ │ ├── YoutubeAtomFeatureCardOverlay.tsx
│ │ │ ├── YoutubeAtomOverlay.tsx
│ │ │ ├── YoutubeAtomPicture.tsx
│ │ │ ├── YoutubeAtomPlaceholder.tsx
│ │ │ ├── YoutubeAtomPlayer.tsx
│ │ │ ├── YoutubeAtomSticky.tsx
│ │ │ ├── YoutubePlayer.ts
│ │ │ ├── eventEmitters.ts
│ │ │ ├── ima.d.ts
│ │ │ └── loadYouTubeApi.ts
│ │ ├── YoutubeBlockComponent.amp.tsx
│ │ ├── YoutubeBlockComponent.importable.tsx
│ │ ├── YoutubeBlockComponent.stories.tsx
│ │ ├── YoutubeEmbedBlockComponent.stories.tsx
│ │ ├── YoutubeEmbedBlockComponent.tsx
│ │ ├── marketing
│ │ │ ├── banners
│ │ │ │ ├── ThreeTierChoiceCardsV2.tsx
│ │ │ │ ├── common
│ │ │ │ │ ├── BannerWrapper.tsx
│ │ │ │ │ ├── PaymentCards.tsx
│ │ │ │ │ └── types.tsx
│ │ │ │ ├── designableBanner
│ │ │ │ │ ├── DesignableBanner.tsx
│ │ │ │ │ ├── DesignableBannerV2.tsx
│ │ │ │ │ ├── components
│ │ │ │ │ │ ├── BannerText.tsx
│ │ │ │ │ │ ├── CustomArticleCountCopy.tsx
│ │ │ │ │ │ ├── DesignableBannerArticleCount.tsx
│ │ │ │ │ │ ├── DesignableBannerArticleCountOptOut.tsx
│ │ │ │ │ │ ├── DesignableBannerBody.tsx
│ │ │ │ │ │ ├── DesignableBannerCloseButton.tsx
│ │ │ │ │ │ ├── DesignableBannerCtas.tsx
│ │ │ │ │ │ ├── DesignableBannerCtasV2.tsx
│ │ │ │ │ │ ├── DesignableBannerHeader.tsx
│ │ │ │ │ │ ├── DesignableBannerReminder.tsx
│ │ │ │ │ │ ├── DesignableBannerReminderSignedOut.tsx
│ │ │ │ │ │ ├── DesignableBannerVisual.tsx
│ │ │ │ │ │ └── choiceCards
│ │ │ │ │ │ │ ├── ChoiceCardInteractive.tsx
│ │ │ │ │ │ │ ├── ChoiceCards.tsx
│ │ │ │ │ │ │ └── ChoiceCardsSupportCta.tsx
│ │ │ │ │ ├── settings.ts
│ │ │ │ │ ├── stories
│ │ │ │ │ │ ├── DesignableBanner.stories.tsx
│ │ │ │ │ │ └── DesignableBannerV2.stories.tsx
│ │ │ │ │ └── styles
│ │ │ │ │ │ ├── buttonStyles.ts
│ │ │ │ │ │ └── templateStyles.ts
│ │ │ │ ├── signInPrompt
│ │ │ │ │ ├── SignInPromptBanner.stories.tsx
│ │ │ │ │ └── SignInPromptBanner.tsx
│ │ │ │ └── utils
│ │ │ │ │ ├── localStorage.ts
│ │ │ │ │ ├── storybook.ts
│ │ │ │ │ └── withCloseable.tsx
│ │ │ ├── epics
│ │ │ │ ├── BylineWithHeadshot.tsx
│ │ │ │ ├── ContributionsEpic.stories.tsx
│ │ │ │ ├── ContributionsEpic.test.tsx
│ │ │ │ ├── ContributionsEpic.tsx
│ │ │ │ ├── ContributionsEpicArticleCountAboveWithOptOut.tsx
│ │ │ │ ├── ContributionsEpicNewsletterSignup.tsx
│ │ │ │ ├── ContributionsEpicSignInCta.tsx
│ │ │ │ ├── ContributionsLiveblogEpic.stories.tsx
│ │ │ │ ├── ContributionsLiveblogEpic.tsx
│ │ │ │ ├── ThreeTierChoiceCards.tsx
│ │ │ │ ├── ctas
│ │ │ │ │ ├── ContributionsEpicButtons.tsx
│ │ │ │ │ ├── ContributionsEpicChoiceCards.tsx
│ │ │ │ │ ├── ContributionsEpicCtasContainer.tsx
│ │ │ │ │ ├── ContributionsEpicReminder.tsx
│ │ │ │ │ ├── ContributionsEpicReminderSignedIn.tsx
│ │ │ │ │ ├── ContributionsEpicReminderSignedOut.tsx
│ │ │ │ │ └── EpicButton.tsx
│ │ │ │ └── utils
│ │ │ │ │ ├── ophan.ts
│ │ │ │ │ ├── storybook.ts
│ │ │ │ │ └── threeTierChoiceCardAmounts.ts
│ │ │ ├── gutters
│ │ │ │ ├── GutterAsk.stories.tsx
│ │ │ │ ├── GutterAsk.tsx
│ │ │ │ ├── GutterAskWrapper.tsx
│ │ │ │ └── utils
│ │ │ │ │ └── storybook.ts
│ │ │ ├── header
│ │ │ │ ├── Header.stories.tsx
│ │ │ │ ├── Header.tsx
│ │ │ │ ├── HeaderWrapper.tsx
│ │ │ │ ├── SignInPromptHeader.stories.tsx
│ │ │ │ ├── SignInPromptHeader.tsx
│ │ │ │ └── common
│ │ │ │ │ └── HeaderDecorator.tsx
│ │ │ ├── hooks
│ │ │ │ ├── useArticleCountOptOut.ts
│ │ │ │ ├── useChoiceCards.ts
│ │ │ │ ├── useContributionsReminderEmailForm.ts
│ │ │ │ ├── useContributionsReminderSignup.ts
│ │ │ │ ├── useEscapeShortcut.ts
│ │ │ │ └── useReminder.ts
│ │ │ ├── lib
│ │ │ │ ├── ReactComponent.tsx
│ │ │ │ ├── articleCountOptOut.ts
│ │ │ │ ├── choiceCards.ts
│ │ │ │ ├── reminders.ts
│ │ │ │ ├── replaceArticleCount.tsx
│ │ │ │ ├── stage.ts
│ │ │ │ ├── storybook.ts
│ │ │ │ ├── tracking.test.ts
│ │ │ │ ├── tracking.ts
│ │ │ │ └── viewLog.ts
│ │ │ └── shared
│ │ │ │ ├── ArticleCountOptOutOverlay.tsx
│ │ │ │ ├── ArticleCountOptOutPopup.tsx
│ │ │ │ └── ResponsiveImage.tsx
│ │ └── numbers
│ │ │ ├── Eight.tsx
│ │ │ ├── Five.tsx
│ │ │ ├── Four.tsx
│ │ │ ├── Nine.tsx
│ │ │ ├── One.tsx
│ │ │ ├── Seven.tsx
│ │ │ ├── Six.tsx
│ │ │ ├── Ten.tsx
│ │ │ ├── Three.tsx
│ │ │ ├── Two.tsx
│ │ │ └── Zero.tsx
│ ├── cricketMatch.test.ts
│ ├── cricketMatch.ts
│ ├── devServer
│ │ ├── docs
│ │ │ ├── amp.tsx
│ │ │ ├── available.tsx
│ │ │ ├── doc.tsx
│ │ │ ├── dotcom.tsx
│ │ │ ├── editionsApp.tsx
│ │ │ ├── editionsCrosswords.tsx
│ │ │ ├── liveApps.tsx
│ │ │ ├── pages.tsx
│ │ │ └── targets.tsx
│ │ ├── routers
│ │ │ ├── amp.ts
│ │ │ ├── dotcom.ts
│ │ │ ├── editionsApp.ts
│ │ │ ├── liveApps.ts
│ │ │ ├── pages.ts
│ │ │ └── targets.ts
│ │ └── send.tsx
│ ├── experiments
│ │ ├── ab-tests.ts
│ │ ├── lib
│ │ │ ├── ab-participations.test.ts
│ │ │ └── ab-participations.ts
│ │ ├── tests
│ │ │ ├── ab-test-test.ts
│ │ │ ├── ad-block-ask.ts
│ │ │ ├── auxia-sign-in-gate.ts
│ │ │ ├── consentless-ads.ts
│ │ │ ├── integrate-ima.ts
│ │ │ ├── mpu-when-no-epic.ts
│ │ │ ├── optimise-spacefinder-inline.ts
│ │ │ ├── sign-in-gate-main-control.ts
│ │ │ ├── sign-in-gate-main-variant.ts
│ │ │ └── user-benefits-api.ts
│ │ └── utils.ts
│ ├── footballMatch.ts
│ ├── footballMatches.test.ts
│ ├── footballMatches.ts
│ ├── footballTables.ts
│ ├── frontend
│ │ ├── README.md
│ │ ├── feArticle.ts
│ │ ├── feCricketMatchPage.ts
│ │ ├── feFootballDataPage.ts
│ │ ├── feFootballMatchListPage.ts
│ │ ├── feFootballMatchPage.ts
│ │ ├── feFootballTablesPage.ts
│ │ ├── feFront.ts
│ │ ├── feTagPage.ts
│ │ └── schemas
│ │ │ ├── feArticle.json
│ │ │ ├── feCricketMatchPage.json
│ │ │ ├── feFootballMatchListPage.json
│ │ │ ├── feFootballMatchPage.json
│ │ │ ├── feFootballTablesPage.json
│ │ │ ├── feFront.json
│ │ │ └── feTagPage.json
│ ├── grid.ts
│ ├── layouts
│ │ ├── AllEditorialNewslettersPageLayout.tsx
│ │ ├── AudioLayout.tsx
│ │ ├── CommentLayout.tsx
│ │ ├── CrosswordLayout.tsx
│ │ ├── DecideLayout.stories.tsx
│ │ ├── DecideLayout.tsx
│ │ ├── FrontLayout.tsx
│ │ ├── FullPageInteractiveLayout.tsx
│ │ ├── GalleryLayout.stories.tsx
│ │ ├── GalleryLayout.tsx
│ │ ├── ImmersiveLayout.tsx
│ │ ├── InteractiveLayout.tsx
│ │ ├── LiveLayout.tsx
│ │ ├── NewsletterSignupLayout.tsx
│ │ ├── PictureLayout.tsx
│ │ ├── ShowcaseLayout.tsx
│ │ ├── SportDataPageLayout.stories.tsx
│ │ ├── SportDataPageLayout.tsx
│ │ ├── StandardLayout.tsx
│ │ ├── TagPageLayout.tsx
│ │ └── lib
│ │ │ ├── interactiveLegacyStyling.test.ts
│ │ │ ├── interactiveLegacyStyling.ts
│ │ │ ├── pageSkin.ts
│ │ │ └── stickiness.tsx
│ ├── lib
│ │ ├── ArticleRenderer.tsx
│ │ ├── acquisitions.test.ts
│ │ ├── acquisitions.ts
│ │ ├── ad-json.amp.test.ts
│ │ ├── ad-json.amp.ts
│ │ ├── ad-targeting.test.ts
│ │ ├── ad-targeting.ts
│ │ ├── adStyles.ts
│ │ ├── age-warning.test.ts
│ │ ├── age-warning.ts
│ │ ├── alreadyVisited.ts
│ │ ├── alternate-lang-links.test.ts
│ │ ├── alternate-lang-links.ts
│ │ ├── articleCount.ts
│ │ ├── articleFormat.ts
│ │ ├── assert-unreachable.ts
│ │ ├── assets.test.ts
│ │ ├── assets.ts
│ │ ├── audio-data.ts
│ │ ├── block-link.amp.ts
│ │ ├── branding.test.ts
│ │ ├── branding.ts
│ │ ├── braze
│ │ │ ├── buildBrazeMessaging.ts
│ │ │ ├── checkBrazeDependencies.test.ts
│ │ │ ├── checkBrazeDependencies.ts
│ │ │ ├── forceBrazeMessage.ts
│ │ │ ├── hasRequiredConsents.test.ts
│ │ │ ├── hasRequiredConsents.ts
│ │ │ ├── initialiseBraze.ts
│ │ │ └── taylorReport.ts
│ │ ├── bridgetApi.ts
│ │ ├── buildNewsletterSignUpText.test.tsx
│ │ ├── buildNewsletterSignUpText.tsx
│ │ ├── byline-tokens.amp.test.ts
│ │ ├── byline-tokens.amp.ts
│ │ ├── byline.test.ts
│ │ ├── byline.ts
│ │ ├── canRenderAds.test.ts
│ │ ├── canRenderAds.ts
│ │ ├── cardHelpers.test.ts
│ │ ├── cardHelpers.ts
│ │ ├── cardWrappers.tsx
│ │ ├── center.ts
│ │ ├── commercial-constants.ts
│ │ ├── contributions.test.ts
│ │ ├── contributions.ts
│ │ ├── dailyArticleCount.test.ts
│ │ ├── dailyArticleCount.ts
│ │ ├── decide-caption.ts
│ │ ├── decide-cation.test.ts
│ │ ├── decideLogo.ts
│ │ ├── decideNavPillar.ts
│ │ ├── decideTrail.ts
│ │ ├── detect-adblock.ts
│ │ ├── discussion.ts
│ │ ├── discussionApi.tsx
│ │ ├── discussionDateFormatter.ts
│ │ ├── discussionFilters.ts
│ │ ├── domUtils.ts
│ │ ├── dynamicSlices.test.ts
│ │ ├── dynamicSlices.tsx
│ │ ├── edition.test.ts
│ │ ├── edition.ts
│ │ ├── emotion.tsx
│ │ ├── enhance.amp.test.ts
│ │ ├── enhance.amp.ts
│ │ ├── errors
│ │ │ └── not-renderable-in-dcr.ts
│ │ ├── escapeData.test.tsx
│ │ ├── escapeData.tsx
│ │ ├── fetchEmail.ts
│ │ ├── find-adslots.amp.test.ts
│ │ ├── find-adslots.amp.ts
│ │ ├── fonts-css.ts
│ │ ├── formatAttrString.test.ts
│ │ ├── formatAttrString.ts
│ │ ├── formatCount.test.ts
│ │ ├── formatCount.ts
│ │ ├── formatTime.test.ts
│ │ ├── formatTime.ts
│ │ ├── frontsBannerAdExclusions.ts
│ │ ├── get-video-id.amp.test.ts
│ │ ├── get-video-id.amp.ts
│ │ ├── getABUrlHash.test.ts
│ │ ├── getAbUrlHash.ts
│ │ ├── getBrazeUuid.ts
│ │ ├── getCountryCode.ts
│ │ ├── getDataLinkName.ts
│ │ ├── getFrontsAdPositions.test.ts
│ │ ├── getFrontsAdPositions.ts
│ │ ├── getIdapiUserData.ts
│ │ ├── getLiveblogAdPositions.test.ts
│ │ ├── getLiveblogAdPositions.ts
│ │ ├── getPrivacyFramework.ts
│ │ ├── getSourceImageUrl_temp_fix.ts
│ │ ├── getTagPageAdPositions.test.ts
│ │ ├── getTagPageAdPositions.ts
│ │ ├── getZIndex.test.ts
│ │ ├── getZIndex.ts
│ │ ├── hasCurrentBrazeUser.test.ts
│ │ ├── hasCurrentBrazeUser.ts
│ │ ├── hiddenStyles.tsx
│ │ ├── hideAge.ts
│ │ ├── identity-component-event.test.ts
│ │ ├── identity-component-event.ts
│ │ ├── identity.ts
│ │ ├── image-fit.amp.test.ts
│ │ ├── image-fit.amp.ts
│ │ ├── image.ts
│ │ ├── isLight.test.ts
│ │ ├── isLight.ts
│ │ ├── isServer.ts
│ │ ├── isValidUrl.test.ts
│ │ ├── isValidUrl.ts
│ │ ├── json.ts
│ │ ├── labs-constants.ts
│ │ ├── labs.test.ts
│ │ ├── labs.ts
│ │ ├── lang.test.ts
│ │ ├── lang.ts
│ │ ├── layoutHelpers.ts
│ │ ├── linkNotificationCount.test.ts
│ │ ├── linkNotificationCount.ts
│ │ ├── liveblogAdSlots.test.ts
│ │ ├── liveblogAdSlots.ts
│ │ ├── memoize.test.ts
│ │ ├── memoize.ts
│ │ ├── messagePicker.test.tsx
│ │ ├── messagePicker.ts
│ │ ├── mixins.ts
│ │ ├── mockRESTCalls.ts
│ │ ├── mockRESTCallsInJest.ts
│ │ ├── newsletter-sign-up-requests.test.ts
│ │ ├── newsletter-sign-up-requests.ts
│ │ ├── notification.test.ts
│ │ ├── notification.ts
│ │ ├── ophan-helpers.test.ts
│ │ ├── ophan-helpers.ts
│ │ ├── parser
│ │ │ ├── jsonParser.ts
│ │ │ ├── parseCheckoutOutCookieData.test.ts
│ │ │ └── parseCheckoutOutCookieData.ts
│ │ ├── permutive.amp.test.ts
│ │ ├── permutive.amp.ts
│ │ ├── pillars.ts
│ │ ├── polyfill.io.ts
│ │ ├── querystring.test.ts
│ │ ├── querystring.ts
│ │ ├── readerRevenueDevUtils.ts
│ │ ├── real-time-config.amp.ts
│ │ ├── region-classes.amp.ts
│ │ ├── renderElement.tsx
│ │ ├── result.ts
│ │ ├── revealStyles.ts
│ │ ├── rootStyles.ts
│ │ ├── scheduler.test.ts
│ │ ├── scheduler.ts
│ │ ├── scripts.amp.ts
│ │ ├── sendTargetingParams.apps.test.ts
│ │ ├── sendTargetingParams.apps.ts
│ │ ├── setAutomat.ts
│ │ ├── sharing-urls.ts
│ │ ├── signInAfterCheckOutText.ts
│ │ ├── slot-machine-flags.ts
│ │ ├── srcset-utils.amp.ts
│ │ ├── stringifyFileBase64.ts
│ │ ├── tag-utils.amp.test.ts
│ │ ├── tag-utils.amp.ts
│ │ ├── themeToPillar.ts
│ │ ├── thrift
│ │ │ ├── nativeConnection.ts
│ │ │ └── protocols.ts
│ │ ├── transparentColour.test.ts
│ │ ├── transparentColour.ts
│ │ ├── tuple.test.ts
│ │ ├── tuple.ts
│ │ ├── unifyPageContent.test.tsx
│ │ ├── unifyPageContent.tsx
│ │ ├── useAB.ts
│ │ ├── useAdBlockAsk.ts
│ │ ├── useAdBlockInUse.ts
│ │ ├── useAdTargeting.ts
│ │ ├── useApi.ts
│ │ ├── useAuthStatus.ts
│ │ ├── useBraze.ts
│ │ ├── useCommentCount.ts
│ │ ├── useCountryCode.ts
│ │ ├── useDetectAdBlock.ts
│ │ ├── useEditionSwitcherBanner.ts
│ │ ├── useHover.tsx
│ │ ├── useHydrated.ts
│ │ ├── useInterval.ts
│ │ ├── useIsBridgetCompatible.test.ts
│ │ ├── useIsBridgetCompatible.ts
│ │ ├── useIsHorizontalScrollingSupported.ts
│ │ ├── useIsInView.ts
│ │ ├── useIsMyGuardianEnabled.ts
│ │ ├── useMatchMedia.ts
│ │ ├── useOnce.ts
│ │ ├── useOnlineStatus.ts
│ │ ├── usePageViewId.ts
│ │ ├── useRequestSignUp.ts
│ │ ├── useSDC.ts
│ │ ├── useShouldAdapt.ts
│ │ ├── useSignInGateSelector.ts
│ │ ├── useSignInGateWillShow.ts
│ │ ├── verticalDivider.ts
│ │ ├── verticalDividerWithBottomOffset.ts
│ │ └── withSignInGateSlot.tsx
│ ├── model
│ │ ├── appsLightboxImages.ts
│ │ ├── article-sections.test.ts
│ │ ├── article-sections.ts
│ │ ├── block-schema.json
│ │ ├── buildCrosswordBlock.ts
│ │ ├── buildLightboxImages.ts
│ │ ├── decideContainerPalette.ts
│ │ ├── editions-crossword-schema.json
│ │ ├── enhance-H2s.test.ts
│ │ ├── enhance-H2s.ts
│ │ ├── enhance-ad-placeholders.test.ts
│ │ ├── enhance-ad-placeholders.ts
│ │ ├── enhance-blockquotes.test.ts
│ │ ├── enhance-blockquotes.ts
│ │ ├── enhance-disclaimer.ts
│ │ ├── enhance-dividers.test.ts
│ │ ├── enhance-dividers.ts
│ │ ├── enhance-dots.test.ts
│ │ ├── enhance-dots.ts
│ │ ├── enhance-embeds.test.ts
│ │ ├── enhance-embeds.ts
│ │ ├── enhance-images.test.ts
│ │ ├── enhance-images.ts
│ │ ├── enhance-interactive-contents-elements.ts
│ │ ├── enhance-newsletters-page.ts
│ │ ├── enhance-numbered-lists.test.ts
│ │ ├── enhance-numbered-lists.ts
│ │ ├── enhance-switches.ts
│ │ ├── enhance-tweets.ts
│ │ ├── enhance-videos.test.ts
│ │ ├── enhance-videos.ts
│ │ ├── enhanceBlocks.ts
│ │ ├── enhanceCards.ts
│ │ ├── enhanceCollections.ts
│ │ ├── enhanceCommercialProperties.test.ts
│ │ ├── enhanceCommercialProperties.ts
│ │ ├── enhanceLists.test.ts
│ │ ├── enhanceLists.ts
│ │ ├── enhanceSnaps.ts
│ │ ├── enhanceStandfirst.ts
│ │ ├── enhanceTableOfContents.test.ts
│ │ ├── enhanceTableOfContents.ts
│ │ ├── enhanceTags.test.ts
│ │ ├── enhanceTags.ts
│ │ ├── enhanceTimeline.test.ts
│ │ ├── enhanceTimeline.ts
│ │ ├── enhanceTreats.ts
│ │ ├── extract-nav.ts
│ │ ├── extractTrendingTopics.test.ts
│ │ ├── extractTrendingTopics.ts
│ │ ├── find-pillar.test.ts
│ │ ├── find-pillar.ts
│ │ ├── groupCards.ts
│ │ ├── groupTrailsByDates.test.ts
│ │ ├── groupTrailsByDates.ts
│ │ ├── guardian.ts
│ │ ├── insertPromotedNewsletter.test.ts
│ │ ├── insertPromotedNewsletter.ts
│ │ ├── isLegacyTableOfContents.ts
│ │ ├── newsletter-page-schema.json
│ │ ├── pinnedPost.ts
│ │ ├── sanitise.test.ts
│ │ ├── sanitise.ts
│ │ ├── slowOrFastByTrails.ts
│ │ ├── transformDots.ts
│ │ ├── unwrapHtml.test.ts
│ │ ├── unwrapHtml.ts
│ │ ├── validate.test.ts
│ │ └── validate.ts
│ ├── palette.ts
│ ├── paletteDeclarations.ts
│ ├── server
│ │ ├── AMPExperimentCache.amp.ts
│ │ ├── dev-index.html
│ │ ├── handler.allEditorialNewslettersPage.web.ts
│ │ ├── handler.article.amp.tsx
│ │ ├── handler.article.apps.ts
│ │ ├── handler.article.web.ts
│ │ ├── handler.editionsCrossword.ts
│ │ ├── handler.front.web.test.ts
│ │ ├── handler.front.web.ts
│ │ ├── handler.sportDataPage.web.test.ts
│ │ ├── handler.sportDataPage.web.ts
│ │ ├── htmlCrosswordPageTemplate.ts
│ │ ├── htmlPageTemplate.ts
│ │ ├── lib
│ │ │ ├── aws
│ │ │ │ ├── aws-metrics.ts
│ │ │ │ └── metrics-baseline.ts
│ │ │ ├── get-content-from-url.test.ts
│ │ │ ├── get-content-from-url.ts
│ │ │ ├── header.ts
│ │ │ ├── logging-middleware.ts
│ │ │ ├── logging-store.ts
│ │ │ └── logging.ts
│ │ ├── prout.ts
│ │ ├── render.allEditorialNewslettersPage.web.tsx
│ │ ├── render.article.amp.test.tsx
│ │ ├── render.article.amp.tsx
│ │ ├── render.article.apps.tsx
│ │ ├── render.article.web.tsx
│ │ ├── render.editionsCrossword.tsx
│ │ ├── render.front.web.tsx
│ │ ├── render.sportDataPage.web.tsx
│ │ ├── server.dev.ts
│ │ ├── server.prod.ts
│ │ └── server.ts
│ ├── sportDataPage.ts
│ ├── static
│ │ ├── badges
│ │ │ ├── 05_july_2022_Badge.svg
│ │ │ ├── 100days.svg
│ │ │ ├── 18_feb_2022_Badge.svg
│ │ │ ├── 56738_Badge.svg
│ │ │ ├── EUReferendumBadge.svg
│ │ │ ├── GE2017Badge.svg
│ │ │ ├── SpecialReportJul21.svg
│ │ │ ├── SpecialReportSep21.svg
│ │ │ ├── anniversary200.svg
│ │ │ ├── australian-election-2019.svg
│ │ │ ├── australian-election-2022.svg
│ │ │ ├── behind-the-lines.svg
│ │ │ ├── beyondthebladebadge.svg
│ │ │ ├── bias-in-britain.svg
│ │ │ ├── calock.svg
│ │ │ ├── cop26-badge.svg
│ │ │ ├── corona-badge.svg
│ │ │ ├── cricket-world-cup.svg
│ │ │ ├── culture-badge.svg
│ │ │ ├── dreams-interrupted.svg
│ │ │ ├── election-badge-4.svg
│ │ │ ├── eohk.svg
│ │ │ ├── eu_election.svg
│ │ │ ├── euro-2020.svg
│ │ │ ├── facebookFiles.svg
│ │ │ ├── futureofcities.svg
│ │ │ ├── ge2019-badge.svg
│ │ │ ├── general-election-2019.svg
│ │ │ ├── green-blood.svg
│ │ │ ├── green-recovery.svg
│ │ │ ├── johnsons-promises.svg
│ │ │ ├── london-versus.svg
│ │ │ ├── lost-in-politics-badge.svg
│ │ │ ├── midterm.svg
│ │ │ ├── new-arrivals.png
│ │ │ ├── newsletter-badge.svg
│ │ │ ├── nhs-70.svg
│ │ │ ├── pp_web.svg
│ │ │ ├── rugby-world-cup.svg
│ │ │ ├── spy-cops-scandal.svg
│ │ │ ├── the-age-of-extinction.svg
│ │ │ ├── the-empty-doorway.svg
│ │ │ ├── the-implant-files.svg
│ │ │ ├── the-last-chance.svg
│ │ │ ├── the-new-populism.svg
│ │ │ ├── the-polluters.svg
│ │ │ ├── the-real-boris-johnson.svg
│ │ │ ├── this-is-europe.svg
│ │ │ ├── tokyo-2020.svg
│ │ │ ├── uk-debt.svg
│ │ │ ├── us-midterm-elections-2022.svg
│ │ │ ├── winter-olympics-2022-badge.svg
│ │ │ ├── womens-world-cup.svg
│ │ │ ├── womens_euros_2022_badge.svg
│ │ │ ├── world-cup-2018.svg
│ │ │ ├── world-cup-2022.svg
│ │ │ └── yemen-at-war.svg
│ │ ├── css
│ │ │ └── print.css
│ │ ├── icons
│ │ │ ├── Star.tsx
│ │ │ ├── arrow-in-circle.svg
│ │ │ ├── arrow-right.svg
│ │ │ ├── audio
│ │ │ │ ├── skip-backward-15.svg
│ │ │ │ └── skip-forward-15.svg
│ │ │ ├── camera.svg
│ │ │ ├── chevron-left-double.svg
│ │ │ ├── chevron-left-single.svg
│ │ │ ├── chevron-right-double.svg
│ │ │ ├── chevron-right-single.svg
│ │ │ ├── clock.svg
│ │ │ ├── comment.svg
│ │ │ ├── down-arrow.svg
│ │ │ ├── email.svg
│ │ │ ├── external-link.svg
│ │ │ ├── facebook.svg
│ │ │ ├── gifting.svg
│ │ │ ├── homescreen
│ │ │ │ ├── apple-touch-icon-120.png
│ │ │ │ ├── apple-touch-icon-240.png
│ │ │ │ ├── apple-touch-icon-360.png
│ │ │ │ ├── apple-touch-icon-512.png
│ │ │ │ ├── apple-touch-icon.svg
│ │ │ │ ├── roundel-114x114.png
│ │ │ │ ├── roundel-152x152.png
│ │ │ │ ├── roundel-192x192.png
│ │ │ │ ├── roundel-256x256.png
│ │ │ │ ├── roundel-512x512.png
│ │ │ │ └── roundel.svg
│ │ │ ├── info.svg
│ │ │ ├── linked-in.svg
│ │ │ ├── messenger.svg
│ │ │ ├── minus.svg
│ │ │ ├── newspaper.svg
│ │ │ ├── plus.svg
│ │ │ ├── profile.svg
│ │ │ ├── quote.svg
│ │ │ ├── refresh.svg
│ │ │ ├── search.svg
│ │ │ ├── share.svg
│ │ │ ├── the-guardian-roundel.svg
│ │ │ ├── tick.svg
│ │ │ ├── triangle.svg
│ │ │ ├── twitter-padded.svg
│ │ │ ├── twitter.svg
│ │ │ ├── video-icon.svg
│ │ │ ├── volume-high.svg
│ │ │ ├── weather
│ │ │ │ ├── weather-1.svg
│ │ │ │ ├── weather-11.svg
│ │ │ │ ├── weather-12.svg
│ │ │ │ ├── weather-13.svg
│ │ │ │ ├── weather-14.svg
│ │ │ │ ├── weather-15.svg
│ │ │ │ ├── weather-16.svg
│ │ │ │ ├── weather-17.svg
│ │ │ │ ├── weather-18.svg
│ │ │ │ ├── weather-19.svg
│ │ │ │ ├── weather-2.svg
│ │ │ │ ├── weather-20.svg
│ │ │ │ ├── weather-21.svg
│ │ │ │ ├── weather-22.svg
│ │ │ │ ├── weather-23.svg
│ │ │ │ ├── weather-24.svg
│ │ │ │ ├── weather-25.svg
│ │ │ │ ├── weather-26.svg
│ │ │ │ ├── weather-29.svg
│ │ │ │ ├── weather-3.svg
│ │ │ │ ├── weather-30.svg
│ │ │ │ ├── weather-31.svg
│ │ │ │ ├── weather-32.svg
│ │ │ │ ├── weather-33.svg
│ │ │ │ ├── weather-34.svg
│ │ │ │ ├── weather-35.svg
│ │ │ │ ├── weather-36.svg
│ │ │ │ ├── weather-37.svg
│ │ │ │ ├── weather-38.svg
│ │ │ │ ├── weather-39.svg
│ │ │ │ ├── weather-4.svg
│ │ │ │ ├── weather-40.svg
│ │ │ │ ├── weather-41.svg
│ │ │ │ ├── weather-42.svg
│ │ │ │ ├── weather-43.svg
│ │ │ │ ├── weather-44.svg
│ │ │ │ ├── weather-5.svg
│ │ │ │ ├── weather-6.svg
│ │ │ │ ├── weather-7.svg
│ │ │ │ └── weather-8.svg
│ │ │ ├── whatsapp.svg
│ │ │ └── x.svg
│ │ ├── js
│ │ │ └── curl-with-js-and-domReady.js
│ │ ├── logos
│ │ │ ├── hands.png
│ │ │ └── the-guardian-labs.svg
│ │ └── manifest.json
│ └── types
│ │ ├── article.amp.tsx
│ │ ├── article.ts
│ │ ├── badge.ts
│ │ ├── blocks.ts
│ │ ├── branding.ts
│ │ ├── commercial.ts
│ │ ├── config.ts
│ │ ├── configContext.ts
│ │ ├── content.ts
│ │ ├── editionsCrossword.ts
│ │ ├── footer.ts
│ │ ├── front.ts
│ │ ├── frontend.ts
│ │ ├── layout.ts
│ │ ├── liveBlog.ts
│ │ ├── mainMedia.ts
│ │ ├── matchReport.ts
│ │ ├── newslettersPage.ts
│ │ ├── onwards.ts
│ │ ├── palette.ts
│ │ ├── renderingTarget.ts
│ │ ├── sentry.ts
│ │ ├── sport.ts
│ │ ├── tag.ts
│ │ ├── tagPage.ts
│ │ ├── territory.ts
│ │ └── trails.ts
├── stories
│ └── generated
│ │ ├── Card.stories.tsx
│ │ └── CardReadme.stories.jsx
├── stylelint.config.mjs
├── tsconfig.build.json
├── tsconfig.json
├── webpack.config.mjs
├── webpack
│ ├── .swcrc.json
│ ├── @types
│ │ ├── webpack-filter-warnings-plugin
│ │ │ └── index.d.ts
│ │ └── webpack-messages
│ │ │ └── index.d.ts
│ ├── browser-targets.js
│ ├── browser-targets.test.ts
│ ├── bundles.js
│ ├── svg.cjs
│ ├── webpack.config.client.js
│ ├── webpack.config.dev-server.js
│ ├── webpack.config.js
│ └── webpack.config.server.js
└── window.guardian.ts
├── package.json
├── patches
└── webpack-manifest-plugin@5.0.0.patch
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── scripts
├── deno
├── README.md
├── bots.ts
├── deno.json
├── deno.lock
├── eslint.ts
├── github.ts
├── iframe-titles.ts
├── json.ts
└── thrasher-tracker.ts
├── env
├── check-dependencies-mismatches.mjs
├── check-node
└── check-package-manager
├── log.js
└── postinstall.sh
/.editorconfig:
--------------------------------------------------------------------------------
1 | ; This file is for unifying the coding style for different editors and IDEs
2 | ; See editorconfig.org
3 |
4 | ; top-most EditorConfig file
5 | root = true
6 |
7 | [*]
8 | indent_style = tab
9 | indent_size = 4
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
15 | [package.json]
16 | indent_size = 2
17 |
18 | [makefile]
19 | indent_style = tab
20 |
21 | [*.{yml,yaml}]
22 | indent_size = 2
23 | indent_style = space
24 |
--------------------------------------------------------------------------------
/.github/actions/setup-node-env/action.yml:
--------------------------------------------------------------------------------
1 | name: 'Setup Environment'
2 | description: 'Sets up Node.js environment and installs dependencies'
3 |
4 | runs:
5 | using: 'composite'
6 | steps:
7 | - run: npm install --global corepack@0.31.0
8 | shell: bash
9 |
10 | - run: corepack enable
11 | shell: bash
12 |
13 | - uses: actions/setup-node@v4
14 | with:
15 | node-version-file: '.nvmrc'
16 | cache: 'pnpm'
17 |
18 | - run: pnpm install --frozen-lockfile
19 | shell: bash
20 |
--------------------------------------------------------------------------------
/.github/labeler.yml:
--------------------------------------------------------------------------------
1 | # https://github.com/marketplace/actions/labeler
2 |
3 | dotcom-rendering:
4 | - changed-files:
5 | - any-glob-to-any-file: 'dotcom-rendering/**/*'
6 | apps-rendering:
7 | - changed-files:
8 | - any-glob-to-any-file: 'apps-rendering/**/*'
9 |
--------------------------------------------------------------------------------
/.github/workflows/build-check.yml:
--------------------------------------------------------------------------------
1 | name: DCR Build Check
2 | on:
3 | push:
4 | paths-ignore:
5 | - 'apps-rendering/**'
6 | - 'dotcom-rendering/docs/**'
7 |
8 | jobs:
9 | build_check:
10 | name: DCR Build Check
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout code
14 | uses: actions/checkout@v4
15 |
16 | - name: Set up Node environment
17 | uses: ./.github/actions/setup-node-env
18 |
19 | - name: Generate production build
20 | run: make build
21 | working-directory: dotcom-rendering
22 |
23 | - name: Validate Build
24 | run: make buildCheck
25 | working-directory: dotcom-rendering
26 |
--------------------------------------------------------------------------------
/.github/workflows/deno.yml:
--------------------------------------------------------------------------------
1 | name: 🦕 Deno health
2 | on:
3 | pull_request:
4 | paths:
5 | - 'scripts/deno/**'
6 |
7 | jobs:
8 | deno:
9 | name: 🦕 Deno health
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v4
13 |
14 | # https://github.com/denoland/setup-deno#latest-stable-for-a-major
15 | - uses: denoland/setup-deno@v1
16 | with:
17 | deno-version: v1.44
18 |
19 | - name: Format
20 | run: deno fmt scripts/deno
21 |
22 | - name: Lint
23 | run: deno lint scripts/deno
24 |
25 | - name: Type-check
26 | run: deno check scripts/deno/**.ts
27 |
--------------------------------------------------------------------------------
/.github/workflows/jest.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 |
4 | jobs:
5 | jest:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v4
9 |
10 | - name: Set up Node environment
11 | uses: ./.github/actions/setup-node-env
12 |
13 | - name: Run Jest
14 | run: CI=true pnpm test
15 | working-directory: dotcom-rendering
16 |
--------------------------------------------------------------------------------
/.github/workflows/labeler.yml:
--------------------------------------------------------------------------------
1 | name: 'Pull Request Labeler'
2 | on:
3 | - pull_request_target
4 |
5 | jobs:
6 | triage:
7 | permissions:
8 | contents: read
9 | pull-requests: write
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/labeler@v5
13 | with:
14 | repo-token: '${{ secrets.GITHUB_TOKEN }}'
15 | sync-labels: true # remove redundant labels after a change
16 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 |
4 | jobs:
5 | check:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v4
9 |
10 | - name: Set up Node environment
11 | uses: ./.github/actions/setup-node-env
12 |
13 | - name: Lint Project
14 | run: make lint-project
15 | working-directory: dotcom-rendering
16 |
17 | - name: Lint
18 | run: make lint
19 | working-directory: dotcom-rendering
20 |
21 | - name: Stylelint
22 | run: make stylelint
23 | working-directory: dotcom-rendering
24 |
--------------------------------------------------------------------------------
/.github/workflows/permissions-advisor.yml:
--------------------------------------------------------------------------------
1 | name: Permissions Advisor
2 |
3 | permissions:
4 | actions: read
5 |
6 | on:
7 | workflow_dispatch:
8 | inputs:
9 | name:
10 | description: 'The name of the workflow file to analyze'
11 | required: true
12 | type: string
13 | count:
14 | description: 'How many last runs to analyze'
15 | required: false
16 | type: number
17 | default: 5
18 |
19 | jobs:
20 | advisor:
21 | runs-on: ubuntu-latest
22 | steps:
23 | - uses: GitHubSecurityLab/actions-permissions/advisor@v1
24 | with:
25 | name: ${{ inputs.name }}
26 | count: ${{ inputs.count }}
27 |
--------------------------------------------------------------------------------
/.github/workflows/prettier.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 |
4 | jobs:
5 | check:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v4
9 |
10 | - name: Set up Node environment
11 | uses: ./.github/actions/setup-node-env
12 |
13 | - name: Prettier check
14 | run: pnpm prettier:check
15 |
--------------------------------------------------------------------------------
/.github/workflows/schema-check.yml:
--------------------------------------------------------------------------------
1 | name: DCR Schema Check
2 | on:
3 | push:
4 | paths-ignore:
5 | - 'apps-rendering/**'
6 | - 'dotcom-rendering/docs/**'
7 |
8 | jobs:
9 | build_check:
10 | name: DCR Schema Check
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout code
14 | uses: actions/checkout@v4
15 |
16 | - name: Set up Node environment
17 | uses: ./.github/actions/setup-node-env
18 |
19 | - name: Run check-schemas script
20 | run: make check-schemas
21 | working-directory: dotcom-rendering
22 |
--------------------------------------------------------------------------------
/.github/workflows/stories-check.yml:
--------------------------------------------------------------------------------
1 | name: DCR Stories Check
2 | on:
3 | push:
4 | paths-ignore:
5 | - 'apps-rendering/**'
6 | - 'dotcom-rendering/docs/**'
7 |
8 | jobs:
9 | build_check:
10 | name: DCR Stories Check
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout code
14 | uses: actions/checkout@v4
15 |
16 | - name: Set up Node environment
17 | uses: ./.github/actions/setup-node-env
18 |
19 | - name: Run check-stories script
20 | run: make check-stories
21 | working-directory: dotcom-rendering
22 |
--------------------------------------------------------------------------------
/.github/workflows/typescript.yml:
--------------------------------------------------------------------------------
1 | name: DCR typescript 🕵♀
2 | on:
3 | push:
4 | paths-ignore:
5 | - 'apps-rendering/**'
6 | - 'dotcom-rendering/docs/**'
7 |
8 | jobs:
9 | typescript:
10 | name: Typescript
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 |
15 | - name: Set up Node environment
16 | uses: ./.github/actions/setup-node-env
17 |
18 | - name: Check typescript
19 | run: pnpm tsc
20 | working-directory: dotcom-rendering
21 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | # don't run this on CI
2 | # https://typicode.github.io/husky/#/?id=with-env-variables
3 | [ -n "$CI" ] && exit 0
4 |
5 | pnpm lint-staged
6 |
--------------------------------------------------------------------------------
/.husky/pre-push:
--------------------------------------------------------------------------------
1 | currentBranch="$(git rev-parse --abbrev-ref HEAD)"
2 |
3 | if [[ $currentBranch == "main" ]]
4 | then
5 | echo "⚠️ You should not push to the \`main\` branch"
6 | exit 1
7 | fi
8 |
9 | cd ./$(dirname "$0")/../dotcom-rendering
10 | make tsc
11 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | save-prefix=''
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 22.14.0
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | dist
2 | deno
3 | .nvmrc
4 | pnpm-lock.yaml
5 |
6 | # generated files
7 | dotcom-rendering/src/model/*-schema.json
8 | dotcom-rendering/src/frontend/schemas
9 | dotcom-rendering/stories/generated
10 |
11 | # specific files
12 | /**/*/curl-with-js-and-domReady.js
13 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | "@guardian/prettier"
2 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "esbenp.prettier-vscode",
4 | "wix.vscode-import-cost",
5 | "orta.vscode-jest",
6 | "editorconfig.editorconfig",
7 | "dbaeumer.vscode-eslint",
8 | "stkb.rewrap",
9 | "styled-components.vscode-styled-components",
10 | "stylelint.vscode-stylelint",
11 | "eamodio.gitlens",
12 | "streetsidesoftware.code-spell-checker",
13 | "denoland.vscode-deno",
14 | "redhat.vscode-yaml"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/.vscode/settings.json.required:
--------------------------------------------------------------------------------
1 | // Required VS Code settings for this project.
2 | // Copy these to .vscode/settings.json to apply them to your editor – but don't commit it!
3 | // https://github.com/guardian/recommendations/blob/main/VSCode.md#do-not-commit-vscode
4 | {
5 | "deno.enablePaths": ["scripts/deno"],
6 | "deno.lint": true,
7 | "deno.unstable": false,
8 | "typescript.tsdk": "node_modules/typescript/lib",
9 | "git.branchProtection": ["main"],
10 | "eslint.workingDirectories": ["./dotcom-rendering"]
11 | }
12 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Welcome to the the Guardian's Apps & Web rendering platforms
2 |
3 | Read our [Code of conduct](./CODE_OF_CONDUCT.md) to help keep things approachable and respectful.
4 |
5 | Interested in our web rendering platform? [Start here ➡️](./dotcom-rendering/docs/contributing/README.md)
6 |
7 | Interested in our apps rendering platform? [Start here ➡️](./apps-rendering/README.md)
8 |
--------------------------------------------------------------------------------
/apps-rendering/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | indent_size = 4
--------------------------------------------------------------------------------
/apps-rendering/.eslintignore:
--------------------------------------------------------------------------------
1 | *.test.ts
2 | node_modules
3 | api-models
4 | webpack.config.ts
5 | cdk.out
6 |
--------------------------------------------------------------------------------
/apps-rendering/.gitignore:
--------------------------------------------------------------------------------
1 | ### Node template
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 |
7 | # Dependency directories
8 | node_modules
9 |
10 | # IDE files
11 | .idea
12 | .vscode/*
13 | !.vscode/extensions.json
14 | .metals/
15 | .bloop/
16 | project/.bloop/
17 | project/metals.sbt
18 | .bsp/
19 |
20 | # System files
21 | .DS_Store
22 |
23 | # Built files
24 | dist
25 |
26 | # Istanbul/Jest code coverage
27 | coverage
28 |
29 | # CDK asset staging directory
30 | .cdk.staging
31 | cdk.out
32 |
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-Bold.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-BoldItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-Light.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-LightItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-Medium.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-MediumItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-Regular.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-RegularItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-RegularItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-Semibold.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GHGuardianHeadline-SemiboldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GHGuardianHeadline-SemiboldItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextEgyptian-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextEgyptian-Bold.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextEgyptian-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextEgyptian-BoldItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextEgyptian-Reg.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextEgyptian-Reg.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextEgyptian-RegItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextEgyptian-RegItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextSans-Bold.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextSans-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextSans-BoldItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextSans-Regular.ttf
--------------------------------------------------------------------------------
/apps-rendering/assets/fonts/GuardianTextSans-RegularItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/apps-rendering/assets/fonts/GuardianTextSans-RegularItalic.ttf
--------------------------------------------------------------------------------
/apps-rendering/cdk.json:
--------------------------------------------------------------------------------
1 | {
2 | "app": "pnpm tsx cdk/bin/cdk.ts",
3 | "context": {
4 | "aws-cdk:enableDiffNoFail": "true",
5 | "@aws-cdk/core:stackRelativeExports": "true"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/apps-rendering/cdk/README.md:
--------------------------------------------------------------------------------
1 | # Infrastructure
2 |
3 | This directory defines the components to be deployed to AWS
4 |
--------------------------------------------------------------------------------
/apps-rendering/config/jestSetup.js:
--------------------------------------------------------------------------------
1 | jest.mock('@guardian/cdk/lib/constants/tracking-tag');
2 |
3 | /**
4 | * Some tests use a JSDOM Jest environment. It appears that TextEncoder is not
5 | * available globally, and so we need to enable it here.
6 | * See https://github.com/jestjs/jest/issues/9983
7 | */
8 | global.TextEncoder = require('util').TextEncoder;
9 |
--------------------------------------------------------------------------------
/apps-rendering/config/jestglobalSetup.js:
--------------------------------------------------------------------------------
1 | // Set environment variable for timezone to have
2 | // consistent timezone no matter which machine
3 | // the tests are running from
4 | export default () => {
5 | process.env.TZ = 'Europe/London';
6 | };
7 |
--------------------------------------------------------------------------------
/apps-rendering/config/tsconfig.client.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig",
3 | "compilerOptions": {
4 | // Output latest features; allow babel to handle browser targeting
5 | "target": "es2020"
6 | },
7 | "include": ["../src/client/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps-rendering/config/tsconfig.server.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig",
3 | "compilerOptions": {
4 | "target": "es2019"
5 | },
6 | "files": ["../src/server/server.ts"]
7 | }
8 |
--------------------------------------------------------------------------------
/apps-rendering/config/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig",
3 | "compilerOptions": {
4 | "allowJs": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/apps-rendering/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Why are you doing this?
2 |
3 |
9 |
10 | ## Changes
11 |
12 | - Change 1
13 | - Change 2
14 |
15 | ## Screenshots
16 |
17 | | Before | After |
18 | | ---------------------------- | ---------------------------- |
19 | | |
|
20 |
--------------------------------------------------------------------------------
/apps-rendering/src/articleFormat.test.ts:
--------------------------------------------------------------------------------
1 | // ----- Imports ----- //
2 |
3 | import { ArticleDesign, ArticleDisplay, Pillar } from 'articleFormat';
4 | import { formatToString } from 'articleFormat';
5 |
6 | // ----- Tests ----- //
7 |
8 | describe('formatToString', () => {
9 | it('creates a string describing ArticleFormat', () => {
10 | const format = formatToString({
11 | design: ArticleDesign.Standard,
12 | display: ArticleDisplay.Immersive,
13 | theme: Pillar.Culture,
14 | });
15 |
16 | expect(format).toBe(
17 | 'Design: Standard, Display: Immersive, Theme: Culture',
18 | );
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/apps-rendering/src/bodyElementKind.ts:
--------------------------------------------------------------------------------
1 | // ----- Types ----- //
2 |
3 | const enum ElementKind {
4 | Text,
5 | Image,
6 | Pullquote,
7 | Interactive,
8 | RichLink,
9 | Tweet,
10 | Embed,
11 | Callout,
12 | LiveEvent,
13 | InteractiveAtom,
14 | ExplainerAtom,
15 | MediaAtom,
16 | GuideAtom,
17 | QandaAtom,
18 | ProfileAtom,
19 | TimelineAtom,
20 | ChartAtom,
21 | AudioAtom,
22 | KnowledgeQuizAtom,
23 | PersonalityQuizAtom,
24 | NewsletterSignUp,
25 | HeadingTwo,
26 | HeadingThree,
27 | SpecialReportAltAtom,
28 | }
29 |
30 | // ----- Exports ----- //
31 |
32 | export { ElementKind };
33 |
--------------------------------------------------------------------------------
/apps-rendering/src/components/Audio/index.tsx:
--------------------------------------------------------------------------------
1 | // ----- Imports ----- //
2 |
3 | import { css } from '@emotion/react';
4 |
5 | // ----- Component ----- //
6 |
7 | interface Props {
8 | src: string;
9 | width: number;
10 | height: number;
11 | }
12 |
13 | const audioStyles = css`
14 | border: none;
15 | `;
16 |
17 | const Audio = ({ src, width, height }: Props) => (
18 |
26 | );
27 |
28 | // ----- Exports ----- //
29 |
30 | export default Audio;
31 |
--------------------------------------------------------------------------------
/apps-rendering/src/components/Bullet/Bullet.stories.tsx:
--------------------------------------------------------------------------------
1 | // ----- Imports ----- //
2 |
3 | import { ArticleDesign, ArticleDisplay, Pillar } from '../../articleFormat';
4 | import Bullet from './';
5 |
6 | // ----- Stories ----- //
7 |
8 | const Default = () => (
9 |
12 | We're unable to serve this media because your browser 13 | does not support HTML 5 audio. 14 |
15 |15 | {text} 16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/ExplainerAtom.test.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '@testing-library/react'; 2 | import '@testing-library/jest-dom'; 3 | import { ExplainerAtom } from './ExplainerAtom'; 4 | 5 | describe('ExplainerAtom', () => { 6 | it('should render', () => { 7 | const { getByText } = render( 8 |4 | Some parts of dotcom are available in AMP format, on{' '} 5 | 6 | https://amp.theguardian.com 7 | 8 | . 9 |
10 |The Editions app is available on iOS, iPadOS and Android.
4 |7 | The only page powered by DCAR in the Editions app is the crosswords 8 | player, which contains a list of recent crosswords and a way to play 9 | them. 10 |
11 | > 12 | ); 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/devServer/docs/liveApps.tsx: -------------------------------------------------------------------------------- 1 | export const LiveApps = () => ( 2 | <> 3 |The Guardian live apps, available on iOS, iPadOS and Android.
4 |4 | This a breakdown of the different kinds of targets DCAR can render 5 | for. To instead see a breakdown by pages see{' '} 6 | Pages. 7 |
8 |foo bar
'; 6 | 7 | expect(stripHTML(test)).toBe('foo bar'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /dotcom-rendering/src/model/sanitise.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'dompurify'; 2 | import createDOMPurify from 'dompurify'; 3 | import { JSDOM } from 'jsdom'; 4 | 5 | const { window } = new JSDOM(''); 6 | const DOMPurify = createDOMPurify(window); 7 | 8 | type Opts = Config & { 9 | RETURN_DOM_FRAGMENT?: false | undefined; 10 | RETURN_DOM?: false | undefined; 11 | }; 12 | 13 | export const sanitiseHTML = (html: string, opts: Opts = {}): string => 14 | DOMPurify.sanitize(html, opts); 15 | 16 | export const stripHTML = (s: string): string => 17 | DOMPurify.sanitize(s, { ALLOWED_TAGS: [] }); 18 | -------------------------------------------------------------------------------- /dotcom-rendering/src/model/transformDots.ts: -------------------------------------------------------------------------------- 1 | // Fix for incorrect use of Middot 2 | export const transformDots = (html: string): string => { 3 | return html.replace( 4 | new RegExp('[•]', 'g'), 5 | '', 6 | ); 7 | }; 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/server/handler.editionsCrossword.ts: -------------------------------------------------------------------------------- 1 | import type { RequestHandler } from 'express'; 2 | import { validateAsEditionsCrosswordType } from '../model/validate'; 3 | import { makePrefetchHeader } from './lib/header'; 4 | import { renderCrosswordHtml } from './render.editionsCrossword'; 5 | 6 | export const handleEditionsCrossword: RequestHandler = ({ body }, res) => { 7 | const editionsCrosswords = validateAsEditionsCrosswordType(body); 8 | const { html, prefetchScripts } = renderCrosswordHtml({ 9 | editionsCrosswords, 10 | }); 11 | 12 | res.status(200).set('Link', makePrefetchHeader(prefetchScripts)).send(html); 13 | }; 14 | -------------------------------------------------------------------------------- /dotcom-rendering/src/server/htmlCrosswordPageTemplate.ts: -------------------------------------------------------------------------------- 1 | interface Props { 2 | html: string; 3 | scriptTags: string[]; 4 | } 5 | 6 | export const htmlCrosswordPageTemplate = (props: Props): string => { 7 | const { html, scriptTags } = props; 8 | 9 | return ` 10 | 11 | 12 | 13 | 14 | 15 | ${scriptTags.join('\n')} 16 | 17 | 18 | ${html} 19 | 20 | `; 21 | }; 22 | -------------------------------------------------------------------------------- /dotcom-rendering/src/server/lib/header.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Formats script paths as a Link header 3 | * @see https://datatracker.ietf.org/doc/html/rfc5988#section-5.5 4 | * @param scriptPaths - the script paths to include in the Link header 5 | */ 6 | export const makePrefetchHeader = (scriptPaths: string[]): string => 7 | scriptPaths.reduce( 8 | (acc, scriptPath) => acc + `<${scriptPath}>; rel=prefetch,`, 9 | '', 10 | ); 11 | -------------------------------------------------------------------------------- /dotcom-rendering/src/server/prout.ts: -------------------------------------------------------------------------------- 1 | // this should get overwritten in CI (see .github/workflows/container.yml) 2 | export const GIT_COMMIT_HASH = 'LOCAL'; 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/server/server.ts: -------------------------------------------------------------------------------- 1 | import { devServer } from './server.dev'; 2 | import { prodServer } from './server.prod'; 3 | 4 | // this export is expected by webpack-hot-server-middleware 5 | // not used in prod 6 | // eslint-disable-next-line import/no-default-export -- it is what Webpack wants 7 | export default devServer; 8 | 9 | // this is the actual production server 10 | if (process.env.NODE_ENV === 'production') { 11 | prodServer(); 12 | } 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/EUReferendumBadge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/GE2017Badge.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/beyondthebladebadge.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/dreams-interrupted.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/futureofcities.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/green-blood.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/new-arrivals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/badges/new-arrivals.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/the-age-of-extinction.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/the-new-populism.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/this-is-europe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/tokyo-2020.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/us-midterm-elections-2022.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/world-cup-2022.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/css/print.css: -------------------------------------------------------------------------------- 1 | [data-print-layout='hide'] { 2 | display: none !important; 3 | color: #000000; 4 | } 5 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/arrow-in-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/audio/skip-backward-15.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/audio/skip-forward-15.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/camera.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-left-double.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-left-single.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-right-double.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-right-single.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/clock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/comment.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/down-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/email.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/external-link.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/facebook.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/gifting.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-120.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-240.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-360.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-512.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/apple-touch-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/roundel-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/roundel-114x114.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/roundel-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/roundel-152x152.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/roundel-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/roundel-192x192.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/roundel-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/roundel-256x256.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/roundel-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/icons/homescreen/roundel-512x512.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/roundel.svg: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/info.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/messenger.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/newspaper.svg: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/plus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/profile.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/quote.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/search.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/the-guardian-roundel.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/tick.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/triangle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/twitter-padded.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/video-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/volume-high.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-1.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-11.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-15.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-16.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-18.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-24.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-30.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-31.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-32.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-33.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-37.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-5.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/x.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/logos/hands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/51a37f970de19d02a8b8db3177563450cb274049/dotcom-rendering/src/static/logos/hands.png -------------------------------------------------------------------------------- /dotcom-rendering/src/types/badge.ts: -------------------------------------------------------------------------------- 1 | export interface DCRBadgeType { 2 | imageSrc: string; 3 | /** Link to an external sponsor page */ 4 | href: string; 5 | } 6 | 7 | export interface FEArticleBadgeType { 8 | seriesTag: string; 9 | imageUrl: string; 10 | enhanced?: DCRBadgeType; 11 | } 12 | -------------------------------------------------------------------------------- /dotcom-rendering/src/types/footer.ts: -------------------------------------------------------------------------------- 1 | interface FooterLink { 2 | text: string; 3 | url: string; 4 | dataLinkName: string; 5 | extraClasses?: string; 6 | } 7 | 8 | export interface FooterType { 9 | footerLinks: FooterLink[][]; 10 | } 11 | -------------------------------------------------------------------------------- /dotcom-rendering/src/types/liveBlog.ts: -------------------------------------------------------------------------------- 1 | export type LiveUpdateType = { 2 | numNewBlocks: number; 3 | html: string; 4 | mostRecentBlockId: string; 5 | }; 6 | 7 | export interface PaginationType { 8 | currentPage: number; 9 | totalPages: number; 10 | newest?: string; 11 | newer?: string; 12 | oldest?: string; 13 | older?: string; 14 | } 15 | -------------------------------------------------------------------------------- /dotcom-rendering/src/types/matchReport.ts: -------------------------------------------------------------------------------- 1 | import type { TeamType } from './sport'; 2 | 3 | export type MatchReportType = { 4 | id: string; 5 | isResult: boolean; 6 | homeTeam: TeamType; 7 | awayTeam: TeamType; 8 | competition: { 9 | fullName: string; 10 | }; 11 | isLive: boolean; 12 | venue: string; 13 | comments: string; 14 | minByMinUrl: string; 15 | reportUrl: string; 16 | }; 17 | -------------------------------------------------------------------------------- /dotcom-rendering/src/types/onwards.ts: -------------------------------------------------------------------------------- 1 | import type { FEFormat } from '../frontend/feArticle'; 2 | import type { FETrailType } from './trails'; 3 | 4 | /** 5 | * Onwards 6 | */ 7 | export type FEOnwards = { 8 | heading: string; 9 | trails: FETrailType[]; 10 | description?: string; 11 | url?: string; 12 | onwardsSource: OnwardsSource; 13 | format: FEFormat; 14 | isCuratedContent?: boolean; 15 | }; 16 | 17 | export type OnwardsSource = 18 | | 'series' 19 | | 'more-on-this-story' 20 | | 'related-stories' 21 | | 'related-content' 22 | | 'more-media-in-section' 23 | | 'more-galleries' 24 | | 'curated-content' 25 | | 'newsletters-page' 26 | | 'unknown-source'; // We should never see this in the analytics data! 27 | -------------------------------------------------------------------------------- /dotcom-rendering/src/types/renderingTarget.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A type defining what where we are targeting a particular rendered 3 | * page to be shown 4 | * 5 | * This can be used to make decisions during rendering, where there 6 | * might be differences in the requirements of each target. 7 | * 8 | * Targets: 9 | * - Web => A full web browser, such as chrome or safari on a desktop computer, laptop or phone. 10 | * - Apps => A webview rendered within the Android or iOS live apps 11 | */ 12 | export type RenderingTarget = 'Web' | 'Apps'; 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/types/sentry.ts: -------------------------------------------------------------------------------- 1 | export type ReportError = ( 2 | error: Error, 3 | feature: string, 4 | tags?: Record