mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-12 03:05:12 +00:00
Add support for custom route file extensions.
This commit is contained in:
60
test/apps/custom-extension/rollup.config.js
Normal file
60
test/apps/custom-extension/rollup.config.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import replace from 'rollup-plugin-replace';
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
|
||||
const mode = process.env.NODE_ENV;
|
||||
const dev = mode === 'development';
|
||||
|
||||
const config = require('../../../config/rollup.js');
|
||||
|
||||
export default {
|
||||
client: {
|
||||
input: config.client.input(),
|
||||
output: config.client.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||
}),
|
||||
svelte({
|
||||
extensions: ['.whokilledthemuffinman', '.jesuslivesineveryone', '.mdx', '.svelte', '.html'],
|
||||
dev,
|
||||
hydratable: true,
|
||||
emitCss: true
|
||||
}),
|
||||
resolve()
|
||||
]
|
||||
},
|
||||
|
||||
server: {
|
||||
input: config.server.input(),
|
||||
output: config.server.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
'process.browser': false,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||
}),
|
||||
svelte({
|
||||
extensions: ['.whokilledthemuffinman', '.jesuslivesineveryone', '.mdx', '.svelte', '.html'],
|
||||
generate: 'ssr',
|
||||
dev
|
||||
}),
|
||||
resolve({
|
||||
preferBuiltins: true
|
||||
})
|
||||
],
|
||||
external: ['sirv', 'polka']
|
||||
},
|
||||
|
||||
serviceworker: {
|
||||
input: config.serviceworker.input(),
|
||||
output: config.serviceworker.output(),
|
||||
plugins: [
|
||||
resolve(),
|
||||
replace({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||
})
|
||||
]
|
||||
}
|
||||
};
|
||||
9
test/apps/custom-extension/src/client.js
Normal file
9
test/apps/custom-extension/src/client.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as sapper from '@sapper/app';
|
||||
|
||||
window.start = () => sapper.start({
|
||||
target: document.querySelector('#sapper')
|
||||
});
|
||||
|
||||
window.prefetchRoutes = () => sapper.prefetchRoutes();
|
||||
window.prefetch = href => sapper.prefetch(href);
|
||||
window.goto = href => sapper.goto(href);
|
||||
6
test/apps/custom-extension/src/routes/[slug].mdx
Normal file
6
test/apps/custom-extension/src/routes/[slug].mdx
Normal file
@@ -0,0 +1,6 @@
|
||||
<script>
|
||||
import { stores } from '@sapper/app';
|
||||
const { page } = stores();
|
||||
</script>
|
||||
|
||||
<h1>{$page.params.slug.toUpperCase()}</h1>
|
||||
3
test/apps/custom-extension/src/routes/_error.svelte
Normal file
3
test/apps/custom-extension/src/routes/_error.svelte
Normal file
@@ -0,0 +1,3 @@
|
||||
<h1>hi</h1>
|
||||
|
||||
<p>hi</p>
|
||||
1
test/apps/custom-extension/src/routes/a.svelte
Normal file
1
test/apps/custom-extension/src/routes/a.svelte
Normal file
@@ -0,0 +1 @@
|
||||
<h1>a</h1>
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Tremendous!</h1>
|
||||
@@ -0,0 +1,8 @@
|
||||
<h1>Great success!</h1>
|
||||
|
||||
<a href="a">a</a>
|
||||
<a href="ambiguous/ok.json">ok</a>
|
||||
<a href="echo-query?message">ok</a>
|
||||
<a href="echo-query?p=one&p=two">ok</a>
|
||||
|
||||
<div class='hydrate-test'></div>
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Bazooom!</h1>
|
||||
9
test/apps/custom-extension/src/server.js
Normal file
9
test/apps/custom-extension/src/server.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import polka from 'polka';
|
||||
import * as sapper from '@sapper/server';
|
||||
|
||||
import { start } from '../../common.js';
|
||||
|
||||
const app = polka()
|
||||
.use(sapper.middleware())
|
||||
|
||||
start(app);
|
||||
81
test/apps/custom-extension/src/service-worker.js
Normal file
81
test/apps/custom-extension/src/service-worker.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import * as sapper from '@sapper/service-worker';
|
||||
|
||||
const ASSETS = `cache${sapper.timestamp}`;
|
||||
|
||||
// `app.shell` is an array of all the files generated by webpack,
|
||||
// `app.files` is an array of everything in the `static` directory
|
||||
const to_cache = sapper.shell.concat(sapper.files);
|
||||
const cached = new Set(to_cache);
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches
|
||||
.open(ASSETS)
|
||||
.then(cache => cache.addAll(to_cache))
|
||||
.then(() => {
|
||||
self.skipWaiting();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(async keys => {
|
||||
// delete old caches
|
||||
for (const key of keys) {
|
||||
if (key !== ASSETS) await caches.delete(key);
|
||||
}
|
||||
|
||||
self.clients.claim();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
if (event.request.method !== 'GET') return;
|
||||
|
||||
const url = new URL(event.request.url);
|
||||
|
||||
// don't try to handle e.g. data: URIs
|
||||
if (!url.protocol.startsWith('http')) return;
|
||||
|
||||
// ignore dev server requests
|
||||
if (url.hostname === self.location.hostname && url.port !== self.location.port) return;
|
||||
|
||||
// always serve assets and webpack-generated files from cache
|
||||
if (url.host === self.location.host && cached.has(url.pathname)) {
|
||||
event.respondWith(caches.match(event.request));
|
||||
return;
|
||||
}
|
||||
|
||||
// for pages, you might want to serve a shell `index.html` file,
|
||||
// which Sapper has generated for you. It's not right for every
|
||||
// app, but if it's right for yours then uncomment this section
|
||||
/*
|
||||
event.respondWith(caches.match('/index.html'));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if (event.request.cache === 'only-if-cached') return;
|
||||
|
||||
// for everything else, try the network first, falling back to
|
||||
// cache if the user is offline. (If the pages never change, you
|
||||
// might prefer a cache-first approach to a network-first one.)
|
||||
event.respondWith(
|
||||
caches
|
||||
.open(`offline${sapper.timestamp}`)
|
||||
.then(async cache => {
|
||||
try {
|
||||
const response = await fetch(event.request);
|
||||
cache.put(event.request, response.clone());
|
||||
return response;
|
||||
} catch(err) {
|
||||
const response = await cache.match(event.request);
|
||||
if (response) return response;
|
||||
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
14
test/apps/custom-extension/src/template.html
Normal file
14
test/apps/custom-extension/src/template.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
|
||||
%sapper.base%
|
||||
%sapper.styles%
|
||||
%sapper.head%
|
||||
</head>
|
||||
<body>
|
||||
<div id='sapper'>%sapper.html%</div>
|
||||
%sapper.scripts%
|
||||
</body>
|
||||
</html>
|
||||
61
test/apps/custom-extension/test.ts
Normal file
61
test/apps/custom-extension/test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import * as assert from 'assert';
|
||||
import { build } from '../../../api';
|
||||
import { AppRunner } from '../AppRunner';
|
||||
|
||||
describe('custom extensions', function() {
|
||||
this.timeout(10000);
|
||||
|
||||
let r: AppRunner;
|
||||
|
||||
// hooks
|
||||
before('build app', () => build({ cwd: __dirname , ext: '.jesuslivesineveryone .whokilledthemuffinman .mdx .svelte' }));
|
||||
before('start runner', async () => {
|
||||
r = await new AppRunner().start(__dirname);
|
||||
});
|
||||
|
||||
after(() => r && r.end());
|
||||
|
||||
|
||||
|
||||
it('works with arbitrary extensions', async () => {
|
||||
await r.load(`/`);
|
||||
|
||||
|
||||
assert.equal(
|
||||
await r.text('h1'),
|
||||
'Great success!'
|
||||
);
|
||||
});
|
||||
|
||||
it('works with other arbitrary extensions', async () => {
|
||||
await r.load(`/const`);
|
||||
|
||||
assert.equal(
|
||||
await r.text('h1'),
|
||||
'Tremendous!'
|
||||
);
|
||||
|
||||
await r.load(`/a`);
|
||||
|
||||
assert.equal(
|
||||
await r.text('h1'),
|
||||
'a'
|
||||
);
|
||||
|
||||
await r.load(`/test-slug`);
|
||||
|
||||
assert.equal(
|
||||
await r.text('h1'),
|
||||
'TEST-SLUG'
|
||||
);
|
||||
|
||||
await r.load(`/unsafe-replacement`);
|
||||
|
||||
assert.equal(
|
||||
await r.text('h1'),
|
||||
'Bazooom!'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -177,4 +177,66 @@ describe('manifest_data', () => {
|
||||
pattern: /^\/foo\/?$/
|
||||
}]);
|
||||
});
|
||||
|
||||
it('works with custom extensions' , () => {
|
||||
const { components, pages, server_routes } = create_manifest_data(path.join(__dirname, 'samples/custom-extension'), '.jazz .beebop .funk .html');
|
||||
|
||||
const index = { name: 'index', file: 'index.funk', has_preload: false };
|
||||
const about = { name: 'about', file: 'about.jazz', has_preload: false };
|
||||
const blog = { name: 'blog', file: 'blog/index.html', has_preload: false };
|
||||
const blog_$slug = { name: 'blog_$slug', file: 'blog/[slug].beebop', has_preload: false };
|
||||
|
||||
assert.deepEqual(components, [
|
||||
index,
|
||||
about,
|
||||
blog,
|
||||
blog_$slug
|
||||
]);
|
||||
|
||||
assert.deepEqual(pages, [
|
||||
{
|
||||
pattern: /^\/$/,
|
||||
parts: [
|
||||
{ component: index, params: [] }
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
pattern: /^\/about\/?$/,
|
||||
parts: [
|
||||
{ component: about, params: [] }
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
pattern: /^\/blog\/?$/,
|
||||
parts: [
|
||||
{ component: blog, params: [] }
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
pattern: /^\/blog\/([^\/]+?)\/?$/,
|
||||
parts: [
|
||||
null,
|
||||
{ component: blog_$slug, params: ['slug'] }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.deepEqual(server_routes, [
|
||||
{
|
||||
name: 'route_blog_json',
|
||||
pattern: /^\/blog.json$/,
|
||||
file: 'blog/index.json.js',
|
||||
params: []
|
||||
},
|
||||
{
|
||||
name: 'route_blog_$slug_json',
|
||||
pattern: /^\/blog\/([^\/]+?).json$/,
|
||||
file: 'blog/[slug].json.js',
|
||||
params: ['slug']
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user