Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | import React from 'react'; import Link from 'next/link'; import { useIntl } from 'react-intl'; import { components } from '@/helpers/mdxjs'; import { author as defaultAuthor } from '@/constants/site'; import styles from '@/styles/blog.module.css'; type BylineMeta = { author?: string; date?: string | null; }; /** * @description MDX component overrides that inject the E-E-A-T byline under the post title. * * Every MDX body opens with `# Title` immediately followed by <Date />, so a page-level * byline rendered above <MDXRemote> produced: author → title → date. Injecting it through * the h1 override lands it under the heading, where a byline belongs, without editing the * 42 MDX files. It stays server-rendered (the <Date /> component is ssr: false, so its * output never reaches a crawler) which is the point of the E-E-A-T byline in SDD-003. * * @param {object} meta - Post frontmatter carrying the author and publication date. * @returns {object} The MDX components map to hand to <MDXRemote />. */ const usePostComponents = (meta: BylineMeta) => { const { formatDate } = useIntl(); const { author, date } = meta; return React.useMemo(() => { const byline = ( <p className={styles.byline}> {/* The entity page is the home: its editor window holds the bio and contact tabs */} <Link href="/">{author ?? defaultAuthor}</Link> {date ? ( <> {' · '} {/* UTC pins the calendar day: date is a date-only ISO string, which parses as UTC midnight and would format one day early behind UTC (see #135). */} <time dateTime={date}> {formatDate(date, { timeZone: 'UTC', day: 'numeric', month: 'short', year: 'numeric', })} </time> </> ) : null} </p> ); return { ...components, h1: (props: React.ComponentPropsWithoutRef<'h1'>) => ( <> {/* jsx-a11y/heading-has-content cannot see through the spread and reads this as an empty heading. The content is real: MDX passes the `# Title` text as children, which is why every built post page has a populated <h1>. Suppressed rather than restructured, because the alternative is to stop forwarding props. */} {/* eslint-disable-next-line jsx-a11y/heading-has-content */} <h1 {...props} /> {byline} </> ), // The byline carries the date now. The <Date /> tag stays in the MDX source because // extractPostDate parses it for datePublished and the sitemap lastmod. Date: () => null, }; }, [formatDate, author, date]); }; export default usePostComponents; |