import * as React from 'react' ; import { buildImageUrl } from 'cloudinary-build-url' ; import type { LoaderData as RootLoaderData } from '../root' ; import type { GitHubFile , MdxListItem , MdxPage } from '~/types' ; import * as mdxBundler from 'mdx-bundler/client' ; import { compileMdx } from '~/utils/compile-mdx.server' ; import { downloadDirList , downloadMdxFileOrDirectory , } from '~/utils/github.server' ; import { AnchorOrLink , getDisplayUrl , getUrl , typedBoolean } from '~/utils/misc' ; import { redisCache } from './redis.server' ; import type { Timings } from './metrics.server' ; import { cachified } from './cache.server' ; import { getSocialMetas } from './seo' ; import { getImageBuilder , getImgProps , getSocialImageWithPreTitle , } from '~/images' ; import { Themed } from './theme-provider' ; import { markdownToHtmlUnwrapped , stripHtml } from './markdown.server' ; type CachifiedOptions = { forceFresh ? : boolean | string ; request ? : Request ; timings ? : Timings ; maxAge ? : number ; expires ? : Date ; } ; const defaultMaxAge = 1000 * 60 * 60 * 24 * 30 ; const getCompiledKey = ( contentDir , slug ) => `${ contentDir }:${ slug }:compiled` ; const checkCompiledValue = ( value ) => typeof value === 'object' && ( value === null || ( 'code' in value && 'frontmatter' in value ) ) ; async function getMdxPage ( { contentDir , slug , } , options ) { const key = getCompiledKey ( contentDir , slug ) ; const page = await cachified ( { cache : redisCache , maxAge : defaultMaxAge , ... options , key , checkValue : checkCompiledValue , getFreshValue : async ( ) => { const pageFiles = await downloadMdxFilesCached ( contentDir , slug , options ) ; const compiledPage = await compileMdxCached ( { contentDir , slug , ... pageFiles , options , } ) . catch ( err => { console . error ( `Failed to get a fresh value for mdx:` , { contentDir , slug , } ) ; return Promise . reject ( err ) ; } ) ; return compiledPage ; } , } ) ; if ( ! page ) { void redisCache . del ( key ) ; } return page ; } async function getMdxPagesInDirectory ( contentDir , options ) { const dirList = await getMdxDirList ( contentDir , options ) ; const pageDatas = await Promise . all ( dirList . map ( async ( { slug } ) => { return { ... ( await downloadMdxFilesCached ( contentDir , slug , options ) ) , slug , } ; } ) ) ; const pages = await Promise . all ( pageDatas . map ( pageData => compileMdxCached ( { contentDir , ... pageData , options } ) ) ) ; return pages . filter ( typedBoolean ) ; } const getDirListKey = ( contentDir ) => `${ contentDir }:dir-list` ; async function getMdxDirList ( contentDir , options ? ) { return cachified ( { cache : redisCache , maxAge : defaultMaxAge , ... options , key : getDirListKey ( contentDir ) , checkValue : ( value ) => Array . isArray ( value ) , getFreshValue : async ( ) => { const fullContentDirPath = `content/${ contentDir }` ; const dirList = ( await downloadDirList ( fullContentDirPath ) ) . map ( ( { name , path } ) => ( { name , slug : path . replace ( `${ fullContentDirPath }/` , '' ) . replace ( /\.mdx$/ , '' ) , } ) ) . filter ( ( { name } ) => name !== 'README.md' ) ; return dirList ; } , } ) ; } const getDownloadKey = ( contentDir , slug ) => `${ contentDir }:${ slug }:downloaded` ; async function downloadMdxFilesCached ( contentDir , slug , options ) { const key = getDownloadKey ( contentDir , slug ) ; const downloaded = await cachified ( { cache : redisCache , maxAge : defaultMaxAge , ... options , key , checkValue : ( value ) => { if ( typeof value !== 'object' ) { return `value is not an object` ; } if ( value === null ) { return `value is null` ; } const download = value as Record < string , unknown > ; if ( ! Array . isArray ( download . files ) ) { return `value.files is not an array` ; } if ( typeof download . entry !== 'string' ) { return `value.entry is not a string` ; } return true ; } , getFreshValue : async ( ) => downloadMdxFileOrDirectory ( `${ contentDir }/${ slug }` ) , } ) ; if ( ! downloaded . files . length ) { void redisCache . del ( key ) ; } return downloaded ; } async function compileMdxCached ( { contentDir , slug , entry , files , options , } ) { const key = getCompiledKey ( contentDir , slug ) ; const page = await cachified ( { cache : redisCache , maxAge : defaultMaxAge , ... options , key , checkValue : checkCompiledValue , getFreshValue : async ( ) => { const compiledPage = await compileMdx < MdxPage [ 'frontmatter' ] > ( slug , files ) ; if ( compiledPage ) { if ( compiledPage . frontmatter . bannerCloudinaryId && ! compiledPage . frontmatter . bannerBlurDataUrl ) { try { compiledPage . frontmatter . bannerBlurDataUrl = await getBlurDataUrl ( compiledPage . frontmatter . bannerCloudinaryId ) ; } catch ( error ) { console . error ( 'oh no, there was an error getting the blur image data url' , error ) ; } } if ( compiledPage . frontmatter . bannerCredit ) { const credit = await markdownToHtmlUnwrapped ( compiledPage . frontmatter . bannerCredit ) ; compiledPage . frontmatter . bannerCredit = credit ; const noHtml = await stripHtml ( credit ) ; if ( ! compiledPage . frontmatter . bannerAlt ) { compiledPage . frontmatter . bannerAlt = noHtml . replace ( /(photo|image)/i , '' ) . trim ( ) ; } if ( ! compiledPage . frontmatter . bannerTitle ) { compiledPage . frontmatter . bannerTitle = noHtml ; } } return { ... compiledPage , slug , editLink : `https://github.com/kentcdodds/kentcdodds.com/edit/main/${ entry }` , } ; } else { return null ; } } , } ) ; if ( ! page ) { void redisCache . del ( key ) ; } return page ; } function getBannerAltProp ( frontmatter ) { return ( frontmatter . bannerAlt ?? frontmatter . bannerTitle ?? frontmatter . bannerCredit ?? frontmatter . title ?? 'Post banner' ) ; } function getBannerTitleProp ( frontmatter ) { return ( frontmatter . bannerTitle ?? frontmatter . bannerAlt ?? frontmatter . bannerCredit ) ; } async function getBlurDataUrl ( cloudinaryId ) { const imageURL = buildImageUrl ( cloudinaryId , { transformations : { resize : { width : 100 } , quality : 'auto' , format : 'webp' , effect : { name : 'blur' , value : '1000' , } , } , } ) ; const dataUrl = await getDataUrlForImage ( imageURL ) ; return dataUrl ; } async function getDataUrlForImage ( imageUrl ) { const res = await fetch ( imageUrl ) ; const arrayBuffer = await res . arrayBuffer ( ) ; const base64 = Buffer . from ( arrayBuffer ) . toString ( 'base64' ) ; const mime = res . headers . get ( 'Content-Type' ) ?? 'image/webp' ; const dataUrl = `data:${ mime };base64,${ base64 }` ; return dataUrl ; } async function getBlogMdxListItems ( options ) { return cachified ( { cache : redisCache , maxAge : defaultMaxAge , ... options , key : 'blog:mdx-list-items' , getFreshValue : async ( ) => { let pages = await getMdxPagesInDirectory ( 'blog' , options ) ; pages = pages . sort ( ( a , z ) => { const aTime = new Date ( a . frontmatter . date ?? '' ) . getTime ( ) ; const zTime = new Date ( z . frontmatter . date ?? '' ) . getTime ( ) ; return aTime > zTime ? - 1 : aTime === zTime ? 0 : 1 ; } ) ; return pages . map ( mapFromMdxPageToMdxListItem ) ; } , } ) ; } function mdxPageMeta ( { data , parentsData , } ) { const { requestInfo } = parentsData . root ; if ( data ?. page ) { const { keywords = [ ] , ... extraMeta } = data . page . frontmatter . meta ?? { } ; let title = data . page . frontmatter . title ; const isDraft = data . page . frontmatter . draft ; if ( isDraft ) title = `(DRAFT) ${ title ?? '' }` ; return { ... ( isDraft ? { robots : 'noindex' } : null ) , ... getSocialMetas ( { origin : requestInfo . origin , title , description : data . page . frontmatter . description , keywords : keywords . join ( ', ' ) , url : getUrl ( requestInfo ) , image : getSocialImageWithPreTitle ( { origin : requestInfo . origin , url : getDisplayUrl ( requestInfo ) , featuredImage : data . page . frontmatter . bannerCloudinaryId ?? 'kentcdodds.com/illustrations/kody-flying_blue' , title : data . page . frontmatter . socialImageTitle ?? data . page . frontmatter . title ?? 'Untitled' , preTitle : data . page . frontmatter . socialImagePreTitle ?? `Check out this article` , } ) , } ) , ... extraMeta , } ; } else { return { title : 'Not found' , description : 'You landed on a page that Kody the Coding Koala could not find 🐨😢' , } ; } } /**
 * This is useful for when you don't want to send all the code for a page to the client.
 */ function mapFromMdxPageToMdxListItem ( page ) { const { code , ... mdxListItem } = page ; return mdxListItem ; } const mdxComponents = { a : AnchorOrLink , Themed , ThemedBlogImage , BlogImage , } ; param code returns function getMdxComponent ( code ) { const Component = mdxBundler . getMDXComponent ( code ) ; function KCDMdxComponent ( { components , ... rest } ) { return ( < Component components = { { ... mdxComponents , ... components } } { ... rest } />); } return KCDMdxComponent ; } function BlogImage ( { cloudinaryId , imgProps , } ) { return ( < img className = "py-8 w-full rounded-lg object-cover" { ... getImgProps ( getImageBuilder ( cloudinaryId , imgProps . alt ) , { widths : [ 350 , 550 , 700 , 845 , 1250 , 1700 , 2550 ] , sizes : [ '(max-width:1023px) 80vw' , '(min-width:1024px) and (max-width:1620px) 50vw' , '850px' , ] , transformations : { background : 'rgb:e6e9ee' } , } ) } { ... imgProps } />); } function ThemedBlogImage ( { darkCloudinaryId , lightCloudinaryId , imgProps , } ) { return ( < Themed light = { < BlogImage cloudinaryId = { lightCloudinaryId } imgProps = { imgProps } / > } dark = { < BlogImage cloudinaryId = { darkCloudinaryId } imgProps = { imgProps } / > } />); } function useMdxComponent ( code ) { return React . useMemo ( ( ) => getMdxComponent ( code ) , [ code ] ) ; } export { getMdxPage , getMdxDirList , getMdxPagesInDirectory , mapFromMdxPageToMdxListItem , getBlogMdxListItems , mdxPageMeta , useMdxComponent , getBannerTitleProp , getBannerAltProp , } ;