11import  *  as  fs  from  "fs" ; 
22import  *  as  path  from  "path" ; 
33import  {  promisify  }  from  "util" ; 
4+ import  {  JSDOM  }  from  "jsdom" ; 
5+ import  {  CallbackWrapper  }  from  "./misc" 
6+ import  *  as  SPAs  from  "../../../config/spa.config" ; 
47
58export  async  function  postProcess ( workDir : string ,  filePattern : string ) : Promise < void >  { 
69  const  readdir  =  promisify ( fs . readdir ) ; 
@@ -15,6 +18,7 @@ export async function postProcess(workDir: string, filePattern: string): Promise
1518  } 
1619
1720  await  postProcessBody ( workDir ,  htmlFiles [ 0 ] ,  txtFiles [ 0 ] ) ; 
21+   await  postProcessHeader ( workDir ,  htmlFiles [ 0 ] ) ; 
1822} 
1923
2024async  function  postProcessBody ( workDir : string ,  htmlFile : string ,  ssrFile : string ) : Promise < void >  { 
@@ -41,5 +45,47 @@ async function postProcessBody(workDir: string, htmlFile: string, ssrFile: strin
4145    console . error ( `Failed to write to file ${ htmlFilePath } ${ err }  ) 
4246  } ) ; 
4347  out . forEach ( str  =>  {  stream . write ( str ) ;  } ) ; 
48+ 
4449  stream . end ( ) ; 
50+ 
51+   let  cbWrapper : CallbackWrapper | undefined ; 
52+   const  waitForBufferFlush  =  new  Promise < void > ( ( resolve )  =>  {  cbWrapper  =  new  CallbackWrapper ( resolve ) ;  } ) ; 
53+ 
54+   stream . on ( "close" ,  function ( )  { 
55+     cbWrapper ?. invoke ( ) ; 
56+   } ) ; 
57+ 
58+   await  waitForBufferFlush ; 
59+ } 
60+ 
61+ async  function  postProcessHeader ( workDir : string ,  htmlFile : string ) : Promise < void >  { 
62+   const  htmlFilePath  =  path . join ( workDir ,  htmlFile ) ; 
63+   const  jsdom  =  await  JSDOM . fromFile ( htmlFilePath ) ; 
64+ 
65+   if  ( ! jsdom )  { 
66+     throw  "JSDOM creation failure" ; 
67+   } 
68+ 
69+   const  writeFile  =  promisify ( fs . writeFile ) ; 
70+   const  hdr : HTMLHeadElement  =  jsdom . window . document . head ; 
71+   const  script  =  jsdom . window . document . createElement ( "script" ) ; 
72+   // Replace with data specific to your site, then test using 
73+   // https://validator.schema.org/ and 
74+   // https://search.google.com/test/rich-results. The second 
75+   // test will effectively fail because 'WebSite' is not 
76+   // specific enough for Google. And so is 'WebPage'. 
77+   // See https://developers.google.com/search/docs/advanced/structured-data/sd-policies#specificity 
78+   const  structuredData  =  `{ 
79+     "@context": "https://schema.org", 
80+     "@type": "WebSite", 
81+     "name": "${ SPAs . appTitle }  
82+     "datePublished": "${ new  Date ( ) . toISOString ( ) . split ( "T" ) [ 0 ] }  
83+   }` ; 
84+ 
85+   script . setAttribute ( "type" ,  "application/ld+json" ) ; 
86+   script . textContent  =  structuredData ; 
87+   hdr . appendChild ( script ) ; 
88+   await  writeFile ( htmlFilePath ,  jsdom . serialize ( ) ) ; 
4589} 
90+ 
91+ 
0 commit comments