├── .nvmrc ├── .npmrc ├── ab-testing ├── .prettierrc ├── cdk │ ├── .gitignore │ ├── cdk.json │ └── tsconfig.json ├── .prettierignore ├── frontend │ ├── src │ │ ├── routes │ │ │ └── +layout.ts │ │ ├── lib │ │ │ └── components │ │ │ │ └── OphanLink.svelte │ │ └── app.html │ ├── vite.config.ts │ └── tsconfig.json ├── deploy-lambda │ ├── src │ │ └── lib │ │ │ └── constants.ts │ └── tsconfig.json └── config │ ├── index.ts │ ├── lib │ ├── types.ts │ └── fastly │ │ └── dictionary.ts │ ├── tsconfig.json │ ├── scripts │ ├── validation │ │ ├── uniqueName.ts │ │ ├── limitServerSide.ts │ │ ├── enoughSpace.ts │ │ └── validExpiration.ts │ └── build │ │ └── build-ab-tests-dict.ts │ └── README.md ├── .prettierrc.json ├── dotcom-rendering ├── scripts │ ├── nginx │ │ ├── Brewfile │ │ ├── nginx-mappings.yaml │ │ └── setup.sh │ ├── jsonSchema │ │ ├── genSchemas.mjs │ │ └── checkSchemas.mjs │ ├── gen-stories │ │ ├── check-stories.mjs │ │ └── gen-stories.mjs │ ├── lighthouse │ │ └── puppeteer-script.js │ └── env │ │ ├── check-files.js │ │ └── check-deps.js ├── __mocks__ │ └── svgMock.tsx ├── src │ ├── lib │ │ ├── isServer.ts │ │ ├── has-string.ts │ │ ├── hideAge.ts │ │ ├── hiddenStyles.tsx │ │ ├── mixins.ts │ │ ├── errors │ │ │ └── not-renderable-in-dcr.ts │ │ ├── isValidUrl.ts │ │ ├── getBrazeUuid.ts │ │ ├── ophan-helpers.ts │ │ ├── useHydrated.ts │ │ ├── slot-machine-flags.ts │ │ ├── labs-constants.ts │ │ ├── braze │ │ │ ├── taylorReport.ts │ │ │ └── hasRequiredConsents.ts │ │ ├── linkNotificationCount.ts │ │ ├── ophan-helpers.test.ts │ │ ├── mockRESTCallsInJest.ts │ │ ├── domUtils.ts │ │ ├── getPrivacyFramework.ts │ │ ├── center.ts │ │ ├── assert-unreachable.ts │ │ ├── parser │ │ │ ├── jsonParser.ts │ │ │ └── parseCheckoutOutCookieData.ts │ │ ├── decideLogo.ts │ │ ├── memoize.ts │ │ ├── useShouldAdapt.ts │ │ ├── themeToPillar.ts │ │ ├── hasCurrentBrazeUser.ts │ │ ├── useConsent.ts │ │ ├── decideNavPillar.ts │ │ ├── layoutHelpers.ts │ │ ├── querystring.ts │ │ ├── json.ts │ │ ├── lang.ts │ │ ├── verticalDivider.ts │ │ ├── usePageViewId.ts │ │ ├── audio-data.ts │ │ ├── getAbUrlHash.ts │ │ ├── useIsMyGuardianEnabled.ts │ │ ├── buildNewsletterSignUpText.tsx │ │ ├── lang.test.ts │ │ ├── formatCount.ts │ │ ├── useAdBlockInUse.ts │ │ ├── useRequestSignUp.ts │ │ ├── revealStyles.ts │ │ ├── querystring.test.ts │ │ ├── commercial-constants.ts │ │ ├── fetchEmail.ts │ │ ├── affiliateLinksUtils.ts │ │ ├── escapeData.test.tsx │ │ ├── canRenderAds.ts │ │ ├── formatCount.test.ts │ │ ├── emotion.tsx │ │ ├── formatAttrString.ts │ │ ├── getZIndex.test.ts │ │ ├── useCountryCode.ts │ │ ├── useOnlineStatus.ts │ │ └── sendTargetingParams.apps.ts │ ├── static │ │ ├── css │ │ │ └── print.css │ │ ├── icons │ │ │ ├── minus.svg │ │ │ ├── triangle.svg │ │ │ ├── comment.svg │ │ │ ├── down-arrow.svg │ │ │ ├── chevron-left-single.svg │ │ │ ├── homescreen │ │ │ │ ├── roundel-114x114.png │ │ │ │ ├── roundel-152x152.png │ │ │ │ ├── roundel-192x192.png │ │ │ │ ├── roundel-256x256.png │ │ │ │ ├── roundel-512x512.png │ │ │ │ ├── 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.svg │ │ │ ├── video-icon.svg │ │ │ ├── x.svg │ │ │ ├── chevron-right-single.svg │ │ │ ├── plus.svg │ │ │ ├── tick.svg │ │ │ ├── clock.svg │ │ │ ├── quote.svg │ │ │ ├── arrow-right.svg │ │ │ ├── facebook.svg │ │ │ ├── chevron-left-double.svg │ │ │ ├── external-link.svg │ │ │ ├── chevron-right-double.svg │ │ │ ├── camera.svg │ │ │ ├── weather │ │ │ │ ├── weather-11.svg │ │ │ │ ├── weather-24.svg │ │ │ │ ├── weather-33.svg │ │ │ │ ├── weather-5.svg │ │ │ │ ├── weather-32.svg │ │ │ │ ├── weather-1.svg │ │ │ │ ├── weather-37.svg │ │ │ │ ├── weather-30.svg │ │ │ │ ├── weather-31.svg │ │ │ │ ├── weather-18.svg │ │ │ │ ├── weather-15.svg │ │ │ │ ├── weather-16.svg │ │ │ │ ├── weather-22.svg │ │ │ │ ├── weather-12.svg │ │ │ │ └── weather-13.svg │ │ │ ├── email.svg │ │ │ ├── info.svg │ │ │ ├── search.svg │ │ │ ├── newspaper.svg │ │ │ ├── messenger.svg │ │ │ ├── refresh.svg │ │ │ ├── volume-high.svg │ │ │ ├── arrow-in-circle.svg │ │ │ ├── gifting.svg │ │ │ ├── profile.svg │ │ │ ├── twitter.svg │ │ │ ├── twitter-padded.svg │ │ │ ├── the-guardian-roundel.svg │ │ │ └── audio │ │ │ │ ├── skip-backward-15.svg │ │ │ │ └── skip-forward-15.svg │ │ ├── logos │ │ │ └── hands.png │ │ └── badges │ │ │ ├── new-arrivals.png │ │ │ ├── green-blood.svg │ │ │ ├── EUReferendumBadge.svg │ │ │ ├── world-cup-2022.svg │ │ │ ├── the-age-of-extinction.svg │ │ │ ├── the-new-populism.svg │ │ │ ├── beyondthebladebadge.svg │ │ │ ├── us-midterm-elections-2022.svg │ │ │ ├── futureofcities.svg │ │ │ ├── tokyo-2020.svg │ │ │ ├── this-is-europe.svg │ │ │ ├── dreams-interrupted.svg │ │ │ ├── GE2017Badge.svg │ │ │ ├── australian-election-2019.svg │ │ │ └── nhs-70.svg │ ├── server │ │ ├── prout.ts │ │ ├── lib │ │ │ └── header.ts │ │ ├── server.ts │ │ ├── handler.editionsCrossword.ts │ │ ├── htmlCrosswordPageTemplate.ts │ │ └── handler.sportDataPage.web.test.ts │ ├── model │ │ ├── enhanceStandfirst.ts │ │ ├── transformDots.ts │ │ ├── sanitise.test.ts │ │ ├── enhanceTags.ts │ │ ├── sanitise.ts │ │ ├── appsLightboxImages.ts │ │ ├── isLegacyTableOfContents.ts │ │ ├── buildCrosswordBlock.ts │ │ ├── pinnedPost.ts │ │ └── enhance-tweets.ts │ ├── types │ │ ├── sentry.ts │ │ ├── footer.ts │ │ ├── badge.ts │ │ ├── liveBlog.ts │ │ ├── matchReport.ts │ │ ├── renderingTarget.ts │ │ ├── hostedContent.ts │ │ └── onwards.ts │ ├── client │ │ ├── atomIframe.ts │ │ ├── embedIframe.ts │ │ ├── webpackPublicPath.ts │ │ ├── debug │ │ │ └── debug.ts │ │ ├── islands │ │ │ ├── onNavigation.ts │ │ │ ├── islands.ts │ │ │ ├── whenIdle.ts │ │ │ ├── getName.ts │ │ │ ├── onInteraction.ts │ │ │ └── getProps.ts │ │ ├── userFeatures │ │ │ ├── cookies │ │ │ │ ├── hideSupportMessaging.ts │ │ │ │ ├── adFree.ts │ │ │ │ ├── allowRejectAll.ts │ │ │ │ ├── userBenefitsExpiry.ts │ │ │ │ └── sIndicatorCapiKey.ts │ │ │ └── fetchJson.ts │ │ ├── decidePublicPath.ts │ │ └── startup.ts │ ├── components │ │ ├── AudioPlayer │ │ │ ├── stories │ │ │ │ ├── default_audio_test.mp3 │ │ │ │ └── default_audio_test.mp3.d.ts │ │ │ └── styles.ts │ │ ├── marketing │ │ │ └── lib │ │ │ │ └── stage.ts │ │ ├── numbers │ │ │ ├── Seven.tsx │ │ │ ├── One.tsx │ │ │ ├── Two.tsx │ │ │ ├── Four.tsx │ │ │ ├── Zero.tsx │ │ │ ├── Five.tsx │ │ │ ├── Ten.tsx │ │ │ ├── Six.tsx │ │ │ ├── Nine.tsx │ │ │ ├── Three.tsx │ │ │ └── Eight.tsx │ │ ├── GuideAtomWrapper.importable.tsx │ │ ├── ProfileAtomWrapper.importable.tsx │ │ ├── Discussion │ │ │ ├── Column.tsx │ │ │ ├── Row.tsx │ │ │ ├── LoadingPicks.stories.tsx │ │ │ ├── LoadingComments.stories.tsx │ │ │ └── Badges.stories.tsx │ │ ├── NewsletterBadge.stories.tsx │ │ ├── Card │ │ │ └── components │ │ │ │ └── HeadlineWrapper.tsx │ │ ├── NewsletterDetail.stories.tsx │ │ ├── ShadyPie.stories.tsx │ │ ├── NewsletterFrequency.stories.tsx │ │ ├── NewsletterPrivacyMessage.stories.tsx │ │ ├── MainMediaEmbedBlockComponent.tsx │ │ ├── Border.tsx │ │ ├── ItemLinkBlockElement.stories.tsx │ │ ├── LastUpdated.stories.tsx │ │ ├── PulsingDot.test.tsx │ │ ├── SetAdTargeting.importable.tsx │ │ ├── ChartAtom.test.tsx │ │ ├── ExplainerAtom.test.tsx │ │ ├── FooterLabel.importable.tsx │ │ ├── EndNote.tsx │ │ ├── ItemLinkBlockElement.tsx │ │ ├── EditionsCrosswordPage.tsx │ │ ├── LabsLogo.stories.tsx │ │ ├── AlreadyVisited.importable.tsx │ │ ├── FocusStyles.importable.tsx │ │ ├── IslandContext.tsx │ │ ├── Byline.tsx │ │ ├── LabsHeader.stories.tsx │ │ ├── EditionSwitcherBanner.stories.tsx │ │ ├── Flex.tsx │ │ ├── ThemedLink │ │ │ ├── ThemedLink.stories.tsx │ │ │ └── ThemedLink.tsx │ │ ├── FootballMatchList.test.tsx │ │ ├── Masthead │ │ │ └── Titlepiece │ │ │ │ ├── constants.ts │ │ │ │ ├── Logo.tsx │ │ │ │ └── EditionDropdown.stories.tsx │ │ ├── ShadyPie.tsx │ │ ├── InteractivesNativePlatformWrapper.importable.tsx │ │ ├── QuoteIcon.tsx │ │ ├── LastUpdated.tsx │ │ ├── InteractivesDisableArticleSwipe.importable.tsx │ │ ├── RightColumn.tsx │ │ ├── ListenToArticle.test.tsx │ │ ├── StarRatingBlockComponent.tsx │ │ ├── FootballTableCrest.tsx │ │ ├── ExternalLink │ │ │ └── ExternalLink.tsx │ │ ├── GalleryAdSlots.tsx │ │ ├── GuardianLabsLines.tsx │ │ ├── SoundcloudBlockComponent.tsx │ │ ├── InteractiveLayoutAtom.test.tsx │ │ ├── MostViewedFooterPlaceholder.stories.tsx │ │ └── CricketScoreboard.stories.tsx │ ├── footballTeam.ts │ ├── devServer │ │ ├── docs │ │ │ ├── styles.ts │ │ │ ├── editionsApp.tsx │ │ │ ├── liveApps.tsx │ │ │ ├── editionsCrosswords.tsx │ │ │ ├── interactive.tsx │ │ │ ├── targets.tsx │ │ │ ├── cricketScorecard.tsx │ │ │ └── newsletters.tsx │ │ ├── routers │ │ │ ├── editionsApp.tsx │ │ │ ├── targets.tsx │ │ │ └── liveApps.tsx │ │ └── send.tsx │ ├── frontend │ │ └── README.md │ ├── layouts │ │ └── lib │ │ │ └── pageSkin.ts │ ├── experiments │ │ ├── utils.ts │ │ └── ab-tests.ts │ ├── storyPackage.ts │ └── footballMatchesV2.ts ├── tsconfig.build.json ├── .fast ├── docs │ ├── images │ │ ├── logo-swc.png │ │ ├── logo-jest.jpg │ │ ├── logo-emotion.png │ │ ├── logo-express.png │ │ ├── logo-preact.jpg │ │ ├── logo-webpack.png │ │ ├── logo-ab-testing.png │ │ ├── logo-chromatic.jpg │ │ ├── logo-storybook.jpg │ │ └── logo-typescript.png │ ├── principles │ │ └── images │ │ │ ├── ie8.png │ │ │ └── chrome70.png │ ├── development │ │ ├── assets │ │ │ ├── local-ar-ios.png │ │ │ ├── local-ar-android.png │ │ │ └── android-clear-cache.png │ │ ├── run-prod-bundle-locally.md │ │ └── storybook.md │ ├── youtube │ │ ├── youtubeimages-2020 │ │ │ ├── embedcapijson.png │ │ │ ├── embeddcrjson.png │ │ │ ├── embedscreenshot.png │ │ │ ├── mediaatomcapijson.png │ │ │ ├── mediaatomdcrjson.png │ │ │ ├── mediaatomscreenshot.png │ │ │ ├── embedcomposerscreenshot.png │ │ │ ├── mediaatomcomposerscreenshot.png │ │ │ ├── structuredataembedscreenshot.png │ │ │ ├── structureddataembedcapijson.png │ │ │ └── structureddataembedcomposer.png │ │ └── youtubeimages-2021 │ │ │ ├── composer-embed-menu.png │ │ │ ├── composer-video-menu.png │ │ │ ├── composer-embed-dialog.png │ │ │ ├── composer-youtube-embed.png │ │ │ ├── composer-generic-embed-code.png │ │ │ ├── composer-youtube-embed-atom.png │ │ │ └── composer-youtube-embed-generic.png │ ├── ads │ │ └── web-ads.md │ ├── contributing │ │ ├── detailed-setup-guide-pics │ │ │ └── high-level-diagram.png │ │ └── README.md │ ├── incidents │ │ └── incident-handling.md │ ├── interactives │ │ └── working-with-interactives.md │ ├── elements │ │ ├── Subheading.md │ │ └── Richlink.md │ ├── patterns │ │ └── decide-layout.md │ ├── architecture │ │ ├── 017-remove-monorepo.md │ │ ├── 018-react-hooks.md │ │ ├── 022-dynamic-imports.md │ │ ├── 014-client-side-computation.md │ │ └── historic-adrs │ │ │ └── 016-react-context-api.md │ ├── duplication.md │ └── contracts │ │ ├── 002-viewer-body-selector.md │ │ └── 004-heatphan-selectors.md ├── fixtures │ └── manual │ │ ├── discussionApiUrl.ts │ │ ├── block-meta-data.ts │ │ ├── ensure.ts │ │ ├── productImage.ts │ │ └── noTopPicks.ts ├── .prout.json ├── cdk.json ├── .eslintignore ├── .gitignore ├── .storybook │ ├── mocks │ │ └── log4js.ts │ └── decorators │ │ └── configContextDecorator.tsx ├── webpack │ ├── svg.cjs │ ├── .swcrc.json │ └── @types │ │ ├── webpack-filter-warnings-plugin │ │ └── index.d.ts │ │ └── webpack-messages │ │ └── index.d.ts ├── Containerfile └── playwright │ └── lib │ └── network.ts ├── pnpm-workspace.yaml ├── .husky ├── pre-commit └── pre-push ├── CONTRIBUTING.md ├── scripts ├── postinstall.sh ├── deno │ ├── deno.json │ ├── github.ts │ └── json.ts └── env │ └── check-package-manager ├── .prettierignore ├── .github ├── workflows │ ├── prettier.yml │ ├── jest.yml │ ├── typescript.yml │ ├── schema-check.yml │ ├── stories-check.yml │ ├── lint.yml │ ├── build-check.yml │ ├── deno.yml │ └── permissions-advisor.yml └── actions │ └── setup-node-env │ └── action.yml ├── .vscode ├── extensions.json └── settings.json.required ├── .editorconfig ├── README.md └── .git-blame-ignore-revs /.nvmrc: -------------------------------------------------------------------------------- 1 | 22.18.0 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-prefix='' 2 | -------------------------------------------------------------------------------- /ab-testing/.prettierrc: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /ab-testing/cdk/.gitignore: -------------------------------------------------------------------------------- 1 | cdk.out 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | "@guardian/prettier" 2 | -------------------------------------------------------------------------------- /ab-testing/.prettierignore: -------------------------------------------------------------------------------- 1 | frontend/.svelte-kit 2 | -------------------------------------------------------------------------------- /ab-testing/frontend/src/routes/+layout.ts: -------------------------------------------------------------------------------- 1 | export const prerender = true; 2 | -------------------------------------------------------------------------------- /dotcom-rendering/scripts/nginx/Brewfile: -------------------------------------------------------------------------------- 1 | brew "guardian/devtools/dev-nginx" 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'dotcom-rendering' 3 | - 'ab-testing/*' 4 | -------------------------------------------------------------------------------- /ab-testing/deploy-lambda/src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const REGION = "eu-west-1"; 2 | -------------------------------------------------------------------------------- /dotcom-rendering/__mocks__/svgMock.tsx: -------------------------------------------------------------------------------- 1 | const SVG = () => null; 2 | 3 | module.exports = SVG; 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/isServer.ts: -------------------------------------------------------------------------------- 1 | export const isServer = typeof window === 'undefined'; 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/has-string.ts: -------------------------------------------------------------------------------- 1 | export const has = (s?: string): boolean => !!s && s.trim() !== ''; 2 | -------------------------------------------------------------------------------- /dotcom-rendering/scripts/jsonSchema/genSchemas.mjs: -------------------------------------------------------------------------------- 1 | import { genSchemas } from './schema.mjs'; 2 | 3 | genSchemas(); 4 | -------------------------------------------------------------------------------- /dotcom-rendering/scripts/jsonSchema/checkSchemas.mjs: -------------------------------------------------------------------------------- 1 | import { checkSchemas } from './schema.mjs'; 2 | 3 | checkSchemas(); 4 | -------------------------------------------------------------------------------- /dotcom-rendering/scripts/gen-stories/check-stories.mjs: -------------------------------------------------------------------------------- 1 | import { checkStories } from './get-stories.mjs'; 2 | 3 | checkStories(); 4 | -------------------------------------------------------------------------------- /dotcom-rendering/scripts/gen-stories/gen-stories.mjs: -------------------------------------------------------------------------------- 1 | import { saveStories } from './get-stories.mjs'; 2 | 3 | saveStories(); 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/css/print.css: -------------------------------------------------------------------------------- 1 | [data-print-layout='hide'] { 2 | display: none !important; 3 | color: #000000; 4 | } 5 | -------------------------------------------------------------------------------- /dotcom-rendering/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /dotcom-rendering/.fast: -------------------------------------------------------------------------------- 1 | Format: [branch] [timestamp] [perf-score] [js size] [tti] 2 | 3 | master 2019-09-24T15:26:28.341009+01:00 0.56 4 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-swc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-swc.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-jest.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-jest.jpg -------------------------------------------------------------------------------- /dotcom-rendering/fixtures/manual/discussionApiUrl.ts: -------------------------------------------------------------------------------- 1 | export const discussionApiUrl = 2 | 'https://discussion.theguardian.com/discussion-api'; 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/triangle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/logos/hands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/src/static/logos/hands.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-emotion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-emotion.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-express.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-express.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-preact.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-preact.jpg -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-webpack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-webpack.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-ab-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-ab-testing.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-chromatic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-chromatic.jpg -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-storybook.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-storybook.jpg -------------------------------------------------------------------------------- /dotcom-rendering/docs/images/logo-typescript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/images/logo-typescript.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/principles/images/ie8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/principles/images/ie8.png -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /dotcom-rendering/scripts/nginx/nginx-mappings.yaml: -------------------------------------------------------------------------------- 1 | name: dotcom-rendering 2 | domain-root: thegulocal.com 3 | mappings: 4 | - prefix: r 5 | port: 3030 6 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/hideAge.ts: -------------------------------------------------------------------------------- 1 | export const hideAge = [ 2 | 'Newsletters', 3 | 'Showcase', 4 | 'How to listen to Podcasts', 5 | 'Get in touch', 6 | ]; 7 | -------------------------------------------------------------------------------- /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/static/badges/new-arrivals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/src/static/badges/new-arrivals.png -------------------------------------------------------------------------------- /dotcom-rendering/.prout.json: -------------------------------------------------------------------------------- 1 | { 2 | "checkpoints": { 3 | "PROD": { 4 | "url": "https://www.theguardian.com/uk", 5 | "overdue": "30M" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/principles/images/chrome70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/principles/images/chrome70.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/development/assets/local-ar-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/development/assets/local-ar-ios.png -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/hiddenStyles.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | 3 | export const hiddenStyles = css` 4 | &.hidden { 5 | display: none; 6 | } 7 | `; 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/mixins.ts: -------------------------------------------------------------------------------- 1 | export const clearFix = ` 2 | :after { 3 | content: ''; 4 | display: table; 5 | clear: both; 6 | } 7 | `; 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/comment.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/development/assets/local-ar-android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/development/assets/local-ar-android.png -------------------------------------------------------------------------------- /ab-testing/cdk/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "node bin/cdk.ts", 3 | "context": { 4 | "aws-cdk:enableDiffNoFail": "true", 5 | "@aws-cdk/core:stackRelativeExports": "true" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/down-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/development/assets/android-clear-cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/development/assets/android-clear-cache.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/embedcapijson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/embedcapijson.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/embeddcrjson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/embeddcrjson.png -------------------------------------------------------------------------------- /dotcom-rendering/src/model/enhanceStandfirst.ts: -------------------------------------------------------------------------------- 1 | import { transformDots } from './transformDots'; 2 | 3 | export const enhanceStandfirst = (html: string): string => transformDots(html); 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-left-single.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/roundel-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/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/HEAD/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/HEAD/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/HEAD/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/HEAD/dotcom-rendering/src/static/icons/homescreen/roundel-512x512.png -------------------------------------------------------------------------------- /dotcom-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 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/embedscreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/embedscreenshot.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/video-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/x.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ab-testing/frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from "@sveltejs/kit/vite"; 2 | import { defineConfig } from "vite"; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()], 6 | }); 7 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomcapijson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomcapijson.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomdcrjson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomdcrjson.png -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-right-single.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/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/HEAD/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/HEAD/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/HEAD/dotcom-rendering/src/static/icons/homescreen/apple-touch-icon-512.png -------------------------------------------------------------------------------- /dotcom-rendering/src/types/sentry.ts: -------------------------------------------------------------------------------- 1 | export type ReportError = ( 2 | error: Error, 3 | feature: string, 4 | tags?: Record, 5 | extras?: Record, 6 | ) => void; 7 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomscreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomscreenshot.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2021/composer-embed-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2021/composer-embed-menu.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2021/composer-video-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2021/composer-video-menu.png -------------------------------------------------------------------------------- /dotcom-rendering/src/client/atomIframe.ts: -------------------------------------------------------------------------------- 1 | import { updateIframeHeight } from './updateIframeHeight'; 2 | 3 | export const atomIframe = (): Promise => 4 | updateIframeHeight('iframe.atom__iframe'); 5 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/embedcomposerscreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/embedcomposerscreenshot.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2021/composer-embed-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2021/composer-embed-dialog.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2021/composer-youtube-embed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2021/composer-youtube-embed.png -------------------------------------------------------------------------------- /dotcom-rendering/src/components/AudioPlayer/stories/default_audio_test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/src/components/AudioPlayer/stories/default_audio_test.mp3 -------------------------------------------------------------------------------- /dotcom-rendering/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .eslintrc.js 3 | storybook-static/ 4 | 5 | # build output 6 | dist 7 | 8 | # playwright 9 | test-results/ 10 | playwright-report/ 11 | playwright/.cache/ 12 | -------------------------------------------------------------------------------- /dotcom-rendering/.gitignore: -------------------------------------------------------------------------------- 1 | # this file helps speed up local builds https://www.typescriptlang.org/tsconfig#incremental 2 | tsconfig.tsbuildinfo 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/ads/web-ads.md: -------------------------------------------------------------------------------- 1 | # Web Ads 2 | 3 | Web ads are served by commercial. 4 | See the commercial docs folder https://github.com/guardian/dotcom-rendering/tree/main/dotcom-rendering/docs/commercial 5 | -------------------------------------------------------------------------------- /dotcom-rendering/src/client/embedIframe.ts: -------------------------------------------------------------------------------- 1 | import { updateIframeHeight } from './updateIframeHeight'; 2 | 3 | export const embedIframe = (): Promise => 4 | updateIframeHeight('iframe.js-embed__iframe'); 5 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/tick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomcomposerscreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/mediaatomcomposerscreenshot.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/structuredataembedscreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/structuredataembedscreenshot.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/structureddataembedcapijson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/structureddataembedcapijson.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2020/structureddataembedcomposer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2020/structureddataembedcomposer.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2021/composer-generic-embed-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2021/composer-generic-embed-code.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2021/composer-youtube-embed-atom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2021/composer-youtube-embed-atom.png -------------------------------------------------------------------------------- /dotcom-rendering/src/components/marketing/lib/stage.ts: -------------------------------------------------------------------------------- 1 | // Default to PROD to avoid risk of showing test data to users 2 | export const isProd = (stage?: string): boolean => 3 | !(stage === 'CODE' || stage === 'DEV'); 4 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/contributing/detailed-setup-guide-pics/high-level-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/contributing/detailed-setup-guide-pics/high-level-diagram.png -------------------------------------------------------------------------------- /dotcom-rendering/docs/youtube/youtubeimages-2021/composer-youtube-embed-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/dotcom-rendering/HEAD/dotcom-rendering/docs/youtube/youtubeimages-2021/composer-youtube-embed-generic.png -------------------------------------------------------------------------------- /dotcom-rendering/src/components/AudioPlayer/stories/default_audio_test.mp3.d.ts: -------------------------------------------------------------------------------- 1 | declare const mp3: string; 2 | 3 | // eslint-disable-next-line import/no-default-export -- it's how storybook imports them 4 | export default mp3; 5 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/quote.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/footballTeam.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The basic information we should have about all football teams is their PA ID 3 | * and their name. 4 | */ 5 | export type FootballTeam = { 6 | name: string; 7 | paID: string; 8 | }; 9 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-left-double.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/external-link.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to the Guardian's Apps & Web rendering platform 2 | 3 | Read our [Code of conduct](./CODE_OF_CONDUCT.md) to help keep things approachable and respectful. 4 | 5 | [Start here ➡️](./dotcom-rendering/docs/contributing/README.md) 6 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/chevron-right-double.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/errors/not-renderable-in-dcr.ts: -------------------------------------------------------------------------------- 1 | export class NotRenderableInDCR extends Error { 2 | constructor() { 3 | super( 4 | 'This page cannot be rendered due to incompatible content that is marked as mandatory.', 5 | ); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/isValidUrl.ts: -------------------------------------------------------------------------------- 1 | /** Checks if a given URL is valid */ 2 | export const isValidUrl = (maybeUrl: string): boolean => { 3 | try { 4 | new URL(maybeUrl); 5 | return true; 6 | } catch (e) { 7 | return false; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /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/static/icons/camera.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/badges/green-blood.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /ab-testing/config/index.ts: -------------------------------------------------------------------------------- 1 | // this file is covered by the dotcom-rendering tsconfig.json, 2 | // not the one in this directory (hence no need for .ts extension) 3 | import { activeABtests, allABTests } from "./abTests"; 4 | 5 | export { allABTests, activeABtests }; 6 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/contributing/README.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | - [Detailed setup guide](./detailed-setup-guide.md) 4 | - [Code style](./code-style.md) 5 | - [Where should my code live?](./where-should-my-code-live.md) 6 | - [How-to guides](./how-to.md) 7 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/numbers/Seven.tsx: -------------------------------------------------------------------------------- 1 | export const Seven = () => ( 2 | 3 | 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/getBrazeUuid.ts: -------------------------------------------------------------------------------- 1 | import { getAuthState } from './identity'; 2 | 3 | export const getBrazeUuid = async (): Promise => { 4 | const authState = await getAuthState(); 5 | return authState.idToken?.claims.braze_uuid; 6 | }; 7 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-11.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/weather/weather-24.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ab-testing/config/lib/types.ts: -------------------------------------------------------------------------------- 1 | type FastlyTestParams = { name: string; type: string; exp: number }; 2 | type AudienceSpace = Map; 3 | 4 | type AllSpace = Map; 5 | 6 | export type { FastlyTestParams, AudienceSpace, AllSpace }; 7 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/numbers/One.tsx: -------------------------------------------------------------------------------- 1 | export const One = () => ( 2 | 3 | 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/incidents/incident-handling.md: -------------------------------------------------------------------------------- 1 | # Incident handling 2 | 3 | In the event of an incident, the best starting point is this doc: 4 | 5 | https://docs.google.com/document/d/1Huoh22rZjZMpxCEUsKuK8rDybdSgR7LfUCQ8_0shmz0/edit?usp=sharing 6 | 7 | (Internal access only.) 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/ophan-helpers.ts: -------------------------------------------------------------------------------- 1 | export const nestedOphanComponents = (...components: string[]): string => 2 | components.join(' : '); 3 | 4 | const spaces = / /g; 5 | 6 | export const ophanComponentId = (name: string): string => 7 | name.toLowerCase().replace(spaces, '-'); 8 | -------------------------------------------------------------------------------- /dotcom-rendering/fixtures/manual/block-meta-data.ts: -------------------------------------------------------------------------------- 1 | export const blockMetaData = { 2 | id: '123', 3 | primaryDateLine: 'Wed 9 Dec 2020 06.30 GMT', 4 | secondaryDateLine: 'Last modified on Wed 9 Dec 2020 13.40 GMT', 5 | attributes: { keyEvent: false, pinned: false, summary: false }, 6 | }; 7 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/GuideAtomWrapper.importable.tsx: -------------------------------------------------------------------------------- 1 | import { GuideAtom } from './GuideAtom/GuideAtom'; 2 | import type { GuideAtomProps } from './GuideAtom/GuideAtom'; 3 | 4 | export const GuideAtomWrapper = (props: GuideAtomProps) => { 5 | return ; 6 | }; 7 | -------------------------------------------------------------------------------- /dotcom-rendering/src/model/sanitise.test.ts: -------------------------------------------------------------------------------- 1 | import { stripHTML } from './sanitise'; 2 | 3 | describe('stripHTML', () => { 4 | it('removes all HTML tags', () => { 5 | const test = '

foo bar

'; 6 | 7 | expect(stripHTML(test)).toBe('foo bar'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/useHydrated.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export const useHydrated = (): boolean => { 4 | const [hydrated, setHydrated] = useState(false); 5 | useEffect(() => { 6 | setHydrated(true); 7 | }, []); 8 | 9 | return hydrated; 10 | }; 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /scripts/postinstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Automatically copy over required settings for vscode 4 | if [ ! -f .vscode/settings.json ] ; 5 | then echo "No VSCode settings.json found. Copying from repo required settings..." \ 6 | && cp .vscode/settings.json.required .vscode/settings.json ; 7 | fi 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/devServer/docs/styles.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | import { space } from '@guardian/source/foundations'; 3 | 4 | export const descriptionLinks = css({ 5 | dt: { 6 | paddingBottom: space[1], 7 | }, 8 | dd: { 9 | paddingBottom: space[1], 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/email.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/info.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ab-testing/deploy-lambda/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@guardian/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "allowImportingTsExtensions": true, 5 | "allowArbitraryExtensions": false, 6 | "erasableSyntaxOnly": true, 7 | "noEmit": true 8 | }, 9 | "exclude": ["node_modules"] 10 | } 11 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/ProfileAtomWrapper.importable.tsx: -------------------------------------------------------------------------------- 1 | import type { ProfileAtomProps } from './ProfileAtom.importable'; 2 | import { ProfileAtom } from './ProfileAtom.importable'; 3 | 4 | export const ProfileAtomWrapper = (props: ProfileAtomProps) => { 5 | return ; 6 | }; 7 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/slot-machine-flags.ts: -------------------------------------------------------------------------------- 1 | interface Flags { 2 | showBodyEnd: boolean; 3 | } 4 | 5 | export const parse = (flags: string): Flags => { 6 | const arr = flags.split(','); 7 | const args = new Set(arr); 8 | 9 | return { 10 | showBodyEnd: args.has('showBodyEnd'), 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/devServer/docs/editionsApp.tsx: -------------------------------------------------------------------------------- 1 | export const EditionsApp = () => ( 2 | <> 3 |

The Editions app is available on iOS, iPadOS and Android.

4 |

Available Pages

5 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/labs-constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Height of the Guardian Labs header 3 | * 4 | * Note this constant is stored separately so that it can be imported 5 | * into two distinct islands without polluting their bundles with extra 6 | * unecessary code. 7 | */ 8 | export const LABS_HEADER_HEIGHT = 55; 9 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/numbers/Two.tsx: -------------------------------------------------------------------------------- 1 | export const Two = () => ( 2 | 3 | 4 | 5 | ); 6 | -------------------------------------------------------------------------------- /dotcom-rendering/src/frontend/README.md: -------------------------------------------------------------------------------- 1 | # The `frontend` Directory 2 | 3 | This contains code related to the requests sent to DCAR from frontend. In practice this means the TypeScript types representing JSON data sent via POST request to DCAR, and the JSON schema files that are generated from them by `scripts/jsonSchema`. 4 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /scripts/deno/deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": false, 4 | "lib": ["deno.window"], 5 | "strict": true 6 | }, 7 | "unstable": ["temporal"], 8 | "fmt": { 9 | "useTabs": true, 10 | "lineWidth": 80, 11 | "indentWidth": 4, 12 | "singleQuote": true, 13 | "proseWrap": "preserve" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /dotcom-rendering/scripts/nginx/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 6 | 7 | brew bundle --file=${DIR}/Brewfile 8 | 9 | dev-nginx setup-app ${DIR}/nginx-mappings.yaml 10 | 11 | echo "🌎 Successfully installed config. https://r.thegulocal.com is now setup." 12 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/numbers/Four.tsx: -------------------------------------------------------------------------------- 1 | export const Four = () => ( 2 | 3 | 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/braze/taylorReport.ts: -------------------------------------------------------------------------------- 1 | import type { TagType } from '../../types/tag'; 2 | 3 | const tagId = 'news/series/cotton-capital'; 4 | 5 | export const suppressForTaylorReport = (tags: TagType[]): boolean => 6 | window.guardian.config.switches.brazeTaylorReport === true && 7 | !tags.find((tag) => tag.id === tagId); 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/newspaper.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /.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 | 14 | # MDX - prettier breaks SVGs 15 | *.mdx 16 | -------------------------------------------------------------------------------- /dotcom-rendering/src/layouts/lib/pageSkin.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | import { breakpoints, from } from '@guardian/source/foundations'; 3 | 4 | const pageSkinContainer = css` 5 | ${from.desktop} { 6 | max-width: ${breakpoints.desktop}px; 7 | margin: auto; 8 | } 9 | `; 10 | 11 | export { pageSkinContainer }; 12 | -------------------------------------------------------------------------------- /ab-testing/frontend/src/lib/components/OphanLink.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | graph 14 | 15 | -------------------------------------------------------------------------------- /dotcom-rendering/src/client/webpackPublicPath.ts: -------------------------------------------------------------------------------- 1 | // allows us to define public path dynamically 2 | // dynamic imports will use this as the base to find their assets 3 | 4 | import { decidePublicPath } from './decidePublicPath'; 5 | 6 | // https://webpack.js.org/guides/public-path/#on-the-fly 7 | __webpack_public_path__ = decidePublicPath(); 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/Discussion/Column.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | 3 | type Props = { children: React.ReactNode }; 4 | 5 | export const Column = ({ children }: Props) => ( 6 |
12 | {children} 13 |
14 | ); 15 | -------------------------------------------------------------------------------- /dotcom-rendering/src/experiments/utils.ts: -------------------------------------------------------------------------------- 1 | import { bypassCommercialMetricsSampling } from '@guardian/commercial-core'; 2 | import { bypassCoreWebVitalsSampling } from '@guardian/core-web-vitals'; 3 | 4 | export const bypassMetricsSampling = (): void => { 5 | void bypassCommercialMetricsSampling(); 6 | void bypassCoreWebVitalsSampling(); 7 | }; 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/messenger.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/volume-high.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dotcom-rendering/src/client/debug/debug.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error: Cannot find module 2 | import debugCss from './debug.css'; 3 | 4 | const style = document.createElement('style'); 5 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- We know this will be a string 6 | style.innerHTML = debugCss; 7 | document.body.appendChild(style); 8 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/NewsletterBadge.stories.tsx: -------------------------------------------------------------------------------- 1 | import { NewsletterBadge } from './NewsletterBadge'; 2 | 3 | export default { 4 | component: NewsletterBadge, 5 | title: 'Components/NewsletterBadge', 6 | }; 7 | 8 | export const Default = () => { 9 | return ; 10 | }; 11 | 12 | Default.storyName = 'Default'; 13 | -------------------------------------------------------------------------------- /.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@v6 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 | -------------------------------------------------------------------------------- /ab-testing/cdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@guardian/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "skipLibCheck": true, 6 | "allowImportingTsExtensions": true, 7 | "erasableSyntaxOnly": true, 8 | "moduleResolution": "nodenext", 9 | "module": "nodenext" 10 | }, 11 | "exclude": ["node_modules"] 12 | } 13 | -------------------------------------------------------------------------------- /dotcom-rendering/.storybook/mocks/log4js.ts: -------------------------------------------------------------------------------- 1 | import type { Logger } from 'log4js'; 2 | 3 | /** 4 | * This is a mock logger to replace [logging.ts][] 5 | * 6 | * [logging.ts]: ../../src/server/lib/logging.ts 7 | */ 8 | export const logger: Partial = { 9 | log: console.log, 10 | warn: console.warn, 11 | debug: console.debug, 12 | }; 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/Card/components/HeadlineWrapper.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | 3 | type Props = { 4 | children: React.ReactNode; 5 | }; 6 | 7 | export const HeadlineWrapper = ({ children }: Props) => ( 8 |
13 | {children} 14 |
15 | ); 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ab-testing/config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@guardian/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "skipLibCheck": true, 6 | "allowImportingTsExtensions": true, 7 | "erasableSyntaxOnly": true, 8 | "moduleResolution": "nodenext", 9 | "module": "nodenext" 10 | }, 11 | "exclude": ["node_modules", "index.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /ab-testing/frontend/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sveltekit.head% 7 | 8 | 9 |
%sveltekit.body%
10 | 11 | 12 | -------------------------------------------------------------------------------- /dotcom-rendering/fixtures/manual/ensure.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined } from '@guardian/libs'; 2 | 3 | export function ensure( 4 | argument: T | undefined | null, 5 | message = 'This value was promised to be there.', 6 | ): T { 7 | if (isUndefined(argument) || argument === null) { 8 | throw new TypeError(message); 9 | } 10 | 11 | return argument; 12 | } 13 | -------------------------------------------------------------------------------- /dotcom-rendering/webpack/svg.cjs: -------------------------------------------------------------------------------- 1 | /** @satisfies {import('webpack').RuleSetRule} */ 2 | const svgr = { 3 | test: /\.svg$/, 4 | use: [ 5 | { 6 | loader: '@svgr/webpack', 7 | options: { 8 | /** this ensures that we keep the viewBox for imported SVGs */ 9 | svgo: false, 10 | }, 11 | }, 12 | ], 13 | }; 14 | 15 | module.exports = { svgr }; 16 | -------------------------------------------------------------------------------- /dotcom-rendering/docs/interactives/working-with-interactives.md: -------------------------------------------------------------------------------- 1 | # Working with Interactives 2 | 3 | Interactive is a Design type for rich content pieces - typically with custom 4 | Javascript for interactive effects. 5 | 6 | DCR aims to support interactive development in a variety of ways. 7 | 8 | _Note, this document is a work in progress and more will be added shortly._ 9 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/NewsletterDetail.stories.tsx: -------------------------------------------------------------------------------- 1 | import { NewsletterDetail } from './NewsletterDetail'; 2 | 3 | export default { 4 | component: NewsletterDetail, 5 | title: 'Components/NewsletterDetail', 6 | }; 7 | 8 | export const Default = () => { 9 | return ; 10 | }; 11 | 12 | Default.storyName = 'Default'; 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/ShadyPie.stories.tsx: -------------------------------------------------------------------------------- 1 | import { ShadyPie } from './ShadyPie'; 2 | 3 | export default { 4 | component: ShadyPie, 5 | title: 'Components/ShadyPie', 6 | }; 7 | 8 | export const Default = () => { 9 | return ( 10 |
11 | 12 |
13 | ); 14 | }; 15 | Default.storyName = 'Default'; 16 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/numbers/Zero.tsx: -------------------------------------------------------------------------------- 1 | export const Zero = () => ( 2 | 3 | 4 | 5 | ); 6 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/arrow-in-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scripts/deno/github.ts: -------------------------------------------------------------------------------- 1 | import { Octokit } from 'npm:octokit@4'; 2 | 3 | /** Github token for Authentication */ 4 | const token = Deno.env.get('GITHUB_TOKEN'); 5 | if (!token) console.warn('Missing GITHUB_TOKEN'); 6 | 7 | /** 8 | * A hydrated Octokit with types for the rest API. 9 | */ 10 | export const octokit = token ? new Octokit({ auth: token }) : undefined; 11 | -------------------------------------------------------------------------------- /scripts/deno/json.ts: -------------------------------------------------------------------------------- 1 | export const fetchJSON = async ( 2 | url: Parameters[0], 3 | { 4 | headers, 5 | parser, 6 | }: { 7 | headers?: HeadersInit; 8 | parser: (data: unknown) => T | Promise; 9 | }, 10 | ): Promise => { 11 | const data: unknown = await fetch(url, { headers }).then((r) => r.json()); 12 | return parser(data); 13 | }; 14 | -------------------------------------------------------------------------------- /dotcom-rendering/src/devServer/docs/liveApps.tsx: -------------------------------------------------------------------------------- 1 | export const LiveApps = () => ( 2 | <> 3 |

The Guardian live apps, available on iOS, iPadOS and Android.

4 |

Available Pages

5 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /dotcom-rendering/src/client/islands/onNavigation.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Will callback each time the reader navigates back or forward in 3 | * their browser 4 | * 5 | * @param callback : This is fired when the popstate event is fired 6 | */ 7 | export const onNavigation = (callback: () => void): void => { 8 | window.addEventListener('popstate', callback, { once: false }); 9 | }; 10 | -------------------------------------------------------------------------------- /.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@v6 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 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/NewsletterFrequency.stories.tsx: -------------------------------------------------------------------------------- 1 | import { NewsletterFrequency } from './NewsletterFrequency'; 2 | 3 | export default { 4 | component: NewsletterFrequency, 5 | title: 'Components/NewsletterFrequency', 6 | }; 7 | 8 | export const Default = () => { 9 | return ; 10 | }; 11 | 12 | Default.storyName = 'Default'; 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/static/icons/gifting.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scripts/env/check-package-manager: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // get the package manager and version we need from package.json 4 | const pkgPackageManager = require('../../package.json').packageManager; 5 | 6 | if (!pkgPackageManager) { 7 | const { warn } = require('../log'); 8 | warn(`The 'packageManager' field is missing from the root package.json`); 9 | process.exit(1); 10 | } 11 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/NewsletterPrivacyMessage.stories.tsx: -------------------------------------------------------------------------------- 1 | import { NewsletterPrivacyMessage } from './NewsletterPrivacyMessage'; 2 | 3 | export default { 4 | component: NewsletterPrivacyMessage, 5 | title: 'Components/NewsletterPrivacyMessage', 6 | }; 7 | 8 | export const Default = () => { 9 | return ; 10 | }; 11 | 12 | Default.storyName = 'Default'; 13 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/linkNotificationCount.ts: -------------------------------------------------------------------------------- 1 | import type { DropdownLinkType } from '../components/Dropdown.importable'; 2 | 3 | export const linkNotificationCount = (links: DropdownLinkType[]): number => { 4 | return links.reduce((runningCount, link) => { 5 | const thisLinkNotificationCount = link.notifications?.length ?? 0; 6 | return runningCount + thisLinkNotificationCount; 7 | }, 0); 8 | }; 9 | -------------------------------------------------------------------------------- /dotcom-rendering/src/lib/ophan-helpers.test.ts: -------------------------------------------------------------------------------- 1 | import { nestedOphanComponents } from './ophan-helpers'; 2 | 3 | describe('Ophan helpers', () => { 4 | it('should handle nested values', () => { 5 | expect(nestedOphanComponents('logo')).toBe('logo'); 6 | expect(nestedOphanComponents('nav', 'sub nav', 'final element')).toBe( 7 | 'nav : sub nav : final element', 8 | ); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /dotcom-rendering/src/components/MainMediaEmbedBlockComponent.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | 3 | type Props = { 4 | title: string; 5 | srcDoc: string; 6 | }; 7 | 8 | export const MainMediaEmbedBlockComponent = ({ title, srcDoc }: Props) => ( 9 |