@newskit-render/core 0.0.0-d55b7d88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (456) hide show
  1. package/.ci/trigger-circleci-workflow.sh +37 -0
  2. package/.eslintignore +23 -0
  3. package/.eslintrc +74 -0
  4. package/.prettierignore +19 -0
  5. package/.prettierrc +7 -0
  6. package/CHANGELOG.md +7638 -0
  7. package/Dockerfile +14 -0
  8. package/Dockerfile.withNewRelic +15 -0
  9. package/README.md +274 -0
  10. package/__tests__/pages/__snapshots__/brightcove.test.tsx.snap +20 -0
  11. package/__tests__/pages/__snapshots__/home.test.tsx.snap +1195 -0
  12. package/__tests__/pages/brightcove.test.tsx +34 -0
  13. package/__tests__/pages/empty.test.tsx +10 -0
  14. package/__tests__/pages/home.test.tsx +16 -0
  15. package/app-context/InstrumentationContextProvider.tsx +36 -0
  16. package/assets/fontFamily.ts +416 -0
  17. package/assets/fonts/Graphik-Black-App.ttf +0 -0
  18. package/assets/fonts/Graphik-BlackItalic-App.ttf +0 -0
  19. package/assets/fonts/Graphik-Bold-App.ttf +0 -0
  20. package/assets/fonts/Graphik-BoldItalic-App.ttf +0 -0
  21. package/assets/fonts/Graphik-Extralight-App.ttf +0 -0
  22. package/assets/fonts/Graphik-ExtralightItalic-App.ttf +0 -0
  23. package/assets/fonts/Graphik-Light-App.ttf +0 -0
  24. package/assets/fonts/Graphik-LightItalic-App.ttf +0 -0
  25. package/assets/fonts/Graphik-Medium-App.ttf +0 -0
  26. package/assets/fonts/Graphik-Medium-Web.woff2 +0 -0
  27. package/assets/fonts/Graphik-MediumItalic-App.ttf +0 -0
  28. package/assets/fonts/Graphik-Regular-App.ttf +0 -0
  29. package/assets/fonts/Graphik-Regular-Web.woff2 +0 -0
  30. package/assets/fonts/Graphik-RegularItalic-App.ttf +0 -0
  31. package/assets/fonts/Graphik-Semibold-App.ttf +0 -0
  32. package/assets/fonts/Graphik-Semibold-Web.woff2 +0 -0
  33. package/assets/fonts/Graphik-SemiboldItalic-App.ttf +0 -0
  34. package/assets/fonts/Graphik-Super-App.ttf +0 -0
  35. package/assets/fonts/Graphik-SuperItalic-App.ttf +0 -0
  36. package/assets/fonts/Graphik-Thin-App.ttf +0 -0
  37. package/assets/fonts/Graphik-ThinItalic-App.ttf +0 -0
  38. package/assets/fonts/Montserrat-Black.ttf +0 -0
  39. package/assets/fonts/Montserrat-BlackItalic.ttf +0 -0
  40. package/assets/fonts/Montserrat-Bold.ttf +0 -0
  41. package/assets/fonts/Montserrat-BoldItalic.ttf +0 -0
  42. package/assets/fonts/Montserrat-ExtraBold.ttf +0 -0
  43. package/assets/fonts/Montserrat-ExtraBoldItalic.ttf +0 -0
  44. package/assets/fonts/Montserrat-ExtraLight.ttf +0 -0
  45. package/assets/fonts/Montserrat-ExtraLightItalic.ttf +0 -0
  46. package/assets/fonts/Montserrat-Italic.ttf +0 -0
  47. package/assets/fonts/Montserrat-Light.ttf +0 -0
  48. package/assets/fonts/Montserrat-LightItalic.ttf +0 -0
  49. package/assets/fonts/Montserrat-Medium.ttf +0 -0
  50. package/assets/fonts/Montserrat-MediumItalic.ttf +0 -0
  51. package/assets/fonts/Montserrat-Regular.ttf +0 -0
  52. package/assets/fonts/Montserrat-SemiBold.ttf +0 -0
  53. package/assets/fonts/Montserrat-SemiBoldItalic.ttf +0 -0
  54. package/assets/fonts/Montserrat-Thin.ttf +0 -0
  55. package/assets/fonts/Montserrat-ThinItalic.ttf +0 -0
  56. package/assets/fonts/PublicoHeadline-Black-App.ttf +0 -0
  57. package/assets/fonts/PublicoHeadline-BlackItalic-App.ttf +0 -0
  58. package/assets/fonts/PublicoHeadline-Bold-App.ttf +0 -0
  59. package/assets/fonts/PublicoHeadline-Bold-Web.woff2 +0 -0
  60. package/assets/fonts/PublicoHeadline-BoldItalic-App.ttf +0 -0
  61. package/assets/fonts/PublicoHeadline-Extrabold-App.ttf +0 -0
  62. package/assets/fonts/PublicoHeadline-ExtraboldItalic-App.ttf +0 -0
  63. package/assets/fonts/PublicoHeadline-Italic-App.ttf +0 -0
  64. package/assets/fonts/PublicoHeadline-Light-App.ttf +0 -0
  65. package/assets/fonts/PublicoHeadline-LightItalic-App.ttf +0 -0
  66. package/assets/fonts/PublicoHeadline-Medium-App.ttf +0 -0
  67. package/assets/fonts/PublicoHeadline-MediumItalic-App.ttf +0 -0
  68. package/assets/fonts/PublicoHeadline-Roman-App.ttf +0 -0
  69. package/assets/fonts/PublicoHeadline-Roman-Web.woff2 +0 -0
  70. package/assets/fonts/PublicoText-Bold-App.ttf +0 -0
  71. package/assets/fonts/PublicoText-BoldItalic-App.ttf +0 -0
  72. package/assets/fonts/PublicoText-Italic-App.ttf +0 -0
  73. package/assets/fonts/PublicoText-Italic-Web.woff2 +0 -0
  74. package/assets/fonts/PublicoText-Roman-App.ttf +0 -0
  75. package/assets/fonts/PublicoText-Roman-Web.woff2 +0 -0
  76. package/assets/fonts/PublicoText-Semibold-App.ttf +0 -0
  77. package/assets/fonts/PublicoText-SemiboldItalic-App.ttf +0 -0
  78. package/assets/fonts/Roboto-Bold.ttf +0 -0
  79. package/assets/fonts/Roboto-Light.ttf +0 -0
  80. package/assets/fonts/Roboto-Medium.ttf +0 -0
  81. package/assets/fonts/Roboto-Regular.ttf +0 -0
  82. package/assets/fonts/TheSun-Bold.ttf +0 -0
  83. package/assets/fonts/TheSun-BoldItalic.ttf +0 -0
  84. package/assets/fonts/TheSun-HeavyCondensed.ttf +0 -0
  85. package/assets/fonts/TheSun-HeavyNarrow.ttf +0 -0
  86. package/assets/fonts/TheSun-Italic.ttf +0 -0
  87. package/assets/fonts/TheSun-Medium.ttf +0 -0
  88. package/assets/fonts/TheSun-MediumItalic.ttf +0 -0
  89. package/assets/fonts/TheSun-Regular.ttf +0 -0
  90. package/assets/fonts/TimesDigital-Bold.ttf +0 -0
  91. package/assets/fonts/TimesDigital-BoldItalic.ttf +0 -0
  92. package/assets/fonts/TimesDigital-BoldSC.ttf +0 -0
  93. package/assets/fonts/TimesDigital-Italic.ttf +0 -0
  94. package/assets/fonts/TimesDigital-Regular.ttf +0 -0
  95. package/assets/fonts/TimesDigital-RegularSC.ttf +0 -0
  96. package/assets/fonts/TimesDigitalW04-Bold.ttf +0 -0
  97. package/assets/fonts/TimesDigitalW04-BoldItalic.ttf +0 -0
  98. package/assets/fonts/TimesDigitalW04-BoldSC.ttf +0 -0
  99. package/assets/fonts/TimesDigitalW04-Italic.ttf +0 -0
  100. package/assets/fonts/TimesDigitalW04-Regular.ttf +0 -0
  101. package/assets/fonts/TimesDigitalW04-RegularSC.ttf +0 -0
  102. package/assets/fonts/TimesModern-Regular.otf +0 -0
  103. package/assets/fonts/attribuitions.mdx +35 -0
  104. package/assets/fonts/bitter-medium.woff +0 -0
  105. package/assets/fonts/bitter-medium.woff2 +0 -0
  106. package/assets/fonts/bitter-mediumitalic.woff +0 -0
  107. package/assets/fonts/bitter-mediumitalic.woff2 +0 -0
  108. package/assets/fonts/bitter-regular.woff +0 -0
  109. package/assets/fonts/bitter-regular.woff2 +0 -0
  110. package/assets/fonts/bitter-semibold.woff +0 -0
  111. package/assets/fonts/bitter-semibold.woff2 +0 -0
  112. package/assets/fonts/dmmono-medium.woff +0 -0
  113. package/assets/fonts/dmmono-medium.woff2 +0 -0
  114. package/assets/fonts/dmsans-bold-webfont.woff +0 -0
  115. package/assets/fonts/dmsans-bold-webfont.woff2 +0 -0
  116. package/assets/fonts/dmsans-bolditalic-webfont.woff +0 -0
  117. package/assets/fonts/dmsans-bolditalic-webfont.woff2 +0 -0
  118. package/assets/fonts/dmsans-italic-webfont.woff +0 -0
  119. package/assets/fonts/dmsans-italic-webfont.woff2 +0 -0
  120. package/assets/fonts/dmsans-medium-webfont.woff +0 -0
  121. package/assets/fonts/dmsans-medium-webfont.woff2 +0 -0
  122. package/assets/fonts/dmsans-mediumitalic-webfont.woff +0 -0
  123. package/assets/fonts/dmsans-mediumitalic-webfont.woff2 +0 -0
  124. package/assets/fonts/dmsans-regular-webfont.woff +0 -0
  125. package/assets/fonts/dmsans-regular-webfont.woff2 +0 -0
  126. package/assets/fonts/notosans-bold-webfont.woff +0 -0
  127. package/assets/fonts/notosans-bold-webfont.woff2 +0 -0
  128. package/assets/fonts/notosans-italic-webfont.woff +0 -0
  129. package/assets/fonts/notosans-italic-webfont.woff2 +0 -0
  130. package/assets/fonts/notosans-medium-webfont.woff +0 -0
  131. package/assets/fonts/notosans-medium-webfont.woff2 +0 -0
  132. package/assets/fonts/notosans-regular-webfont.woff +0 -0
  133. package/assets/fonts/notosans-regular-webfont.woff2 +0 -0
  134. package/assets/fonts/poppins-bold-webfont.woff +0 -0
  135. package/assets/fonts/poppins-bold-webfont.woff2 +0 -0
  136. package/assets/fonts/poppins-bolditalic-webfont.woff +0 -0
  137. package/assets/fonts/poppins-bolditalic-webfont.woff2 +0 -0
  138. package/assets/fonts/poppins-extrabold-webfont.woff +0 -0
  139. package/assets/fonts/poppins-extrabold-webfont.woff2 +0 -0
  140. package/assets/fonts/poppins-extrabolditalic-webfont.woff +0 -0
  141. package/assets/fonts/poppins-extrabolditalic-webfont.woff2 +0 -0
  142. package/assets/fonts/poppins-italic-webfont.woff +0 -0
  143. package/assets/fonts/poppins-italic-webfont.woff2 +0 -0
  144. package/assets/fonts/poppins-light-webfont.woff +0 -0
  145. package/assets/fonts/poppins-light-webfont.woff2 +0 -0
  146. package/assets/fonts/poppins-lightitalic-webfont.woff +0 -0
  147. package/assets/fonts/poppins-lightitalic-webfont.woff2 +0 -0
  148. package/assets/fonts/poppins-medium-webfont.woff +0 -0
  149. package/assets/fonts/poppins-medium-webfont.woff2 +0 -0
  150. package/assets/fonts/poppins-mediumitalic-webfont.woff +0 -0
  151. package/assets/fonts/poppins-mediumitalic-webfont.woff2 +0 -0
  152. package/assets/fonts/poppins-regular-webfont.woff +0 -0
  153. package/assets/fonts/poppins-regular-webfont.woff2 +0 -0
  154. package/assets/fonts/poppins-semibold-webfont.woff +0 -0
  155. package/assets/fonts/poppins-semibold-webfont.woff2 +0 -0
  156. package/assets/fonts/poppins-semibolditalic-webfont.woff +0 -0
  157. package/assets/fonts/poppins-semibolditalic-webfont.woff2 +0 -0
  158. package/assets/fonts/source-serif-pro-600.woff +0 -0
  159. package/assets/fonts/source-serif-pro-600.woff2 +0 -0
  160. package/assets/fonts/source-serif-pro-600italic.woff +0 -0
  161. package/assets/fonts/source-serif-pro-600italic.woff2 +0 -0
  162. package/assets/fonts/source-serif-pro-700.woff +0 -0
  163. package/assets/fonts/source-serif-pro-700.woff2 +0 -0
  164. package/assets/fonts/source-serif-pro-700italic.woff +0 -0
  165. package/assets/fonts/source-serif-pro-700italic.woff2 +0 -0
  166. package/assets/fonts/source-serif-pro-italic.woff +0 -0
  167. package/assets/fonts/source-serif-pro-italic.woff2 +0 -0
  168. package/assets/fonts/source-serif-pro-regular.woff +0 -0
  169. package/assets/fonts/source-serif-pro-regular.woff2 +0 -0
  170. package/components/AccountDropdown/AccountDropdown.tsx +65 -0
  171. package/components/AccountDropdown/__tests__/AcountDropdown.test.tsx +83 -0
  172. package/components/AccountDropdown/accounts.ts +47 -0
  173. package/components/AccountDropdown/index.tsx +2 -0
  174. package/components/AccountDropdown/utils.ts +21 -0
  175. package/components/ErrorPage/ErrorPage.tsx +135 -0
  176. package/components/ad/index.tsx +35 -0
  177. package/components/article/Highlights.tsx +77 -0
  178. package/components/article/MetaBox.tsx +50 -0
  179. package/components/article/RelatedArticles.tsx +53 -0
  180. package/components/article/RelatedTopics.tsx +59 -0
  181. package/components/article/ShareBarComponent.tsx +53 -0
  182. package/components/article/__tests__/__snapshots__/index.test.tsx.snap +1568 -0
  183. package/components/article/__tests__/index.test.tsx +171 -0
  184. package/components/article/__tests__/mocks.ts +105 -0
  185. package/components/article/index.tsx +320 -0
  186. package/components/common/BackToHomepage.tsx +37 -0
  187. package/components/common/NavLink.tsx +26 -0
  188. package/components/common/NewskitLogo.tsx +52 -0
  189. package/components/common/NewskitLogoShort.tsx +48 -0
  190. package/components/common/SectionTitleBar.tsx +57 -0
  191. package/components/common/ShareButton.tsx +18 -0
  192. package/components/common/ViewMoreButton.tsx +20 -0
  193. package/components/common/iconNavLink/IconNavLink.tsx +70 -0
  194. package/components/common/iconNavLink/__tests__/IconNavLink.test.tsx +35 -0
  195. package/components/common/iconNavLink/index.ts +3 -0
  196. package/components/common/iconNavLink/types.ts +24 -0
  197. package/components/common/icons/IconAccount.tsx +13 -0
  198. package/components/common/icons/IconFilledTwitter.tsx +14 -0
  199. package/components/common/icons/StyledIconFilledChevronRight.tsx +12 -0
  200. package/components/footer/__snapshots__/index.test.tsx.snap +192 -0
  201. package/components/footer/index.test.tsx +13 -0
  202. package/components/footer/index.tsx +151 -0
  203. package/components/header/banner-messages.ts +39 -0
  204. package/components/header/index.tsx +52 -0
  205. package/components/header/navigation-links.ts +20 -0
  206. package/components/layout/Gutter.tsx +11 -0
  207. package/components/layout/LayoutTemplate.tsx +26 -0
  208. package/components/layout/MainGrid.tsx +66 -0
  209. package/components/layout/index.tsx +3 -0
  210. package/components/layout/layoutTypes.ts +13 -0
  211. package/components/section/ArticleSlice.tsx +35 -0
  212. package/components/section/CollectionBlock.tsx +54 -0
  213. package/components/section/SectionContext.tsx +9 -0
  214. package/components/section/__tests__/ArticleSlice.test.tsx +128 -0
  215. package/components/section/__tests__/CollectionBlock.test.tsx +83 -0
  216. package/components/section/__tests__/pageBlock.test.tsx +24 -0
  217. package/components/section/__tests__/sectionUtils.test.ts +94 -0
  218. package/components/section/index.tsx +39 -0
  219. package/components/section/layouts/Block.tsx +79 -0
  220. package/components/section/layouts/FallBack.tsx +24 -0
  221. package/components/section/layouts/Lead.tsx +43 -0
  222. package/components/section/layouts/Rows.tsx +82 -0
  223. package/components/section/layouts/SectionTitle.tsx +57 -0
  224. package/components/section/layouts/__tests__/Lead.test.tsx +37 -0
  225. package/components/section/layouts/__tests__/Rows.test.tsx +40 -0
  226. package/components/section/layouts/__tests__/SectionTitle.test.tsx +37 -0
  227. package/components/section/layouts/__tests__/__snapshots__/Lead.test.tsx.snap +180 -0
  228. package/components/section/layouts/__tests__/__snapshots__/SectionTitle.test.tsx.snap +354 -0
  229. package/components/section/layouts/gridUtils.ts +21 -0
  230. package/components/section/layouts/index.tsx +4 -0
  231. package/components/section/layouts/types.ts +13 -0
  232. package/components/section/pageBlock.tsx +23 -0
  233. package/components/section/sectionUtils.ts +61 -0
  234. package/components/teaser/index.test.tsx +50 -0
  235. package/components/teaser/index.tsx +64 -0
  236. package/components/teaser/teaserVariants.ts +33 -0
  237. package/components/teaser/variant-types.ts +49 -0
  238. package/components/teaser/variants/featureVariant.ts +42 -0
  239. package/components/teaser/variants/horizontal.ts +14 -0
  240. package/components/teaser/variants/titleTeaserVariant.ts +32 -0
  241. package/components/teaser/variants/titleVertical.ts +24 -0
  242. package/components/utils/index.test.ts +12 -0
  243. package/components/utils/index.ts +6 -0
  244. package/config/__tests__/index.test.ts +54 -0
  245. package/config/environment.ts +80 -0
  246. package/config/index.ts +2 -0
  247. package/config/multiTenancy.ts +11 -0
  248. package/constants/index.ts +2 -0
  249. package/context/app-context/AppContext.test.tsx +56 -0
  250. package/context/app-context/holidayStopListContextOverrides.ts +18 -0
  251. package/context/app-context/index.tsx +34 -0
  252. package/context/app-context/paymentMethodContext.tsx +70 -0
  253. package/context/index.tsx +2 -0
  254. package/context/multi-tenancy/MultiTenancy.test.tsx +48 -0
  255. package/context/multi-tenancy/index.tsx +32 -0
  256. package/css/index.ts +15 -0
  257. package/cypress/axe/terminal-log.js +19 -0
  258. package/cypress/config/visual.config.ts +11 -0
  259. package/cypress/config/visual.skip.config.ts +10 -0
  260. package/cypress/e2e/account/accessibility.cy.js +88 -0
  261. package/cypress/e2e/account/banners.cy.js +169 -0
  262. package/cypress/e2e/account/cancellation.cy.js +219 -0
  263. package/cypress/e2e/account/holiday-stops.cy.js +109 -0
  264. package/cypress/e2e/account/main-api.cy.js +102 -0
  265. package/cypress/e2e/account/newsletters-and-alerts.cy.js +149 -0
  266. package/cypress/e2e/account/newsletters-page.cy.js +69 -0
  267. package/cypress/e2e/account/payment-page.cy.js +98 -0
  268. package/cypress/e2e/account/personal-details.cy.js +1161 -0
  269. package/cypress/e2e/account/subscription-and-billing.cy.js +434 -0
  270. package/cypress/e2e/checkout/account-creation.cy.js +8 -0
  271. package/cypress/e2e/checkout/payment-details.cy.js +19 -0
  272. package/cypress/e2e/core/home-page.cy.js +6 -0
  273. package/cypress/e2e/help-hub/accessibility.cy.js +35 -0
  274. package/cypress/e2e/help-hub/article-page.cy.js +115 -0
  275. package/cypress/e2e/help-hub/landing-page.cy.js +94 -0
  276. package/cypress/e2e/help-hub/result-page.cy.js +117 -0
  277. package/cypress/fixtures/empty.html +10 -0
  278. package/cypress/fixtures/example.json +5 -0
  279. package/cypress/fixtures/holiday-stops.json +40 -0
  280. package/cypress/fixtures/paymentFailure.js +24 -0
  281. package/cypress/fixtures/testDates.js +26 -0
  282. package/cypress/support/commands.js +125 -0
  283. package/cypress/support/consentValues.js +5839 -0
  284. package/cypress/support/e2e.js +22 -0
  285. package/cypress/support/users.js +58 -0
  286. package/cypress/visual/account/print-visual-regression.cy.js +9 -0
  287. package/cypress/visual/account/visual-regression.cy.js +40 -0
  288. package/cypress/visual/empty/empty.cy.js +5 -0
  289. package/cypress.config.ts +38 -0
  290. package/helpers/__tests__/getUser.test.ts +45 -0
  291. package/helpers/__tests__/logger.test.ts +62 -0
  292. package/helpers/__tests__/useThemeDropdownObject.test.ts +49 -0
  293. package/helpers/a11y.ts +7 -0
  294. package/helpers/addCacheHeaders.ts +8 -0
  295. package/helpers/getUser.ts +37 -0
  296. package/helpers/getYear.ts +1 -0
  297. package/helpers/global-types.ts +186 -0
  298. package/helpers/logger/getWinstonLogger.ts +19 -0
  299. package/helpers/logger/index.ts +20 -0
  300. package/helpers/logger/replaceConsoleWithLogger.ts +14 -0
  301. package/helpers/mocks/articleMock.ts +50 -0
  302. package/helpers/mocks/getPageMock.ts +369 -0
  303. package/helpers/mocks/getRadioPostMock.ts +71 -0
  304. package/helpers/mocks/getRadioPostsMock.ts +26 -0
  305. package/helpers/mocks/getRecommendationsMock.ts +20 -0
  306. package/helpers/mocks/index.ts +7 -0
  307. package/helpers/multiTenancy.ts +19 -0
  308. package/helpers/setupTests.ts +5 -0
  309. package/helpers/test-utils.tsx +33 -0
  310. package/helpers/useThemeDropdownObject.tsx +73 -0
  311. package/infrastructure/.circleci/config.yml +1187 -0
  312. package/infrastructure/INFRASTRUCTURE.md +142 -0
  313. package/infrastructure/build_and_deploy.png +0 -0
  314. package/infrastructure/helm/Chart.yaml +21 -0
  315. package/infrastructure/helm/templates/_helpers.tpl +87 -0
  316. package/infrastructure/helm/templates/deployment.yaml +45 -0
  317. package/infrastructure/helm/templates/horizontalpodautoscaler.yaml +21 -0
  318. package/infrastructure/helm/templates/ingress.yaml +31 -0
  319. package/infrastructure/helm/templates/networkpolicy.yaml +26 -0
  320. package/infrastructure/helm/templates/secret.yaml +12 -0
  321. package/infrastructure/helm/templates/service.yaml +15 -0
  322. package/infrastructure/helm/values-dev.yaml +39 -0
  323. package/infrastructure/helm/values-local.yaml +30 -0
  324. package/infrastructure/helm/values-pr.yaml +40 -0
  325. package/infrastructure/helm/values-prod.yaml +39 -0
  326. package/infrastructure/helm/values-staging.yaml +39 -0
  327. package/infrastructure/helm/values.yaml +44 -0
  328. package/infrastructure/pull_request.png +0 -0
  329. package/infrastructure/release-documentation-cli.config.json +18 -0
  330. package/infrastructure/remove_pr.png +0 -0
  331. package/infrastructure/terraform-ecr/dev.tfvars +3 -0
  332. package/infrastructure/terraform-ecr/ecr.tf +69 -0
  333. package/infrastructure/terraform-ecr/main.tf +3 -0
  334. package/infrastructure/terraform-ecr/variables.tf +19 -0
  335. package/infrastructure/terraform-ecr/versions.tf +12 -0
  336. package/infrastructure/terraform-newrelic/alerts.tf +290 -0
  337. package/infrastructure/terraform-newrelic/dashboards.tf +347 -0
  338. package/infrastructure/terraform-newrelic/dev.tfvars +3 -0
  339. package/infrastructure/terraform-newrelic/lighthouse-script-dev.js +53 -0
  340. package/infrastructure/terraform-newrelic/lighthouse-script-prod.js +54 -0
  341. package/infrastructure/terraform-newrelic/lighthouse-script-stage.js +54 -0
  342. package/infrastructure/terraform-newrelic/main.tf +11 -0
  343. package/infrastructure/terraform-newrelic/monitors.tf +11 -0
  344. package/infrastructure/terraform-newrelic/prod.tfvars +3 -0
  345. package/infrastructure/terraform-newrelic/staging.tfvars +3 -0
  346. package/infrastructure/terraform-newrelic/variables.tf +33 -0
  347. package/infrastructure/terraform-newrelic/versions.tf +18 -0
  348. package/jest.config.js +40 -0
  349. package/jest.config.pact.js +18 -0
  350. package/newrelic.js +86 -0
  351. package/next-env.d.ts +5 -0
  352. package/next.config.js +95 -0
  353. package/package.json +127 -0
  354. package/pages/_app.tsx +117 -0
  355. package/pages/_document.tsx +112 -0
  356. package/pages/_error.tsx +68 -0
  357. package/pages/account/add/[field].tsx +34 -0
  358. package/pages/account/cancellation/index.tsx +22 -0
  359. package/pages/account/delete/confirm/index.tsx +16 -0
  360. package/pages/account/delete/error/index.tsx +16 -0
  361. package/pages/account/delete/index.tsx +16 -0
  362. package/pages/account/delete/success/index.tsx +16 -0
  363. package/pages/account/dream-team/index.tsx +19 -0
  364. package/pages/account/edit/[field].tsx +45 -0
  365. package/pages/account/family/index.tsx +19 -0
  366. package/pages/account/holiday-stop/index.tsx +19 -0
  367. package/pages/account/holiday-stop/previous-holiday-stops.tsx +19 -0
  368. package/pages/account/holiday-stop/upcoming-holiday-stops.tsx +19 -0
  369. package/pages/account/index.tsx +33 -0
  370. package/pages/account/newsletters/index.tsx +19 -0
  371. package/pages/account/newsletters-and-alerts/index.tsx +24 -0
  372. package/pages/account/payment/[paymentMethod].tsx +37 -0
  373. package/pages/account/payment/index.tsx +23 -0
  374. package/pages/account/payment-methods/index.tsx +21 -0
  375. package/pages/account/subscription-and-billing/index.tsx +29 -0
  376. package/pages/api/account/get-session/index.ts +33 -0
  377. package/pages/api/account/invoice/index.ts +35 -0
  378. package/pages/api/account/mutate/index.ts +8 -0
  379. package/pages/api/account/query/index.ts +7 -0
  380. package/pages/api/auth/[...nextauth].ts +11 -0
  381. package/pages/api/competitions-sitemap.ts +19 -0
  382. package/pages/api/feed.ts +23 -0
  383. package/pages/api/health-check.ts +7 -0
  384. package/pages/api/news-sitemap.ts +18 -0
  385. package/pages/api/pages-sitemap.ts +27 -0
  386. package/pages/api/robots.ts +19 -0
  387. package/pages/api/sitemap.ts +24 -0
  388. package/pages/checkout/account-creation/index.tsx +13 -0
  389. package/pages/checkout/payment-details/index.tsx +10 -0
  390. package/pages/empty.tsx +6 -0
  391. package/pages/help-hub/article/[title]/index.tsx +25 -0
  392. package/pages/help-hub/error.tsx +23 -0
  393. package/pages/help-hub/index.tsx +51 -0
  394. package/pages/help-hub/results.tsx +25 -0
  395. package/pages/index.tsx +19 -0
  396. package/pages/player/brightcove.tsx +19 -0
  397. package/pages/rss/create/index.tsx +18 -0
  398. package/pages/rss/feed/[feedId]/index.tsx +21 -0
  399. package/pages/rss/index.tsx +18 -0
  400. package/public/ads.min.js +8175 -0
  401. package/public/assets/display-base-header.svg +25 -0
  402. package/public/assets/display-personalDetails-header-sun.svg +55 -0
  403. package/public/assets/display-personalDetails-header-times.svg +90 -0
  404. package/public/assets/display-personalDetails-header-vr.svg +46 -0
  405. package/public/assets/dream-team.svg +10 -0
  406. package/public/assets/navigationPrimary-brandMark-sun.svg +9 -0
  407. package/public/assets/navigationPrimary-brandMark-times.svg +18 -0
  408. package/public/assets/navigationPrimary-brandMark-vr.svg +10 -0
  409. package/public/assets/newsletters/bestoftimes-101.png +0 -0
  410. package/public/assets/newsletters/books-115.png +0 -0
  411. package/public/assets/newsletters/environment-140.png +0 -0
  412. package/public/assets/newsletters/fashion-108.png +0 -0
  413. package/public/assets/newsletters/food-106.png +0 -0
  414. package/public/assets/newsletters/football-111.png +0 -0
  415. package/public/assets/newsletters/ireland-152.png +0 -0
  416. package/public/assets/newsletters/law-121.png +0 -0
  417. package/public/assets/newsletters/money-107.png +0 -0
  418. package/public/assets/newsletters/moneymentor-150.png +0 -0
  419. package/public/assets/newsletters/placeholder.png +0 -0
  420. package/public/assets/newsletters/politics-119.png +0 -0
  421. package/public/assets/newsletters/property-113.png +0 -0
  422. package/public/assets/newsletters/puzzles-125.png +0 -0
  423. package/public/assets/newsletters/scotland-134.png +0 -0
  424. package/public/assets/newsletters/theatre-127.png +0 -0
  425. package/public/assets/newsletters/travel-149.png +0 -0
  426. package/public/assets/newsletters/tv-133.png +0 -0
  427. package/public/assets/newsletters/us-153.png +0 -0
  428. package/public/assets/no-subscription.svg +15 -0
  429. package/public/assets/pending-activation.svg +16 -0
  430. package/public/assets/personal-details-header.svg +91 -0
  431. package/public/assets/plchldr150x100.png +0 -0
  432. package/public/assets/previous-subscription.svg +15 -0
  433. package/public/assets/primary-navigation-logo-white.svg +6 -0
  434. package/public/assets/primary-navigation-logo.svg +6 -0
  435. package/public/assets/tls-logo-white.svg +3 -0
  436. package/public/favicon.ico +0 -0
  437. package/public/icon.png +0 -0
  438. package/public/prebid.min.js +1 -0
  439. package/queries/getPage.ts +100 -0
  440. package/queries/getRadioPost.ts +61 -0
  441. package/queries/getRadioPosts.ts +16 -0
  442. package/queries/getUserSubscription.ts +9 -0
  443. package/queries/index.ts +3 -0
  444. package/scripts/k8s-local.sh +137 -0
  445. package/scripts/nr-exports.sh +7 -0
  446. package/temp/_app.tsx +15 -0
  447. package/temp/_document.tsx +61 -0
  448. package/temp/app-context-test.tsx +51 -0
  449. package/temp/app-context.tsx +25 -0
  450. package/temp/config-index.ts +1 -0
  451. package/temp/context-index.tsx +1 -0
  452. package/temp/header.tsx +45 -0
  453. package/temp/next.config.js +56 -0
  454. package/tsconfig.json +51 -0
  455. package/tsconfig.test.json +6 -0
  456. package/validation/index.tsx +24 -0
@@ -0,0 +1,171 @@
1
+ import React from 'react'
2
+ import { ArticleRecommendationsProviderContext } from '@newskit-render/standalone-components'
3
+ import { within } from '@testing-library/react'
4
+ import Article from '..'
5
+ import { Video } from '../../../helpers/global-types'
6
+ import { renderWithTheme } from '../../../helpers/test-utils'
7
+ import { dpaTemplatesMock, articleData } from './mocks'
8
+
9
+ const ArticleWrapper = (props) => (
10
+ <ArticleRecommendationsProviderContext.Provider
11
+ value={{
12
+ dpaTemplates: dpaTemplatesMock,
13
+ }}
14
+ >
15
+ <Article {...props} />
16
+ </ArticleRecommendationsProviderContext.Provider>
17
+ )
18
+
19
+ jest.mock('@newskit-render/my-account', () => {
20
+ return {
21
+ PastDueBannerExternal: 'PastDueBannerExternal',
22
+ }
23
+ })
24
+
25
+ jest.mock('next/router', () => {
26
+ return {
27
+ useRouter: () => ({ asPath: '' }),
28
+ }
29
+ })
30
+
31
+ jest.mock('../../../helpers/getYear', () => ({
32
+ getYear: jest.fn().mockReturnValue('YYYY'),
33
+ }))
34
+
35
+ describe('Article', () => {
36
+ beforeAll(() => {
37
+ HTMLImageElement.prototype.loading = 'lazy'
38
+ })
39
+ test('should render tile and sub title', () => {
40
+ const { getByTestId, asFragment } = renderWithTheme(
41
+ ArticleWrapper,
42
+ articleData
43
+ )
44
+ const headLine = within(getByTestId('HeadLine'))
45
+ const kicker = within(getByTestId('Kicker'))
46
+ const title = headLine.getByText(
47
+ 'Mock Article: Lorem ipsum dolor sit amet consectetur adipiscing elit'
48
+ )
49
+ const subTitle = kicker.getByText('Kicker title')
50
+ expect(title).toBeInTheDocument()
51
+ expect(subTitle).toBeInTheDocument()
52
+ expect(asFragment()).toMatchSnapshot()
53
+ })
54
+
55
+ test('should render byline', () => {
56
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
57
+ const byline = within(getByTestId('MetaBox'))
58
+ const authorName = byline.getByText('John Smith')
59
+ const authorTitle = byline.getByText('John Smith')
60
+ expect(authorName).toBeInTheDocument()
61
+ expect(authorTitle).toBeInTheDocument()
62
+ })
63
+
64
+ test('should render published time', () => {
65
+ articleData.updatedDateTime = undefined
66
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
67
+ const metaBox = within(getByTestId('MetaBox'))
68
+ const date = metaBox.getByText('Thu February 14 2019, 12:00am')
69
+ expect(date).toBeInTheDocument()
70
+ })
71
+
72
+ test('should render related topics', () => {
73
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
74
+ const topics = within(getByTestId('RelatedTopics')).getAllByTestId('tag')
75
+ expect(topics[0].getAttribute('href')).toBe(null)
76
+ expect(within(topics[0]).getByText('Some topic one')).toBeInTheDocument()
77
+ expect(topics[1].getAttribute('href')).toBe(null)
78
+ expect(within(topics[1]).getByText('Some topic one')).toBeInTheDocument()
79
+ expect(topics[1].getAttribute('href')).toBe(null)
80
+ expect(within(topics[1]).getByText('Some topic one')).toBeInTheDocument()
81
+ })
82
+
83
+ test('should not render related topics', () => {
84
+ articleData.topics = undefined
85
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
86
+ expect(() => getByTestId('topics')).toThrow()
87
+ })
88
+
89
+ test('should render highlights panel', () => {
90
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
91
+ const title = within(getByTestId('Highlights')).getAllByText(
92
+ 'Highlights'
93
+ )[0]
94
+ const card = within(getByTestId('Highlights')).getAllByTestId(
95
+ 'article-recommendation-small'
96
+ )[0]
97
+ expect(title).toBeInTheDocument()
98
+ expect(card).toBeInTheDocument()
99
+ })
100
+
101
+ test('should render related articles panel', () => {
102
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
103
+ const title = within(getByTestId('RelatedArticles')).getByText('Related')
104
+ const card = within(getByTestId('RelatedArticles')).getAllByTestId(
105
+ 'article-recommendation-large'
106
+ )[0]
107
+
108
+ expect(title).toBeInTheDocument()
109
+ expect(card).toBeInTheDocument()
110
+ })
111
+
112
+ test('should render image', () => {
113
+ const { getByAltText } = renderWithTheme(ArticleWrapper, articleData)
114
+ const img = getByAltText('testIMG')
115
+ expect(img.getAttribute('src')).toBe(
116
+ '/_next/image?url=%2Fimg%2Furl&w=3840&q=75'
117
+ )
118
+ })
119
+
120
+ test('should not render image', () => {
121
+ articleData.media = undefined
122
+ const { getByAltText } = renderWithTheme(ArticleWrapper, articleData)
123
+ expect(() => getByAltText('testIMG')).toThrow()
124
+ })
125
+
126
+ test('should render paragraphs', () => {
127
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
128
+ const paragraphs = getByTestId('ArticleContent')
129
+ expect(within(paragraphs).getByText('paragraph one')).toBeInTheDocument()
130
+ expect(within(paragraphs).getByText('paragraph two')).toBeInTheDocument()
131
+ expect(within(paragraphs).getByText('paragraph three')).toBeInTheDocument()
132
+ })
133
+
134
+ test('should not render paragraphs', () => {
135
+ articleData.summary = undefined
136
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
137
+ expect(() =>
138
+ within(getByTestId('ArticleContent')).getAllByTestId('ArticleParagraph')
139
+ ).toThrow()
140
+ })
141
+
142
+ test('should render video', () => {
143
+ const articleWithVideo = {
144
+ ...articleData,
145
+ media: {
146
+ accountId: '5067014667001',
147
+ videoId: '6288769193001',
148
+ posterImage: {
149
+ crops: [
150
+ {
151
+ url: 'https://www.thesun.co.uk/wp-content/uploads/2021/12/image-5923b09d66.jpg?strip=all&w=600&h=338&crop=1',
152
+ alt: null,
153
+ aspectRatio: null,
154
+ },
155
+ ],
156
+ },
157
+ },
158
+ }
159
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleWithVideo)
160
+ const video = getByTestId('bc-video-player')
161
+ const articleVideo = articleWithVideo?.media as Video
162
+ expect(video.getAttribute('data-account')).toBe(articleVideo.accountId)
163
+ expect(video.getAttribute('data-video-id')).toBe(articleVideo.videoId)
164
+ })
165
+
166
+ test('should not render video', () => {
167
+ articleData.media = undefined
168
+ const { getByTestId } = renderWithTheme(ArticleWrapper, articleData)
169
+ expect(() => getByTestId('bc-video-player')).toThrow()
170
+ })
171
+ })
@@ -0,0 +1,105 @@
1
+ import { DpaTemplate } from '@newskit-render/standalone-components'
2
+ import { ArticleProps } from '..'
3
+ import { Slug, URL } from '../../../helpers/global-types'
4
+
5
+ export const articleData: ArticleProps = {
6
+ id: 'demo-1',
7
+ url: 'https://mock-site-url/some-location' as URL,
8
+ label: 'Mock label',
9
+ slug: 'some-location' as Slug,
10
+ publisher: 'DEMO',
11
+ headline:
12
+ 'Mock Article: Lorem ipsum dolor sit amet consectetur adipiscing elit',
13
+ kicker: 'Kicker title',
14
+ authors: undefined,
15
+ flags: [],
16
+ topics: [
17
+ {
18
+ name: 'Some topic one',
19
+ slug: 'some-topic-one',
20
+ link: undefined,
21
+ },
22
+ {
23
+ name: 'Some topic one',
24
+ slug: 'some-topic-one',
25
+ link: undefined,
26
+ },
27
+ ],
28
+ template: undefined,
29
+ bylines: [
30
+ {
31
+ type: 'author',
32
+ slug: 'mock-author',
33
+ name: 'John Smith',
34
+ },
35
+ {
36
+ value: 'Еditor, UK',
37
+ type: 'inline',
38
+ },
39
+ ],
40
+ publishedDateTime: '2019-02-14T00:00:00.000Z',
41
+ updatedDateTime: '2019-02-14T00:37:17.000Z',
42
+ summary: {
43
+ children: [
44
+ {
45
+ text: 'paragraph one',
46
+ },
47
+ {
48
+ text: 'paragraph two',
49
+ },
50
+ {
51
+ url: 'http://this-is-a-url/',
52
+ text: 'paragraph three',
53
+ },
54
+ {
55
+ text: 'paragraph four',
56
+ },
57
+ ],
58
+ },
59
+ media: {
60
+ crops: [{ url: '/img/url', alt: 'testIMG', aspectRatio: '1:1' }],
61
+ },
62
+ highlights: [
63
+ {
64
+ title: 'Test Box',
65
+ href: 'https://plchldr.co/i/50x50',
66
+ },
67
+ {
68
+ title: 'Prince Harry',
69
+ href: 'https://plchldr.co/i/50x50',
70
+ },
71
+ ],
72
+ relatedArticles: [
73
+ {
74
+ title: 'Prince Harry',
75
+ text: 'news',
76
+ href: 'https://plchldr.co/i/70x50',
77
+ },
78
+ {
79
+ title: 'Meghan Markle',
80
+ text: 'news',
81
+ href: 'https://plchldr.co/i/70x50',
82
+ },
83
+ ],
84
+ articleURL: 'http://article-url.com',
85
+ twitterUsername: 'twitterUser',
86
+ siteHost: 'hostname',
87
+ gscId: '4320982',
88
+ }
89
+
90
+ export const dpaTemplatesMock: DpaTemplate = [
91
+ {
92
+ templateId: 'list-1',
93
+ columnCount: '1',
94
+ size: 'small',
95
+ recommendedArticles: articleData.relatedArticles,
96
+ adlibraryMPU: [],
97
+ },
98
+ {
99
+ templateId: 'list-2',
100
+ columnCount: { xs: '1', sm: '2', lg: '4' },
101
+ size: 'large',
102
+ recommendedArticles: articleData.relatedArticles,
103
+ adlibraryMPU: [],
104
+ },
105
+ ]
@@ -0,0 +1,320 @@
1
+ /* eslint-disable react/no-array-index-key */
2
+ import React from 'react'
3
+ import {
4
+ Block,
5
+ Cell,
6
+ VideoPlayer,
7
+ Visible,
8
+ Stack,
9
+ StackChild,
10
+ Headline,
11
+ TextBlock,
12
+ Divider,
13
+ } from 'newskit'
14
+ import {
15
+ SEOComponent,
16
+ Image,
17
+ getAspectRatio,
18
+ } from '@newskit-render/shared-components'
19
+ import { UserData } from '@newskit-render/my-account'
20
+ import { Article } from '@newskit-render/standalone-components'
21
+ import MetaBoxComponent from './MetaBox'
22
+ import Ad from '../ad'
23
+ import Highlights from './Highlights'
24
+ import RelatedArticles from './RelatedArticles'
25
+ import RelatedTopics from './RelatedTopics'
26
+ import ShareBarComponent from './ShareBarComponent'
27
+ import {
28
+ URL,
29
+ Slug,
30
+ Media,
31
+ Topic,
32
+ Byline,
33
+ ParagraphBlock,
34
+ } from '../../helpers/global-types'
35
+ import ShareButton from '../common/ShareButton'
36
+ import Layout from '../layout'
37
+ import { ratioMap } from '../section/sectionUtils'
38
+
39
+ export type UniversalArticle = {
40
+ id: string
41
+ url?: URL
42
+ label?: string
43
+ slug?: Slug
44
+ publisher?: string
45
+ headline?: string
46
+ kicker?: string
47
+ media?: Media
48
+ flags?: string[]
49
+ topics?: Topic[]
50
+ template?: string
51
+ authors?: string[]
52
+ bylines?: Byline[]
53
+ publishedDateTime?: string
54
+ updatedDateTime?: string
55
+ summary?: ParagraphBlock
56
+ highlights?: {
57
+ title: string
58
+ href: string
59
+ }[]
60
+ relatedArticles?: {
61
+ title: string
62
+ tag: string
63
+ text: string
64
+ href: string
65
+ }[]
66
+ }
67
+
68
+ export type ArticleProps = {
69
+ relatedArticles?: Article[]
70
+ id: string
71
+ url?: URL
72
+ label?: string
73
+ slug?: Slug
74
+ publisher?: string
75
+ headline?: string
76
+ kicker?: string
77
+ media?: Media
78
+ flags?: string[]
79
+ topics?: Topic[]
80
+ template?: string
81
+ authors?: string[]
82
+ bylines?: Byline[]
83
+ publishedDateTime?: string
84
+ updatedDateTime?: string
85
+ summary?: ParagraphBlock
86
+ articleURL: string
87
+ twitterUsername?: string
88
+ siteHost: string
89
+ gscId?: string
90
+ user?: UserData
91
+ }
92
+
93
+ const ArticlePage: React.FC<ArticleProps> = ({
94
+ publishedDateTime,
95
+ updatedDateTime,
96
+ headline,
97
+ kicker,
98
+ summary,
99
+ media,
100
+ bylines,
101
+ topics,
102
+ articleURL,
103
+ twitterUsername,
104
+ siteHost,
105
+ gscId,
106
+ user,
107
+ }) => {
108
+ return (
109
+ <>
110
+ <SEOComponent
111
+ title={headline as string}
112
+ description={(summary ? summary.children[0].text : '') as string}
113
+ url={articleURL}
114
+ siteHost={siteHost}
115
+ gscId={gscId}
116
+ fbType="article"
117
+ fbImageUrl={
118
+ (media && 'crops' in media && media.crops[0]
119
+ ? media.crops[0].url
120
+ : '') as string
121
+ }
122
+ twUsername={twitterUsername}
123
+ />
124
+ <Layout
125
+ withTopOffset
126
+ withBottomOffset
127
+ backgroundColor="interfaceBackground"
128
+ user={user}
129
+ >
130
+ <Cell xs={12} md={10} lg={7} xsOffset={0} mdOffset={1}>
131
+ <Block marginBlockEnd="space050" data-testid="HeadLine">
132
+ <Headline
133
+ overrides={{
134
+ typographyPreset: {
135
+ xs: 'editorialHeadline050',
136
+ md: 'editorialHeadline070',
137
+ lg: 'editorialHeadline070',
138
+ xl: 'editorialHeadline080',
139
+ },
140
+ heading: {
141
+ stylePreset: 'inkContrast',
142
+ },
143
+ }}
144
+ headingAs="h1"
145
+ >
146
+ {headline}
147
+ </Headline>
148
+ </Block>
149
+ <Block marginBlockEnd="space080" data-testid="Kicker">
150
+ <Headline
151
+ headingAs="h2"
152
+ overrides={{
153
+ typographyPreset: {
154
+ xs: 'editorialSubheadline020',
155
+ md: 'editorialSubheadline040',
156
+ lg: 'editorialSubheadline040',
157
+ xl: 'editorialSubheadline050',
158
+ },
159
+ heading: {
160
+ stylePreset: 'inkBase',
161
+ },
162
+ }}
163
+ >
164
+ {kicker || 'Kicker title mock'}
165
+ </Headline>
166
+ </Block>
167
+ <Block
168
+ marginBlockEnd={{
169
+ xs: 'space040',
170
+ md: 'space080',
171
+ }}
172
+ >
173
+ <Visible xs sm>
174
+ <Block
175
+ marginBlockEnd={{
176
+ xs: 'space040',
177
+ }}
178
+ >
179
+ <MetaBoxComponent
180
+ bylines={bylines as Byline[]}
181
+ publishedDateTime={publishedDateTime as string}
182
+ updatedDateTime={updatedDateTime}
183
+ topics={topics}
184
+ />
185
+ </Block>
186
+ <Block
187
+ marginBlockEnd={{
188
+ xs: 'space040',
189
+ }}
190
+ >
191
+ <Divider />
192
+ </Block>
193
+ <Block marginBlockEnd="space050">
194
+ <ShareButton />
195
+ </Block>
196
+ </Visible>
197
+ <Visible md lg xl>
198
+ <Stack
199
+ flow="horizontal-bottom"
200
+ stackDistribution="space-between"
201
+ wrap="nowrap"
202
+ data-testid="MetaBox"
203
+ >
204
+ <MetaBoxComponent
205
+ bylines={bylines as Byline[]}
206
+ publishedDateTime={publishedDateTime as string}
207
+ updatedDateTime={updatedDateTime}
208
+ topics={topics}
209
+ />
210
+ <StackChild alignSelf="flex-end">
211
+ <ShareBarComponent />
212
+ </StackChild>
213
+ </Stack>
214
+ </Visible>
215
+ </Block>
216
+ {media && 'crops' in media && (
217
+ <Block
218
+ marginBlockEnd={{
219
+ xs: 'space060',
220
+ lg: 'space070',
221
+ }}
222
+ >
223
+ <Image
224
+ aspectRatio={getAspectRatio(
225
+ ratioMap[media?.crops[0].aspectRatio]
226
+ ? ratioMap[media?.crops[0].aspectRatio]
227
+ : media?.crops[0].aspectRatio
228
+ )}
229
+ src={media.crops[0].url}
230
+ alt={media.crops[0].alt}
231
+ />
232
+ </Block>
233
+ )}
234
+ {media && 'videoId' in media && (
235
+ <Block
236
+ marginBlockEnd={{
237
+ xs: 'space060',
238
+ lg: 'space070',
239
+ }}
240
+ >
241
+ <VideoPlayer
242
+ config={{
243
+ 'data-video-id': media.videoId,
244
+ 'data-account': media.accountId,
245
+ 'data-player': 'default',
246
+ 'data-embed': 'default',
247
+ controls: true,
248
+ }}
249
+ />
250
+ </Block>
251
+ )}
252
+ <Block
253
+ marginBlockEnd={{
254
+ xs: 'space060',
255
+ md: 'space080',
256
+ lg: 'space100',
257
+ }}
258
+ data-testid="ArticleContent"
259
+ >
260
+ {summary &&
261
+ summary.children.map((p, i) => (
262
+ <Block
263
+ key={i}
264
+ marginBlockEnd={{
265
+ xs: 'space050',
266
+ lg: 'space070',
267
+ }}
268
+ data-testid="ArticleParagraph"
269
+ >
270
+ <TextBlock
271
+ stylePreset="inkContrast"
272
+ typographyPreset={{
273
+ xs: 'editorialParagraph010',
274
+ md: 'editorialParagraph020',
275
+ xl: 'editorialParagraph030',
276
+ }}
277
+ >
278
+ {p.text}
279
+ </TextBlock>
280
+ </Block>
281
+ ))}
282
+ </Block>
283
+ <Visible xs sm>
284
+ <Block marginBlockEnd="space050">
285
+ <Divider />
286
+ </Block>
287
+ <Block marginBlockEnd="space100">
288
+ <ShareButton />
289
+ </Block>
290
+ </Visible>
291
+ <Visible md lg xl>
292
+ <Block marginBlockEnd="space050">
293
+ <Divider />
294
+ </Block>
295
+ <Block marginBlockEnd="space100">
296
+ <Stack
297
+ flow="horizontal-bottom"
298
+ stackDistribution="flex-end"
299
+ wrap="nowrap"
300
+ spaceInline="space060"
301
+ >
302
+ <ShareBarComponent />
303
+ </Stack>
304
+ </Block>
305
+ </Visible>
306
+ {topics && <RelatedTopics topics={topics} />}
307
+ </Cell>
308
+ <Cell xs={12} lg={3} lgOffset={1}>
309
+ <Ad id="advert-article-sidebar" maxWidth="300px" />
310
+ <Highlights />
311
+ </Cell>
312
+ <Cell xs={12}>
313
+ <RelatedArticles />
314
+ </Cell>
315
+ </Layout>
316
+ </>
317
+ )
318
+ }
319
+
320
+ export default ArticlePage
@@ -0,0 +1,37 @@
1
+ import { BackButton } from '@newskit-render/shared-components'
2
+ import { Block, Divider, Stack, StackChild } from 'newskit'
3
+ import React from 'react'
4
+
5
+ export const BackToHomepage = () => {
6
+ return (
7
+ <>
8
+ <Block marginBlockEnd="space030">
9
+ <Divider />
10
+ </Block>
11
+
12
+ <Block marginBlockEnd="space030">
13
+ <Stack flow="horizontal-center" stackDistribution="center">
14
+ <StackChild>
15
+ <BackButton
16
+ backButton={{
17
+ text: 'Go back to homepage',
18
+ href: '/',
19
+ 'aria-label': 'Back to homepage',
20
+ }}
21
+ backButtonOverrides={{
22
+ asLink: true,
23
+ iconSize: 'iconSize030',
24
+ paddingInline: 'spaceInsetSquish010',
25
+ paddingBlock: 'spaceInsetSquish010',
26
+ typographyPreset: 'utilityButton020',
27
+ }}
28
+ />
29
+ </StackChild>
30
+ </Stack>
31
+ </Block>
32
+ <Block marginBlockEnd="space050">
33
+ <Divider />
34
+ </Block>
35
+ </>
36
+ )
37
+ }
@@ -0,0 +1,26 @@
1
+ import React from 'react'
2
+ import { NextLink } from '@newskit-render/shared-components'
3
+
4
+ const NavLink = ({
5
+ href,
6
+ ariaLabel,
7
+ buttonText,
8
+ }: {
9
+ buttonText: string
10
+ href: string
11
+ ariaLabel?: string
12
+ }) => (
13
+ <NextLink
14
+ type="standalone"
15
+ overrides={{
16
+ typographyPreset: 'utilityMeta020',
17
+ stylePreset: 'linkStandaloneInverse',
18
+ }}
19
+ href={href}
20
+ aria-label={ariaLabel}
21
+ >
22
+ {buttonText}
23
+ </NextLink>
24
+ )
25
+
26
+ export default NavLink