mirror of
https://github.com/danbulant/nollup-apexcharts-bug
synced 2026-07-09 21:11:15 +00:00
initial commit
This commit is contained in:
commit
73f8c00f95
96 changed files with 18419 additions and 0 deletions
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
**/node_modules/
|
||||||
|
/dist/
|
||||||
|
.DS_Store
|
||||||
|
**/.history
|
||||||
|
src/tmp/
|
||||||
|
.routify
|
||||||
|
.netlify
|
||||||
|
assets/build
|
||||||
|
.vercel
|
||||||
7
.nolluprc.js
Normal file
7
.nolluprc.js
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = {
|
||||||
|
hot: true,
|
||||||
|
contentBase: 'assets',
|
||||||
|
publicPath: 'build',
|
||||||
|
historyApiFallback: '__app.html',
|
||||||
|
port: 5000
|
||||||
|
}
|
||||||
73
README.md
Normal file
73
README.md
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
### Oh hai! ❤
|
||||||
|
We've created a new project called [**stackmix**](https://github.com/roxiness/stackmix). It's an experimental CLI that let's you customize new Routify templates. Go check it out!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# routify-starter
|
||||||
|
|
||||||
|
Starter template for [Routify](https://github.com/roxiness/routify).
|
||||||
|
|
||||||
|
### Get started
|
||||||
|
|
||||||
|
#### Starter templates
|
||||||
|
| Template | Description |
|
||||||
|
|-------------------------------------------|-------------------------------------------------------------|
|
||||||
|
| [master](https://example.routify.dev/) | Default template, includes examples folder |
|
||||||
|
| [blog](https://blog-example.routify.dev/) | Generates a blog from local markdown posts. Includes mdsvex |
|
||||||
|
| [auth](https://auth-example.routify.dev/) | Embedded login on protected pages. Includes Auth0 |
|
||||||
|
|
||||||
|
To use a template, run:
|
||||||
|
|
||||||
|
`npx @roxi/routify init`
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
`npx @roxi/routify init --branch <branch-name>`
|
||||||
|
|
||||||
|
The above commands will populate the current directory, they don't create a new one.
|
||||||
|
|
||||||
|
### npm scripts
|
||||||
|
|
||||||
|
| Syntax | Description |
|
||||||
|
|------------------|-----------------------------------------------------------------------------------|
|
||||||
|
| `dev` | Development (port 5000) |
|
||||||
|
| `dev:nollup` | Development with crazy fast rebuilds (port 5000) |
|
||||||
|
| `dev-dynamic` | Development with dynamic imports |
|
||||||
|
| `build` | Build a bundled app with SSR + prerendering and dynamic imports |
|
||||||
|
| `serve` | Run after a build to preview. Serves SPA on 5000 and SSR on 5005 |
|
||||||
|
| `deploy:*` | Deploy to netlify or now |
|
||||||
|
| `export` | Create static pages from content in dist folder (used by `npm run build`) |
|
||||||
|
|
||||||
|
### SSR and pre-rendering
|
||||||
|
|
||||||
|
SSR and pre-rendering are included in the default build process.
|
||||||
|
|
||||||
|
`npm run deploy:(now|netlify)` will deploy the app with SSR and prerendering included.
|
||||||
|
|
||||||
|
To render async data, call the `$ready()` helper whenever your data is ready.
|
||||||
|
|
||||||
|
If $ready() is present, rendering will be delayed till the function has been called.
|
||||||
|
|
||||||
|
Otherwise it will be rendered instantly.
|
||||||
|
|
||||||
|
See [src/pages/example/api/[showId].svelte](https://github.com/roxiness/routify-starter/blob/master/src/pages/example/api/%5BshowId%5D.svelte) for an example.
|
||||||
|
|
||||||
|
### Production
|
||||||
|
|
||||||
|
* For SPA or SSR apps please make sure that url rewrite is enabled on the server.
|
||||||
|
* For SPA redirect to `__app.html`.
|
||||||
|
* For SSR redirect to the lambda function or express server.
|
||||||
|
|
||||||
|
### Typescript
|
||||||
|
|
||||||
|
For Typescript, we recommend [@lamualfa](https://github.com/lamualfa) excellent [routify-ts](https://github.com/lamualfa/routify-ts/)
|
||||||
|
|
||||||
|
New project: `npx routify-ts init <project-name> [routify-init-args]`
|
||||||
|
|
||||||
|
Existing project: `npx routify-ts convert [project-directory]`
|
||||||
|
|
||||||
|
|
||||||
|
### Issues?
|
||||||
|
|
||||||
|
File on Github! See https://github.com/sveltech/routify/issues .
|
||||||
16
api/netlify/package.json
Normal file
16
api/netlify/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "ssr",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "ssr.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "node utils/build.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"esbuild": "^0.8.8",
|
||||||
|
"tossr": "^1.3.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
api/netlify/ssr.js
Normal file
11
api/netlify/ssr.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
const { tossr } = require('tossr')
|
||||||
|
const { script, template } = require('./bundle.json')
|
||||||
|
|
||||||
|
exports.handler = async (event, context) => {
|
||||||
|
const qs = Object.entries(event.queryStringParameters)
|
||||||
|
.map(([key, value]) => `${key}=${value}`)
|
||||||
|
.join('&');
|
||||||
|
const body = await tossr(template, script, `${event.path}?${qs}`);
|
||||||
|
return { statusCode: 200, body: body + '\n<!--ssr rendered-->' }
|
||||||
|
}
|
||||||
26
api/netlify/utils/build.js
Normal file
26
api/netlify/utils/build.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* Creates a JSON and inlines it with esbuild for ssr.js to consume
|
||||||
|
* {
|
||||||
|
* data: duh,
|
||||||
|
* script: inlined main.js
|
||||||
|
* template: __app.html
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { resolve } = require('path')
|
||||||
|
const { readFileSync, writeFileSync } = require('fs')
|
||||||
|
const { build } = require('esbuild')
|
||||||
|
|
||||||
|
const scriptPath = resolve(__dirname, '../../../dist/build/main.js')
|
||||||
|
const templatePath = resolve(__dirname, '../../../dist/__app.html')
|
||||||
|
const bundlePath = resolve(__dirname, '../build/bundle.js')
|
||||||
|
|
||||||
|
build({ entryPoints: [scriptPath], outfile: bundlePath, bundle: true }).then(() => {
|
||||||
|
const bundle = {
|
||||||
|
date: new Date,
|
||||||
|
script: readFileSync(bundlePath, 'utf8'),
|
||||||
|
template: readFileSync(templatePath, 'utf8')
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileSync(resolve(__dirname, '../bundle.json'), JSON.stringify(bundle, null, 2))
|
||||||
|
})
|
||||||
36
api/vercel-ssr/build.js
Normal file
36
api/vercel-ssr/build.js
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
const { resolve } = require('path')
|
||||||
|
const { existsSync } = require('fs')
|
||||||
|
const { execSync } = require('child_process')
|
||||||
|
const { rollup } = require('rollup')
|
||||||
|
|
||||||
|
const shouldBuildSpa = process.env.NOW_GITHUB_DEPLOYMENT || process.env.NOW_BUILDER
|
||||||
|
const script = resolve(__dirname, '../../dist/build/main.js')
|
||||||
|
const bundlePath = resolve(__dirname, '../../dist/build/bundle.js')
|
||||||
|
|
||||||
|
build()
|
||||||
|
|
||||||
|
|
||||||
|
async function build() {
|
||||||
|
if (shouldBuildSpa)
|
||||||
|
execSync('npm install && npm run build:app', { cwd: resolve('..', '..'), stdio: 'inherit' })
|
||||||
|
else
|
||||||
|
await waitForAppToExist()
|
||||||
|
|
||||||
|
buildSSRBundle()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForAppToExist() {
|
||||||
|
while (!existsSync(script)) {
|
||||||
|
console.log(`checking if "${script}" exists`)
|
||||||
|
await new Promise(r => setTimeout(r, 2000))
|
||||||
|
}
|
||||||
|
console.log(`found "${script}"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildSSRBundle() {
|
||||||
|
const bundle = await rollup({
|
||||||
|
input: script,
|
||||||
|
inlineDynamicImports: true,
|
||||||
|
})
|
||||||
|
await bundle.write({ format: 'umd', file: bundlePath, name: 'roxi-ssr' })
|
||||||
|
}
|
||||||
11
api/vercel-ssr/index.js
Normal file
11
api/vercel-ssr/index.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
const { tossr } = require('tossr')
|
||||||
|
|
||||||
|
const script = fs.readFileSync(require.resolve('../../dist/build/bundle.js'), 'utf8')
|
||||||
|
const template = fs.readFileSync(require.resolve('../../dist/__app.html'), 'utf8')
|
||||||
|
|
||||||
|
module.exports = async (req, res) => {
|
||||||
|
const html = await tossr(template, script, req.url, {})
|
||||||
|
res.send(html + '\n<!--ssr rendered-->')
|
||||||
|
}
|
||||||
|
|
||||||
8
api/vercel-ssr/package.json
Normal file
8
api/vercel-ssr/package.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"vercel-build": "node ./build.js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"rollup": "^2.28.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
assets/404.svg
Normal file
1
assets/404.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><linearGradient id="a" x1="2.625" x2="25.637" y1="13.491" y2="13.491" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2B2E81"/><stop offset="1" stop-color="#BE4F9C"/></linearGradient><path fill="url(#a)" d="M10.5 15.5H12v.5c0 .3.2.5.5.5s.5-.2.5-.5v-.5h.5c.3 0 .5-.2.5-.5s-.2-.5-.5-.5H13V13c0-.3-.2-.5-.5-.5s-.5.2-.5.5v1.5h-.9l.6-3.4c.1-.3-.1-.5-.4-.6-.3-.1-.5.1-.6.4l-.8 4c0 .1 0 .3.1.4s.4.2.5.2z"/><linearGradient id="b" x1="2.625" x2="25.637" y1="13.491" y2="13.491" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2B2E81"/><stop offset="1" stop-color="#BE4F9C"/></linearGradient><path fill="url(#b)" d="M20.5 15.5H22v.5c0 .3.2.5.5.5s.5-.2.5-.5v-.5h.5c.3 0 .5-.2.5-.5s-.2-.5-.5-.5H23V13c0-.3-.2-.5-.5-.5s-.5.2-.5.5v1.5h-.9l.6-3.4c.1-.3-.1-.5-.4-.6-.3-.1-.5.1-.6.4l-.8 4c0 .1 0 .3.1.4s.4.2.5.2z"/><linearGradient id="c" x1="2.625" x2="25.637" y1="22" y2="22" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2B2E81"/><stop offset="1" stop-color="#BE4F9C"/></linearGradient><path fill="url(#c)" d="M6.5 21.5h-.6c-.1-.3-.2-.6-.4-.9l.5-.4c.2-.2.2-.5 0-.7s-.5-.2-.7 0l-.4.4c-.3-.2-.6-.3-.9-.4V19c0-.3-.2-.5-.5-.5s-.5.2-.5.5v.6c-.3.1-.6.2-.9.4l-.4-.4c-.2-.2-.5-.2-.7 0s-.2.4 0 .6l.4.4c-.2.3-.3.6-.4.9H.5c-.3 0-.5.2-.5.5s.2.5.5.5h.6c.1.3.2.6.4.9l-.5.4c-.2.2-.2.5 0 .7.1.1.2.1.4.1s.3 0 .4-.1l.4-.4c.3.2.6.3.9.4v.5c0 .3.2.5.5.5s.4-.2.4-.5v-.6c.3-.1.6-.2.9-.4l.4.4c.1.1.2.1.4.1s.3 0 .4-.1c.2-.2.2-.5 0-.7l-.4-.4c.2-.3.3-.6.4-.9h.6c.1.1.3-.1.3-.4s-.2-.5-.5-.5zm-3 2c-.8 0-1.5-.7-1.5-1.5 0-.4.2-.8.4-1.1.3-.3.7-.4 1.1-.4.8 0 1.5.7 1.5 1.5s-.7 1.5-1.5 1.5z"/><linearGradient id="d" x1="2.625" x2="25.637" y1="22" y2="22" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2B2E81"/><stop offset="1" stop-color="#BE4F9C"/></linearGradient><circle cx="3.5" cy="22" r=".5" fill="url(#d)"/><linearGradient id="e" x1="2.625" x2="25.637" y1="16" y2="16" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2B2E81"/><stop offset="1" stop-color="#BE4F9C"/></linearGradient><path fill="url(#e)" d="M31.5 12h-.8l.6-.6c.2-.2.2-.5 0-.7l-1.4-1.4c-.2-.2-.5-.2-.7 0l-.6.6V9c0-.3-.2-.5-.5-.5h-1V8c0-.8-.7-1.5-1.5-1.5h-17C7.7 6.5 7 7.2 7 8v5.6c-.3.1-.6.2-.9.4l-.4-.4c-.2-.2-.5-.2-.7 0s-.2.4 0 .6l.4.4c-.2.3-.3.6-.4.9h-.5c-.3 0-.5.2-.5.5s.2.5.5.5h.6c.1.3.2.6.4.9l-.5.4c-.2.2-.2.5 0 .7.1.1.2.1.4.1s.3 0 .4-.1l.4-.4c.3.2.6.3.9.4V20c0 .8.7 1.5 1.5 1.5H14v3h-3.5c-.3 0-.5.2-.5.5s.2.5.5.5h13c.3 0 .5-.2.5-.5s-.2-.5-.5-.5H20v-3h5.5c.8 0 1.5-.7 1.5-1.5v-1.5h1c.3 0 .5-.2.5-.5v-.8l.6.6c.2.2.5.2.7 0l1.4-1.4c.2-.2.2-.5 0-.7l-.5-.7h.8c.3 0 .5-.2.5-.5v-2c0-.3-.2-.5-.5-.5zm-4.5.5c.6 0 1 .4 1 1s-.4 1-1 1v-2zm-18.5-5h17c.3 0 .5.2.5.5v9.5H8V8c0-.3.2-.5.5-.5zM7 17.4c-.6-.2-1-.8-1-1.4 0-.4.2-.8.4-1.1.2-.2.4-.3.6-.3v2.8zm12 7.1h-4v-3h4v3zm6.5-4h-17c-.3 0-.5-.2-.5-.5v-1.5h18V20c0 .3-.2.5-.5.5zM31 14h-.7c-.2 0-.4.1-.5.4-.1.2-.1.4-.2.6-.1.2-.1.4.1.6l.5.5-.7.7-.5-.6c-.2-.2-.4-.2-.6-.1-.2.1-.4.2-.6.2-.2.1-.3.3-.3.5v.7H27v-2c1.1 0 2-.9 2-2s-.9-2-2-2v-2h.5v.7c0 .2.1.4.3.5.2.1.4.1.6.2.2.1.4.1.6-.1l.5-.5.7.7-.5.5c-.2.2-.2.4-.1.6.1.2.2.4.2.6.1.2.3.4.5.4h.7v.9z"/><linearGradient id="f" x1="2.625" x2="25.637" y1="13.5" y2="13.5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2B2E81"/><stop offset="1" stop-color="#BE4F9C"/></linearGradient><path fill="url(#f)" d="M16.5 16.5h1c.8 0 1.5-.7 1.5-1.5v-3c0-.8-.7-1.5-1.5-1.5h-1c-.8 0-1.5.7-1.5 1.5v3c0 .8.7 1.5 1.5 1.5zM16 12c0-.3.2-.5.5-.5h1c.3 0 .5.2.5.5v3c0 .3-.2.5-.5.5h-1c-.3 0-.5-.2-.5-.5v-3z"/></svg>
|
||||||
|
After Width: | Height: | Size: 3.5 KiB |
22
assets/__app.html
Normal file
22
assets/__app.html
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||||
|
|
||||||
|
<title>Svelte app</title>
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#E938C2">
|
||||||
|
<link rel="apple-touch-icon" href="/images/touch-icons/logo-192.png">
|
||||||
|
|
||||||
|
<link rel="manifest" href="/manifest.json">
|
||||||
|
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||||
|
<link rel="modulepreload" href="/build/main.js" />
|
||||||
|
|
||||||
|
<script type="module" src="/build/main.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>Please enable Javascript for best experience.</noscript>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
assets/favicon.ico
Normal file
BIN
assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
BIN
assets/favicon.png
Normal file
BIN
assets/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
66
assets/global.css
Normal file
66
assets/global.css
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
html, body {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: rgb(0,100,200);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: rgb(0,80,160);
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button, select, textarea {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
padding: 0.4em;
|
||||||
|
margin: 0 0 0.5em 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:disabled {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"] {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
color: #333;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled):active {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus {
|
||||||
|
border-color: #666;
|
||||||
|
}
|
||||||
BIN
assets/images/touch-icons/logo-192.png
Normal file
BIN
assets/images/touch-icons/logo-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
BIN
assets/images/touch-icons/logo-800.png
Normal file
BIN
assets/images/touch-icons/logo-800.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
21
assets/manifest.json
Normal file
21
assets/manifest.json
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"theme_color": "#E938C2",
|
||||||
|
"name": "Routify app",
|
||||||
|
"short_name": "Routify app",
|
||||||
|
"start_url": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/images/touch-icons/logo-192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/images/touch-icons/logo-800.png",
|
||||||
|
"sizes": "800x800",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "maskable any"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
2
assets/robots.txt
Normal file
2
assets/robots.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
23
netlify.toml
Normal file
23
netlify.toml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
[build]
|
||||||
|
publish = "dist"
|
||||||
|
functions = "api/netlify"
|
||||||
|
command = "npm run build && cd api/netlify && npm run build"
|
||||||
|
|
||||||
|
# Dev doesn't work yet. Any takers?
|
||||||
|
# [dev]
|
||||||
|
# command = "npm run dev:ssr"
|
||||||
|
# targetPort = 5000
|
||||||
|
# publish = "assets"
|
||||||
|
# autoLaunch = true
|
||||||
|
|
||||||
|
[[redirects]]
|
||||||
|
# SSR and SPA
|
||||||
|
from = "/*"
|
||||||
|
to = "/.netlify/functions/ssr"
|
||||||
|
status = 200
|
||||||
|
|
||||||
|
# SPA only
|
||||||
|
# from = "/*"
|
||||||
|
# to = "/__app.html"
|
||||||
|
# status = 200
|
||||||
11798
package-lock.json
generated
Normal file
11798
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
61
package.json
Normal file
61
package.json
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"name": "svelte-app",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"@comments scripts": {
|
||||||
|
"dev": "develop with blazing fast rebuilds",
|
||||||
|
"dev:features": "develop with features like SSR and serviceworker enabled",
|
||||||
|
"build": "run build scripts below",
|
||||||
|
"build:app": "build single page application (SPA)",
|
||||||
|
"build:static": "Generate static pages",
|
||||||
|
"serve": "serve content in 'dist' folder",
|
||||||
|
"rollup": "run the rollup bundler",
|
||||||
|
"nollup": "run the nollup no-bundler",
|
||||||
|
"routify": "run routify"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "run-p routify nollup",
|
||||||
|
"dev:ssr": "run-p routify rollup",
|
||||||
|
"build": "run-s build:*",
|
||||||
|
"build:app": "routify -b && rollup -c",
|
||||||
|
"build:static": "spank",
|
||||||
|
"serve": "spassr --ssr",
|
||||||
|
"rollup": "rollup -cw",
|
||||||
|
"nollup": "nollup -c --verbose",
|
||||||
|
"routify": "routify"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-commonjs": "^19.0.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^13.0.0",
|
||||||
|
"@roxi/routify": "^2.18.1",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"nollup": "^0.16.4",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"postcss": "^8.2.14",
|
||||||
|
"postcss-import": "^14.0.1",
|
||||||
|
"rollup": "^2.47.0",
|
||||||
|
"rollup-plugin-hot": "^0.1.1",
|
||||||
|
"rollup-plugin-livereload": "^2.0.0",
|
||||||
|
"rollup-plugin-svelte": "^7.1.0",
|
||||||
|
"rollup-plugin-svelte-hot": "^1.0.0-7",
|
||||||
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
|
"rollup-plugin-workbox": "^5.2.1",
|
||||||
|
"spank": "^1.7.0",
|
||||||
|
"spassr": "^2.6.0",
|
||||||
|
"svelte": "^3.38.2",
|
||||||
|
"svelte-preprocess": "^4.7.3",
|
||||||
|
"tossr": "^1.4.2"
|
||||||
|
},
|
||||||
|
"routify": {
|
||||||
|
"extensions": "svelte,html,svx,md"
|
||||||
|
},
|
||||||
|
"spassr": {},
|
||||||
|
"spank": {
|
||||||
|
"blacklist": [
|
||||||
|
"/example/modal/basic/4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"apexcharts": "^3.28.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
4325
pnpm-lock.yaml
Normal file
4325
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
94
rollup.config.js
Normal file
94
rollup.config.js
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
import svelte from 'rollup-plugin-svelte-hot';
|
||||||
|
import Hmr from 'rollup-plugin-hot'
|
||||||
|
import resolve from '@rollup/plugin-node-resolve';
|
||||||
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import livereload from 'rollup-plugin-livereload';
|
||||||
|
import { terser } from 'rollup-plugin-terser';
|
||||||
|
import { copySync, removeSync } from 'fs-extra'
|
||||||
|
import { spassr } from 'spassr'
|
||||||
|
import getConfig from '@roxi/routify/lib/utils/config'
|
||||||
|
import autoPreprocess from 'svelte-preprocess'
|
||||||
|
import postcssImport from 'postcss-import'
|
||||||
|
import { injectManifest } from 'rollup-plugin-workbox'
|
||||||
|
|
||||||
|
|
||||||
|
const { distDir } = getConfig() // use Routify's distDir for SSOT
|
||||||
|
const assetsDir = 'assets'
|
||||||
|
const buildDir = `${distDir}/build`
|
||||||
|
const isNollup = !!process.env.NOLLUP
|
||||||
|
const production = !process.env.ROLLUP_WATCH;
|
||||||
|
|
||||||
|
// clear previous builds
|
||||||
|
removeSync(distDir)
|
||||||
|
removeSync(buildDir)
|
||||||
|
|
||||||
|
|
||||||
|
const serve = () => ({
|
||||||
|
writeBundle: async () => {
|
||||||
|
const options = {
|
||||||
|
assetsDir: [assetsDir, distDir],
|
||||||
|
entrypoint: `${assetsDir}/__app.html`,
|
||||||
|
script: `${buildDir}/main.js`
|
||||||
|
}
|
||||||
|
spassr({ ...options, port: 5000 })
|
||||||
|
spassr({ ...options, ssr: true, port: 5005, ssrOptions: { inlineDynamicImports: true, dev: true } })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const copyToDist = () => ({ writeBundle() { copySync(assetsDir, distDir) } })
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
preserveEntrySignatures: false,
|
||||||
|
input: [`src/main.js`],
|
||||||
|
output: {
|
||||||
|
sourcemap: true,
|
||||||
|
format: 'esm',
|
||||||
|
dir: buildDir,
|
||||||
|
// for performance, disabling filename hashing in development
|
||||||
|
chunkFileNames:`[name]${production && '-[hash]' || ''}.js`
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
svelte({
|
||||||
|
emitCss: false,
|
||||||
|
hot: isNollup,
|
||||||
|
preprocess: [
|
||||||
|
autoPreprocess({
|
||||||
|
postcss: { plugins: [postcssImport()] },
|
||||||
|
defaults: { style: 'postcss' }
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
|
||||||
|
// resolve matching modules from current working directory
|
||||||
|
resolve({
|
||||||
|
browser: true,
|
||||||
|
dedupe: importee => !!importee.match(/svelte(\/|$)/)
|
||||||
|
}),
|
||||||
|
commonjs(),
|
||||||
|
|
||||||
|
production && terser(),
|
||||||
|
!production && !isNollup && serve(),
|
||||||
|
!production && !isNollup && livereload(distDir), // refresh entire window when code is updated
|
||||||
|
!production && isNollup && Hmr({ inMemory: true, public: assetsDir, }), // refresh only updated code
|
||||||
|
{
|
||||||
|
// provide node environment on the client
|
||||||
|
transform: code => ({
|
||||||
|
code: code.replace(/process\.env\.NODE_ENV/g, `"${process.env.NODE_ENV}"`),
|
||||||
|
map: { mappings: '' }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
injectManifest({
|
||||||
|
globDirectory: assetsDir,
|
||||||
|
globPatterns: ['**/*.{js,css,svg}', '__app.html'],
|
||||||
|
swSrc: `src/sw.js`,
|
||||||
|
swDest: `${distDir}/serviceworker.js`,
|
||||||
|
maximumFileSizeToCacheInBytes: 10000000, // 10 MB,
|
||||||
|
mode: 'production'
|
||||||
|
}),
|
||||||
|
production && copyToDist(),
|
||||||
|
],
|
||||||
|
watch: {
|
||||||
|
clearScreen: false,
|
||||||
|
buildDelay: 100,
|
||||||
|
}
|
||||||
|
}
|
||||||
6
sandbox.config.json
Normal file
6
sandbox.config.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"container": {
|
||||||
|
"port": 5000,
|
||||||
|
"template": "node"
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/App.svelte
Normal file
10
src/App.svelte
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<script>
|
||||||
|
import { Router } from "@roxi/routify";
|
||||||
|
import { routes } from "../.routify/routes";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style global>
|
||||||
|
@import "../assets/global.css";
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<Router {routes} />
|
||||||
20
src/Serviceworker.svelte
Normal file
20
src/Serviceworker.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* This file handles serviceworker registration
|
||||||
|
* To enable it, import it from another file, ie. src/pages/_layout.svelte
|
||||||
|
* ⚠ The imported component could get treeshaken if not used, eg. <SW />
|
||||||
|
* For configuring the serviceworker, refer to sw.js
|
||||||
|
*/
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
import("workbox-window").then(async ({ Workbox }) => {
|
||||||
|
const wb = new Workbox("/serviceworker.js");
|
||||||
|
const registration = await wb.register();
|
||||||
|
|
||||||
|
// Reload the page if the PWA has been updated. Change strategy if needed.
|
||||||
|
wb.addEventListener("redundant", () => {
|
||||||
|
location.reload();
|
||||||
|
console.log("updated app");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
14
src/chart.js
Normal file
14
src/chart.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import ApexCharts from "apexcharts";
|
||||||
|
|
||||||
|
export const chart = (node, options) => {
|
||||||
|
console.log(ApexCharts);
|
||||||
|
let myChart = new ApexCharts(node, options)
|
||||||
|
myChart.render()
|
||||||
|
|
||||||
|
return {
|
||||||
|
update(options) {
|
||||||
|
myChart.updateOptions(options)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
6
src/main.js
Normal file
6
src/main.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import HMR from '@roxi/routify/hmr'
|
||||||
|
import App from './App.svelte';
|
||||||
|
|
||||||
|
const app = HMR(App, { target: document.body }, 'routify-app')
|
||||||
|
|
||||||
|
export default app;
|
||||||
24
src/pages/_fallback.svelte
Normal file
24
src/pages/_fallback.svelte
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script>
|
||||||
|
import { url } from '@roxi/routify'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.huge {
|
||||||
|
font-size: 12rem;
|
||||||
|
}
|
||||||
|
.e404 {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="e404">
|
||||||
|
<div class="huge">404</div>
|
||||||
|
<div class="big">Page not found.
|
||||||
|
<!-- link to the parent folder of _fallback.svelte -->
|
||||||
|
<a href={$url('../')}>Go back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
2
src/pages/_layout.svelte
Normal file
2
src/pages/_layout.svelte
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!-- routify:options preload="proximity" -->
|
||||||
|
<slot />
|
||||||
110
src/pages/example/Splash.svelte
Normal file
110
src/pages/example/Splash.svelte
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
<script>
|
||||||
|
import { draw } from 'svelte/transition'
|
||||||
|
let duration = 2000
|
||||||
|
let drawing = true
|
||||||
|
let show = false
|
||||||
|
let error = false
|
||||||
|
setTimeout(() => (show = true))
|
||||||
|
setTimeout(() => (drawing = false), 1800)
|
||||||
|
setTimeout(() => (error = true), 5000)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.error {min-height: 100px}
|
||||||
|
.svg {
|
||||||
|
width: 200px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
path {
|
||||||
|
transition: 0.3s ease;
|
||||||
|
stroke-width: 1;
|
||||||
|
stroke: black;
|
||||||
|
stroke-width: 0;
|
||||||
|
}
|
||||||
|
.svg.drawing path {
|
||||||
|
stroke-width: 2;
|
||||||
|
fill-opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="svg" class:drawing>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
style="isolation:isolate"
|
||||||
|
viewBox="0 0 1000 1000">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="_clipPath_40vHZL606H8eXCPAFONHYpjfq1ISybTL">
|
||||||
|
<rect width="1000" height="1000" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g clip-path="url(#_clipPath_40vHZL606H8eXCPAFONHYpjfq1ISybTL)">
|
||||||
|
<linearGradient
|
||||||
|
id="_lgradient_2"
|
||||||
|
x1="-0.011142038971568513"
|
||||||
|
y1="-0.011791871475954507"
|
||||||
|
x2="0.9938039543302696"
|
||||||
|
y2="0.9909604299907665"
|
||||||
|
gradientTransform="matrix(532,0,0,368.749,249,625.251)"
|
||||||
|
gradientUnits="userSpaceOnUse">
|
||||||
|
<stop
|
||||||
|
offset="1.7391304347826086%"
|
||||||
|
stop-opacity="1"
|
||||||
|
style="stop-color:rgb(255,124,247)" />
|
||||||
|
<stop
|
||||||
|
offset="100%"
|
||||||
|
stop-opacity="1"
|
||||||
|
style="stop-color:rgb(255,203,252)" />
|
||||||
|
</linearGradient>
|
||||||
|
{#if show}
|
||||||
|
<path
|
||||||
|
transition:draw|local={{ duration }}
|
||||||
|
d=" M 564.251 625.251 L 659 720 L 700 675 L 781 994 L 457 921 L 506
|
||||||
|
873 L 249 626 L 249 626 L 542.5 626 C 549.812 626 557.065 625.748
|
||||||
|
564.251 625.251 Z "
|
||||||
|
fill="url(#_lgradient_2)" />
|
||||||
|
<linearGradient
|
||||||
|
id="_lgradient_3"
|
||||||
|
x1="0.13056277056277052"
|
||||||
|
y1="0.05232744783306609"
|
||||||
|
x2="0.9350649350649348"
|
||||||
|
y2="0.7710005350454795"
|
||||||
|
gradientTransform="matrix(770,0,0,623,84,3)"
|
||||||
|
gradientUnits="userSpaceOnUse">
|
||||||
|
<stop
|
||||||
|
offset="2.1739130434782608%"
|
||||||
|
stop-opacity="1"
|
||||||
|
style="stop-color:rgb(241,93,232)" />
|
||||||
|
<stop
|
||||||
|
offset="100%"
|
||||||
|
stop-opacity="1"
|
||||||
|
style="stop-color:rgb(184,58,177)" />
|
||||||
|
</linearGradient>
|
||||||
|
<path
|
||||||
|
transition:draw|local={{ duration }}
|
||||||
|
d=" M 542.5 215.388 L 84 215.388 L 203 3 L 542.5 3 L 542.5 3 C
|
||||||
|
714.422 3 854 142.578 854 314.5 C 854 486.422 714.422 626 542.5 626
|
||||||
|
L 249 626 L 364 413.612 L 542.5 413.612 L 542.5 413.612 C 597.201
|
||||||
|
413.612 641.612 369.201 641.612 314.5 C 641.612 259.799 597.201
|
||||||
|
215.388 542.5 215.388 L 542.5 215.388 L 542.5 215.388 Z "
|
||||||
|
fill="url(#_lgradient_3)" />
|
||||||
|
{/if}
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h1 style="">Generating routes...</h1>
|
||||||
|
<div class="error">
|
||||||
|
{#if error}
|
||||||
|
<h3>Your app should probably have loaded by now</h3>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
18
src/pages/example/_components/CrudWidget/Index.svelte
Normal file
18
src/pages/example/_components/CrudWidget/Index.svelte
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<script>
|
||||||
|
import { leftover } from "@roxi/routify";
|
||||||
|
import list from "./_list.svelte";
|
||||||
|
import update from "./_update.svelte";
|
||||||
|
import view from "./_view.svelte";
|
||||||
|
export let data;
|
||||||
|
const components = { list, update, view };
|
||||||
|
|
||||||
|
$: [id, action = "view"] = $leftover.split("/");
|
||||||
|
$: component = (id && components[action]) || list;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div style="width: 512px; margin: auto;" class="card shadow">
|
||||||
|
<h1 style="text-align: center; margin-top: -8px">CrudWidget</h1>
|
||||||
|
<svelte:component this={component} {data} {id} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
25
src/pages/example/_components/CrudWidget/_list.svelte
Normal file
25
src/pages/example/_components/CrudWidget/_list.svelte
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
export let data;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.item {
|
||||||
|
display: inline-block;
|
||||||
|
width: 50%;
|
||||||
|
height: 128px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="items">
|
||||||
|
{#each data as item}
|
||||||
|
<a href={$url('../:id', { id: item.id })} class="item">
|
||||||
|
{#each Object.entries(item).slice(0, 3) as [name, value]}
|
||||||
|
<div>
|
||||||
|
<b>{name}:</b>
|
||||||
|
{value}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
18
src/pages/example/_components/CrudWidget/_update.svelte
Normal file
18
src/pages/example/_components/CrudWidget/_update.svelte
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
export let data, id;
|
||||||
|
$: item = data.filter(item => item.id == id)[0];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div >
|
||||||
|
<div >
|
||||||
|
{#each Object.entries(item) as [name, value]}
|
||||||
|
<div>
|
||||||
|
<b>{name}:</b>
|
||||||
|
<input type="text" {value}>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<a href="{$url('../:id', {id})}">Back</a>
|
||||||
|
</div>
|
||||||
22
src/pages/example/_components/CrudWidget/_view.svelte
Normal file
22
src/pages/example/_components/CrudWidget/_view.svelte
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
export let data = [],
|
||||||
|
id;
|
||||||
|
$: item = data.filter(item => item.id == id)[0];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if item}
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
{#each Object.entries(item) as [name, value]}
|
||||||
|
<div>
|
||||||
|
<b>{name}:</b>
|
||||||
|
{value}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<a href={$url('../', { id })}>[Back]</a>
|
||||||
|
<a href={$url('../:id/update', { id })}>[Update]</a>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
107
src/pages/example/_components/NavLinks.svelte
Normal file
107
src/pages/example/_components/NavLinks.svelte
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
<script>
|
||||||
|
import { url, isActive } from "@roxi/routify";
|
||||||
|
let show = false;
|
||||||
|
const _links = [
|
||||||
|
["/", "⯇ BACK TO APP"],
|
||||||
|
["./index", "Home"],
|
||||||
|
["./modal", "Modal"],
|
||||||
|
["./reset", "Reset"],
|
||||||
|
["./layouts", "Layouts"],
|
||||||
|
["./widget", "Widget"],
|
||||||
|
["./aliasing", "Aliasing"],
|
||||||
|
["./404", "404"],
|
||||||
|
["./api", "Api"],
|
||||||
|
["./app", "App"],
|
||||||
|
["./transitions/tabs", "Transitions"],
|
||||||
|
];
|
||||||
|
|
||||||
|
function handleBurger() {
|
||||||
|
show = !show;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
aside {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.active {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.mobile-nav {
|
||||||
|
font-size: 18px;
|
||||||
|
background: white;
|
||||||
|
padding: 8px;
|
||||||
|
box-shadow: 0px 5px 20px 5px rgba(0, 0, 0, 0.075);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.mobile-nav * {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
|
||||||
|
top: 6px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.burger {
|
||||||
|
font-size: 24px;
|
||||||
|
position: absolute;
|
||||||
|
left: 8px;
|
||||||
|
top: 4px;
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
nav {
|
||||||
|
margin: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0px 5px 20px 5px rgba(0, 0, 0, 0.075);
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
.link {
|
||||||
|
padding: 0 16px;
|
||||||
|
min-width: 56px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<aside>
|
||||||
|
<nav class="mobile-nav">
|
||||||
|
<span class="burger" on:click={handleBurger}>☰</span>
|
||||||
|
<span class="title">Routify Examples</span>
|
||||||
|
<span />
|
||||||
|
</nav>
|
||||||
|
<nav class:show on:click={() => (show = false)}>
|
||||||
|
{#each _links as [path, name]}
|
||||||
|
<a class="link" class:active={$isActive(path)} href={$url(path)}>
|
||||||
|
{name}
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
26
src/pages/example/_components/RenderStatus.svelte
Normal file
26
src/pages/example/_components/RenderStatus.svelte
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script>
|
||||||
|
import { fade } from "svelte/transition";
|
||||||
|
|
||||||
|
let show = true;
|
||||||
|
let render = window.__preRendered ? "prerender" : window.__ssrRendered ? "ssr" : "spa";
|
||||||
|
setTimeout(() => {
|
||||||
|
show = false;
|
||||||
|
}, 3000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.box {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 20px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{#if show}
|
||||||
|
<div transition:fade|local class="box">source: {render}</div>
|
||||||
|
{/if}
|
||||||
6
src/pages/example/_components/RoutifyIntro.svelte
Normal file
6
src/pages/example/_components/RoutifyIntro.svelte
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<h1>Routify Starter</h1>
|
||||||
|
|
||||||
|
To see an example app, go to
|
||||||
|
<a href="/example">/example</a>
|
||||||
|
|
||||||
|
<p>To delete the example app, simply delete the ./src/pages/example folder.</p>
|
||||||
1
src/pages/example/_components/assets/kevin.js
Normal file
1
src/pages/example/_components/assets/kevin.js
Normal file
File diff suppressed because one or more lines are too long
1
src/pages/example/_components/assets/logo.js
Normal file
1
src/pages/example/_components/assets/logo.js
Normal file
File diff suppressed because one or more lines are too long
359
src/pages/example/_data.js
Normal file
359
src/pages/example/_data.js
Normal file
|
|
@ -0,0 +1,359 @@
|
||||||
|
export const todos = [
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 1,
|
||||||
|
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
|
||||||
|
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 2,
|
||||||
|
"title": "qui est esse",
|
||||||
|
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 3,
|
||||||
|
"title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
|
||||||
|
"body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 4,
|
||||||
|
"title": "eum et est occaecati",
|
||||||
|
"body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 5,
|
||||||
|
"title": "nesciunt quas odio",
|
||||||
|
"body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 6,
|
||||||
|
"title": "dolorem eum magni eos aperiam quia",
|
||||||
|
"body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 7,
|
||||||
|
"title": "magnam facilis autem",
|
||||||
|
"body": "dolore placeat quibusdam ea quo vitae\nmagni quis enim qui quis quo nemo aut saepe\nquidem repellat excepturi ut quia\nsunt ut sequi eos ea sed quas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 8,
|
||||||
|
"title": "dolorem dolore est ipsam",
|
||||||
|
"body": "dignissimos aperiam dolorem qui eum\nfacilis quibusdam animi sint suscipit qui sint possimus cum\nquaerat magni maiores excepturi\nipsam ut commodi dolor voluptatum modi aut vitae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 9,
|
||||||
|
"title": "nesciunt iure omnis dolorem tempora et accusantium",
|
||||||
|
"body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 10,
|
||||||
|
"title": "optio molestias id quia eum",
|
||||||
|
"body": "quo et expedita modi cum officia vel magni\ndoloribus qui repudiandae\nvero nisi sit\nquos veniam quod sed accusamus veritatis error"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export const users = [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Leanne Graham",
|
||||||
|
"username": "Bret",
|
||||||
|
"email": "Sincere@april.biz",
|
||||||
|
"address": {
|
||||||
|
"street": "Kulas Light",
|
||||||
|
"suite": "Apt. 556",
|
||||||
|
"city": "Gwenborough",
|
||||||
|
"zipcode": "92998-3874",
|
||||||
|
"geo": {
|
||||||
|
"lat": "-37.3159",
|
||||||
|
"lng": "81.1496"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "1-770-736-8031 x56442",
|
||||||
|
"website": "hildegard.org",
|
||||||
|
"company": {
|
||||||
|
"name": "Romaguera-Crona",
|
||||||
|
"catchPhrase": "Multi-layered client-server neural-net",
|
||||||
|
"bs": "harness real-time e-markets"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Ervin Howell",
|
||||||
|
"username": "Antonette",
|
||||||
|
"email": "Shanna@melissa.tv",
|
||||||
|
"address": {
|
||||||
|
"street": "Victor Plains",
|
||||||
|
"suite": "Suite 879",
|
||||||
|
"city": "Wisokyburgh",
|
||||||
|
"zipcode": "90566-7771",
|
||||||
|
"geo": {
|
||||||
|
"lat": "-43.9509",
|
||||||
|
"lng": "-34.4618"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "010-692-6593 x09125",
|
||||||
|
"website": "anastasia.net",
|
||||||
|
"company": {
|
||||||
|
"name": "Deckow-Crist",
|
||||||
|
"catchPhrase": "Proactive didactic contingency",
|
||||||
|
"bs": "synergize scalable supply-chains"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Clementine Bauch",
|
||||||
|
"username": "Samantha",
|
||||||
|
"email": "Nathan@yesenia.net",
|
||||||
|
"address": {
|
||||||
|
"street": "Douglas Extension",
|
||||||
|
"suite": "Suite 847",
|
||||||
|
"city": "McKenziehaven",
|
||||||
|
"zipcode": "59590-4157",
|
||||||
|
"geo": {
|
||||||
|
"lat": "-68.6102",
|
||||||
|
"lng": "-47.0653"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "1-463-123-4447",
|
||||||
|
"website": "ramiro.info",
|
||||||
|
"company": {
|
||||||
|
"name": "Romaguera-Jacobson",
|
||||||
|
"catchPhrase": "Face to face bifurcated interface",
|
||||||
|
"bs": "e-enable strategic applications"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"name": "Patricia Lebsack",
|
||||||
|
"username": "Karianne",
|
||||||
|
"email": "Julianne.OConner@kory.org",
|
||||||
|
"address": {
|
||||||
|
"street": "Hoeger Mall",
|
||||||
|
"suite": "Apt. 692",
|
||||||
|
"city": "South Elvis",
|
||||||
|
"zipcode": "53919-4257",
|
||||||
|
"geo": {
|
||||||
|
"lat": "29.4572",
|
||||||
|
"lng": "-164.2990"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "493-170-9623 x156",
|
||||||
|
"website": "kale.biz",
|
||||||
|
"company": {
|
||||||
|
"name": "Robel-Corkery",
|
||||||
|
"catchPhrase": "Multi-tiered zero tolerance productivity",
|
||||||
|
"bs": "transition cutting-edge web services"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"name": "Chelsey Dietrich",
|
||||||
|
"username": "Kamren",
|
||||||
|
"email": "Lucio_Hettinger@annie.ca",
|
||||||
|
"address": {
|
||||||
|
"street": "Skiles Walks",
|
||||||
|
"suite": "Suite 351",
|
||||||
|
"city": "Roscoeview",
|
||||||
|
"zipcode": "33263",
|
||||||
|
"geo": {
|
||||||
|
"lat": "-31.8129",
|
||||||
|
"lng": "62.5342"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "(254)954-1289",
|
||||||
|
"website": "demarco.info",
|
||||||
|
"company": {
|
||||||
|
"name": "Keebler LLC",
|
||||||
|
"catchPhrase": "User-centric fault-tolerant solution",
|
||||||
|
"bs": "revolutionize end-to-end systems"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"name": "Mrs. Dennis Schulist",
|
||||||
|
"username": "Leopoldo_Corkery",
|
||||||
|
"email": "Karley_Dach@jasper.info",
|
||||||
|
"address": {
|
||||||
|
"street": "Norberto Crossing",
|
||||||
|
"suite": "Apt. 950",
|
||||||
|
"city": "South Christy",
|
||||||
|
"zipcode": "23505-1337",
|
||||||
|
"geo": {
|
||||||
|
"lat": "-71.4197",
|
||||||
|
"lng": "71.7478"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "1-477-935-8478 x6430",
|
||||||
|
"website": "ola.org",
|
||||||
|
"company": {
|
||||||
|
"name": "Considine-Lockman",
|
||||||
|
"catchPhrase": "Synchronised bottom-line interface",
|
||||||
|
"bs": "e-enable innovative applications"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"name": "Kurtis Weissnat",
|
||||||
|
"username": "Elwyn.Skiles",
|
||||||
|
"email": "Telly.Hoeger@billy.biz",
|
||||||
|
"address": {
|
||||||
|
"street": "Rex Trail",
|
||||||
|
"suite": "Suite 280",
|
||||||
|
"city": "Howemouth",
|
||||||
|
"zipcode": "58804-1099",
|
||||||
|
"geo": {
|
||||||
|
"lat": "24.8918",
|
||||||
|
"lng": "21.8984"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "210.067.6132",
|
||||||
|
"website": "elvis.io",
|
||||||
|
"company": {
|
||||||
|
"name": "Johns Group",
|
||||||
|
"catchPhrase": "Configurable multimedia task-force",
|
||||||
|
"bs": "generate enterprise e-tailers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"name": "Nicholas Runolfsdottir V",
|
||||||
|
"username": "Maxime_Nienow",
|
||||||
|
"email": "Sherwood@rosamond.me",
|
||||||
|
"address": {
|
||||||
|
"street": "Ellsworth Summit",
|
||||||
|
"suite": "Suite 729",
|
||||||
|
"city": "Aliyaview",
|
||||||
|
"zipcode": "45169",
|
||||||
|
"geo": {
|
||||||
|
"lat": "-14.3990",
|
||||||
|
"lng": "-120.7677"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "586.493.6943 x140",
|
||||||
|
"website": "jacynthe.com",
|
||||||
|
"company": {
|
||||||
|
"name": "Abernathy Group",
|
||||||
|
"catchPhrase": "Implemented secondary concept",
|
||||||
|
"bs": "e-enable extensible e-tailers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"name": "Glenna Reichert",
|
||||||
|
"username": "Delphine",
|
||||||
|
"email": "Chaim_McDermott@dana.io",
|
||||||
|
"address": {
|
||||||
|
"street": "Dayna Park",
|
||||||
|
"suite": "Suite 449",
|
||||||
|
"city": "Bartholomebury",
|
||||||
|
"zipcode": "76495-3109",
|
||||||
|
"geo": {
|
||||||
|
"lat": "24.6463",
|
||||||
|
"lng": "-168.8889"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "(775)976-6794 x41206",
|
||||||
|
"website": "conrad.com",
|
||||||
|
"company": {
|
||||||
|
"name": "Yost and Sons",
|
||||||
|
"catchPhrase": "Switchable contextually-based project",
|
||||||
|
"bs": "aggregate real-time technologies"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"name": "Clementina DuBuque",
|
||||||
|
"username": "Moriah.Stanton",
|
||||||
|
"email": "Rey.Padberg@karina.biz",
|
||||||
|
"address": {
|
||||||
|
"street": "Kattie Turnpike",
|
||||||
|
"suite": "Suite 198",
|
||||||
|
"city": "Lebsackbury",
|
||||||
|
"zipcode": "31428-2261",
|
||||||
|
"geo": {
|
||||||
|
"lat": "-38.2386",
|
||||||
|
"lng": "57.2232"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"phone": "024-648-3804",
|
||||||
|
"website": "ambrose.net",
|
||||||
|
"company": {
|
||||||
|
"name": "Hoeger LLC",
|
||||||
|
"catchPhrase": "Centralized empowering task-force",
|
||||||
|
"bs": "target end-to-end models"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
export const posts = [
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 1,
|
||||||
|
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
|
||||||
|
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 2,
|
||||||
|
"title": "qui est esse",
|
||||||
|
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 3,
|
||||||
|
"title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
|
||||||
|
"body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 4,
|
||||||
|
"title": "eum et est occaecati",
|
||||||
|
"body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 5,
|
||||||
|
"title": "nesciunt quas odio",
|
||||||
|
"body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 6,
|
||||||
|
"title": "dolorem eum magni eos aperiam quia",
|
||||||
|
"body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 7,
|
||||||
|
"title": "magnam facilis autem",
|
||||||
|
"body": "dolore placeat quibusdam ea quo vitae\nmagni quis enim qui quis quo nemo aut saepe\nquidem repellat excepturi ut quia\nsunt ut sequi eos ea sed quas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 8,
|
||||||
|
"title": "dolorem dolore est ipsam",
|
||||||
|
"body": "dignissimos aperiam dolorem qui eum\nfacilis quibusdam animi sint suscipit qui sint possimus cum\nquaerat magni maiores excepturi\nipsam ut commodi dolor voluptatum modi aut vitae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 9,
|
||||||
|
"title": "nesciunt iure omnis dolorem tempora et accusantium",
|
||||||
|
"body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userId": 1,
|
||||||
|
"id": 10,
|
||||||
|
"title": "optio molestias id quia eum",
|
||||||
|
"body": "quo et expedita modi cum officia vel magni\ndoloribus qui repudiandae\nvero nisi sit\nquos veniam quod sed accusamus veritatis error"
|
||||||
|
}
|
||||||
|
]
|
||||||
24
src/pages/example/_fallback.svelte
Normal file
24
src/pages/example/_fallback.svelte
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script>
|
||||||
|
import { url } from '@roxi/routify'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.huge {
|
||||||
|
font-size: 12rem;
|
||||||
|
}
|
||||||
|
.e404 {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="e404">
|
||||||
|
<div class="huge">404</div>
|
||||||
|
<div class="big">Page not found.
|
||||||
|
<!-- link to the parent folder of _fallback.svelte -->
|
||||||
|
<a href={$url('../')}>Go back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
54
src/pages/example/_reset.svelte
Normal file
54
src/pages/example/_reset.svelte
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
import NavLinks from "./_components/NavLinks.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.example {
|
||||||
|
background-color: #ffeffe;
|
||||||
|
background-attachment: fixed;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
* :global(.card) {
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
border-width: 1px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
padding: 2rem;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
* :global(.shadow) {
|
||||||
|
box-shadow: 0px 5px 20px 5px rgba(0, 0, 0, 0.075);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
overflow: auto;
|
||||||
|
height: calc(100%);
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Reset files doesn't inherit the parent scope.
|
||||||
|
This ensures that the example app doesn't inherit
|
||||||
|
layouts from the main app. -->
|
||||||
|
<div class="example">
|
||||||
|
<div class="nav">
|
||||||
|
<NavLinks />
|
||||||
|
<!-- we load RenderStatus popup dynamically as it's not
|
||||||
|
important and we don't want to slow down the initial load -->
|
||||||
|
{#await import('./_components/RenderStatus.svelte') then Module}
|
||||||
|
<svelte:component this={Module.default} />
|
||||||
|
{/await}
|
||||||
|
</div>
|
||||||
|
<div class="main">
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
15
src/pages/example/aliasing/_layout.svelte
Normal file
15
src/pages/example/aliasing/_layout.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="text-align: center">
|
||||||
|
<div style="font-weight: bold">
|
||||||
|
<a href={$url('./')}>Aliasing</a> |
|
||||||
|
<a href={$url('./v1')}>V1</a> |
|
||||||
|
<a href={$url('./v1.1')}>V1.1</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
3
src/pages/example/aliasing/index.svelte
Normal file
3
src/pages/example/aliasing/index.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
<p>Pages can redirect to other pages while not changing the current URL.</p>
|
||||||
|
<p>By using _fallback.svelte we can reference whole libraries and modules instead of having to duplicate them.</p>
|
||||||
4
src/pages/example/aliasing/v1.1/_fallback.svelte
Normal file
4
src/pages/example/aliasing/v1.1/_fallback.svelte
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<script>
|
||||||
|
import {goto, leftover} from '@roxi/routify'
|
||||||
|
$goto('../../v1/'+$leftover, null, true, true)
|
||||||
|
</script>
|
||||||
22
src/pages/example/aliasing/v1.1/_layout.svelte
Normal file
22
src/pages/example/aliasing/v1.1/_layout.svelte
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>V1.1 has only one file: feature2.svelte</p>
|
||||||
|
<p>The rest are handled with _fallback.svelte, which redirects to v1</p>
|
||||||
|
|
||||||
|
<code>
|
||||||
|
<pre>
|
||||||
|
/** _fallback.svelte **/
|
||||||
|
import {`{(goto, leftover)}`} from '@roxi/routify'
|
||||||
|
$goto('../../v1/'+$leftover, null, true, true)
|
||||||
|
</pre>
|
||||||
|
</code>
|
||||||
|
|
||||||
|
<a href={$url('./feature1')}>Feature 1</a>
|
||||||
|
<a href={$url('./feature2')}>Feature 2</a>
|
||||||
|
<a href={$url('./feature3')}>Feature 3</a>
|
||||||
|
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
3
src/pages/example/aliasing/v1.1/feature2.svelte
Normal file
3
src/pages/example/aliasing/v1.1/feature2.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>Feature 2</h1>
|
||||||
|
|
||||||
|
<b>v1.1 feature</b>
|
||||||
1
src/pages/example/aliasing/v1.1/index.svelte
Normal file
1
src/pages/example/aliasing/v1.1/index.svelte
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<h1>Welcome to v2</h1>
|
||||||
16
src/pages/example/aliasing/v1/_layout.svelte
Normal file
16
src/pages/example/aliasing/v1/_layout.svelte
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<script>
|
||||||
|
import { url } from '@roxi/routify'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>V1 has three files, which can be seen in the links below </p>
|
||||||
|
|
||||||
|
|
||||||
|
<a href={$url('./feature1')}>Feature 1</a> |
|
||||||
|
<a href={$url('./feature2')}>Feature 2</a> |
|
||||||
|
<a href={$url('./feature3')}>Feature 3</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
3
src/pages/example/aliasing/v1/feature1.svelte
Normal file
3
src/pages/example/aliasing/v1/feature1.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>Feature 1</h1>
|
||||||
|
|
||||||
|
<b>v1 feature</b>
|
||||||
3
src/pages/example/aliasing/v1/feature2.svelte
Normal file
3
src/pages/example/aliasing/v1/feature2.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>Feature 2</h1>
|
||||||
|
|
||||||
|
<b>v1 feature</b>
|
||||||
3
src/pages/example/aliasing/v1/feature3.svelte
Normal file
3
src/pages/example/aliasing/v1/feature3.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>Feature 3</h1>
|
||||||
|
|
||||||
|
<b>v1 feature</b>
|
||||||
1
src/pages/example/aliasing/v1/index.svelte
Normal file
1
src/pages/example/aliasing/v1/index.svelte
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<h1>Welcome to v1</h1>
|
||||||
30
src/pages/example/api/[showId].svelte
Normal file
30
src/pages/example/api/[showId].svelte
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<script>
|
||||||
|
import { ready, url, params } from "@roxi/routify";
|
||||||
|
let series = {};
|
||||||
|
|
||||||
|
$: updateShow($params.showId);
|
||||||
|
|
||||||
|
function updateShow(id) {
|
||||||
|
fetch(`https://api.tvmaze.com/shows/${id}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => {
|
||||||
|
series = json;
|
||||||
|
$ready();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="text-align: center; max-width: 540px; margin: auto">
|
||||||
|
<h4>
|
||||||
|
<a href={$url('./')}>Go back</a>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
{#if series.id}
|
||||||
|
<img src={series.image.medium.replace('http:', 'https:')} alt="cover" style="height: 295px" />
|
||||||
|
<h1>{series.name} ({series.premiered.split('-')[0]})</h1>
|
||||||
|
<p>
|
||||||
|
{@html series.summary}
|
||||||
|
</p>
|
||||||
|
<a href={series.url}>Read more on TVMaze</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
16
src/pages/example/api/_layout.svelte
Normal file
16
src/pages/example/api/_layout.svelte
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<script>
|
||||||
|
const movies = [
|
||||||
|
[32, "Fargo"],
|
||||||
|
[179, "The Wire"],
|
||||||
|
[318, "Community"],
|
||||||
|
[5, "True Detective"],
|
||||||
|
[532, "Scrubs"],
|
||||||
|
[30960, "Cobra Kai"],
|
||||||
|
[530, "Seinfeld"],
|
||||||
|
[347, "It's Always Sunny in Philadelphia"]
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<slot scoped={{movies}}>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
20
src/pages/example/api/index.svelte
Normal file
20
src/pages/example/api/index.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script>
|
||||||
|
import { url, prefetch } from "@roxi/routify";
|
||||||
|
export let scoped;
|
||||||
|
const options = {
|
||||||
|
validFor: 3600 * 24 * 31, // don't refresh assets on the page for a month
|
||||||
|
writeHeaders: true // useful for debugging
|
||||||
|
};
|
||||||
|
const { movies } = scoped;
|
||||||
|
// console.log(movies)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="text-align: center">
|
||||||
|
{#each movies as [showId, title]}
|
||||||
|
<h3>
|
||||||
|
<a use:prefetch={options} href={$url('./:showId', { showId })}>
|
||||||
|
{title}
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
24
src/pages/example/app/_fallback.svelte
Normal file
24
src/pages/example/app/_fallback.svelte
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script>
|
||||||
|
import { url } from '@roxi/routify'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.huge {
|
||||||
|
font-size: 12rem;
|
||||||
|
}
|
||||||
|
.e404 {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="e404">
|
||||||
|
<div class="huge">404</div>
|
||||||
|
<div class="big">Page not found.
|
||||||
|
<!-- link to the parent folder of _fallback.svelte -->
|
||||||
|
<a href={$url('./')}>Go back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
27
src/pages/example/app/_reset.svelte
Normal file
27
src/pages/example/app/_reset.svelte
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<script>
|
||||||
|
import { goto, url } from "@roxi/routify";
|
||||||
|
import { user } from "./_store";
|
||||||
|
|
||||||
|
/** We set the static parameter to true since we don't want to change the browser's URL
|
||||||
|
* Notice the $: prefix which makes the statement reactive. This way if the user logs
|
||||||
|
* out the $goto is called again.
|
||||||
|
* **/
|
||||||
|
$: if (!$user) $goto("./login", {}, true);
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
$user = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $user}
|
||||||
|
<a href={$url('/example')}>Back to examples</a>
|
||||||
|
<a href={$url('./')}>Home</a>
|
||||||
|
<a href={$url('./about')}>About</a>
|
||||||
|
<button on:click={logout} style="position: absolute; right: 24px">
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
|
{/if}
|
||||||
3
src/pages/example/app/_store.js
Normal file
3
src/pages/example/app/_store.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
import {writable} from 'svelte/store'
|
||||||
|
|
||||||
|
export const user = writable(false)
|
||||||
1
src/pages/example/app/index.svelte
Normal file
1
src/pages/example/app/index.svelte
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<h1>Welcome logged in user</h1>
|
||||||
2
src/pages/example/app/login/_reset.svelte
Normal file
2
src/pages/example/app/login/_reset.svelte
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!-- We don't want to inherit the parent layout on the login page, so we use a reset to clear the scope. -->
|
||||||
|
<slot></slot>
|
||||||
40
src/pages/example/app/login/index.svelte
Normal file
40
src/pages/example/app/login/index.svelte
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<script>
|
||||||
|
import { user } from "../_store.js";
|
||||||
|
import { goto, url } from "@roxi/routify";
|
||||||
|
|
||||||
|
let username = "anything";
|
||||||
|
let password = "goes";
|
||||||
|
|
||||||
|
function login() {
|
||||||
|
$user = { username };
|
||||||
|
/** We want to $goto our current location.
|
||||||
|
* Since we're now logged in, we shouldn't be redirected to this login page again.
|
||||||
|
* **/
|
||||||
|
$goto(window.location.href);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="width: 256px; margin: 128px auto; text-align: center">
|
||||||
|
<h1>Login</h1>
|
||||||
|
<input type="text" bind:value={username} />
|
||||||
|
<br />
|
||||||
|
<input type="text" bind:value={password} />
|
||||||
|
<br />
|
||||||
|
<button on:click={login}>Submit</button>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
This login page is actually located at
|
||||||
|
<a href={$url()}>{$url()}</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You are seeing it here, because we're using $goto with the static option
|
||||||
|
enabled. This renders the login page, without changing the URL in the
|
||||||
|
browser.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
On submit, we're "redirected" to the current URL in your browser.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
24
src/pages/example/index.svelte
Normal file
24
src/pages/example/index.svelte
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script>
|
||||||
|
import base64Logo from "./_components/assets/logo.js";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- routify:option name="example-app" -->
|
||||||
|
|
||||||
|
<div style="width: 100%; text-align: center; margin-top: 4rem;">
|
||||||
|
<img src="data:image/png;base64, {base64Logo}" alt="logo" style="max-width: 100%; padding-bottom: 128px" />
|
||||||
|
<div>
|
||||||
|
<b>Guide:</b>
|
||||||
|
<br />
|
||||||
|
<a href="https://routify.dev">https://routify.dev</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<b>This template:</b>
|
||||||
|
<br />
|
||||||
|
<a href="https://github.com/roxiness/routify-starter">
|
||||||
|
https://github.com/roxiness/routify-starter
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
30
src/pages/example/layouts/_layout.svelte
Normal file
30
src/pages/example/layouts/_layout.svelte
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.layout-container :global(.card) {
|
||||||
|
width: 66%;
|
||||||
|
margin: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0px 5px 20px 5px rgba(0, 0, 0, 0.075);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
* > :global(.layout-container) {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div >
|
||||||
|
<div class="layout-container">
|
||||||
|
<div class="card">
|
||||||
|
<a href={$url('./child')}>Child</a>
|
||||||
|
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
15
src/pages/example/layouts/child/_layout.svelte
Normal file
15
src/pages/example/layouts/child/_layout.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="layout-container">
|
||||||
|
<div class="card">
|
||||||
|
<a href={$url('./grandchild')}>Grandchild</a>
|
||||||
|
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
13
src/pages/example/layouts/child/grandchild/_layout.svelte
Normal file
13
src/pages/example/layouts/child/grandchild/_layout.svelte
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="layout-container">
|
||||||
|
<div class="card">
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
3
src/pages/example/layouts/child/grandchild/index.svelte
Normal file
3
src/pages/example/layouts/child/grandchild/index.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div style="text-align: center">
|
||||||
|
<h4>I'm src/pages/example/nesting/child/grandchild/index.svelte</h4>
|
||||||
|
</div>
|
||||||
3
src/pages/example/layouts/child/index.svelte
Normal file
3
src/pages/example/layouts/child/index.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div style="text-align: center">
|
||||||
|
<h1>I'm src/pages/example/nesting/child/index.svelte</h1>
|
||||||
|
</div>
|
||||||
3
src/pages/example/layouts/index.svelte
Normal file
3
src/pages/example/layouts/index.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div style="text-align: center">
|
||||||
|
<h1>I'm src/pages/example/nesting/index.svelte</h1>
|
||||||
|
</div>
|
||||||
74
src/pages/example/modal/_layout.svelte
Normal file
74
src/pages/example/modal/_layout.svelte
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
<script>
|
||||||
|
import { url, route } from "@roxi/routify";
|
||||||
|
|
||||||
|
$: match = $route.path.match(/\/modal\/([^\/]+)\//);
|
||||||
|
$: active = match && match[1];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* :global(.cards) {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
* :global(.card) {
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
border-width: 1px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
padding: 2rem;
|
||||||
|
background: white;
|
||||||
|
list-style: none;
|
||||||
|
width: 25%;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
* :global(.container) {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
padding-top: 5rem;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
* :global(.modal) {
|
||||||
|
margin: auto;
|
||||||
|
background: white;
|
||||||
|
font-size: 5rem;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
width: 30%;
|
||||||
|
padding-top: 3rem;
|
||||||
|
padding-bottom: 3rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.active {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div data-routify="scroll-lock">
|
||||||
|
|
||||||
|
<div class="center">
|
||||||
|
<a href={$url('./basic')} class={active === 'basic' ? 'active' : ''}>
|
||||||
|
Basic
|
||||||
|
</a>
|
||||||
|
<a href={$url('./animated')} class={active === 'animated' ? 'active' : ''}>
|
||||||
|
Animated
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
14
src/pages/example/modal/animated/[key].svelte
Normal file
14
src/pages/example/modal/animated/[key].svelte
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script>
|
||||||
|
import { goto } from "@roxi/routify";
|
||||||
|
export let scoped
|
||||||
|
$: ({ send, receive, key } = scoped);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container" on:click={() => $goto('./')} >
|
||||||
|
<div
|
||||||
|
class="modal"
|
||||||
|
in:receive|local={{ key: 'modal' }}
|
||||||
|
out:send|local={{ key: 'modal' }}>
|
||||||
|
{key}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
21
src/pages/example/modal/animated/_layout.svelte
Normal file
21
src/pages/example/modal/animated/_layout.svelte
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script>
|
||||||
|
import { url, context, afterPageLoad } from "@roxi/routify";
|
||||||
|
import { crossfade, fade } from "svelte/transition";
|
||||||
|
import Target from "./_target.svelte";
|
||||||
|
|
||||||
|
const [send, receive] = crossfade({});
|
||||||
|
$: _key = $context.child && $context.child.params.key
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="cards">
|
||||||
|
{#each Array(12) as item, key}
|
||||||
|
<a class="card" href={$url('./:key', { key })} style="background: #333">
|
||||||
|
<!-- <Target/> is a placeholder that takes the size of its parent element.
|
||||||
|
If a modal is show and its key matches this cards key, <Target/> is hidden.
|
||||||
|
This triggers the modal transition. -->
|
||||||
|
<Target {receive} {send} hide={key == _key} />
|
||||||
|
<div class="content" style="color: white">{key}</div>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<slot scoped={{ send, receive, fade, key: _key }} />
|
||||||
21
src/pages/example/modal/animated/_target.svelte
Normal file
21
src/pages/example/modal/animated/_target.svelte
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script>
|
||||||
|
export let send, receive, hide;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.canvas {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{#if !hide}
|
||||||
|
<div
|
||||||
|
class="canvas"
|
||||||
|
in:receive|local={{ key: 'modal' }}
|
||||||
|
out:send|local={{ key: 'modal' }} />
|
||||||
|
{/if}
|
||||||
0
src/pages/example/modal/animated/index.svelte
Normal file
0
src/pages/example/modal/animated/index.svelte
Normal file
11
src/pages/example/modal/basic/[key].svelte
Normal file
11
src/pages/example/modal/basic/[key].svelte
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script>
|
||||||
|
import { goto, url } from "@roxi/routify";
|
||||||
|
export let key
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container" on:click={() => $goto('./')} >
|
||||||
|
<div class="modal" >
|
||||||
|
{key}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
15
src/pages/example/modal/basic/_layout.svelte
Normal file
15
src/pages/example/modal/basic/_layout.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script>
|
||||||
|
import { url, params } from "@roxi/routify";
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="cards">
|
||||||
|
{#each Array(12) as item, key}
|
||||||
|
<a class="card" href={$url('./:key', { key })}>
|
||||||
|
<div class="content">{key}</div>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot />
|
||||||
0
src/pages/example/modal/basic/index.svelte
Normal file
0
src/pages/example/modal/basic/index.svelte
Normal file
0
src/pages/example/modal/index.svelte
Normal file
0
src/pages/example/modal/index.svelte
Normal file
24
src/pages/example/reset/_fallback.svelte
Normal file
24
src/pages/example/reset/_fallback.svelte
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script>
|
||||||
|
import { url } from '@roxi/routify'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.huge {
|
||||||
|
font-size: 12rem;
|
||||||
|
}
|
||||||
|
.e404 {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="e404">
|
||||||
|
<div class="huge">404</div>
|
||||||
|
<div class="big">Page not found.
|
||||||
|
<!-- link to the parent folder of _fallback.svelte -->
|
||||||
|
<a href={$url('../')}>Go back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
3
src/pages/example/reset/_reset.svelte
Normal file
3
src/pages/example/reset/_reset.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<slot>
|
||||||
|
<!-- optional fallback -->
|
||||||
|
</slot>
|
||||||
20
src/pages/example/reset/index.svelte
Normal file
20
src/pages/example/reset/index.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script>
|
||||||
|
import { url } from '@roxi/routify'
|
||||||
|
import base64Kevin from "../_components/assets/kevin.js";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.center {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<img src="data:image/png;base64, {base64Kevin}" alt="KEVIN!" class="center" />
|
||||||
|
|
||||||
|
<a href={$url('../../')}>Go back</a>
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<script>
|
||||||
|
import { url, isActive } from "@roxi/routify";
|
||||||
|
export let urls, height;
|
||||||
|
let linkElems = [];
|
||||||
|
let overlay;
|
||||||
|
let clientWidth
|
||||||
|
$: urlsWithElem = linkElems.map((elem, i) => ({ ...urls[i], elem }));
|
||||||
|
$: activeUrl = urlsWithElem.find(({active}) => active)
|
||||||
|
$: if (overlay && clientWidth && activeUrl) copyDimensions(activeUrl.elem, overlay);
|
||||||
|
$: color = activeUrl && activeUrl.color
|
||||||
|
|
||||||
|
function copyDimensions(source, target) {
|
||||||
|
target.style.left = source.offsetLeft + "px";
|
||||||
|
target.style.top = source.offsetTop + "px";
|
||||||
|
target.style.width = source.clientWidth + "px";
|
||||||
|
target.style.height = source.clientHeight + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveElement = el => (linkElems = [...linkElems, el]);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
nav {
|
||||||
|
width: 100%;
|
||||||
|
background: white;
|
||||||
|
display: flex;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
box-shadow: 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
padding: 0 16px;
|
||||||
|
line-height: 100%;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #aaa;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-decoration: none;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
transition: all 0.8s;
|
||||||
|
/* transition-delay: 0.05s */
|
||||||
|
}
|
||||||
|
a.active {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
/* background: #555; */
|
||||||
|
transition: 0.3s all;
|
||||||
|
background: linear-gradient(
|
||||||
|
rgba(0, 0, 0, 0.15),
|
||||||
|
rgba(0, 0, 0, 0.15)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<nav bind:clientWidth>
|
||||||
|
{#each urls as { name, path, active, href }, i}
|
||||||
|
<a
|
||||||
|
style="line-height: {height}"
|
||||||
|
{href}
|
||||||
|
class:active
|
||||||
|
use:saveElement>
|
||||||
|
{name}
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
<div class="overlay" bind:this={overlay} style="background-color: {color}" />
|
||||||
|
</nav>
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<script>
|
||||||
|
import { scale, fly } from "svelte/transition";
|
||||||
|
import { route } from "@roxi/routify";
|
||||||
|
import { Transition } from "@roxi/routify/decorators";
|
||||||
|
|
||||||
|
export let scoped;
|
||||||
|
const { width } = scoped;
|
||||||
|
|
||||||
|
const configs = [
|
||||||
|
{
|
||||||
|
// New and old route are identical, do nothing
|
||||||
|
condition: ({ routes }) => routes[0] === routes[1],
|
||||||
|
transition: () => {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: c => c.toAncestor,
|
||||||
|
transition: scale,
|
||||||
|
inParams: { start: 1.2 },
|
||||||
|
outParams: { start: 0.8 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: c => c.toDescendant,
|
||||||
|
transition: scale,
|
||||||
|
inParams: { start: 0.8 },
|
||||||
|
outParams: { start: 1.2 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: c => c.toHigherIndex,
|
||||||
|
transition: fly,
|
||||||
|
inParams: { x: $width, duration: 500 },
|
||||||
|
outParams: { x: -$width, duration: 500 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
condition: c => c.toLowerIndex,
|
||||||
|
transition: fly,
|
||||||
|
inParams: { x: -$width, duration: 500 },
|
||||||
|
outParams: { x: $width, duration: 500 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// No matching config. We don't want a transition
|
||||||
|
condition: () => true,
|
||||||
|
transition: () => {}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Transition {configs}>
|
||||||
|
<slot />
|
||||||
|
</Transition>
|
||||||
58
src/pages/example/transitions/tabs/_reset.svelte
Normal file
58
src/pages/example/transitions/tabs/_reset.svelte
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script>
|
||||||
|
import { TabsTransition } from "@roxi/routify/decorators";
|
||||||
|
import BottomNav from "./_components/BottomNav.svelte";
|
||||||
|
import { url, isActive } from "@roxi/routify";
|
||||||
|
|
||||||
|
const _urls = [
|
||||||
|
["./home", "Home", "#7fc5bb"],
|
||||||
|
["./feed", "Feed", "#0bf5cc"],
|
||||||
|
["./updates", "Updates", "#88f0d0"],
|
||||||
|
["./settings", "Settings", "#a1fac3"],
|
||||||
|
];
|
||||||
|
$: urls = _urls.map(([path, name, color]) => ({
|
||||||
|
name,
|
||||||
|
href: $url(path),
|
||||||
|
color,
|
||||||
|
active: !!$isActive(path),
|
||||||
|
}));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global(body) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
* :global(.inset) {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
main.inset {
|
||||||
|
bottom: 64px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
* :global(*) {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background: #555;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div style="height: 100%">
|
||||||
|
<main class="inset">
|
||||||
|
<slot decorator={TabsTransition} />
|
||||||
|
</main>
|
||||||
|
<BottomNav {urls} height="64px" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href={$url('../../')}>Back to examples</a>
|
||||||
|
|
||||||
|
<!-- routify:options bundle=true -->
|
||||||
20
src/pages/example/transitions/tabs/feed/[id]/index.svelte
Normal file
20
src/pages/example/transitions/tabs/feed/[id]/index.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script>
|
||||||
|
export let id;
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
a {
|
||||||
|
font-size: 1.5em;
|
||||||
|
padding: 12px 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="card" style="width: 512px;">
|
||||||
|
<h1>{id}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<a href={$url('../../home')}>Go home</a>
|
||||||
|
<a href={$url('../')}>Go back</a>
|
||||||
19
src/pages/example/transitions/tabs/feed/_layout.svelte
Normal file
19
src/pages/example/transitions/tabs/feed/_layout.svelte
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
background: #0bf5cc;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
* :global(.card) {
|
||||||
|
background: white;
|
||||||
|
width: 256px;
|
||||||
|
height: 256px;
|
||||||
|
display: inline-block;
|
||||||
|
box-shadow: 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
margin: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- routify:options index=1 -->
|
||||||
|
<main>
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
13
src/pages/example/transitions/tabs/feed/index.svelte
Normal file
13
src/pages/example/transitions/tabs/feed/index.svelte
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import { url } from "@roxi/routify";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="padding-top: 20px">
|
||||||
|
<h1>Feed</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#each new Array(10) as item, id}
|
||||||
|
<a class="card" href={$url('./:id', { id })}>
|
||||||
|
<h3 class="item">{id}</h3>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
13
src/pages/example/transitions/tabs/home.svelte
Normal file
13
src/pages/example/transitions/tabs/home.svelte
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
background: #7fc5bb;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- routify:options index=0 -->
|
||||||
|
<main>
|
||||||
|
<br />
|
||||||
|
<h1>Home</h1>
|
||||||
|
</main>
|
||||||
4
src/pages/example/transitions/tabs/index.svelte
Normal file
4
src/pages/example/transitions/tabs/index.svelte
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<script>
|
||||||
|
import { redirect } from '@roxi/routify'
|
||||||
|
$redirect('./home')
|
||||||
|
</script>
|
||||||
12
src/pages/example/transitions/tabs/settings.svelte
Normal file
12
src/pages/example/transitions/tabs/settings.svelte
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
background: #a1fac3;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- routify:options index=3 -->
|
||||||
|
<main>
|
||||||
|
<br>
|
||||||
|
<h1>Settings</h1>
|
||||||
|
</main>
|
||||||
14
src/pages/example/transitions/tabs/updates.svelte
Normal file
14
src/pages/example/transitions/tabs/updates.svelte
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
background: #88F0D0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- routify:options index=2 -->
|
||||||
|
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<br />
|
||||||
|
<h1>Updates</h1>
|
||||||
|
</main>
|
||||||
16
src/pages/example/widget/_fallback.svelte
Normal file
16
src/pages/example/widget/_fallback.svelte
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<script>
|
||||||
|
import CrudWidget from "../_components/CrudWidget/Index.svelte";
|
||||||
|
import { users } from "../_data";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="text-align: center">
|
||||||
|
<p>
|
||||||
|
By using a _fallback.svelte in example/widget, we can grab the leftover URL
|
||||||
|
and pass it to an embedded widget.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Alternatively, the widget can grab the leftover URL itself.</p>
|
||||||
|
<p>This allows for reusable navigable components.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CrudWidget data={users} />
|
||||||
10
src/pages/index.svelte
Normal file
10
src/pages/index.svelte
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<script>
|
||||||
|
import { metatags } from '@roxi/routify'
|
||||||
|
import { chart } from "../chart";
|
||||||
|
metatags.title = 'My Routify app'
|
||||||
|
metatags.description = 'Description coming soon...'
|
||||||
|
|
||||||
|
var opts = {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div use:chart={opts} />
|
||||||
108
src/sw.js
Normal file
108
src/sw.js
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import { registerRoute, setDefaultHandler, setCatchHandler } from 'workbox-routing';
|
||||||
|
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
|
||||||
|
import { skipWaiting, clientsClaim } from 'workbox-core';
|
||||||
|
import { precacheAndRoute, matchPrecache } from 'workbox-precaching';
|
||||||
|
import { ExpirationPlugin } from 'workbox-expiration';
|
||||||
|
import { RoutifyPlugin, freshCacheData } from '@roxi/routify/workbox-plugin'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********
|
||||||
|
* CONFIG *
|
||||||
|
**********/
|
||||||
|
|
||||||
|
const entrypointUrl = '__app.html' // entrypoint
|
||||||
|
const fallbackImage = '404.svg'
|
||||||
|
const files = self.__WB_MANIFEST // files matching globDirectory and globPattern in rollup.config.js
|
||||||
|
|
||||||
|
const externalAssetsConfig = () => ({
|
||||||
|
cacheName: 'external',
|
||||||
|
plugins: [
|
||||||
|
RoutifyPlugin({
|
||||||
|
validFor: 60 // cache is considered fresh for n seconds.
|
||||||
|
}),
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 50, // last used entries will be purged when we hit this limit
|
||||||
|
purgeOnQuotaError: true // purge external assets on quota error
|
||||||
|
})]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**************
|
||||||
|
* INITIALIZE *
|
||||||
|
**************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* precache all files
|
||||||
|
* remember to precache __app.html and 404.svg if caching of all files is disabled
|
||||||
|
*/
|
||||||
|
precacheAndRoute(files)
|
||||||
|
|
||||||
|
/** precache only fallback files */
|
||||||
|
// precacheAndRoute(files.filter(file =>
|
||||||
|
// ['__app.html', '404.svg']
|
||||||
|
// .includes(file.url)
|
||||||
|
// ))
|
||||||
|
|
||||||
|
skipWaiting() // auto update service workers across all tabs when new release is available
|
||||||
|
clientsClaim() // take control of client without having to wait for refresh
|
||||||
|
|
||||||
|
/**
|
||||||
|
* manually upgrade service worker by sending a SKIP_WAITING message.
|
||||||
|
* (remember to disable skipWaiting() above)
|
||||||
|
*/
|
||||||
|
// addEventListener('message', event => { if (event.data && event.data.type === 'SKIP_WAITING') skipWaiting(); });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********
|
||||||
|
* ROUTES *
|
||||||
|
**********/
|
||||||
|
|
||||||
|
// serve local pages from the SPA entry point (__app.html)
|
||||||
|
registerRoute(isLocalPage, matchPrecache(entrypointUrl))
|
||||||
|
|
||||||
|
// serve local assets from cache first
|
||||||
|
registerRoute(isLocalAsset, new CacheFirst())
|
||||||
|
|
||||||
|
// serve external assets from cache if they're fresh
|
||||||
|
registerRoute(hasFreshCache, new CacheFirst(externalAssetsConfig()))
|
||||||
|
|
||||||
|
// serve external pages and assets
|
||||||
|
setDefaultHandler(new NetworkFirst(externalAssetsConfig()));
|
||||||
|
|
||||||
|
// serve a fallback for 404s if possible or respond with an error
|
||||||
|
setCatchHandler(async ({ event }) => {
|
||||||
|
switch (event.request.destination) {
|
||||||
|
case 'document':
|
||||||
|
return await matchPrecache(entrypointUrl)
|
||||||
|
case 'image':
|
||||||
|
return await matchPrecache(fallbackImage)
|
||||||
|
default:
|
||||||
|
return Response.error();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********
|
||||||
|
* CONDITIONS *
|
||||||
|
**********/
|
||||||
|
|
||||||
|
function isLocalAsset({ url, request }) { return url.host === self.location.host && request.destination != 'document' }
|
||||||
|
function isLocalPage({ url, request }) { return url.host === self.location.host && request.destination === 'document' }
|
||||||
|
function hasFreshCache(event) { return !!freshCacheData(event) }
|
||||||
|
|
||||||
|
/** Example condition */
|
||||||
|
function hasWitheringCache(event) {
|
||||||
|
const cache = freshCacheData(event)
|
||||||
|
if (cache) {
|
||||||
|
const { cachedAt, validFor, validLeft, validUntil } = cache
|
||||||
|
// return true if half the fresh time has passed
|
||||||
|
return validFor / 2 > validFor - validLeft
|
||||||
|
}
|
||||||
|
}
|
||||||
17
vercel.json
Normal file
17
vercel.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"functions": {
|
||||||
|
"api/vercel-ssr/index.js": {
|
||||||
|
"includeFiles": "dist/**"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": "filesystem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/.*",
|
||||||
|
"dest": "/api/vercel-ssr/index.js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue