11'use strict'
22import PropTypes from 'prop-types'
3- import React , { PureComponent } from 'react'
3+ import React , { PureComponent , useEffect } from 'react'
44import serialize from 'serialize-javascript'
5+ import DOMPurify from 'dompurify'
56
67// @twreporter
78import webfonts from '@twreporter/react-components/lib/text/utils/webfonts'
@@ -16,6 +17,53 @@ const _ = {
1617 map,
1718}
1819
20+ const TYPEKIT_CONFIG = {
21+ kitId : 'vlk1qbe' ,
22+ scriptTimeout : 3000 ,
23+ async : true
24+ }
25+
26+ const TypekitLoader = ( ) => {
27+ useEffect ( ( ) => {
28+ // Add wf-loading class immediately
29+ const h = document . documentElement
30+ h . className += ' wf-loading'
31+
32+ // Create timeout to handle inactive state
33+ const t = setTimeout ( ( ) => {
34+ h . className = h . className . replace ( / \b w f - l o a d i n g \b / g, '' ) + ' wf-inactive'
35+ } , TYPEKIT_CONFIG . scriptTimeout )
36+
37+ // Create and load the script
38+ const script = document . createElement ( 'script' )
39+ script . src = `https://use.typekit.net/${ TYPEKIT_CONFIG . kitId } .js`
40+ script . async = true
41+
42+ script . onload = script . onreadystatechange = function ( ) {
43+ const state = this . readyState
44+ if ( state && state !== 'complete' && state !== 'loaded' ) return
45+
46+ try {
47+ Typekit . load ( TYPEKIT_CONFIG )
48+ } catch ( e ) {
49+ console . error ( 'Failed to load Typekit:' , e )
50+ }
51+ }
52+
53+ document . head . appendChild ( script )
54+
55+ // Cleanup function
56+ return ( ) => {
57+ clearTimeout ( t )
58+ if ( script . parentNode ) {
59+ document . head . removeChild ( script )
60+ }
61+ }
62+ } , [ ] ) // Empty dependency array - only run once
63+
64+ return null
65+ }
66+
1967export default class Html extends PureComponent {
2068 static propTypes = {
2169 scripts : PropTypes . array . isRequired ,
@@ -110,34 +158,32 @@ export default class Html extends PureComponent {
110158 { styleElement }
111159 </ head >
112160 < body >
113- < div id = "root" dangerouslySetInnerHTML = { { __html : contentMarkup } } />
161+ < div id = "root" dangerouslySetInnerHTML = { { __html : DOMPurify . sanitize ( contentMarkup ) } } />
114162 < script
115163 defer
116164 src = "https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.zh-Hant-TW"
117165 />
118166 < script
119- dangerouslySetInnerHTML = { {
120- __html : `window.__REDUX_STATE__=${ serialize ( store . getState ( ) ) } ;` ,
121- } }
122- charSet = "UTF-8"
123- />
167+ id = "initial-state"
168+ type = "application/json"
169+ >
170+ { serialize ( store . getState ( ) , { isJSON : true } ) }
171+ </ script >
172+ < script >
173+ { `
174+ try {
175+ window.__REDUX_STATE__ = JSON.parse(document.getElementById('initial-state').textContent);
176+ } catch (e) {
177+ console.error('Failed to parse initial state:', e);
178+ window.__REDUX_STATE__ = {};
179+ }
180+ ` }
181+ </ script >
124182 { _ . map ( scripts , ( script , key ) => (
125183 < script src = { script } key = { 'scripts' + key } charSet = "UTF-8" />
126184 ) ) }
127185 { scriptElement }
128- < script
129- dangerouslySetInnerHTML = { {
130- __html : `(function(d) {
131- var config = {
132- kitId: 'vlk1qbe',
133- scriptTimeout: 3000,
134- async: true
135- },
136- h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
137- })(document);
138- ` ,
139- } }
140- />
186+ < TypekitLoader />
141187 </ body >
142188 </ html >
143189 )
0 commit comments