Initial commit. Files are uploaded to the filesystem.

This commit is contained in:
ThePendulum
2025-09-25 06:19:37 +02:00
commit 745b00dcdc
64 changed files with 9572 additions and 0 deletions

19
renderer/+config.ts Normal file
View File

@@ -0,0 +1,19 @@
import type { Config } from 'vike/types'
// https://vike.dev/config
export default {
// https://vike.dev/clientRouting
clientRouting: true,
// https://vike.dev/meta
meta: {
// Define new setting 'title'
title: {
env: { server: true, client: true }
},
// Define new setting 'description'
description: {
env: { server: true }
}
},
hydrationCanBeAborted: true
} satisfies Config

View File

@@ -0,0 +1,9 @@
// https://vike.dev/onPageTransitionEnd
export { onPageTransitionEnd }
import type { OnPageTransitionEndAsync } from 'vike/types'
const onPageTransitionEnd: OnPageTransitionEndAsync = async (): ReturnType<OnPageTransitionEndAsync> => {
console.log('Page transition end')
document.querySelector('body')!.classList.remove('page-is-transitioning')
}

View File

@@ -0,0 +1,9 @@
// https://vike.dev/onPageTransitionStart
export { onPageTransitionStart }
import type { OnPageTransitionStartAsync } from 'vike/types'
const onPageTransitionStart: OnPageTransitionStartAsync = async (): ReturnType<OnPageTransitionStartAsync> => {
console.log('Page transition start')
document.querySelector('body')!.classList.add('page-is-transitioning')
}

View File

@@ -0,0 +1,21 @@
// https://vike.dev/onRenderClient
export { onRenderClient }
import { createVueApp } from './createVueApp'
import { getPageTitle } from './getPageTitle'
import type { OnRenderClientAsync } from 'vike/types'
let app: ReturnType<typeof createVueApp>
const onRenderClient: OnRenderClientAsync = async (pageContext): ReturnType<OnRenderClientAsync> => {
// This onRenderClient() hook only supports SSR, see https://vike.dev/render-modes for how to modify onRenderClient()
// to support SPA
if (!pageContext.Page) throw new Error('My onRenderClient() hook expects pageContext.Page to be defined')
if (!app) {
app = createVueApp(pageContext)
app.mount('#app')
} else {
app.changePage(pageContext)
}
document.title = getPageTitle(pageContext)
}

55
renderer/+onRenderHtml.ts Normal file
View File

@@ -0,0 +1,55 @@
// https://vike.dev/onRenderHtml
export { onRenderHtml }
import { renderToString as renderToString_ } from '@vue/server-renderer'
import type { App } from 'vue'
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
import { createVueApp } from './createVueApp'
import logoUrl from '../assets/img/logo.svg'
import type { OnRenderHtmlAsync } from 'vike/types'
import { getPageTitle } from './getPageTitle'
const onRenderHtml: OnRenderHtmlAsync = async (pageContext): ReturnType<OnRenderHtmlAsync> => {
// This onRenderHtml() hook only supports SSR, see https://vike.dev/render-modes for how to modify
// onRenderHtml() to support SPA
if (!pageContext.Page) throw new Error('My render() hook expects pageContext.Page to be defined')
const app = createVueApp(pageContext)
const appHtml = await renderToString(app)
const title = getPageTitle(pageContext)
const desc = pageContext.data?.description || pageContext.config.description || 'Demo of using Vike'
const documentHtml = escapeInject`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="${logoUrl}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="${desc}" />
<title>${title}</title>
</head>
<body>
<div id="app">${dangerouslySkipEscape(appHtml)}</div>
</body>
</html>`
return {
documentHtml,
pageContext: {
// We can add custom pageContext properties here, see https://vike.dev/pageContext#custom
}
}
}
async function renderToString(app: App) {
let err: unknown
// Workaround: renderToString_() swallows errors in production, see https://github.com/vuejs/core/issues/7876
app.config.errorHandler = (err_) => {
err = err_
}
const appHtml = await renderToString_(app)
if (err) throw err
return appHtml
}

30
renderer/createVueApp.ts Normal file
View File

@@ -0,0 +1,30 @@
import { createSSRApp, h, shallowRef } from 'vue'
import { setPageContext } from './usePageContext'
import { setData } from './useData'
import type { PageContext } from 'vike/types'
import { objectAssign } from './utils'
// import Layout from './Layout.vue'
export function createVueApp(pageContext: PageContext) {
const pageContextRef = shallowRef(pageContext)
const dataRef = shallowRef(pageContext.data)
const pageRef = shallowRef(pageContext.Page)
// const RootComponent = () => h(Layout, null, () => h(pageRef.value))
const RootComponent = () => h(pageContext.config.Layout, null, () => h(pageRef.value))
const app = createSSRApp(RootComponent)
setPageContext(app, pageContextRef)
setData(app, dataRef)
// app.changePage() is called upon navigation, see +onRenderClient.ts
objectAssign(app, {
changePage: (pageContext: PageContext) => {
pageContextRef.value = pageContext
dataRef.value = pageContext.data
pageRef.value = pageContext.Page
}
})
return app
}

14
renderer/getPageTitle.ts Normal file
View File

@@ -0,0 +1,14 @@
export { getPageTitle }
import type { PageContext } from 'vike/types'
function getPageTitle(pageContext: PageContext): string {
const title =
// Title defined dynamically by data()
pageContext.data?.title ||
// Title defined statically by /pages/some-page/+title.js (or by `export default { title }` in /pages/some-page/+config.js)
// The setting 'pageContext.config.title' is a custom setting we defined at ./+config.ts
pageContext.config.title ||
'Vike Demo'
return title
}

29
renderer/types.ts Normal file
View File

@@ -0,0 +1,29 @@
export type { Component }
import type { ComponentPublicInstance } from 'vue'
type Component = ComponentPublicInstance // https://stackoverflow.com/questions/63985658/how-to-type-vue-instance-out-of-definecomponent-in-vue-3/63986086#63986086
type Page = Component
// https://vike.dev/pageContext#typescript
declare global {
namespace Vike {
interface PageContext {
Page: Page
data?: {
/** Value for <title> defined dynamically by by /pages/some-page/+data.js */
title?: string
/** Value for <meta name="description"> defined dynamically */
description?: string
}
config: {
/** Value for <title> defined statically by /pages/some-page/+title.js (or by `export default { title }` in /pages/some-page/+config.js) */
title?: string
/** Value for <meta name="description"> defined statically */
description?: string
}
/** https://vike.dev/render */
abortReason?: string
}
}
}

19
renderer/useData.ts Normal file
View File

@@ -0,0 +1,19 @@
// https://vike.dev/useData
export { useData }
export { setData }
import { inject } from 'vue'
import type { App, InjectionKey, Ref } from 'vue'
const key: InjectionKey<Ref<unknown>> = Symbol()
/** https://vike.dev/useData */
function useData<Data>(): Ref<Data> {
const data = inject(key)
if (!data) throw new Error('setData() not called')
return data as Ref<Data>
}
function setData(app: App, data: Ref<unknown>): void {
app.provide(key, data)
}

View File

@@ -0,0 +1,20 @@
// https://vike.dev/usePageContext
export { usePageContext }
export { setPageContext }
import { inject } from 'vue'
import type { App, InjectionKey, Ref } from 'vue'
import type { PageContext } from 'vike/types'
const key: InjectionKey<Ref<PageContext>> = Symbol()
/** https://vike.dev/usePageContext */
function usePageContext(): Ref<PageContext> {
const pageContext = inject(key)
if (!pageContext) throw new Error('setPageContext() not called in parent')
return pageContext
}
function setPageContext(app: App, pageContext: Ref<PageContext>): void {
app.provide(key, pageContext)
}

7
renderer/utils.ts Normal file
View File

@@ -0,0 +1,7 @@
// Same as Object.assign() but with type inference
export function objectAssign<Obj extends object, ObjAddendum>(
obj: Obj,
objAddendum: ObjAddendum
): asserts obj is Obj & ObjAddendum {
Object.assign(obj, objAddendum)
}