| 178 | } |
| 179 | |
| 180 | private async createPages() { |
| 181 | // load public/index.html and add tags to _document |
| 182 | const htmlContent = await fs.promises.readFile( |
| 183 | path.join(this.appDir, `${this.isCra ? 'public/' : ''}index.html`), |
| 184 | 'utf8' |
| 185 | ) |
| 186 | const $ = cheerio.load(htmlContent) |
| 187 | // note: title tag and meta[viewport] needs to be placed in _app |
| 188 | // not _document |
| 189 | const titleTag = $('title')[0] |
| 190 | const metaViewport = $('meta[name="viewport"]')[0] |
| 191 | const headTags = $('head').children() |
| 192 | const bodyTags = $('body').children() |
| 193 | |
| 194 | const pageExt = this.shouldUseTypeScript ? 'tsx' : 'js' |
| 195 | const appPage = path.join(this.pagesDir, `_app.${pageExt}`) |
| 196 | const documentPage = path.join(this.pagesDir, `_document.${pageExt}`) |
| 197 | const catchAllPage = path.join(this.pagesDir, `[[...slug]].${pageExt}`) |
| 198 | |
| 199 | const gatherTextChildren = (children: CheerioElement[]) => { |
| 200 | return children |
| 201 | .map((child) => { |
| 202 | if (child.type === 'text') { |
| 203 | return child.data |
| 204 | } |
| 205 | return '' |
| 206 | }) |
| 207 | .join('') |
| 208 | } |
| 209 | |
| 210 | const serializeAttrs = (attrs: CheerioElement['attribs']) => { |
| 211 | const attrStr = Object.keys(attrs || {}) |
| 212 | .map((name) => { |
| 213 | const reactName = htmlToReactAttributes[name] || name |
| 214 | const value = attrs[name] |
| 215 | |
| 216 | // allow process.env access to work dynamically still |
| 217 | if (value.match(/%([a-zA-Z0-9_]{0,})%/)) { |
| 218 | return `${reactName}={\`${value.replace( |
| 219 | /%([a-zA-Z0-9_]{0,})%/g, |
| 220 | (subStr) => { |
| 221 | return `\${process.env.${subStr.slice(1, -1)}}` |
| 222 | } |
| 223 | )}\`}` |
| 224 | } |
| 225 | return `${reactName}="${value}"` |
| 226 | }) |
| 227 | .join(' ') |
| 228 | |
| 229 | return attrStr.length > 0 ? ` ${attrStr}` : '' |
| 230 | } |
| 231 | const serializedHeadTags: string[] = [] |
| 232 | const serializedBodyTags: string[] = [] |
| 233 | |
| 234 | headTags.map((_index, element) => { |
| 235 | if ( |
| 236 | element.tagName === 'title' || |
| 237 | (element.tagName === 'meta' && element.attribs.name === 'viewport') |