import type { ReactNode , ReactElement } from 'react' ; import type { GatsbySSR } from 'gatsby' ; import React from 'react' ; import { renderToString } from 'react-dom/server' ; import { collect } from 'linaria/server' ; import type { PluginOptions } from './utils' ; import { isLinariaStyleElement } from './utils' ; let bodyHTML ; export const replaceRenderer = ( { bodyComponent } ) => { bodyHTML = renderToString ( bodyComponent as ReactElement ) ; } ; export const onPreRenderHTML = ( { pathname , getHeadComponents , replaceHeadComponents , getPostBodyComponents , replacePostBodyComponents , } , pluginOptions ) => { const options = pluginOptions as unknown as PluginOptions ; if ( ! options . extractCritical ) { return ; } const headComponents = getHeadComponents ( ) ; type LinariaStyleSheet = { href : string ; text : string ; } ; const linariaStyleSheets = [ ] ; const otherElements = [ ] ; for ( const element of headComponents ) { if ( isLinariaStyleElement ( element ) ) { linariaStyleSheets . push ( { href : element . props [ 'data-href' ] , text : element . props . dangerouslySetInnerHTML . __html , } ) ; } else { otherElements . push ( element ) ; } } const { critical } = collect ( bodyHTML , linariaStyleSheets . map ( style => style . text ) . join ( '' ) ) ; replaceHeadComponents ( [ ... otherElements , < style key = "linaria-critical-css" data - linaria - critical = { pathname } dangerouslySetInnerHTML = { { __html : critical } } />, ] ) ; replacePostBodyComponents ( [ ... getPostBodyComponents ( ) , linariaStyleSheets . map ( style => style . href ) . map ( href => ( < link key = { href } rel = "stylesheet" type = "text/css" href = { href } / > ) ) , ] ) ; } ;