create-vike 0.0.320 → 0.0.321
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.testRun.ts +32 -6
- package/boilerplate-react/package.json +3 -2
- package/boilerplate-react/pages/_error/+Page.jsx +27 -20
- package/boilerplate-react/pages/index/+Page.jsx +2 -2
- package/boilerplate-react/pages/index/Counter.jsx +2 -2
- package/boilerplate-react/pages/star-wars/@id/+Page.jsx +17 -0
- package/boilerplate-react/pages/star-wars/@id/+data.js +33 -0
- package/boilerplate-react/pages/star-wars/index/+Page.jsx +25 -0
- package/boilerplate-react/pages/star-wars/index/+data.js +35 -0
- package/boilerplate-react/renderer/+config.h.js +13 -5
- package/boilerplate-react/renderer/+onPageTransitionEnd.js +7 -0
- package/boilerplate-react/renderer/+onPageTransitionStart.js +7 -0
- package/boilerplate-react/renderer/+onRenderClient.jsx +24 -11
- package/boilerplate-react/renderer/+onRenderHtml.jsx +12 -8
- package/boilerplate-react/renderer/Link.jsx +4 -1
- package/boilerplate-react/renderer/PageShell.css +4 -16
- package/boilerplate-react/renderer/PageShell.jsx +24 -23
- package/boilerplate-react/renderer/css/code.css +6 -0
- package/boilerplate-react/renderer/css/index.css +4 -0
- package/boilerplate-react/renderer/css/links.css +3 -0
- package/boilerplate-react/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-react/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-react/renderer/css/reset.css +7 -0
- package/boilerplate-react/renderer/getPageTitle.js +12 -0
- package/boilerplate-react/renderer/useData.js +10 -0
- package/boilerplate-react/renderer/usePageContext.jsx +5 -6
- package/boilerplate-react-ts/package.json +3 -2
- package/boilerplate-react-ts/pages/_error/+Page.tsx +27 -15
- package/boilerplate-react-ts/pages/index/+Page.tsx +2 -2
- package/boilerplate-react-ts/pages/index/Counter.tsx +2 -2
- package/boilerplate-react-ts/pages/star-wars/@id/+Page.tsx +18 -0
- package/boilerplate-react-ts/pages/star-wars/@id/+data.ts +36 -0
- package/boilerplate-react-ts/pages/star-wars/index/+Page.tsx +26 -0
- package/boilerplate-react-ts/pages/star-wars/index/+data.ts +38 -0
- package/boilerplate-react-ts/pages/star-wars/types.ts +12 -0
- package/boilerplate-react-ts/renderer/+config.h.ts +13 -5
- package/boilerplate-react-ts/renderer/+onPageTransitionEnd.ts +9 -0
- package/boilerplate-react-ts/renderer/+onPageTransitionStart.ts +9 -0
- package/boilerplate-react-ts/renderer/+onRenderClient.tsx +23 -10
- package/boilerplate-react-ts/renderer/+onRenderHtml.tsx +10 -7
- package/boilerplate-react-ts/renderer/Link.tsx +5 -2
- package/boilerplate-react-ts/renderer/PageShell.css +4 -16
- package/boilerplate-react-ts/renderer/PageShell.tsx +23 -22
- package/boilerplate-react-ts/renderer/css/code.css +6 -0
- package/boilerplate-react-ts/renderer/css/index.css +4 -0
- package/boilerplate-react-ts/renderer/css/links.css +3 -0
- package/boilerplate-react-ts/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-react-ts/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-react-ts/renderer/css/reset.css +7 -0
- package/boilerplate-react-ts/renderer/getPageTitle.ts +14 -0
- package/boilerplate-react-ts/renderer/types.ts +16 -12
- package/boilerplate-react-ts/renderer/useData.ts +10 -0
- package/boilerplate-react-ts/renderer/usePageContext.tsx +5 -6
- package/boilerplate-vue/package.json +2 -1
- package/boilerplate-vue/pages/_error/+Page.vue +19 -8
- package/boilerplate-vue/pages/star-wars/@id/+Page.vue +13 -0
- package/boilerplate-vue/pages/star-wars/@id/+data.js +33 -0
- package/boilerplate-vue/pages/star-wars/index/+Page.vue +15 -0
- package/boilerplate-vue/pages/star-wars/index/+data.js +34 -0
- package/boilerplate-vue/renderer/+config.h.js +13 -5
- package/boilerplate-vue/renderer/+onPageTransitionEnd.js +7 -0
- package/boilerplate-vue/renderer/+onPageTransitionStart.js +7 -0
- package/boilerplate-vue/renderer/+onRenderClient.js +13 -6
- package/boilerplate-vue/renderer/+onRenderHtml.js +8 -8
- package/boilerplate-vue/renderer/Link.vue +10 -2
- package/boilerplate-vue/renderer/PageShell.vue +17 -19
- package/boilerplate-vue/renderer/app.js +31 -10
- package/boilerplate-vue/renderer/css/code.css +6 -0
- package/boilerplate-vue/renderer/css/index.css +4 -0
- package/boilerplate-vue/renderer/css/links.css +3 -0
- package/boilerplate-vue/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-vue/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-vue/renderer/css/reset.css +7 -0
- package/boilerplate-vue/renderer/getPageTitle.js +12 -0
- package/boilerplate-vue/renderer/useData.js +11 -0
- package/boilerplate-vue/renderer/usePageContext.js +5 -5
- package/boilerplate-vue-ts/package.json +2 -1
- package/boilerplate-vue-ts/pages/_error/+Page.vue +19 -8
- package/boilerplate-vue-ts/pages/star-wars/@id/+Page.vue +14 -0
- package/boilerplate-vue-ts/pages/star-wars/@id/+data.ts +36 -0
- package/boilerplate-vue-ts/pages/star-wars/index/+Page.vue +16 -0
- package/boilerplate-vue-ts/pages/star-wars/index/+data.ts +37 -0
- package/boilerplate-vue-ts/pages/star-wars/types.ts +12 -0
- package/boilerplate-vue-ts/renderer/+config.h.ts +13 -5
- package/boilerplate-vue-ts/renderer/+onPageTransitionEnd.ts +9 -0
- package/boilerplate-vue-ts/renderer/+onPageTransitionStart.ts +9 -0
- package/boilerplate-vue-ts/renderer/+onRenderClient.ts +13 -6
- package/boilerplate-vue-ts/renderer/+onRenderHtml.ts +8 -8
- package/boilerplate-vue-ts/renderer/Link.vue +10 -2
- package/boilerplate-vue-ts/renderer/PageShell.vue +17 -19
- package/boilerplate-vue-ts/renderer/app.ts +38 -9
- package/boilerplate-vue-ts/renderer/css/code.css +6 -0
- package/boilerplate-vue-ts/renderer/css/index.css +4 -0
- package/boilerplate-vue-ts/renderer/css/links.css +3 -0
- package/boilerplate-vue-ts/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-vue-ts/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-vue-ts/renderer/css/reset.css +7 -0
- package/boilerplate-vue-ts/renderer/getPageTitle.ts +14 -0
- package/boilerplate-vue-ts/renderer/types.ts +18 -14
- package/boilerplate-vue-ts/renderer/useData.ts +11 -0
- package/boilerplate-vue-ts/renderer/usePageContext.ts +5 -6
- package/package.json +1 -1
package/.testRun.ts
CHANGED
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
expectLog,
|
|
11
11
|
editFile,
|
|
12
12
|
editFileRevert,
|
|
13
|
-
sleep,
|
|
14
13
|
test,
|
|
15
|
-
expect
|
|
14
|
+
expect,
|
|
15
|
+
sleep
|
|
16
16
|
} from '@brillout/test-e2e'
|
|
17
17
|
import assert from 'assert'
|
|
18
18
|
|
|
@@ -37,8 +37,8 @@ function testRun(
|
|
|
37
37
|
const html = await fetchHtml('/')
|
|
38
38
|
// Solid injects attribute: <h1 data-hk="0-0-2-1-0">Welcome</h1>
|
|
39
39
|
expect(html).toMatch(partRegex`<h1${/[^\>]*/}>Welcome</h1>`)
|
|
40
|
-
// Vue injects: `<!--[-->
|
|
41
|
-
expect(html).toMatch(partRegex`<a ${/[^\>]+/}>${/.*/}
|
|
40
|
+
// Vue injects: `<!--[-->Welcome<!--]-->`
|
|
41
|
+
expect(html).toMatch(partRegex`<a ${/[^\>]+/}>${/.*/}Welcome${/.*/}</a>`)
|
|
42
42
|
expect(html).toMatch(partRegex`<a ${/[^\>]+/}>${/.*/}About${/.*/}</a>`)
|
|
43
43
|
})
|
|
44
44
|
|
|
@@ -107,11 +107,37 @@ function testRun(
|
|
|
107
107
|
|
|
108
108
|
test('error page', async () => {
|
|
109
109
|
await page.goto(getServerUrl() + '/does-not-exist')
|
|
110
|
-
expect(await page.textContent('
|
|
111
|
-
expect(await page.textContent('p')).toBe('This page could not be found.')
|
|
110
|
+
expect(await page.textContent('#page-content')).toBe('Page not found.')
|
|
112
111
|
expectLog(
|
|
113
112
|
'Failed to load resource: the server responded with a status of 404 (Not Found)',
|
|
114
113
|
(log) => log.logSource === 'Browser Error' && partRegex`http://${/[^\/]+/}:3000/does-not-exist`.test(log.logText)
|
|
115
114
|
)
|
|
116
115
|
})
|
|
116
|
+
|
|
117
|
+
test('data fetching page, HTML', async () => {
|
|
118
|
+
const html = await fetchHtml('/star-wars')
|
|
119
|
+
expect(html).toContain('<a href="/star-wars/6">Revenge of the Sith</a>')
|
|
120
|
+
expect(html).toContain('<a href="/star-wars/4">The Phantom Menace</a>')
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('data fetching page, DOM', async () => {
|
|
124
|
+
await page.goto(getServerUrl() + '/star-wars')
|
|
125
|
+
const text = await page.textContent('body')
|
|
126
|
+
expect(text).toContain('Revenge of the Sith')
|
|
127
|
+
expect(text).toContain('The Phantom Menace')
|
|
128
|
+
|
|
129
|
+
if (uiFramewok === 'vue') {
|
|
130
|
+
// Attempt to make test less flaky: it some times throws a "Hydration Mismatch" error (I don't know why).
|
|
131
|
+
await sleep(1000)
|
|
132
|
+
}
|
|
133
|
+
await page.click('a[href="/star-wars/4"]')
|
|
134
|
+
await autoRetry(async () => {
|
|
135
|
+
expect(await page.textContent('h1')).toBe('The Phantom Menace')
|
|
136
|
+
})
|
|
137
|
+
const pageContent =
|
|
138
|
+
uiFramewok === 'vue'
|
|
139
|
+
? 'The Phantom Menace Release Date: 1999-05-19 Director: George Lucas Producer: Rick McCallum'
|
|
140
|
+
: 'The Phantom MenaceRelease Date: 1999-05-19Director: George LucasProducer: Rick McCallum'
|
|
141
|
+
expect(await page.textContent('body')).toContain(pageContent)
|
|
142
|
+
})
|
|
117
143
|
}
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
17
17
|
"eslint-plugin-react-refresh": "^0.4.5",
|
|
18
18
|
"express": "^4.18.2",
|
|
19
|
+
"node-fetch": "^3.3.2",
|
|
19
20
|
"prop-types": "15.8.1",
|
|
20
21
|
"react": "^18.2.0",
|
|
21
22
|
"react-dom": "^18.2.0",
|
|
22
23
|
"sirv": "^2.0.3",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
24
|
+
"vike": "^0.4.156",
|
|
25
|
+
"vite": "^5.0.10"
|
|
25
26
|
},
|
|
26
27
|
"type": "module"
|
|
27
28
|
}
|
|
@@ -1,24 +1,31 @@
|
|
|
1
|
-
import PropTypes from 'prop-types'
|
|
2
|
-
|
|
3
1
|
export { Page }
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<h1>404 Page Not Found</h1>
|
|
13
|
-
<p>This page could not be found.</p>
|
|
14
|
-
</>
|
|
15
|
-
)
|
|
16
|
-
} else {
|
|
17
|
-
return (
|
|
18
|
-
<>
|
|
19
|
-
<h1>500 Internal Error</h1>
|
|
20
|
-
<p>Something went wrong.</p>
|
|
21
|
-
</>
|
|
22
|
-
)
|
|
3
|
+
import { usePageContext } from '../../renderer/usePageContext'
|
|
4
|
+
|
|
5
|
+
function Page() {
|
|
6
|
+
const pageContext = usePageContext()
|
|
7
|
+
let { abortReason } = pageContext
|
|
8
|
+
if (!abortReason) {
|
|
9
|
+
abortReason = pageContext.is404 ? 'Page not found.' : 'Something went wrong.'
|
|
23
10
|
}
|
|
11
|
+
return (
|
|
12
|
+
<Center>
|
|
13
|
+
<p style={{ fontSize: '1.3em' }}>{abortReason}</p>
|
|
14
|
+
</Center>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function Center({ children }) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
style={{
|
|
22
|
+
height: 'calc(100vh - 100px)',
|
|
23
|
+
display: 'flex',
|
|
24
|
+
justifyContent: 'center',
|
|
25
|
+
alignItems: 'center'
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
{children}
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
24
31
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { Page }
|
|
2
|
+
|
|
3
|
+
import { useData } from '../../../renderer/useData'
|
|
4
|
+
|
|
5
|
+
function Page() {
|
|
6
|
+
const { movie } = useData()
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
<h1>{movie.title}</h1>
|
|
10
|
+
Release Date: {movie.release_date}
|
|
11
|
+
<br />
|
|
12
|
+
Director: {movie.director}
|
|
13
|
+
<br />
|
|
14
|
+
Producer: {movie.producer}
|
|
15
|
+
</>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// https://vike.dev/data
|
|
2
|
+
export { data }
|
|
3
|
+
|
|
4
|
+
// The node-fetch package (which only works on the server-side) can be used since
|
|
5
|
+
// this file always runs on the server-side, see https://vike.dev/data#server-side
|
|
6
|
+
import fetch from 'node-fetch'
|
|
7
|
+
|
|
8
|
+
const data = async (pageContext) => {
|
|
9
|
+
await sleep(300) // Simulate slow network
|
|
10
|
+
|
|
11
|
+
const response = await fetch(`https://brillout.github.io/star-wars/api/films/${pageContext.routeParams.id}.json`)
|
|
12
|
+
let movie = await response.json()
|
|
13
|
+
|
|
14
|
+
// We remove data we don't need because the data is passed to the client; we should
|
|
15
|
+
// minimize what is sent over the network.
|
|
16
|
+
movie = minimize(movie)
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
movie,
|
|
20
|
+
// The page's <title>
|
|
21
|
+
title: movie.title
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function minimize(movie) {
|
|
26
|
+
const { id, title, release_date, director, producer } = movie
|
|
27
|
+
movie = { id, title, release_date, director, producer }
|
|
28
|
+
return movie
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function sleep(milliseconds) {
|
|
32
|
+
return new Promise((r) => setTimeout(r, milliseconds))
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default Page
|
|
2
|
+
|
|
3
|
+
import { useData } from '../../../renderer/useData'
|
|
4
|
+
|
|
5
|
+
function Page() {
|
|
6
|
+
const { movies } = useData()
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
<h1>Star Wars Movies</h1>
|
|
10
|
+
<ol>
|
|
11
|
+
{movies.map(({ id, title, release_date }) => (
|
|
12
|
+
<li key={id}>
|
|
13
|
+
<a href={`/star-wars/${id}`}>{title}</a> ({release_date})
|
|
14
|
+
</li>
|
|
15
|
+
))}
|
|
16
|
+
</ol>
|
|
17
|
+
<p>
|
|
18
|
+
Source: <a href="https://brillout.github.io/star-wars/">brillout.github.io/star-wars</a>.
|
|
19
|
+
</p>
|
|
20
|
+
<p>
|
|
21
|
+
Data can be fetched by using the <code>data()</code> hook.
|
|
22
|
+
</p>
|
|
23
|
+
</>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// https://vike.dev/data
|
|
2
|
+
export { data }
|
|
3
|
+
|
|
4
|
+
// The node-fetch package (which only works on the server-side) can be used since
|
|
5
|
+
// this file always runs on the server-side, see https://vike.dev/data#server-side
|
|
6
|
+
import fetch from 'node-fetch'
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line no-unused-vars
|
|
9
|
+
const data = async (pageContext) => {
|
|
10
|
+
await sleep(700) // Simulate slow network
|
|
11
|
+
|
|
12
|
+
const response = await fetch('https://brillout.github.io/star-wars/api/films.json')
|
|
13
|
+
const moviesData = await response.json()
|
|
14
|
+
|
|
15
|
+
// We remove data we don't need because the data is passed to the client; we should
|
|
16
|
+
// minimize what is sent over the network.
|
|
17
|
+
const movies = minimize(moviesData)
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
movies,
|
|
21
|
+
// The page's <title>
|
|
22
|
+
title: `${movies.length} Star Wars Movies`
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function minimize(movies) {
|
|
27
|
+
return movies.map((movie) => {
|
|
28
|
+
const { title, release_date, id } = movie
|
|
29
|
+
return { title, release_date, id }
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function sleep(milliseconds) {
|
|
34
|
+
return new Promise((r) => setTimeout(r, milliseconds))
|
|
35
|
+
}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
// https://vike.dev/config
|
|
2
2
|
export default {
|
|
3
|
-
|
|
3
|
+
// https://vike.dev/clientRouting
|
|
4
4
|
clientRouting: true,
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
// https://vike.dev/meta
|
|
6
|
+
meta: {
|
|
7
|
+
// Define new setting 'title'
|
|
8
|
+
title: {
|
|
9
|
+
env: { server: true, client: true }
|
|
10
|
+
},
|
|
11
|
+
// Define new setting 'description'
|
|
12
|
+
description: {
|
|
13
|
+
env: { server: true }
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
hydrationCanBeAborted: true
|
|
9
17
|
}
|
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
// https://vike.dev/onRenderClient
|
|
2
2
|
export { onRenderClient }
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import ReactDOM from 'react-dom/client'
|
|
5
5
|
import { PageShell } from './PageShell'
|
|
6
|
+
import { getPageTitle } from './getPageTitle'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (!
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
let root
|
|
9
|
+
function onRenderClient(pageContext) {
|
|
10
|
+
const { Page } = pageContext
|
|
11
|
+
|
|
12
|
+
// This onRenderClient() hook only supports SSR, see https://vike.dev/render-modes for how to modify onRenderClient()
|
|
13
|
+
// to support SPA
|
|
14
|
+
if (!Page) throw new Error('My onRenderClient() hook expects pageContext.Page to be defined')
|
|
15
|
+
|
|
16
|
+
const container = document.getElementById('react-root')
|
|
17
|
+
if (!container) throw new Error('DOM element #react-root not found')
|
|
18
|
+
|
|
19
|
+
const page = (
|
|
16
20
|
<PageShell pageContext={pageContext}>
|
|
17
|
-
<Page
|
|
21
|
+
<Page />
|
|
18
22
|
</PageShell>
|
|
19
23
|
)
|
|
24
|
+
if (pageContext.isHydration) {
|
|
25
|
+
root = ReactDOM.hydrateRoot(container, page)
|
|
26
|
+
} else {
|
|
27
|
+
if (!root) {
|
|
28
|
+
root = ReactDOM.createRoot(container)
|
|
29
|
+
}
|
|
30
|
+
root.render(page)
|
|
31
|
+
}
|
|
32
|
+
document.title = getPageTitle(pageContext)
|
|
20
33
|
}
|
|
@@ -5,22 +5,25 @@ import ReactDOMServer from 'react-dom/server'
|
|
|
5
5
|
import { PageShell } from './PageShell'
|
|
6
6
|
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
|
|
7
7
|
import logoUrl from './logo.svg'
|
|
8
|
+
import { getPageTitle } from './getPageTitle'
|
|
9
|
+
|
|
10
|
+
function onRenderHtml(pageContext) {
|
|
11
|
+
const { Page } = pageContext
|
|
8
12
|
|
|
9
|
-
async function onRenderHtml(pageContext) {
|
|
10
|
-
const { Page, pageProps } = pageContext
|
|
11
13
|
// This onRenderHtml() hook only supports SSR, see https://vike.dev/render-modes for how to modify
|
|
12
14
|
// onRenderHtml() to support SPA
|
|
13
|
-
if (!Page) throw new Error('My
|
|
15
|
+
if (!Page) throw new Error('My onRenderHtml() hook expects pageContext.Page to be defined')
|
|
16
|
+
|
|
17
|
+
// Alternativly, we can use an HTML stream, see https://vike.dev/stream
|
|
14
18
|
const pageHtml = ReactDOMServer.renderToString(
|
|
15
19
|
<PageShell pageContext={pageContext}>
|
|
16
|
-
<Page
|
|
20
|
+
<Page />
|
|
17
21
|
</PageShell>
|
|
18
22
|
)
|
|
19
23
|
|
|
20
24
|
// See https://vike.dev/head
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const desc = (documentProps && documentProps.description) || 'App using Vite + Vike'
|
|
25
|
+
const title = getPageTitle(pageContext)
|
|
26
|
+
const desc = pageContext.data?.description || pageContext.config.description || 'Demo of using Vike'
|
|
24
27
|
|
|
25
28
|
const documentHtml = escapeInject`<!DOCTYPE html>
|
|
26
29
|
<html lang="en">
|
|
@@ -39,7 +42,8 @@ async function onRenderHtml(pageContext) {
|
|
|
39
42
|
return {
|
|
40
43
|
documentHtml,
|
|
41
44
|
pageContext: {
|
|
42
|
-
// We can add
|
|
45
|
+
// We can add custom pageContext properties here, see https://vike.dev/pageContext#custom
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
}
|
|
49
|
+
|
|
@@ -9,6 +9,9 @@ Link.propTypes = {
|
|
|
9
9
|
}
|
|
10
10
|
function Link(props) {
|
|
11
11
|
const pageContext = usePageContext()
|
|
12
|
-
const
|
|
12
|
+
const { urlPathname } = pageContext
|
|
13
|
+
const { href } = props
|
|
14
|
+
const isActive = href === '/' ? urlPathname === href : urlPathname.startsWith(href)
|
|
15
|
+
const className = [props.className, isActive && 'is-active'].filter(Boolean).join(' ')
|
|
13
16
|
return <a {...props} className={className} />
|
|
14
17
|
}
|
|
@@ -1,19 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
margin: 0;
|
|
5
|
-
font-family: sans-serif;
|
|
1
|
+
#sidebar a {
|
|
2
|
+
padding: 2px 10px;
|
|
3
|
+
margin-left: -10px;
|
|
6
4
|
}
|
|
7
|
-
|
|
8
|
-
box-sizing: border-box;
|
|
9
|
-
}
|
|
10
|
-
a {
|
|
11
|
-
text-decoration: none;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.navitem {
|
|
15
|
-
padding: 3px 10px;
|
|
16
|
-
}
|
|
17
|
-
.navitem.is-active {
|
|
5
|
+
#sidebar a.is-active {
|
|
18
6
|
background-color: #eee;
|
|
19
7
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
export { PageShell }
|
|
2
|
+
|
|
1
3
|
import React from 'react'
|
|
2
4
|
import PropTypes from 'prop-types'
|
|
3
|
-
import
|
|
4
|
-
import './
|
|
5
|
+
import { childrenPropType } from './PropTypeValues'
|
|
6
|
+
import logoUrl from './logo.svg'
|
|
5
7
|
import { PageContextProvider } from './usePageContext'
|
|
6
8
|
import { Link } from './Link'
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
export { PageShell }
|
|
9
|
+
import './css/index.css'
|
|
10
|
+
import './PageShell.css'
|
|
10
11
|
|
|
11
12
|
PageShell.propTypes = {
|
|
12
13
|
pageContext: PropTypes.any,
|
|
@@ -19,12 +20,9 @@ function PageShell({ pageContext, children }) {
|
|
|
19
20
|
<Layout>
|
|
20
21
|
<Sidebar>
|
|
21
22
|
<Logo />
|
|
22
|
-
<Link
|
|
23
|
-
|
|
24
|
-
</Link>
|
|
25
|
-
<Link className="navitem" href="/about">
|
|
26
|
-
About
|
|
27
|
-
</Link>
|
|
23
|
+
<Link href="/">Welcome</Link>
|
|
24
|
+
<Link href="/about">About</Link>
|
|
25
|
+
<Link href="/star-wars">Data Fetching</Link>
|
|
28
26
|
</Sidebar>
|
|
29
27
|
<Content>{children}</Content>
|
|
30
28
|
</Layout>
|
|
@@ -56,13 +54,14 @@ Sidebar.propTypes = {
|
|
|
56
54
|
function Sidebar({ children }) {
|
|
57
55
|
return (
|
|
58
56
|
<div
|
|
57
|
+
id="sidebar"
|
|
59
58
|
style={{
|
|
60
59
|
padding: 20,
|
|
61
60
|
flexShrink: 0,
|
|
62
61
|
display: 'flex',
|
|
63
62
|
flexDirection: 'column',
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
lineHeight: '1.8em',
|
|
64
|
+
borderRight: '2px solid #eee'
|
|
66
65
|
}}
|
|
67
66
|
>
|
|
68
67
|
{children}
|
|
@@ -75,15 +74,17 @@ Content.propTypes = {
|
|
|
75
74
|
}
|
|
76
75
|
function Content({ children }) {
|
|
77
76
|
return (
|
|
78
|
-
<div
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
<div id="page-container">
|
|
78
|
+
<div
|
|
79
|
+
id="page-content"
|
|
80
|
+
style={{
|
|
81
|
+
padding: 20,
|
|
82
|
+
paddingBottom: 50,
|
|
83
|
+
minHeight: '100vh'
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
{children}
|
|
87
|
+
</div>
|
|
87
88
|
</div>
|
|
88
89
|
)
|
|
89
90
|
}
|
|
@@ -97,7 +98,7 @@ function Logo() {
|
|
|
97
98
|
}}
|
|
98
99
|
>
|
|
99
100
|
<a href="/">
|
|
100
|
-
<img src={
|
|
101
|
+
<img src={logoUrl} height={64} width={64} alt="logo" />
|
|
101
102
|
</a>
|
|
102
103
|
</div>
|
|
103
104
|
)
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg version="1.1" id="L9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
|
|
2
|
+
<path fill="#aaa" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50">
|
|
3
|
+
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" from="0 50 50" to="360 50 50" repeatCount="indefinite"></animateTransform>
|
|
4
|
+
</path>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#page-container {
|
|
2
|
+
position: relative;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
#page-container::before {
|
|
6
|
+
content: '';
|
|
7
|
+
position: absolute;
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
z-index: 999;
|
|
11
|
+
background: no-repeat url('./page-transition-loading-animation/loading.svg');
|
|
12
|
+
background-size: 100px;
|
|
13
|
+
background-position: center center;
|
|
14
|
+
pointer-events: none;
|
|
15
|
+
opacity: 0;
|
|
16
|
+
}
|
|
17
|
+
body.page-is-transitioning #page-container::before {
|
|
18
|
+
opacity: 1;
|
|
19
|
+
}
|
|
20
|
+
#page-content,
|
|
21
|
+
#page-container::before {
|
|
22
|
+
transition: opacity 0.5s ease-in-out;
|
|
23
|
+
}
|
|
24
|
+
body.page-is-transitioning #page-content {
|
|
25
|
+
opacity: 0.17;
|
|
26
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { getPageTitle }
|
|
2
|
+
|
|
3
|
+
function getPageTitle(pageContext) {
|
|
4
|
+
const title =
|
|
5
|
+
// Title defined dynamically by data()
|
|
6
|
+
pageContext.data?.title ||
|
|
7
|
+
// Title defined statically by /pages/some-page/+title.js (or by `export default { title }` in /pages/some-page/+config.js)
|
|
8
|
+
// The setting 'pageContext.config.title' is a custom setting we defined at ./+config.ts
|
|
9
|
+
pageContext.config.title ||
|
|
10
|
+
'Vike Demo'
|
|
11
|
+
return title
|
|
12
|
+
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// https://vike.dev/usePageContext
|
|
2
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
3
|
+
export { usePageContext }
|
|
4
|
+
export { PageContextProvider }
|
|
3
5
|
|
|
4
6
|
import React, { useContext } from 'react'
|
|
5
7
|
import PropTypes from 'prop-types'
|
|
6
8
|
import { childrenPropType } from './PropTypeValues'
|
|
7
9
|
|
|
8
|
-
export { PageContextProvider }
|
|
9
|
-
// eslint-disable-next-line react-refresh/only-export-components
|
|
10
|
-
export { usePageContext }
|
|
11
|
-
|
|
12
10
|
const Context = React.createContext(undefined)
|
|
13
11
|
|
|
14
12
|
PageContextProvider.propTypes = {
|
|
@@ -19,6 +17,7 @@ function PageContextProvider({ pageContext, children }) {
|
|
|
19
17
|
return <Context.Provider value={pageContext}>{children}</Context.Provider>
|
|
20
18
|
}
|
|
21
19
|
|
|
20
|
+
/** https://vike.dev/usePageContext */
|
|
22
21
|
function usePageContext() {
|
|
23
22
|
const pageContext = useContext(Context)
|
|
24
23
|
return pageContext
|
|
@@ -24,13 +24,14 @@
|
|
|
24
24
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
25
25
|
"eslint-plugin-react-refresh": "^0.4.5",
|
|
26
26
|
"express": "^4.18.2",
|
|
27
|
+
"node-fetch": "^3.3.2",
|
|
27
28
|
"react": "^18.2.0",
|
|
28
29
|
"react-dom": "^18.2.0",
|
|
29
30
|
"sirv": "^2.0.3",
|
|
30
31
|
"ts-node": "^10.9.1",
|
|
31
32
|
"typescript": "^5.3.3",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
33
|
+
"vike": "^0.4.156",
|
|
34
|
+
"vite": "^5.0.10"
|
|
34
35
|
},
|
|
35
36
|
"type": "module"
|
|
36
37
|
}
|