1
1
import * as fs from "fs" ;
2
2
import * as path from "path" ;
3
3
import { promisify } from "util" ;
4
+ import { JSDOM } from "jsdom" ;
5
+ import { CallbackWrapper } from "./misc"
6
+ import * as SPAs from "../../../config/spa.config" ;
4
7
5
8
export async function postProcess ( workDir : string , filePattern : string ) : Promise < void > {
6
9
const readdir = promisify ( fs . readdir ) ;
@@ -15,6 +18,7 @@ export async function postProcess(workDir: string, filePattern: string): Promise
15
18
}
16
19
17
20
await postProcessBody ( workDir , htmlFiles [ 0 ] , txtFiles [ 0 ] ) ;
21
+ await postProcessHeader ( workDir , htmlFiles [ 0 ] ) ;
18
22
}
19
23
20
24
async function postProcessBody ( workDir : string , htmlFile : string , ssrFile : string ) : Promise < void > {
@@ -41,5 +45,47 @@ async function postProcessBody(workDir: string, htmlFile: string, ssrFile: strin
41
45
console . error ( `Failed to write to file ${ htmlFilePath } , error: ${ err } ` )
42
46
} ) ;
43
47
out . forEach ( str => { stream . write ( str ) ; } ) ;
48
+
44
49
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 ( ) ) ;
45
89
}
90
+
91
+
0 commit comments