Skip to content

Commit

Permalink
Merge branch 'main' of github.com:yooouuri/vite-plugin-vue-ssr into a…
Browse files Browse the repository at this point in the history
…dd-h3
  • Loading branch information
yooouuri committed Jun 28, 2024
2 parents b5368d1 + 85c85bd commit 9c10541
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 47 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@babel/parser": "^7.24.7",
"@babel/traverse": "^7.24.7",
"@babel/types": "^7.24.7",
"@unhead/ssr": "^1.9.14",
"node-html-parser": "^6.1.13"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion playground/pinia-example/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ export default defineConfig({
},
build: {
target: [ 'es2022', 'edge89', 'firefox89', 'chrome89', 'safari15' ],
}
},
})
2 changes: 1 addition & 1 deletion playground/vue-router/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ export default defineConfig({
},
build: {
target: [ 'es2022', 'edge89', 'firefox89', 'chrome89', 'safari15' ],
}
},
})
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 27 additions & 45 deletions src/plugin/generateHtml.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import { parse, HTMLElement } from 'node-html-parser'
import { parse } from 'node-html-parser'
import type { VueHeadClient, MergeHead } from '@unhead/vue'
import { renderSSRHead } from '@unhead/ssr'
import { State } from '../types'

function rawAttributesToAttributes(raw: string) {
const attrs: Record<string, any> = {}

const re = /([a-zA-Z()[\]#@$.?:][a-zA-Z0-9-_:()[\]#]*)(?:\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+))?/g
let match

while ((match = re.exec(raw))) {
const key = match[1]
let val = match[2] || null
if (val && (val[0] === `'` || val[0] === `"`)) val = val.slice(1, val.length - 1)
attrs[key] = attrs[key] || val
}

return attrs
}

export async function generateHtml(template: string,
preloadLinks: string,
rendered: string,
Expand All @@ -22,6 +39,7 @@ export async function generateHtml(template: string,
}

const body = root.querySelector('body')
const html = root.querySelector('html')

if (state.value !== undefined) {
const { uneval } = await import('devalue')
Expand All @@ -33,53 +51,17 @@ export async function generateHtml(template: string,
body?.insertAdjacentHTML('beforeend', `<div id="teleports">${teleports['#teleports']}</div>`)
}

const resolvedTags = await head.resolveTags()

const htmlTitle = root.querySelector('title')

if (htmlTitle !== null) {
const title = resolvedTags.find(t => t.tag === 'title')

if (title !== undefined) {
htmlTitle.textContent = title.textContent ?? ''
}
}

const allowedTags = ['meta', 'link', 'base', 'style', 'script', 'noscript']

resolvedTags
.filter(tag => tag.tag === allowedTags.find(allowed => allowed === tag.tag))
.forEach(tag => {
let props = ''

for (const [key, value] of Object.entries(tag.props)) {
props = `${props} ${key}="${value}"`
}

const el = new HTMLElement(tag.tag, {}, props)
el.textContent = tag.innerHTML
?? tag.textContent
?? ''
const payload = await renderSSRHead(head)

htmlHead?.appendChild(el)
})

const bodyAttrs = resolvedTags.find(t => t.tag === 'bodyAttrs')

if (bodyAttrs !== undefined) {
for (const [key, value] of Object.entries(bodyAttrs.props)) {
body?.setAttribute(key, value)
}
if (payload.headTags.includes('<title>')) {
root.querySelector('title')?.remove()
}

const htmlAttrs = resolvedTags.find(t => t.tag === 'htmlAttrs')
const htmlRoot = root.querySelector('html')

if (htmlAttrs !== undefined) {
for (const [key, value] of Object.entries(htmlAttrs.props)) {
htmlRoot?.setAttribute(key, value)
}
}
htmlHead?.insertAdjacentHTML('afterbegin', payload.headTags)
html?.setAttributes(rawAttributesToAttributes(payload.htmlAttrs))
body?.setAttributes(rawAttributesToAttributes(payload.bodyAttrs))
body?.insertAdjacentHTML('afterbegin', payload.bodyTagsOpen)
body?.insertAdjacentHTML('beforeend', payload.bodyTags)

return root.toString()
}

0 comments on commit 9c10541

Please sign in to comment.