mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-13 19:45:26 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e8ed6612c | ||
|
|
5ec748b95d | ||
|
|
64b16715cd | ||
|
|
9ea5e5e251 | ||
|
|
68b78f56d6 | ||
|
|
68e93a8fa0 | ||
|
|
99ae39b8a8 | ||
|
|
1b489f4687 | ||
|
|
91f2c6e49c | ||
|
|
f5e07e9f78 | ||
|
|
17297a9794 | ||
|
|
9ef4f33e38 | ||
|
|
30966ee7f2 | ||
|
|
ae90f774e1 | ||
|
|
0706b5f50a |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,5 +1,20 @@
|
|||||||
# sapper changelog
|
# sapper changelog
|
||||||
|
|
||||||
|
## 0.20.2
|
||||||
|
|
||||||
|
* Add `immutable` cache control header for hashed assets ([#425](https://github.com/sveltejs/sapper/pull/425))
|
||||||
|
* Handle value-less query string params ([#426](https://github.com/sveltejs/sapper/issues/426))
|
||||||
|
|
||||||
|
## 0.20.1
|
||||||
|
|
||||||
|
* Update shimport
|
||||||
|
|
||||||
|
## 0.20.0
|
||||||
|
|
||||||
|
* Decode `req.params` and `req.query` ([#417](https://github.com/sveltejs/sapper/issues/417))
|
||||||
|
* Decode URLs before writing files in `sapper export` ([#414](https://github.com/sveltejs/sapper/pull/414))
|
||||||
|
* Generate server sourcemaps for Rollup apps in dev mode ([#418](https://github.com/sveltejs/sapper/pull/418))
|
||||||
|
|
||||||
## 0.19.3
|
## 0.19.3
|
||||||
|
|
||||||
* Better unicode route handling ([#347](https://github.com/sveltejs/sapper/issues/347))
|
* Better unicode route handling ([#347](https://github.com/sveltejs/sapper/issues/347))
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<svelte:component this={child.component} {...child.props}/>
|
|
||||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sapper",
|
"name": "sapper",
|
||||||
"version": "0.19.0",
|
"version": "0.20.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -6287,9 +6287,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shimport": {
|
"shimport": {
|
||||||
"version": "0.0.10",
|
"version": "0.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/shimport/-/shimport-0.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/shimport/-/shimport-0.0.11.tgz",
|
||||||
"integrity": "sha512-3xPFDLmcLj87sx0OwA60qbloMQUsu6VGF97IG4RqxTf91sGeiaaXOPxM1PoQHbaTm4TOhH8zosokqLAZtuNGnA=="
|
"integrity": "sha512-wRlG/wMuV/czrzJEWBUPjydU/Ve0kTrTH8wHLRjuY6S2BDB+qDDXkTY/WrNc/7t5jnd0LPVO1sRIE7Ga6uXTpw=="
|
||||||
},
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sapper",
|
"name": "sapper",
|
||||||
"version": "0.19.3",
|
"version": "0.20.2",
|
||||||
"description": "Military-grade apps, engineered by Svelte",
|
"description": "Military-grade apps, engineered by Svelte",
|
||||||
"main": "dist/middleware.js",
|
"main": "dist/middleware.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"html-minifier": "^3.5.16",
|
"html-minifier": "^3.5.16",
|
||||||
"shimport": "^0.0.10",
|
"shimport": "0.0.11",
|
||||||
"source-map-support": "^0.5.6",
|
"source-map-support": "^0.5.6",
|
||||||
"sourcemap-codec": "^1.4.1",
|
"sourcemap-codec": "^1.4.1",
|
||||||
"string-hash": "^1.1.3",
|
"string-hash": "^1.1.3",
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ async function execute(emitter: EventEmitter, opts: Opts) {
|
|||||||
|
|
||||||
function save(path: string, status: number, type: string, body: string) {
|
function save(path: string, status: number, type: string, body: string) {
|
||||||
const { pathname } = resolve(origin, path);
|
const { pathname } = resolve(origin, path);
|
||||||
let file = pathname.slice(1);
|
let file = decodeURIComponent(pathname.slice(1));
|
||||||
|
|
||||||
if (saved.has(file)) return;
|
if (saved.has(file)) return;
|
||||||
saved.add(file);
|
saved.add(file);
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ function generate_client(
|
|||||||
import root from '${get_file(path_to_routes, manifest_data.root)}';
|
import root from '${get_file(path_to_routes, manifest_data.root)}';
|
||||||
import error from '${posixify(`${path_to_routes}/_error.html`)}';
|
import error from '${posixify(`${path_to_routes}/_error.html`)}';
|
||||||
|
|
||||||
|
const d = decodeURIComponent;
|
||||||
|
|
||||||
${manifest_data.components.map(component => {
|
${manifest_data.components.map(component => {
|
||||||
const annotation = bundler === 'webpack'
|
const annotation = bundler === 'webpack'
|
||||||
? `/* webpackChunkName: "${component.name}" */ `
|
? `/* webpackChunkName: "${component.name}" */ `
|
||||||
@@ -88,7 +90,7 @@ function generate_client(
|
|||||||
if (part === null) return 'null';
|
if (part === null) return 'null';
|
||||||
|
|
||||||
if (part.params.length > 0) {
|
if (part.params.length > 0) {
|
||||||
const props = part.params.map((param, i) => `${param}: match[${i + 1}]`);
|
const props = part.params.map((param, i) => `${param}: d(match[${i + 1}])`);
|
||||||
return `{ component: ${part.component.name}, params: match => ({ ${props.join(', ')} }) }`;
|
return `{ component: ${part.component.name}, params: match => ({ ${props.join(', ')} }) }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +140,8 @@ function generate_server(
|
|||||||
// This file is generated by Sapper — do not edit it!
|
// This file is generated by Sapper — do not edit it!
|
||||||
${imports.join('\n')}
|
${imports.join('\n')}
|
||||||
|
|
||||||
|
const d = decodeURIComponent;
|
||||||
|
|
||||||
export const manifest = {
|
export const manifest = {
|
||||||
server_routes: [
|
server_routes: [
|
||||||
${manifest_data.server_routes.map(route => `{
|
${manifest_data.server_routes.map(route => `{
|
||||||
@@ -145,7 +149,7 @@ function generate_server(
|
|||||||
pattern: ${route.pattern},
|
pattern: ${route.pattern},
|
||||||
handlers: ${route.name},
|
handlers: ${route.name},
|
||||||
params: ${route.params.length > 0
|
params: ${route.params.length > 0
|
||||||
? `match => ({ ${route.params.map((param, i) => `${param}: match[${i + 1}]`).join(', ')} })`
|
? `match => ({ ${route.params.map((param, i) => `${param}: d(match[${i + 1}])`).join(', ')} })`
|
||||||
: `() => ({})`}
|
: `() => ({})`}
|
||||||
}`).join(',\n\n\t\t\t\t')}
|
}`).join(',\n\n\t\t\t\t')}
|
||||||
],
|
],
|
||||||
@@ -165,7 +169,7 @@ function generate_server(
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (part.params.length > 0) {
|
if (part.params.length > 0) {
|
||||||
const params = part.params.map((param, i) => `${param}: match[${i + 1}]`);
|
const params = part.params.map((param, i) => `${param}: d(match[${i + 1}])`);
|
||||||
props.push(`params: match => ({ ${params.join(', ')} })`);
|
props.push(`params: match => ({ ${params.join(', ')} })`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ export default function middleware(opts: {
|
|||||||
|
|
||||||
serve({
|
serve({
|
||||||
prefix: '/client/',
|
prefix: '/client/',
|
||||||
cache_control: dev() ? 'no-cache' : 'max-age=31536000'
|
cache_control: dev() ? 'no-cache' : 'max-age=31536000, immutable'
|
||||||
}),
|
}),
|
||||||
|
|
||||||
get_server_route_handler(manifest.server_routes),
|
get_server_route_handler(manifest.server_routes),
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ export default {
|
|||||||
output: () => {
|
output: () => {
|
||||||
return {
|
return {
|
||||||
dir: locations.dest(),
|
dir: locations.dest(),
|
||||||
format: 'cjs'
|
format: 'cjs',
|
||||||
|
sourcemap: dev()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ function select_route(url: URL): Target {
|
|||||||
const query: Record<string, string | true> = {};
|
const query: Record<string, string | true> = {};
|
||||||
if (url.search.length > 0) {
|
if (url.search.length > 0) {
|
||||||
url.search.slice(1).split('&').forEach(searchParam => {
|
url.search.slice(1).split('&').forEach(searchParam => {
|
||||||
const [, key, value] = /([^=]+)=(.*)/.exec(searchParam);
|
const [, key, value] = /([^=]+)(?:=(.*))?/.exec(searchParam);
|
||||||
query[key] = value || true;
|
query[key] = decodeURIComponent((value || '').replace(/\+/g, ' '));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return { url, path, page, match, query };
|
return { url, path, page, match, query };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { init, prefetchRoutes } from '../../../runtime.js';
|
import { init, goto, prefetchRoutes } from '../../../runtime.js';
|
||||||
import { Store } from 'svelte/store.js';
|
import { Store } from 'svelte/store.js';
|
||||||
import { manifest } from './manifest/client.js';
|
import { manifest } from './manifest/client.js';
|
||||||
|
|
||||||
@@ -11,3 +11,4 @@ window.init = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.prefetchRoutes = prefetchRoutes;
|
window.prefetchRoutes = prefetchRoutes;
|
||||||
|
window.goto = goto;
|
||||||
@@ -106,6 +106,14 @@ const posts = [
|
|||||||
<p>If you didn't have adult onset diabetes, I wouldn't mind giving you a little sugar. Everybody dance NOW. And the soup of the day is bread. Great, now I'm gonna smell to high heaven like a tuna melt!</p>
|
<p>If you didn't have adult onset diabetes, I wouldn't mind giving you a little sugar. Everybody dance NOW. And the soup of the day is bread. Great, now I'm gonna smell to high heaven like a tuna melt!</p>
|
||||||
<p>That's how Tony Wonder lost a nut. She calls it a Mayonegg. Go ahead, touch the Cornballer. There's a new daddy in town. A discipline daddy.</p>
|
<p>That's how Tony Wonder lost a nut. She calls it a Mayonegg. Go ahead, touch the Cornballer. There's a new daddy in town. A discipline daddy.</p>
|
||||||
`
|
`
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: 'Encödïng test',
|
||||||
|
slug: 'encödïng-test',
|
||||||
|
html: `
|
||||||
|
<p>It works</p>
|
||||||
|
`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
12
test/app/routes/echo/page/[slug].html
Normal file
12
test/app/routes/echo/page/[slug].html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<h1>{slug} ({message})</h1>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
preload({ params, query }) {
|
||||||
|
return {
|
||||||
|
slug: params.slug,
|
||||||
|
message: query.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
15
test/app/routes/echo/server-route/[slug].js
Normal file
15
test/app/routes/echo/server-route/[slug].js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
export function get(req, res) {
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'text/html'
|
||||||
|
});
|
||||||
|
|
||||||
|
res.end(`
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head><meta charset="utf-8"></head>
|
||||||
|
<body>
|
||||||
|
<h1>${req.params.slug}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
|
}
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
<a href='credentials?creds=include'>credentials</a>
|
<a href='credentials?creds=include'>credentials</a>
|
||||||
<a rel=prefetch class='{page === "blog" ? "selected" : ""}' href='blog'>blog</a>
|
<a rel=prefetch class='{page === "blog" ? "selected" : ""}' href='blog'>blog</a>
|
||||||
<a href="const">const</a>
|
<a href="const">const</a>
|
||||||
|
<a href="echo/page/encöded?message=hëllö+wörld">echo/page/encöded?message=hëllö+wörld</a>
|
||||||
|
<a href="echo/page/empty?message">echo/page/empty?message</a>
|
||||||
|
|
||||||
<div class='hydrate-test'></div>
|
<div class='hydrate-test'></div>
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ function testExport({ basepath = '' }) {
|
|||||||
'blog/how-to-use-sapper/index.html',
|
'blog/how-to-use-sapper/index.html',
|
||||||
'blog/what-is-sapper/index.html',
|
'blog/what-is-sapper/index.html',
|
||||||
'blog/why-the-name/index.html',
|
'blog/why-the-name/index.html',
|
||||||
|
'blog/encödïng-test/index.html',
|
||||||
|
|
||||||
'blog.json',
|
'blog.json',
|
||||||
'blog/a-very-long-post.json',
|
'blog/a-very-long-post.json',
|
||||||
@@ -101,6 +102,7 @@ function testExport({ basepath = '' }) {
|
|||||||
'blog/how-to-use-sapper.json',
|
'blog/how-to-use-sapper.json',
|
||||||
'blog/what-is-sapper.json',
|
'blog/what-is-sapper.json',
|
||||||
'blog/why-the-name.json',
|
'blog/why-the-name.json',
|
||||||
|
'blog/encödïng-test.json',
|
||||||
|
|
||||||
'favicon.png',
|
'favicon.png',
|
||||||
'global.css',
|
'global.css',
|
||||||
@@ -751,6 +753,50 @@ function run({ mode, basepath = '' }) {
|
|||||||
assert.equal(title, 'reserved words are okay as routes');
|
assert.equal(title, 'reserved words are okay as routes');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('encodes req.params and req.query for server-rendered pages', () => {
|
||||||
|
return nightmare.goto(`${base}/echo/page/encöded?message=hëllö+wörld`)
|
||||||
|
.page.title()
|
||||||
|
.then(title => {
|
||||||
|
assert.equal(title, 'encöded (hëllö wörld)');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('encodes req.params and req.query for client-rendered pages', () => {
|
||||||
|
return nightmare.goto(base).init()
|
||||||
|
.click('a[href="echo/page/encöded?message=hëllö+wörld"]')
|
||||||
|
.wait(100)
|
||||||
|
.page.title()
|
||||||
|
.then(title => {
|
||||||
|
assert.equal(title, 'encöded (hëllö wörld)');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts value-less query string parameter on server', () => {
|
||||||
|
return nightmare.goto(`${base}/echo/page/empty?message`)
|
||||||
|
.page.title()
|
||||||
|
.then(title => {
|
||||||
|
assert.equal(title, 'empty ()');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts value-less query string parameter on client', () => {
|
||||||
|
return nightmare.goto(base).init()
|
||||||
|
.click('a[href="echo/page/empty?message"]')
|
||||||
|
.wait(100)
|
||||||
|
.page.title()
|
||||||
|
.then(title => {
|
||||||
|
assert.equal(title, 'empty ()');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('encodes req.params for server routes', () => {
|
||||||
|
return nightmare.goto(`${base}/echo/server-route/encöded`)
|
||||||
|
.page.title()
|
||||||
|
.then(title => {
|
||||||
|
assert.equal(title, 'encöded');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('headers', () => {
|
describe('headers', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user