diff --git a/blog-website/api/fallback/redirect.test.ts b/blog-website/api/fallback/redirect.test.ts index 9ef284b84fb..219374b8477 100644 --- a/blog-website/api/fallback/redirect.test.ts +++ b/blog-website/api/fallback/redirect.test.ts @@ -10,8 +10,8 @@ describe('redirect', () => { expect( redirect( 'https://blog.johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, location: @@ -19,10 +19,10 @@ describe('redirect', () => { }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://blog.johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html' + 'x-ms-original-url: https://blog.johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://blog.johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html to https://johnnyreilly.com/simple-fading-in-and-out-using-css-transitions' + 'Redirecting https://blog.johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html to https://johnnyreilly.com/simple-fading-in-and-out-using-css-transitions', ); }); @@ -32,8 +32,8 @@ describe('redirect', () => { expect( redirect( 'https://blog.johnnyreilly.com/2021/01/30/aspnet-serilog-and-application-insights', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, location: @@ -41,10 +41,10 @@ describe('redirect', () => { }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://blog.johnnyreilly.com/2021/01/30/aspnet-serilog-and-application-insights' + 'x-ms-original-url: https://blog.johnnyreilly.com/2021/01/30/aspnet-serilog-and-application-insights', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://blog.johnnyreilly.com/2021/01/30/aspnet-serilog-and-application-insights to https://johnnyreilly.com/aspnet-serilog-and-application-insights' + 'Redirecting https://blog.johnnyreilly.com/2021/01/30/aspnet-serilog-and-application-insights to https://johnnyreilly.com/aspnet-serilog-and-application-insights', ); }); @@ -54,8 +54,8 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, location: @@ -63,10 +63,10 @@ describe('redirect', () => { }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html' + 'x-ms-original-url: https://johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html to https://johnnyreilly.com/simple-fading-in-and-out-using-css-transitions' + 'Redirecting https://johnnyreilly.com/2013/12/simple-fading-in-and-out-using-css-transitions.html to https://johnnyreilly.com/simple-fading-in-and-out-using-css-transitions', ); }); @@ -76,18 +76,18 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/feeds/posts/default?alt=rss', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, location: 'https://johnnyreilly.com/rss.xml', }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/feeds/posts/default?alt=rss' + 'x-ms-original-url: https://johnnyreilly.com/feeds/posts/default?alt=rss', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/feeds/posts/default?alt=rss to https://johnnyreilly.com/rss.xml' + 'Redirecting https://johnnyreilly.com/feeds/posts/default?alt=rss to https://johnnyreilly.com/rss.xml', ); }); @@ -97,18 +97,18 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/feeds/posts/default', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, location: 'https://johnnyreilly.com/atom.xml', }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/feeds/posts/default' + 'x-ms-original-url: https://johnnyreilly.com/feeds/posts/default', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/feeds/posts/default to https://johnnyreilly.com/atom.xml' + 'Redirecting https://johnnyreilly.com/feeds/posts/default to https://johnnyreilly.com/atom.xml', ); }); @@ -118,18 +118,18 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/search/label/uglifyjs', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, location: 'https://johnnyreilly.com/search?q=uglifyjs', }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/search/label/uglifyjs' + 'x-ms-original-url: https://johnnyreilly.com/search/label/uglifyjs', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/search/label/uglifyjs to https://johnnyreilly.com/search?q=uglifyjs' + 'Redirecting https://johnnyreilly.com/search/label/uglifyjs to https://johnnyreilly.com/search?q=uglifyjs', ); }); @@ -139,18 +139,18 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/2020/12/', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, - location: 'https://johnnyreilly.com/archive', + location: 'https://johnnyreilly.com/blog', }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/2020/12/' + 'x-ms-original-url: https://johnnyreilly.com/2020/12/', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/2020/12/ to https://johnnyreilly.com/archive' + 'Redirecting https://johnnyreilly.com/2020/12/ to https://johnnyreilly.com/blog', ); }); @@ -160,18 +160,18 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/2020/', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, - location: 'https://johnnyreilly.com/archive', + location: 'https://johnnyreilly.com/blog', }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/2020/' + 'x-ms-original-url: https://johnnyreilly.com/2020/', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/2020/ to https://johnnyreilly.com/archive' + 'Redirecting https://johnnyreilly.com/2020/ to https://johnnyreilly.com/blog', ); }); @@ -181,8 +181,8 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/assets/images/robski-dynamic-auth-9ac401590462e2bece9156353b92d187.png', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 301, location: @@ -190,10 +190,10 @@ describe('redirect', () => { }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/assets/images/robski-dynamic-auth-9ac401590462e2bece9156353b92d187.png' + 'x-ms-original-url: https://johnnyreilly.com/assets/images/robski-dynamic-auth-9ac401590462e2bece9156353b92d187.png', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/assets/images/robski-dynamic-auth-9ac401590462e2bece9156353b92d187.png to https://johnnyreilly.com/assets/images/robski-dynamic-auth-b50b7efd118b1c8ed1297a010749e0f4.webp' + 'Redirecting https://johnnyreilly.com/assets/images/robski-dynamic-auth-9ac401590462e2bece9156353b92d187.png to https://johnnyreilly.com/assets/images/robski-dynamic-auth-b50b7efd118b1c8ed1297a010749e0f4.webp', ); }); @@ -206,7 +206,7 @@ describe('redirect', () => { }); expect(mockLogger.mock.calls[0][0]).toBe( - 'Redirecting to https://johnnyreilly.com/404 as no explicit redirect exists' + 'Redirecting to https://johnnyreilly.com/404 as no explicit redirect exists', ); }); @@ -216,8 +216,8 @@ describe('redirect', () => { expect( redirect( 'https://johnnyreilly.com/robots.txt', - mockLogger as unknown as Logger - ) + mockLogger as unknown as Logger, + ), ).toEqual({ status: 302, location: @@ -225,10 +225,10 @@ describe('redirect', () => { }); expect(mockLogger.mock.calls[0][0]).toBe( - 'x-ms-original-url: https://johnnyreilly.com/robots.txt' + 'x-ms-original-url: https://johnnyreilly.com/robots.txt', ); expect(mockLogger.mock.calls[1][0]).toBe( - 'Redirecting https://johnnyreilly.com/robots.txt to https://johnnyreilly.com/404?originalUrl=https%3A%2F%2Fjohnnyreilly.com%2Frobots.txt as no explicit redirect exists' + 'Redirecting https://johnnyreilly.com/robots.txt to https://johnnyreilly.com/404?originalUrl=https%3A%2F%2Fjohnnyreilly.com%2Frobots.txt as no explicit redirect exists', ); }); }); diff --git a/blog-website/api/fallback/redirect.ts b/blog-website/api/fallback/redirect.ts index cafa5b3e720..62269805d0b 100644 --- a/blog-website/api/fallback/redirect.ts +++ b/blog-website/api/fallback/redirect.ts @@ -22,7 +22,7 @@ export function redirect(originalUrl: string, log: Logger) { // parsedURL.pathname example: /2019/06/typescript-webpack-you-down-with-pnp.html const matchedRoute = redirects.find((route) => - parsedURL.pathname.includes(route.route) + parsedURL.pathname.includes(route.route), ); if (matchedRoute) { @@ -56,7 +56,7 @@ export function redirect(originalUrl: string, log: Logger) { // cater for https://johnnyreilly.com/2019/06/ or https://johnnyreilly.com/2019/ if (parsedURL.pathname.match(yearMonthRegex)) { - const bloggerArchiveRedirect = '/archive'; + const bloggerArchiveRedirect = '/blog'; return redirect301({ log, originalUrl, @@ -68,11 +68,11 @@ export function redirect(originalUrl: string, log: Logger) { if (parsedURL.pathname.startsWith('/assets/images/')) { const fileNameWithoutHashAndSuffix = parsedURL.pathname.substring( 0, - parsedURL.pathname.lastIndexOf('-') + parsedURL.pathname.lastIndexOf('-'), ); const likelyImageRedirect = imagePaths.find((imageFile) => - imageFile.includes(fileNameWithoutHashAndSuffix) + imageFile.includes(fileNameWithoutHashAndSuffix), ); if (likelyImageRedirect) { @@ -90,7 +90,7 @@ export function redirect(originalUrl: string, log: Logger) { : `${baseUrl}/404`; log( - `Redirecting ${originalUrl} to ${location} as no explicit redirect exists` + `Redirecting ${originalUrl} to ${location} as no explicit redirect exists`, ); return { diff --git a/blog-website/api/fallback/redirectsBacklinks.ts b/blog-website/api/fallback/redirectsBacklinks.ts index 35208b7ac3b..24d6c335434 100644 --- a/blog-website/api/fallback/redirectsBacklinks.ts +++ b/blog-website/api/fallback/redirectsBacklinks.ts @@ -1,7 +1,7 @@ export const redirectsBacklinks = [ { route: '/cache-rules-everything-around-me', - redirect: '/dotnet-imemorycache-getorcreatefortimespanasync' + redirect: '/dotnet-imemorycache-getorcreatefortimespanasync', }, { route: '/2019/10/definitely-typed-movie.html', @@ -284,4 +284,8 @@ export const redirectsBacklinks = [ route: '/tags/type-script', redirect: '/tags/typescript', }, + { + route: '/archive', + redirect: '/blog', + }, ]; diff --git a/blog-website/blog/2021-10-15-structured-data-seo-and-react/index.md b/blog-website/blog/2021-10-15-structured-data-seo-and-react/index.md index a028a7876b8..ac444081eae 100644 --- a/blog-website/blog/2021-10-15-structured-data-seo-and-react/index.md +++ b/blog-website/blog/2021-10-15-structured-data-seo-and-react/index.md @@ -97,15 +97,18 @@ function App() { author: { '@type': 'Person', name: 'John Reilly', - url: 'https://twitter.com/johnny_reilly', + url: 'https://johnnyreilly.com/about', }, }; return (
- + + + + - - diff --git a/blog-website/src/pages/blog-archive.js b/blog-website/src/pages/blog.js similarity index 56% rename from blog-website/src/pages/blog-archive.js rename to blog-website/src/pages/blog.js index ebe01fd6fd6..52bbf56ab98 100644 --- a/blog-website/src/pages/blog-archive.js +++ b/blog-website/src/pages/blog.js @@ -4,6 +4,7 @@ import clsx from 'clsx'; import Layout from '@theme/Layout'; import Link from '@docusaurus/Link'; import styles from './styles.module.css'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; /** * @typedef {Object} BlogPost - creates a new type named 'BlogPost' @@ -46,7 +47,7 @@ const yearsOfPosts = Array.from(postsByYear, ([year, posts]) => ({ })); function Year( - /** @type {{ year: string; posts: BlogPost[]; }} */ { year, posts } + /** @type {{ year: string; posts: BlogPost[]; }} */ { year, posts }, ) { return (
@@ -65,28 +66,58 @@ function Year( } function BlogArchive() { + const { siteConfig } = useDocusaurusContext(); + + // https://developers.google.com/search/docs/appearance/structured-data/breadcrumb#json-ld + const breadcrumbStructuredData = { + '@context': 'https://schema.org', + '@type': 'BreadcrumbList', + name: 'Blog breadcrumb', + itemListElement: [ + { + '@type': 'ListItem', + position: 1, + name: 'Home', + item: siteConfig.url, + }, + { + '@type': 'ListItem', + position: 2, + name: 'Blog', + }, + ], + }; + return ( - -
-
-

Blog Archive

-

Historic posts

-
-
-
- {yearsOfPosts && yearsOfPosts.length > 0 && ( -
-
-
- {yearsOfPosts.map((props, idx) => ( - - ))} + <> + + + +