mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-15 12:24:47 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2ed73f103 | ||
|
|
133ac07ed2 | ||
|
|
7417de101e | ||
|
|
2792b7c5d1 | ||
|
|
cf8d5ee717 | ||
|
|
8e4517a1ad | ||
|
|
91894722ee | ||
|
|
933b3b76a6 | ||
|
|
3ed4d1d887 | ||
|
|
dda936e53b | ||
|
|
ac4eb84f3d | ||
|
|
9e70e68c0c | ||
|
|
22389eab99 | ||
|
|
fe6b7976ef | ||
|
|
54e92c3b99 | ||
|
|
e6c1a54164 | ||
|
|
629b5601c8 | ||
|
|
8bdd363a19 | ||
|
|
8fcc27d44f | ||
|
|
f6e72a0432 | ||
|
|
f886a12bd7 | ||
|
|
6c03cfd46a | ||
|
|
78480fe5e8 | ||
|
|
5cba40b7e0 | ||
|
|
c99b787632 | ||
|
|
99a25308fc | ||
|
|
c0ada5c52f | ||
|
|
d51e1a0af8 | ||
|
|
5e5a8c4c69 | ||
|
|
49f8b2c4bd | ||
|
|
2754ba0ee4 | ||
|
|
1ad27573c6 | ||
|
|
f10b941c4e | ||
|
|
6ca869a3b1 | ||
|
|
a2204a9d2e |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,11 +3,7 @@ yarn.lock
|
|||||||
yarn-error.log
|
yarn-error.log
|
||||||
node_modules
|
node_modules
|
||||||
cypress/screenshots
|
cypress/screenshots
|
||||||
test/app/.sapper
|
|
||||||
test/app/src/manifest
|
|
||||||
__sapper__
|
__sapper__
|
||||||
test/app/export
|
|
||||||
test/app/build
|
|
||||||
sapper
|
sapper
|
||||||
runtime.js
|
runtime.js
|
||||||
dist
|
dist
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ sudo: false
|
|||||||
language: node_js
|
language: node_js
|
||||||
|
|
||||||
node_js:
|
node_js:
|
||||||
- "11"
|
- "stable"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
# sapper changelog
|
# sapper changelog
|
||||||
|
|
||||||
|
## 0.27.0
|
||||||
|
|
||||||
|
* Change license from LIL to MIT ([#652](https://github.com/sveltejs/sapper/pull/652))
|
||||||
|
* Fix index server route mapping ([#624](https://github.com/sveltejs/sapper/issues/624))
|
||||||
|
|
||||||
|
## 0.26.1
|
||||||
|
|
||||||
|
* Handle skipped segments ([#663](https://github.com/sveltejs/sapper/pull/663))
|
||||||
|
|
||||||
## 0.26.0
|
## 0.26.0
|
||||||
|
|
||||||
* Update to Svelte 3
|
* Update to Svelte 3
|
||||||
|
|||||||
10
LICENSE
10
LICENSE
@@ -1,9 +1,7 @@
|
|||||||
Copyright (c) 2017 [these people](https://github.com/sveltejs/sapper/graphs/contributors).
|
Copyright (c) 2016-19 [these people](https://github.com/sveltejs/sapper/graphs/contributors)
|
||||||
|
|
||||||
Permission is hereby granted by the authors of this software, to any person, to use the software for any purpose, free of charge, including the rights to run, read, copy, change, distribute and sell it, and including usage rights to any patents the authors may hold on it, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
This license, or a link to its text, must be included with all copies of the software and any derivative works.
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
Any modification to the software submitted to the authors may be incorporated into the software under the terms of this license.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
The software is provided "as is", without warranty of any kind, including but not limited to the warranties of title, fitness, merchantability and non-infringement. The authors have no obligation to provide support or updates for the software, and may not be held liable for any damages, claims or other liability arising from its use.
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# sapper
|
# sapper
|
||||||
|
|
||||||
[Military-grade progressive web apps, powered by Svelte.](https://sapper.svelte.technology)
|
[Military-grade progressive web apps, powered by Svelte.](https://sapper.svelte.dev)
|
||||||
|
|
||||||
|
|
||||||
## What is Sapper?
|
## What is Sapper?
|
||||||
|
|
||||||
Sapper is a framework for building high-performance universal web apps. [Read the guide](https://sapper.svelte.technology/guide) or the [introductory blog post](https://svelte.technology/blog/sapper-towards-the-ideal-web-app-framework) to learn more.
|
Sapper is a framework for building high-performance universal web apps. [Read the guide](https://sapper.svelte.dev/docs) or the [introductory blog post](https://svelte.dev/blog/sapper-towards-the-ideal-web-app-framework) to learn more.
|
||||||
|
|
||||||
|
|
||||||
## Get started
|
## Get started
|
||||||
@@ -74,4 +74,4 @@ npm run test
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[LIL](LICENSE)
|
[LIL](LICENSE)
|
||||||
|
|||||||
1416
package-lock.json
generated
1416
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
50
package.json
50
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sapper",
|
"name": "sapper",
|
||||||
"version": "0.26.0",
|
"version": "0.27.0",
|
||||||
"description": "Military-grade apps, engineered by Svelte",
|
"description": "Military-grade apps, engineered by Svelte",
|
||||||
"bin": {
|
"bin": {
|
||||||
"sapper": "./sapper"
|
"sapper": "./sapper"
|
||||||
@@ -18,50 +18,50 @@
|
|||||||
"test": "test"
|
"test": "test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"html-minifier": "^3.5.21",
|
"html-minifier": "^4.0.0",
|
||||||
"http-link-header": "^1.0.2",
|
"http-link-header": "^1.0.2",
|
||||||
"shimport": "^1.0.0",
|
"shimport": "^1.0.0",
|
||||||
"sourcemap-codec": "^1.4.4",
|
"sourcemap-codec": "^1.4.4",
|
||||||
"string-hash": "^1.1.3"
|
"string-hash": "^1.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mocha": "^5.2.5",
|
"@types/mocha": "^5.2.6",
|
||||||
"@types/node": "^10.12.21",
|
"@types/node": "^10.14.6",
|
||||||
"@types/puppeteer": "^1.11.3",
|
"@types/puppeteer": "^1.12.4",
|
||||||
"agadoo": "^1.0.1",
|
"agadoo": "^1.0.1",
|
||||||
"cheap-watch": "^1.0.2",
|
"cheap-watch": "^1.0.2",
|
||||||
"cookie": "^0.3.1",
|
"cookie": "^0.3.1",
|
||||||
"devalue": "^1.1.0",
|
"devalue": "^1.1.0",
|
||||||
"eslint": "^5.12.1",
|
"eslint": "^5.16.0",
|
||||||
"eslint-plugin-import": "^2.16.0",
|
"eslint-plugin-import": "^2.17.2",
|
||||||
"kleur": "^3.0.1",
|
"kleur": "^3.0.3",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^6.1.4",
|
||||||
"node-fetch": "^2.3.0",
|
"node-fetch": "^2.5.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"polka": "^0.5.1",
|
"polka": "^0.5.2",
|
||||||
"port-authority": "^1.0.5",
|
"port-authority": "^1.0.5",
|
||||||
"pretty-bytes": "^5.1.0",
|
"pretty-bytes": "^5.2.0",
|
||||||
"puppeteer": "^1.12.0",
|
"puppeteer": "^1.15.0",
|
||||||
"require-relative": "^0.8.7",
|
"require-relative": "^0.8.7",
|
||||||
"rollup": "^1.1.2",
|
"rollup": "^1.11.3",
|
||||||
"rollup-plugin-commonjs": "^9.2.0",
|
"rollup-plugin-commonjs": "^9.3.4",
|
||||||
"rollup-plugin-json": "^3.1.0",
|
"rollup-plugin-json": "^4.0.0",
|
||||||
"rollup-plugin-node-resolve": "^4.0.0",
|
"rollup-plugin-node-resolve": "^4.2.3",
|
||||||
"rollup-plugin-replace": "^2.1.0",
|
"rollup-plugin-replace": "^2.2.0",
|
||||||
"rollup-plugin-string": "^2.0.2",
|
"rollup-plugin-string": "^3.0.0",
|
||||||
"rollup-plugin-sucrase": "^2.1.0",
|
"rollup-plugin-sucrase": "^2.1.0",
|
||||||
"rollup-plugin-svelte": "^5.0.3",
|
"rollup-plugin-svelte": "^5.0.3",
|
||||||
"sade": "^1.4.2",
|
"sade": "^1.4.2",
|
||||||
"sirv": "^0.2.2",
|
"sirv": "^0.4.0",
|
||||||
"sucrase": "^3.9.5",
|
"sucrase": "^3.10.1",
|
||||||
"svelte": "^3.0.0-beta.11",
|
"svelte": "^3.2.0",
|
||||||
"svelte-loader": "^2.13.3",
|
"svelte-loader": "^2.13.3",
|
||||||
"webpack": "^4.29.0",
|
"webpack": "^4.30.0",
|
||||||
"webpack-format-messages": "^2.0.5",
|
"webpack-format-messages": "^2.0.5",
|
||||||
"yootils": "0.0.15"
|
"yootils": "0.0.15"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"svelte": "^3.0.0"
|
"svelte": "^3.2.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha --opts mocha.opts",
|
"test": "mocha --opts mocha.opts",
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
"express"
|
"express"
|
||||||
],
|
],
|
||||||
"author": "Rich Harris",
|
"author": "Rich Harris",
|
||||||
"license": "LIL",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/sveltejs/sapper/issues"
|
"url": "https://github.com/sveltejs/sapper/issues"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import sucrase from 'rollup-plugin-sucrase';
|
import sucrase from 'rollup-plugin-sucrase';
|
||||||
import string from 'rollup-plugin-string';
|
import { string } from 'rollup-plugin-string';
|
||||||
import json from 'rollup-plugin-json';
|
import json from 'rollup-plugin-json';
|
||||||
import resolve from 'rollup-plugin-node-resolve';
|
import resolve from 'rollup-plugin-node-resolve';
|
||||||
import commonjs from 'rollup-plugin-commonjs';
|
import commonjs from 'rollup-plugin-commonjs';
|
||||||
@@ -52,7 +52,8 @@ export default [
|
|||||||
output: {
|
output: {
|
||||||
dir: 'dist',
|
dir: 'dist',
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
sourcemap: true
|
sourcemap: true,
|
||||||
|
chunkFileNames: '[name].js'
|
||||||
},
|
},
|
||||||
external,
|
external,
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
@@ -101,7 +101,11 @@ export function select_target(url: URL): Target {
|
|||||||
if (url.origin !== location.origin) return null;
|
if (url.origin !== location.origin) return null;
|
||||||
if (!url.pathname.startsWith(initial_data.baseUrl)) return null;
|
if (!url.pathname.startsWith(initial_data.baseUrl)) return null;
|
||||||
|
|
||||||
const path = url.pathname.slice(initial_data.baseUrl.length);
|
let path = url.pathname.slice(initial_data.baseUrl.length);
|
||||||
|
|
||||||
|
if (path === '') {
|
||||||
|
path = '/';
|
||||||
|
}
|
||||||
|
|
||||||
// avoid accidental clashes between server routes and page routes
|
// avoid accidental clashes between server routes and page routes
|
||||||
if (ignore.some(pattern => pattern.test(path))) return;
|
if (ignore.some(pattern => pattern.test(path))) return;
|
||||||
@@ -288,14 +292,22 @@ export async function hydrate_target(target: Target): Promise<{
|
|||||||
let l = 1;
|
let l = 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
let segment_dirty = false;
|
||||||
branch = await Promise.all(route.parts.map(async (part, i) => {
|
branch = await Promise.all(route.parts.map(async (part, i) => {
|
||||||
|
const segment = segments[i];
|
||||||
|
|
||||||
|
if (current_branch[i] && current_branch[i].segment !== segment) segment_dirty = true;
|
||||||
|
|
||||||
props.segments[l] = segments[i + 1]; // TODO make this less confusing
|
props.segments[l] = segments[i + 1]; // TODO make this less confusing
|
||||||
if (!part) return null;
|
if (!part) return { segment };
|
||||||
|
|
||||||
const j = l++;
|
const j = l++;
|
||||||
|
|
||||||
const segment = segments[i];
|
if (!session_dirty && !segment_dirty && current_branch[i] && current_branch[i].part === part.i) {
|
||||||
if (!session_dirty && current_branch[i] && current_branch[i].segment === segment && current_branch[i].part === part.i) return current_branch[i];
|
return current_branch[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
segment_dirty = false;
|
||||||
|
|
||||||
const { default: component, preload } = await load_component(components[part.i]);
|
const { default: component, preload } = await load_component(components[part.i]);
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
export const IGNORE = '__SAPPER__IGNORE__';
|
|
||||||
@@ -5,10 +5,8 @@ import cookie from 'cookie';
|
|||||||
import devalue from 'devalue';
|
import devalue from 'devalue';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import URL from 'url';
|
import URL from 'url';
|
||||||
import { IGNORE } from '../constants';
|
import { Manifest, Page, Req, Res } from './types';
|
||||||
import { Manifest, Page, Props, Req, Res } from './types';
|
|
||||||
import { build_dir, dev, src_dir } from '@sapper/internal/manifest-server';
|
import { build_dir, dev, src_dir } from '@sapper/internal/manifest-server';
|
||||||
import { stores } from '@sapper/internal/shared';
|
|
||||||
import App from '@sapper/internal/App.svelte';
|
import App from '@sapper/internal/App.svelte';
|
||||||
|
|
||||||
export function get_page_handler(
|
export function get_page_handler(
|
||||||
@@ -328,8 +326,6 @@ export function get_page_handler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return function find_route(req: Req, res: Res, next: () => void) {
|
return function find_route(req: Req, res: Res, next: () => void) {
|
||||||
if (req[IGNORE]) return next();
|
|
||||||
|
|
||||||
if (req.path === '/service-worker-index.html') {
|
if (req.path === '/service-worker-index.html') {
|
||||||
const homePage = pages.find(page => page.pattern.test('/'));
|
const homePage = pages.find(page => page.pattern.test('/'));
|
||||||
handle_page(homePage, req, res);
|
handle_page(homePage, req, res);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { IGNORE } from '../constants';
|
|
||||||
import { Req, Res, ServerRoute } from './types';
|
import { Req, Res, ServerRoute } from './types';
|
||||||
|
|
||||||
export function get_server_route_handler(routes: ServerRoute[]) {
|
export function get_server_route_handler(routes: ServerRoute[]) {
|
||||||
@@ -64,8 +63,6 @@ export function get_server_route_handler(routes: ServerRoute[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return function find_route(req: Req, res: Res, next: () => void) {
|
return function find_route(req: Req, res: Res, next: () => void) {
|
||||||
if (req[IGNORE]) return next();
|
|
||||||
|
|
||||||
for (const route of routes) {
|
for (const route of routes) {
|
||||||
if (route.pattern.test(req.path)) {
|
if (route.pattern.test(req.path)) {
|
||||||
handle_route(route, req, res, next);
|
handle_route(route, req, res, next);
|
||||||
@@ -75,4 +72,4 @@ export function get_server_route_handler(routes: ServerRoute[]) {
|
|||||||
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { Handler, Req, Res } from './types';
|
|||||||
import { get_server_route_handler } from './get_server_route_handler';
|
import { get_server_route_handler } from './get_server_route_handler';
|
||||||
import { get_page_handler } from './get_page_handler';
|
import { get_page_handler } from './get_page_handler';
|
||||||
import { lookup } from './mime';
|
import { lookup } from './mime';
|
||||||
import { IGNORE } from '../constants';
|
|
||||||
|
|
||||||
export default function middleware(opts: {
|
export default function middleware(opts: {
|
||||||
session?: (req: Req, res: Res) => any,
|
session?: (req: Req, res: Res) => any,
|
||||||
@@ -15,15 +14,8 @@ export default function middleware(opts: {
|
|||||||
|
|
||||||
let emitted_basepath = false;
|
let emitted_basepath = false;
|
||||||
|
|
||||||
return compose_handlers([
|
return compose_handlers(ignore, [
|
||||||
ignore && ((req: Req, res: Res, next: () => void) => {
|
|
||||||
req[IGNORE] = should_ignore(req.path, ignore);
|
|
||||||
next();
|
|
||||||
}),
|
|
||||||
|
|
||||||
(req: Req, res: Res, next: () => void) => {
|
(req: Req, res: Res, next: () => void) => {
|
||||||
if (req[IGNORE]) return next();
|
|
||||||
|
|
||||||
if (req.baseUrl === undefined) {
|
if (req.baseUrl === undefined) {
|
||||||
let { originalUrl } = req;
|
let { originalUrl } = req;
|
||||||
if (req.url === '/' && originalUrl[originalUrl.length - 1] !== '/') {
|
if (req.url === '/' && originalUrl[originalUrl.length - 1] !== '/') {
|
||||||
@@ -73,24 +65,26 @@ export default function middleware(opts: {
|
|||||||
].filter(Boolean));
|
].filter(Boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compose_handlers(handlers: Handler[]) {
|
export function compose_handlers(ignore: any, handlers: Handler[]): Handler {
|
||||||
return (req: Req, res: Res, next: () => void) => {
|
const total = handlers.length;
|
||||||
let i = 0;
|
|
||||||
function go() {
|
|
||||||
const handler = handlers[i];
|
|
||||||
|
|
||||||
if (handler) {
|
function nth_handler(n: number, req: Req, res: Res, next: () => void) {
|
||||||
handler(req, res, () => {
|
if (n >= total) {
|
||||||
i += 1;
|
return next();
|
||||||
go();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go();
|
handlers[n](req, res, () => nth_handler(n+1, req, res, next));
|
||||||
};
|
}
|
||||||
|
|
||||||
|
return !ignore
|
||||||
|
? (req, res, next) => nth_handler(0, req, res, next)
|
||||||
|
: (req, res, next) => {
|
||||||
|
if (should_ignore(req.path, ignore)) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
nth_handler(0, req, res, next);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function should_ignore(uri: string, val: any) {
|
export function should_ignore(uri: string, val: any) {
|
||||||
@@ -116,8 +110,6 @@ export function serve({ prefix, pathname, cache_control }: {
|
|||||||
: (file: string) => (cache.has(file) ? cache : cache.set(file, fs.readFileSync(path.resolve(build_dir, file)))).get(file)
|
: (file: string) => (cache.has(file) ? cache : cache.set(file, fs.readFileSync(path.resolve(build_dir, file)))).get(file)
|
||||||
|
|
||||||
return (req: Req, res: Res, next: () => void) => {
|
return (req: Req, res: Res, next: () => void) => {
|
||||||
if (req[IGNORE]) return next();
|
|
||||||
|
|
||||||
if (filter(req)) {
|
if (filter(req)) {
|
||||||
const type = lookup(req.path);
|
const type = lookup(req.path);
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ You can also add a script to your package.json...
|
|||||||
|
|
||||||
When you run `sapper export`, Sapper first builds a production version of your app, as though you had run `sapper build`, and copies the contents of your `assets` folder to the destination. It then starts the server, and navigates to the root of your app. From there, it follows any `<a>` elements it finds, and captures any data served by the app.
|
When you run `sapper export`, Sapper first builds a production version of your app, as though you had run `sapper build`, and copies the contents of your `assets` folder to the destination. It then starts the server, and navigates to the root of your app. From there, it follows any `<a>` elements it finds, and captures any data served by the app.
|
||||||
|
|
||||||
Because of this, any pages you want to be included in the exported site must be reachable by `<a>` elements. Additionally, any non-page routes should be requested in `preload`, *not* in `oncreate` or elsewhere.
|
Because of this, any pages you want to be included in the exported site must be reachable by `<a>` elements. Additionally, any non-page routes should be requested in `preload`, *not* in `onMount` or elsewhere.
|
||||||
|
|
||||||
|
|
||||||
### When not to export
|
### When not to export
|
||||||
@@ -60,4 +60,4 @@ Because `sapper export` writes to the filesystem, it isn't possible to have two
|
|||||||
|
|
||||||
The solution is to rename one of the routes to avoid conflict — for example, `src/routes/foo-bar.js`. (Note that you would also need to update any code that fetches data from `/foo/bar` to reference `/foo-bar` instead.)
|
The solution is to rename one of the routes to avoid conflict — for example, `src/routes/foo-bar.js`. (Note that you would also need to update any code that fetches data from `/foo/bar` to reference `/foo-bar` instead.)
|
||||||
|
|
||||||
For *pages*, we skirt around this problem by writing `export/foo/index.html` instead of `export/foo`.
|
For *pages*, we skirt around this problem by writing `export/foo/index.html` instead of `export/foo`.
|
||||||
|
|||||||
737
site/package-lock.json
generated
737
site/package-lock.json
generated
@@ -846,9 +846,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sveltejs/site-kit": {
|
"@sveltejs/site-kit": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.0.4.tgz",
|
||||||
"integrity": "sha512-S5mZG2PkWGDXGZaIJQh5JtF7RLG2uIO36f9juUkUHhjqlz6FaBl2D4zyofmvGergSd6m9NgQ+iXLiFIK9WNmBg==",
|
"integrity": "sha512-BaQhIL1iPhCF+iDXfy9psDvRdFzfyMPkWnoZHfVz+INpHsU2aJmRZOPl9rykXmPyiPo+AwTTNK5vjIvmtwHLPQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sindresorhus/slugify": "^0.9.1",
|
"@sindresorhus/slugify": "^0.9.1",
|
||||||
@@ -862,9 +862,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "11.13.8",
|
"version": "11.13.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.10.tgz",
|
||||||
"integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg==",
|
"integrity": "sha512-leUNzbFTMX94TWaIKz8N15Chu55F9QSH+INKayQr5xpkasBQBRF3qQXfo3/dOnMU/dEIit+Y/SU8HyOjq++GwA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/resolve": {
|
"@types/resolve": {
|
||||||
@@ -900,27 +900,6 @@
|
|||||||
"color-convert": "^1.9.0"
|
"color-convert": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"anymatch": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"micromatch": "^3.1.4",
|
|
||||||
"normalize-path": "^2.1.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"normalize-path": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"remove-trailing-separator": "^1.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"arr-diff": {
|
"arr-diff": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
|
||||||
@@ -969,12 +948,6 @@
|
|||||||
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
|
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"async-each": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"atob": {
|
"atob": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||||
@@ -1042,12 +1015,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"binary-extensions": {
|
|
||||||
"version": "1.13.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
|
|
||||||
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@@ -1088,14 +1055,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"version": "4.5.5",
|
"version": "4.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.6.tgz",
|
||||||
"integrity": "sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA==",
|
"integrity": "sha512-o/hPOtbU9oX507lIqon+UvPYqpx3mHc8cV3QemSBTXwkG8gSQSK6UKvXcE/DcleU3+A59XTUHyCvZ5qGy8xVAg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"caniuse-lite": "^1.0.30000960",
|
"caniuse-lite": "^1.0.30000963",
|
||||||
"electron-to-chromium": "^1.3.124",
|
"electron-to-chromium": "^1.3.127",
|
||||||
"node-releases": "^1.1.14"
|
"node-releases": "^1.1.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buffer-from": {
|
"buffer-from": {
|
||||||
@@ -1143,9 +1110,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30000963",
|
"version": "1.0.30000967",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000963.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz",
|
||||||
"integrity": "sha512-n4HUiullc7Lw0LyzpeLa2ffP8KxFBGdxqD/8G3bSL6oB758hZ2UE2CVK+tQN958tJIi0/tfpjAc67aAtoHgnrQ==",
|
"integrity": "sha512-rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
@@ -1159,26 +1126,6 @@
|
|||||||
"supports-color": "^5.3.0"
|
"supports-color": "^5.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chokidar": {
|
|
||||||
"version": "2.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz",
|
|
||||||
"integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"anymatch": "^2.0.0",
|
|
||||||
"async-each": "^1.0.1",
|
|
||||||
"braces": "^2.3.2",
|
|
||||||
"fsevents": "^1.2.7",
|
|
||||||
"glob-parent": "^3.1.0",
|
|
||||||
"inherits": "^2.0.3",
|
|
||||||
"is-binary-path": "^1.0.0",
|
|
||||||
"is-glob": "^4.0.0",
|
|
||||||
"normalize-path": "^3.0.0",
|
|
||||||
"path-is-absolute": "^1.0.0",
|
|
||||||
"readdirp": "^2.2.1",
|
|
||||||
"upath": "^1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"class-utils": {
|
"class-utils": {
|
||||||
"version": "0.3.6",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
||||||
@@ -1432,9 +1379,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"electron-to-chromium": {
|
"electron-to-chromium": {
|
||||||
"version": "1.3.127",
|
"version": "1.3.133",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.127.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.133.tgz",
|
||||||
"integrity": "sha512-1o25iFRf/dbgauTWalEzmD1EmRN3a2CzP/K7UVpYLEBduk96LF0FyUdCcf4Ry2mAWJ1VxyblFjC93q6qlLwA2A==",
|
"integrity": "sha512-lyoC8aoqbbDqsprb6aPdt9n3DpOZZzdz/T4IZKsR0/dkZIxnJVUjjcpOSwA66jPRIOyDAamCTAUqweU05kKNSg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"error-ex": {
|
"error-ex": {
|
||||||
@@ -1648,535 +1595,6 @@
|
|||||||
"map-cache": "^0.2.2"
|
"map-cache": "^0.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fsevents": {
|
|
||||||
"version": "1.2.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
|
|
||||||
"integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"nan": "^2.12.1",
|
|
||||||
"node-pre-gyp": "^0.12.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"abbrev": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"aproba": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"are-we-there-yet": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"delegates": "^1.0.0",
|
|
||||||
"readable-stream": "^2.0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"balanced-match": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
|
||||||
"version": "1.1.11",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"balanced-match": "^1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chownr": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"code-point-at": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"console-control-strings": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"core-util-is": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"debug": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"ms": "^2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"deep-extend": {
|
|
||||||
"version": "0.6.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"delegates": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"detect-libc": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"fs-minipass": {
|
|
||||||
"version": "1.2.5",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"minipass": "^2.2.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fs.realpath": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"gauge": {
|
|
||||||
"version": "2.7.4",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"aproba": "^1.0.3",
|
|
||||||
"console-control-strings": "^1.0.0",
|
|
||||||
"has-unicode": "^2.0.0",
|
|
||||||
"object-assign": "^4.1.0",
|
|
||||||
"signal-exit": "^3.0.0",
|
|
||||||
"string-width": "^1.0.1",
|
|
||||||
"strip-ansi": "^3.0.1",
|
|
||||||
"wide-align": "^1.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"glob": {
|
|
||||||
"version": "7.1.3",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"fs.realpath": "^1.0.0",
|
|
||||||
"inflight": "^1.0.4",
|
|
||||||
"inherits": "2",
|
|
||||||
"minimatch": "^3.0.4",
|
|
||||||
"once": "^1.3.0",
|
|
||||||
"path-is-absolute": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has-unicode": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"iconv-lite": {
|
|
||||||
"version": "0.4.24",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"safer-buffer": ">= 2.1.2 < 3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ignore-walk": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"minimatch": "^3.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inflight": {
|
|
||||||
"version": "1.0.6",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"once": "^1.3.0",
|
|
||||||
"wrappy": "1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inherits": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"ini": {
|
|
||||||
"version": "1.3.5",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"is-fullwidth-code-point": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"number-is-nan": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isarray": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"minimatch": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"brace-expansion": "^1.1.7"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minimist": {
|
|
||||||
"version": "0.0.8",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"minipass": {
|
|
||||||
"version": "2.3.5",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "^5.1.2",
|
|
||||||
"yallist": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minizlib": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"minipass": "^2.2.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mkdirp": {
|
|
||||||
"version": "0.5.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"minimist": "0.0.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ms": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"needle": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"debug": "^4.1.0",
|
|
||||||
"iconv-lite": "^0.4.4",
|
|
||||||
"sax": "^1.2.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node-pre-gyp": {
|
|
||||||
"version": "0.12.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"detect-libc": "^1.0.2",
|
|
||||||
"mkdirp": "^0.5.1",
|
|
||||||
"needle": "^2.2.1",
|
|
||||||
"nopt": "^4.0.1",
|
|
||||||
"npm-packlist": "^1.1.6",
|
|
||||||
"npmlog": "^4.0.2",
|
|
||||||
"rc": "^1.2.7",
|
|
||||||
"rimraf": "^2.6.1",
|
|
||||||
"semver": "^5.3.0",
|
|
||||||
"tar": "^4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nopt": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"abbrev": "1",
|
|
||||||
"osenv": "^0.1.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"npm-bundled": {
|
|
||||||
"version": "1.0.6",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"npm-packlist": {
|
|
||||||
"version": "1.4.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"ignore-walk": "^3.0.1",
|
|
||||||
"npm-bundled": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"npmlog": {
|
|
||||||
"version": "4.1.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"are-we-there-yet": "~1.1.2",
|
|
||||||
"console-control-strings": "~1.1.0",
|
|
||||||
"gauge": "~2.7.3",
|
|
||||||
"set-blocking": "~2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"number-is-nan": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"object-assign": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"once": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"wrappy": "1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"os-homedir": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"os-tmpdir": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"osenv": {
|
|
||||||
"version": "0.1.5",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"os-homedir": "^1.0.0",
|
|
||||||
"os-tmpdir": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"path-is-absolute": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"process-nextick-args": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"rc": {
|
|
||||||
"version": "1.2.8",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"deep-extend": "^0.6.0",
|
|
||||||
"ini": "~1.3.0",
|
|
||||||
"minimist": "^1.2.0",
|
|
||||||
"strip-json-comments": "~2.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"minimist": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"readable-stream": {
|
|
||||||
"version": "2.3.6",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"core-util-is": "~1.0.0",
|
|
||||||
"inherits": "~2.0.3",
|
|
||||||
"isarray": "~1.0.0",
|
|
||||||
"process-nextick-args": "~2.0.0",
|
|
||||||
"safe-buffer": "~5.1.1",
|
|
||||||
"string_decoder": "~1.1.1",
|
|
||||||
"util-deprecate": "~1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rimraf": {
|
|
||||||
"version": "2.6.3",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"glob": "^7.1.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"safe-buffer": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"safer-buffer": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"sax": {
|
|
||||||
"version": "1.2.4",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"semver": {
|
|
||||||
"version": "5.7.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"set-blocking": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"signal-exit": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"string-width": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"code-point-at": "^1.0.0",
|
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
|
||||||
"strip-ansi": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string_decoder": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "~5.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-json-comments": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"tar": {
|
|
||||||
"version": "4.4.8",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"chownr": "^1.1.1",
|
|
||||||
"fs-minipass": "^1.2.5",
|
|
||||||
"minipass": "^2.3.4",
|
|
||||||
"minizlib": "^1.1.1",
|
|
||||||
"mkdirp": "^0.5.0",
|
|
||||||
"safe-buffer": "^5.1.2",
|
|
||||||
"yallist": "^3.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"util-deprecate": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"wide-align": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"string-width": "^1.0.2 || 2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wrappy": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"yallist": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"function-bind": {
|
"function-bind": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
@@ -2189,27 +1607,6 @@
|
|||||||
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
|
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"glob-parent": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
|
|
||||||
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-glob": "^3.1.0",
|
|
||||||
"path-dirname": "^1.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"is-glob": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
|
|
||||||
"integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-extglob": "^2.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"globals": {
|
"globals": {
|
||||||
"version": "11.12.0",
|
"version": "11.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||||
@@ -2377,15 +1774,6 @@
|
|||||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-binary-path": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"binary-extensions": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-buffer": {
|
"is-buffer": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
@@ -2449,21 +1837,6 @@
|
|||||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
|
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-extglob": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"is-glob": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"is-extglob": "^2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-module": {
|
"is-module": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||||
@@ -2778,13 +2151,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
},
|
},
|
||||||
"nan": {
|
|
||||||
"version": "2.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
|
|
||||||
"integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"nanomatch": {
|
"nanomatch": {
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||||
@@ -2825,9 +2191,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node-releases": {
|
"node-releases": {
|
||||||
"version": "1.1.17",
|
"version": "1.1.18",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.17.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.18.tgz",
|
||||||
"integrity": "sha512-/SCjetyta1m7YXLgtACZGDYJdCSIBAWorDWkGCGZlydP2Ll7J48l7j/JxNYZ+xsgSPbWfdulVS/aY+GdjUsQ7Q==",
|
"integrity": "sha512-/mnVgm6u/8OwlIsoyRXtTI0RfQcxZoAZbdwyXap0EeWwcOpDDymyCHM2/aR9XKmHXrvizHoPAOs0pcbiJ6RUaA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"semver": "^5.3.0"
|
"semver": "^5.3.0"
|
||||||
@@ -2845,12 +2211,6 @@
|
|||||||
"validate-npm-package-license": "^3.0.1"
|
"validate-npm-package-license": "^3.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"normalize-path": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"npm-run-all": {
|
"npm-run-all": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
|
||||||
@@ -2953,18 +2313,6 @@
|
|||||||
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
|
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"path-dirname": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"path-is-absolute": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"path-key": {
|
"path-key": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||||
@@ -3059,17 +2407,6 @@
|
|||||||
"util-deprecate": "~1.0.1"
|
"util-deprecate": "~1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readdirp": {
|
|
||||||
"version": "2.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
|
|
||||||
"integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"graceful-fs": "^4.1.11",
|
|
||||||
"micromatch": "^3.1.10",
|
|
||||||
"readable-stream": "^2.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
|
||||||
@@ -3159,12 +2496,6 @@
|
|||||||
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
|
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"remove-trailing-separator": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
|
||||||
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"repeat-element": {
|
"repeat-element": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
|
||||||
@@ -3205,13 +2536,13 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"rollup": {
|
"rollup": {
|
||||||
"version": "1.10.1",
|
"version": "1.11.3",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.11.3.tgz",
|
||||||
"integrity": "sha512-pW353tmBE7QP622ITkGxtqF0d5gSRCVPD9xqM+fcPjudeZfoXMFW2sCzsTe2TU/zU1xamIjiS9xuFCPVT9fESw==",
|
"integrity": "sha512-81MR7alHcFKxgWzGfG7jSdv+JQxSOIOD/Fa3iNUmpzbd7p+V19e1l9uffqT8/7YAHgGOzmoPGN3Fx3L2ptOf5g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/estree": "0.0.39",
|
"@types/estree": "0.0.39",
|
||||||
"@types/node": "^11.13.5",
|
"@types/node": "^11.13.9",
|
||||||
"acorn": "^6.1.1"
|
"acorn": "^6.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3394,9 +2725,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"sirv": {
|
"sirv": {
|
||||||
"version": "0.2.5",
|
"version": "0.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-0.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.2.tgz",
|
||||||
"integrity": "sha512-q7F1VElkj/WPrXwWsdHK9gqi2rd94oaMQc3VtN8N1TNHrKxlsd7hGsPFiOIodRxre8eHCV1XK1iqC1BDaZ+IKA==",
|
"integrity": "sha512-dQbZnsMaIiTQPZmbGmktz+c74zt/hyrJEB4tdp2Jj0RNv9J6B/OWR5RyrZEvIn9fyh9Zlg2OlE2XzKz6wMKGAw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@polka/url": "^0.5.0",
|
"@polka/url": "^0.5.0",
|
||||||
"mime": "^2.3.1"
|
"mime": "^2.3.1"
|
||||||
@@ -3662,9 +2993,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"svelte": {
|
"svelte": {
|
||||||
"version": "3.1.0",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.2.2.tgz",
|
||||||
"integrity": "sha512-b5TyzV7Dx1ijN4QPNarhKq5rX98QHDmi18nF0G8KV3d5KX3Jj98Yu4+tzM97ktnXcfoVJmvONvPaX1ZI0mr8Dw==",
|
"integrity": "sha512-B6ePpPodCQodVFDwv/uByaWs0KvXojaXZiB/db1x7WXbyxgLJ8xZF3j1lk5M83Ox0AWlX0fQnCTAaZmfT6xqdw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"terser": {
|
"terser": {
|
||||||
@@ -3881,12 +3212,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"upath": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"upper-case": {
|
"upper-case": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
||||||
|
|||||||
@@ -15,30 +15,29 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@polka/send": "^0.4.0",
|
"@polka/send": "^0.4.0",
|
||||||
"compression": "^1.7.1",
|
"compression": "^1.7.4",
|
||||||
"highlight.js": "^9.15.6",
|
"highlight.js": "^9.15.6",
|
||||||
"marked": "^0.6.2",
|
"marked": "^0.6.2",
|
||||||
"polka": "^0.5.2",
|
"polka": "^0.5.2",
|
||||||
"prismjs": "^1.16.0",
|
"prismjs": "^1.16.0",
|
||||||
"sirv": "^0.2.0"
|
"sirv": "^0.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.4.4",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||||
"@babel/plugin-transform-runtime": "^7.0.0",
|
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.4.4",
|
||||||
"@babel/runtime": "^7.0.0",
|
"@babel/runtime": "^7.4.4",
|
||||||
"@sveltejs/site-kit": "^1.0.1",
|
"@sveltejs/site-kit": "^1.0.4",
|
||||||
"chokidar": "^2.0.4",
|
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"rollup": "^1.0.0",
|
"rollup": "^1.11.3",
|
||||||
"rollup-plugin-babel": "^4.0.2",
|
"rollup-plugin-babel": "^4.3.2",
|
||||||
"rollup-plugin-commonjs": "^9.1.6",
|
"rollup-plugin-commonjs": "^9.3.4",
|
||||||
"rollup-plugin-node-resolve": "^4.0.0",
|
"rollup-plugin-node-resolve": "^4.2.3",
|
||||||
"rollup-plugin-replace": "^2.0.0",
|
"rollup-plugin-replace": "^2.2.0",
|
||||||
"rollup-plugin-svelte": "^5.0.1",
|
"rollup-plugin-svelte": "^5.0.3",
|
||||||
"rollup-plugin-terser": "^4.0.4",
|
"rollup-plugin-terser": "^4.0.4",
|
||||||
"sapper": "alpha",
|
"sapper": "alpha",
|
||||||
"svelte": "^3.1.0"
|
"svelte": "^3.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,13 +49,16 @@
|
|||||||
|
|
||||||
<div style="grid-area: start; display: flex; flex-direction: column; min-width: 0" slot="how">
|
<div style="grid-area: start; display: flex; flex-direction: column; min-width: 0" slot="how">
|
||||||
<pre class="language-bash" style="margin: 0 0 1em 0; min-width: 0; min-height: 0">
|
<pre class="language-bash" style="margin: 0 0 1em 0; min-width: 0; min-height: 0">
|
||||||
npx degit sveltejs/template my-svelte-project
|
# for Rollup
|
||||||
cd my-svelte-project
|
npx degit sveltejs/sapper-template#rollup my-app
|
||||||
|
# for webpack
|
||||||
|
npx degit sveltejs/sapper-template#webpack my-app
|
||||||
|
cd my-app
|
||||||
|
|
||||||
npm install
|
npm install
|
||||||
npm run dev & open http://localhost:5000
|
npm run dev & open http://localhost:3000
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p class="cta"><a rel="prefetch" href="docs">Learn Sapper</a></p>
|
<p class="cta"><a rel="prefetch" href="docs">Learn Sapper</a></p>
|
||||||
</div>
|
</div>
|
||||||
</Blurb>
|
</Blurb>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<html lang='en' class="theme-default typo-default">
|
<html lang='en' class="theme-default typo-default">
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name='viewport' content='width=device-width;initial-scale=1.0'>
|
<meta name='viewport' content='width=device-width,initial-scale=1.0'>
|
||||||
<meta name='theme-color' content='#ff3e00'>
|
<meta name='theme-color' content='#159794'>
|
||||||
|
|
||||||
%sapper.base%
|
%sapper.base%
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"background_color": "#ffffff",
|
"background_color": "#ffffff",
|
||||||
"theme_color": "#ff3e00",
|
"theme_color": "#159794",
|
||||||
"name": "Sapper",
|
"name": "Sapper",
|
||||||
"short_name": "Sapper",
|
"short_name": "Sapper",
|
||||||
"display": "minimal-ui",
|
"display": "minimal-ui",
|
||||||
|
|||||||
@@ -251,11 +251,11 @@ function generate_app(manifest_data: ManifestData, path_to_routes: string) {
|
|||||||
|
|
||||||
let l = max_depth;
|
let l = max_depth;
|
||||||
|
|
||||||
let pyramid = `<svelte:component this={level${l}.component} {...level${l}.props}/>`;
|
let pyramid = `<svelte:component this="{level${l}.component}" {...level${l}.props}/>`;
|
||||||
|
|
||||||
while (l-- > 1) {
|
while (l-- > 1) {
|
||||||
pyramid = `
|
pyramid = `
|
||||||
<svelte:component this={level${l}.component} segment={segments[${l}]} {...level${l}.props}>
|
<svelte:component this="{level${l}.component}" segment="{segments[${l}]}" {...level${l}.props}>
|
||||||
{#if level${l + 1}}
|
{#if level${l + 1}}
|
||||||
${pyramid.replace(/\n/g, '\n\t\t\t\t\t')}
|
${pyramid.replace(/\n/g, '\n\t\t\t\t\t')}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -281,7 +281,7 @@ function generate_app(manifest_data: ManifestData, path_to_routes: string) {
|
|||||||
setContext(CONTEXT_KEY, stores);
|
setContext(CONTEXT_KEY, stores);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Layout segment={segments[0]} {...level0.props}>
|
<Layout segment="{segments[0]}" {...level0.props}>
|
||||||
{#if error}
|
{#if error}
|
||||||
<Error {error} {status}/>
|
<Error {error} {status}/>
|
||||||
{:else}
|
{:else}
|
||||||
|
|||||||
@@ -25,6 +25,19 @@ export default function create_manifest_data(cwd: string): ManifestData {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function find_layout(file_name: string, component_name: string, dir: string = '') {
|
||||||
|
const ext = component_extensions.find((ext) => fs.existsSync(path.join(cwd, dir, `${file_name}${ext}`)));
|
||||||
|
const file = posixify(path.join(dir, `${file_name}${ext}`))
|
||||||
|
|
||||||
|
return ext
|
||||||
|
? {
|
||||||
|
name: component_name,
|
||||||
|
file: file,
|
||||||
|
has_preload: has_preload(file)
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
const components: PageComponent[] = [];
|
const components: PageComponent[] = [];
|
||||||
const pages: Page[] = [];
|
const pages: Page[] = [];
|
||||||
const server_routes: ServerRoute[] = [];
|
const server_routes: ServerRoute[] = [];
|
||||||
@@ -61,15 +74,19 @@ export default function create_manifest_data(cwd: string): ManifestData {
|
|||||||
const is_dir = fs.statSync(resolved).isDirectory();
|
const is_dir = fs.statSync(resolved).isDirectory();
|
||||||
|
|
||||||
const ext = path.extname(basename);
|
const ext = path.extname(basename);
|
||||||
|
|
||||||
|
if (basename[0] === '_') return null;
|
||||||
|
if (basename[0] === '.' && basename !== '.well-known') return null;
|
||||||
if (!is_dir && !/^\.[a-z]+$/i.test(ext)) return null; // filter out tmp files etc
|
if (!is_dir && !/^\.[a-z]+$/i.test(ext)) return null; // filter out tmp files etc
|
||||||
|
|
||||||
const segment = is_dir
|
const segment = is_dir
|
||||||
? basename
|
? basename
|
||||||
: basename.slice(0, -path.extname(basename).length);
|
: basename.slice(0, -ext.length);
|
||||||
|
|
||||||
const parts = get_parts(segment);
|
const parts = get_parts(segment);
|
||||||
const is_index = is_dir ? false : basename.startsWith('index.');
|
const is_index = is_dir ? false : basename.startsWith('index.');
|
||||||
const is_page = component_extensions.indexOf(ext) !== -1;
|
const is_page = component_extensions.indexOf(ext) !== -1;
|
||||||
|
const route_suffix = basename.slice(basename.indexOf('.'), -ext.length);
|
||||||
|
|
||||||
parts.forEach(part => {
|
parts.forEach(part => {
|
||||||
if (/\]\[/.test(part.content)) {
|
if (/\]\[/.test(part.content)) {
|
||||||
@@ -88,39 +105,35 @@ export default function create_manifest_data(cwd: string): ManifestData {
|
|||||||
file: posixify(file),
|
file: posixify(file),
|
||||||
is_dir,
|
is_dir,
|
||||||
is_index,
|
is_index,
|
||||||
is_page
|
is_page,
|
||||||
|
route_suffix
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.sort(comparator);
|
.sort(comparator);
|
||||||
|
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
if (item.basename[0] === '_') return;
|
|
||||||
|
|
||||||
if (item.basename[0] === '.') {
|
|
||||||
if (item.file !== '.well-known') return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const segments = parent_segments.slice();
|
const segments = parent_segments.slice();
|
||||||
|
|
||||||
if (item.is_index && segments.length > 0) {
|
if (item.is_index) {
|
||||||
const last_segment = segments[segments.length - 1].slice();
|
if (item.route_suffix) {
|
||||||
const suffix = item.basename
|
if (segments.length > 0) {
|
||||||
.slice(0, -path.extname(item.basename).length).
|
const last_segment = segments[segments.length - 1].slice();
|
||||||
replace('index', '');
|
const last_part = last_segment[last_segment.length - 1];
|
||||||
|
|
||||||
if (suffix) {
|
if (last_part.dynamic) {
|
||||||
const last_part = last_segment[last_segment.length - 1];
|
last_segment.push({ dynamic: false, content: item.route_suffix });
|
||||||
if (last_part.dynamic) {
|
} else {
|
||||||
last_segment.push({ dynamic: false, content: suffix });
|
last_segment[last_segment.length - 1] = {
|
||||||
|
dynamic: false,
|
||||||
|
content: `${last_part.content}${item.route_suffix}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
segments[segments.length - 1] = last_segment;
|
||||||
} else {
|
} else {
|
||||||
last_segment[last_segment.length - 1] = {
|
segments.push(item.parts);
|
||||||
dynamic: false,
|
|
||||||
content: `${last_part.content}${suffix}`
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
segments[segments.length - 1] = last_segment;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
segments.push(item.parts);
|
segments.push(item.parts);
|
||||||
@@ -130,16 +143,7 @@ export default function create_manifest_data(cwd: string): ManifestData {
|
|||||||
params.push(...item.parts.filter(p => p.dynamic).map(p => p.content));
|
params.push(...item.parts.filter(p => p.dynamic).map(p => p.content));
|
||||||
|
|
||||||
if (item.is_dir) {
|
if (item.is_dir) {
|
||||||
const ext = component_extensions.find((ext: string) => {
|
const component = find_layout('_layout', `${get_slug(item.file)}__layout`, item.file);
|
||||||
const index = path.join(dir, item.basename, `_layout${ext}`);
|
|
||||||
return fs.existsSync(index);
|
|
||||||
});
|
|
||||||
|
|
||||||
const component = ext && {
|
|
||||||
name: `${get_slug(item.file)}__layout`,
|
|
||||||
file: `${item.file}/_layout${ext}`,
|
|
||||||
has_preload: has_preload(`${item.file}/_layout${ext}`)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (component) components.push(component);
|
if (component) components.push(component);
|
||||||
|
|
||||||
@@ -154,8 +158,6 @@ export default function create_manifest_data(cwd: string): ManifestData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (item.is_page) {
|
else if (item.is_page) {
|
||||||
const is_index = item.basename === `index${item.ext}`;
|
|
||||||
|
|
||||||
const component = {
|
const component = {
|
||||||
name: get_slug(item.file),
|
name: get_slug(item.file),
|
||||||
file: item.file,
|
file: item.file,
|
||||||
@@ -164,22 +166,20 @@ export default function create_manifest_data(cwd: string): ManifestData {
|
|||||||
|
|
||||||
components.push(component);
|
components.push(component);
|
||||||
|
|
||||||
const parts = (is_index && stack[stack.length - 1] === null)
|
const parts = (item.is_index && stack[stack.length - 1] === null)
|
||||||
? stack.slice(0, -1).concat({ component, params })
|
? stack.slice(0, -1).concat({ component, params })
|
||||||
: stack.concat({ component, params })
|
: stack.concat({ component, params })
|
||||||
|
|
||||||
const page = {
|
pages.push({
|
||||||
pattern: get_pattern(is_index ? parent_segments : segments, true),
|
pattern: get_pattern(segments, true),
|
||||||
parts
|
parts
|
||||||
};
|
});
|
||||||
|
|
||||||
pages.push(page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
server_routes.push({
|
server_routes.push({
|
||||||
name: `route_${get_slug(item.file)}`,
|
name: `route_${get_slug(item.file)}`,
|
||||||
pattern: get_pattern(segments, false),
|
pattern: get_pattern(segments, !item.route_suffix),
|
||||||
file: item.file,
|
file: item.file,
|
||||||
params: params
|
params: params
|
||||||
});
|
});
|
||||||
@@ -187,23 +187,8 @@ export default function create_manifest_data(cwd: string): ManifestData {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const root_ext = component_extensions.find(ext => fs.existsSync(path.join(cwd, `_layout${ext}`)));
|
const root = find_layout('_layout', 'main') || default_layout;
|
||||||
const root = root_ext
|
const error = find_layout('_error', 'error') || default_error;
|
||||||
? {
|
|
||||||
name: 'main',
|
|
||||||
file: `_layout${root_ext}`,
|
|
||||||
has_preload: has_preload(`_layout${root_ext}`)
|
|
||||||
}
|
|
||||||
: default_layout;
|
|
||||||
|
|
||||||
const error_ext = component_extensions.find(ext => fs.existsSync(path.join(cwd, `_error${ext}`)));
|
|
||||||
const error = error_ext
|
|
||||||
? {
|
|
||||||
name: 'error',
|
|
||||||
file: `_error${error_ext}`,
|
|
||||||
has_preload: has_preload(`_error${error_ext}`)
|
|
||||||
}
|
|
||||||
: default_error;
|
|
||||||
|
|
||||||
walk(cwd, [], [], []);
|
walk(cwd, [], [], []);
|
||||||
|
|
||||||
@@ -249,7 +234,7 @@ type Part = {
|
|||||||
spread?: boolean;
|
spread?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function is_spead(path: string) {
|
function is_spread(path: string) {
|
||||||
const spread_pattern = /\[\.{3}/g;
|
const spread_pattern = /\[\.{3}/g;
|
||||||
return spread_pattern.test(path)
|
return spread_pattern.test(path)
|
||||||
}
|
}
|
||||||
@@ -259,9 +244,9 @@ function comparator(
|
|||||||
b: { basename: string, parts: Part[], file: string, is_index: boolean }
|
b: { basename: string, parts: Part[], file: string, is_index: boolean }
|
||||||
) {
|
) {
|
||||||
if (a.is_index !== b.is_index) {
|
if (a.is_index !== b.is_index) {
|
||||||
if (a.is_index) return is_spead(a.file) ? 1 : -1;
|
if (a.is_index) return is_spread(a.file) ? 1 : -1;
|
||||||
|
|
||||||
return is_spead(b.file) ? -1 : 1;
|
return is_spread(b.file) ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const max = Math.max(a.parts.length, b.parts.length);
|
const max = Math.max(a.parts.length, b.parts.length);
|
||||||
@@ -334,7 +319,6 @@ function get_parts(part: string): Part[] {
|
|||||||
function get_slug(file: string) {
|
function get_slug(file: string) {
|
||||||
let name = file
|
let name = file
|
||||||
.replace(/[\\\/]index/, '')
|
.replace(/[\\\/]index/, '')
|
||||||
.replace(/_default([\/\\index])?\.html$/, 'index')
|
|
||||||
.replace(/[\/\\]/g, '_')
|
.replace(/[\/\\]/g, '_')
|
||||||
.replace(/\.\w+$/, '')
|
.replace(/\.\w+$/, '')
|
||||||
.replace(/\[([^(]+)(?:\([^(]+\))?\]/, '$$$1')
|
.replace(/\[([^(]+)(?:\([^(]+\))?\]/, '$$$1')
|
||||||
@@ -347,19 +331,19 @@ function get_slug(file: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function get_pattern(segments: Part[][], add_trailing_slash: boolean) {
|
function get_pattern(segments: Part[][], add_trailing_slash: boolean) {
|
||||||
return new RegExp(
|
const path = segments.map(segment => {
|
||||||
`^` +
|
return segment.map(part => {
|
||||||
segments.map(segment => {
|
return part.dynamic
|
||||||
return '\\/' + segment.map(part => {
|
? part.qualifier || part.spread ? '(.+)' : '([^\\/]+?)'
|
||||||
return part.dynamic
|
: encodeURI(part.content.normalize())
|
||||||
? part.qualifier || part.spread ? '(.+)' : '([^\\/]+?)'
|
.replace(/\?/g, '%3F')
|
||||||
: encodeURI(part.content.normalize())
|
.replace(/#/g, '%23')
|
||||||
.replace(/\?/g, '%3F')
|
.replace(/%5B/g, '[')
|
||||||
.replace(/#/g, '%23')
|
.replace(/%5D/g, ']');
|
||||||
.replace(/%5B/g, '[')
|
}).join('');
|
||||||
.replace(/%5D/g, ']');
|
}).join('\\/');
|
||||||
}).join('');
|
|
||||||
}).join('') +
|
const trailing = add_trailing_slash && segments.length ? '\\/?$' : '$';
|
||||||
(add_trailing_slash ? '\\\/?$' : '$')
|
|
||||||
);
|
return new RegExp(`^\\/${path}${trailing}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,77 @@
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import puppeteer from 'puppeteer';
|
import puppeteer from 'puppeteer';
|
||||||
import * as ports from 'port-authority';
|
|
||||||
import { fork, ChildProcess } from 'child_process';
|
import { fork, ChildProcess } from 'child_process';
|
||||||
|
import { AddressInfo } from 'net';
|
||||||
|
|
||||||
|
import { wait } from '../utils'
|
||||||
|
|
||||||
|
const DEFAULT_ENTRY = '__sapper__/build/server/server.js';
|
||||||
|
const DELAY = parseInt(process.env.SAPPER_TEST_DELAY) || 50;
|
||||||
|
|
||||||
declare const start: () => Promise<void>;
|
declare const start: () => Promise<void>;
|
||||||
declare const prefetchRoutes: () => Promise<void>;
|
declare const prefetchRoutes: () => Promise<void>;
|
||||||
declare const prefetch: (href: string) => Promise<void>;
|
declare const prefetch: (href: string) => Promise<void>;
|
||||||
declare const goto: (href: string) => Promise<void>;
|
declare const goto: (href: string) => Promise<void>;
|
||||||
|
|
||||||
type StartOpts = {
|
|
||||||
requestInterceptor?: (interceptedRequst: puppeteer.Request) => any
|
|
||||||
};
|
|
||||||
|
|
||||||
export class AppRunner {
|
export class AppRunner {
|
||||||
cwd: string;
|
exiting: boolean;
|
||||||
entry: string;
|
terminate: Promise<any>;
|
||||||
port: number;
|
|
||||||
proc: ChildProcess;
|
server: ChildProcess;
|
||||||
|
address: AddressInfo;
|
||||||
|
base: string;
|
||||||
messages: any[];
|
messages: any[];
|
||||||
|
errors: Error[];
|
||||||
|
|
||||||
browser: puppeteer.Browser;
|
browser: puppeteer.Browser;
|
||||||
page: puppeteer.Page;
|
page: puppeteer.Page;
|
||||||
|
|
||||||
constructor(cwd: string, entry: string) {
|
sapper = {
|
||||||
this.cwd = cwd;
|
start: () => this.page.evaluate(() => start()).then(() => void 0),
|
||||||
this.entry = path.join(cwd, entry);
|
prefetchRoutes: () => this.page.evaluate(() => prefetchRoutes()).then(() => void 0),
|
||||||
|
prefetch: (href: string) => this.page.evaluate((href: string) => prefetch(href), href).then(() => void 0),
|
||||||
|
goto: (href: string) => this.page.evaluate((href: string) => goto(href), href).then(() => void 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor() {
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
|
this.errors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async start({ requestInterceptor }: StartOpts = {}) {
|
async start(cwd: string, entry: string = DEFAULT_ENTRY) {
|
||||||
this.port = await ports.find(3000);
|
const server_listening = deferred();
|
||||||
|
const server_closed = deferred();
|
||||||
|
const browser_closed = deferred();
|
||||||
|
|
||||||
this.proc = fork(this.entry, [], {
|
this.terminate = Promise.all([server_closed, browser_closed]);
|
||||||
cwd: this.cwd,
|
|
||||||
env: {
|
this.server = fork(path.join(cwd, entry), [], { cwd });
|
||||||
PORT: String(this.port)
|
this.server.on('exit', () => {
|
||||||
|
server_listening.reject();
|
||||||
|
server_closed.settle(this.exiting);
|
||||||
|
});
|
||||||
|
this.server.on('message', message => {
|
||||||
|
if (!message.__sapper__) return;
|
||||||
|
|
||||||
|
switch (message.event) {
|
||||||
|
case 'listening':
|
||||||
|
this.address = message.address;
|
||||||
|
this.base = `http://localhost:${this.address.port}`;
|
||||||
|
|
||||||
|
server_listening.resolve();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'error':
|
||||||
|
this.errors.push(Object.assign(new Error(), message.error));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.messages.push(message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.proc.on('message', message => {
|
|
||||||
if (!message.__sapper__) return;
|
|
||||||
this.messages.push(message);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.browser = await puppeteer.launch({ args: ['--no-sandbox'] });
|
this.browser = await puppeteer.launch({ args: ['--no-sandbox'] });
|
||||||
|
this.browser.on('disconnected', () => browser_closed.settle(this.exiting));
|
||||||
|
|
||||||
this.page = await this.browser.newPage();
|
this.page = await this.browser.newPage();
|
||||||
this.page.on('console', msg => {
|
this.page.on('console', msg => {
|
||||||
@@ -54,25 +82,28 @@ export class AppRunner {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (requestInterceptor) {
|
await server_listening;
|
||||||
await this.page.setRequestInterception(true);
|
|
||||||
this.page.on('request', requestInterceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return this;
|
||||||
page: this.page,
|
|
||||||
base: `http://localhost:${this.port}`,
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
start: () => this.page.evaluate(() => start()).then(() => void 0),
|
|
||||||
prefetchRoutes: () => this.page.evaluate(() => prefetchRoutes()).then(() => void 0),
|
|
||||||
prefetch: (href: string) => this.page.evaluate((href: string) => prefetch(href), href).then(() => void 0),
|
|
||||||
goto: (href: string) => this.page.evaluate((href: string) => goto(href), href).then(() => void 0),
|
|
||||||
title: () => this.page.$eval('h1', node => node.textContent).then(serializable => String(serializable))
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
capture(fn: () => any): Promise<string[]> {
|
load(url: string) {
|
||||||
|
if (url[0] === '/') {
|
||||||
|
url = `${this.base}${url}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.page.goto(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
text(selector: string) {
|
||||||
|
return this.page.$eval(selector, node => node.textContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
wait(extra_ms: number = 0) {
|
||||||
|
return wait(DELAY + extra_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
capture_requests(fn: () => any): Promise<string[]> {
|
||||||
return new Promise((fulfil, reject) => {
|
return new Promise((fulfil, reject) => {
|
||||||
const requests: string[] = [];
|
const requests: string[] = [];
|
||||||
const pending: Set<string> = new Set();
|
const pending: Set<string> = new Set();
|
||||||
@@ -120,13 +151,55 @@ export class AppRunner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
end() {
|
async intercept_requests(interceptor: (request: puppeteer.Request) => void, fn: () => any): Promise<void> {
|
||||||
return Promise.all([
|
const unique_interceptor = request => interceptor(request);
|
||||||
this.browser.close(),
|
|
||||||
new Promise(fulfil => {
|
this.page.prependListener('request', unique_interceptor);
|
||||||
this.proc.once('exit', fulfil);
|
await this.page.setRequestInterception(true);
|
||||||
this.proc.kill();
|
|
||||||
})
|
const result = await Promise.resolve(fn());
|
||||||
]);
|
|
||||||
|
await this.page.setRequestInterception(false);
|
||||||
|
this.page.removeListener('request', unique_interceptor);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
end() {
|
||||||
|
this.exiting = true;
|
||||||
|
|
||||||
|
this.server.kill();
|
||||||
|
this.browser.close();
|
||||||
|
|
||||||
|
return this.terminate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Deferred<T> extends Promise<T> {
|
||||||
|
resolve: (value?: T | PromiseLike<T>) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
settle: (result?: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function settle<T>(this: Deferred<T>, result: boolean) {
|
||||||
|
if (result) {
|
||||||
|
this.resolve();
|
||||||
|
} else {
|
||||||
|
this.reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deferred<T>() {
|
||||||
|
let resolve, reject;
|
||||||
|
|
||||||
|
const deferred = new Promise((_resolve, _reject) => {
|
||||||
|
resolve = _resolve;
|
||||||
|
reject = _reject;
|
||||||
|
}) as Deferred<T>;
|
||||||
|
|
||||||
|
deferred.resolve = resolve;
|
||||||
|
deferred.reject = reject;
|
||||||
|
deferred.settle = settle;
|
||||||
|
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|||||||
14
test/apps/basics/src/routes/skipped/[one]/[two].svelte
Normal file
14
test/apps/basics/src/routes/skipped/[one]/[two].svelte
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<script context="module">
|
||||||
|
export function preload({ params }) {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let one;
|
||||||
|
export let two;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>{one}:{two}</h1>
|
||||||
|
|
||||||
|
<a href="skipped/y/1">skipped/y/1</a>
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware())
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
|
||||||
|
|
||||||
declare let deleted: { id: number };
|
declare let deleted: { id: number };
|
||||||
declare let el: any;
|
declare let el: any;
|
||||||
|
|
||||||
function get(url: string, opts?: any): Promise<{ headers: Record<string, string>, body: string }> {
|
type Response = { headers: http.IncomingHttpHeaders, body: string };
|
||||||
|
|
||||||
|
function get(url: string, opts: http.RequestOptions = {}): Promise<Response> {
|
||||||
return new Promise((fulfil, reject) => {
|
return new Promise((fulfil, reject) => {
|
||||||
const req = http.get(url, opts || {}, res => {
|
const req = http.get(url, opts, res => {
|
||||||
res.on('error', reject);
|
res.on('error', reject);
|
||||||
|
|
||||||
let body = '';
|
let body = '';
|
||||||
res.on('data', chunk => body += chunk);
|
res.on('data', chunk => body += chunk);
|
||||||
res.on('end', () => {
|
res.on('end', () => {
|
||||||
fulfil({
|
fulfil({
|
||||||
headers: res.headers as Record<string, string>,
|
headers: res.headers,
|
||||||
body
|
body
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -30,114 +30,104 @@ function get(url: string, opts?: any): Promise<{ headers: Record<string, string>
|
|||||||
describe('basics', function() {
|
describe('basics', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
let prefetch: (href: string) => Promise<void>;
|
|
||||||
let goto: (href: string) => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes, prefetch, goto, title } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('serves /', async () => {
|
it('serves /', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'Great success!'
|
'Great success!'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('serves /?', async () => {
|
it('serves /?', async () => {
|
||||||
await page.goto(`${base}?`);
|
await r.load('/?');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'Great success!'
|
'Great success!'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('serves static route', async () => {
|
it('serves static route', async () => {
|
||||||
await page.goto(`${base}/a`);
|
await r.load('/a');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'a'
|
'a'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('serves static route from dir/index.html file', async () => {
|
it('serves static route from dir/index.html file', async () => {
|
||||||
await page.goto(`${base}/b`);
|
await r.load('/b');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'b'
|
'b'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('serves dynamic route', async () => {
|
it('serves dynamic route', async () => {
|
||||||
await page.goto(`${base}/test-slug`);
|
await r.load('/test-slug');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'TEST-SLUG'
|
'TEST-SLUG'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates to a new page without reloading', async () => {
|
it('navigates to a new page without reloading', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
const requests: string[] = await runner.capture(async () => {
|
const requests: string[] = await r.capture_requests(async () => {
|
||||||
await page.click('a[href="a"]');
|
await r.page.click('a[href="a"]');
|
||||||
|
await r.wait();
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.deepEqual(requests, []);
|
assert.deepEqual(requests, []);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'a'
|
'a'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates programmatically', async () => {
|
it('navigates programmatically', async () => {
|
||||||
await page.goto(`${base}/a`);
|
await r.load('/a');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
await r.sapper.goto('b');
|
||||||
await goto('b');
|
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'b'
|
'b'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prefetches programmatically', async () => {
|
it('prefetches programmatically', async () => {
|
||||||
await page.goto(`${base}/a`);
|
await r.load(`/a`);
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
const requests = await runner.capture(() => prefetch('b'));
|
const requests = await r.capture_requests(() => r.sapper.prefetch('b'));
|
||||||
|
|
||||||
assert.equal(requests.length, 2);
|
assert.equal(requests.length, 2);
|
||||||
assert.equal(requests[1], `${base}/b.json`);
|
assert.equal(requests[1], `${r.base}/b.json`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO equivalent test for a webpack app
|
// TODO equivalent test for a webpack app
|
||||||
it('sets Content-Type, Link...modulepreload, and Cache-Control headers', async () => {
|
it('sets Content-Type, Link...modulepreload, and Cache-Control headers', async () => {
|
||||||
const { headers } = await get(base);
|
const { headers } = await get(r.base);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
headers['content-type'],
|
headers['content-type'],
|
||||||
@@ -157,162 +147,163 @@ describe('basics', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('calls a delete handler', async () => {
|
it('calls a delete handler', async () => {
|
||||||
await page.goto(`${base}/delete-test`);
|
await r.load('/delete-test');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
await page.click('.del');
|
await r.page.click('.del');
|
||||||
await page.waitForFunction(() => deleted);
|
await r.page.waitForFunction(() => deleted);
|
||||||
|
|
||||||
assert.equal(await page.evaluate(() => deleted.id), 42);
|
assert.equal(await r.page.evaluate(() => deleted.id), 42);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('hydrates initial route', async () => {
|
it('hydrates initial route', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
|
|
||||||
await page.evaluate(() => {
|
await r.page.evaluate(() => {
|
||||||
el = document.querySelector('.hydrate-test');
|
el = document.querySelector('.hydrate-test');
|
||||||
});
|
});
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
assert.ok(await page.evaluate(() => {
|
assert.ok(await r.page.evaluate(() => {
|
||||||
return document.querySelector('.hydrate-test') === el;
|
return document.querySelector('.hydrate-test') === el;
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not attempt client-side navigation to server routes', async () => {
|
it('does not attempt client-side navigation to server routes', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click(`[href="ambiguous/ok.json"]`);
|
await r.page.click('[href="ambiguous/ok.json"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.body.textContent),
|
await r.text('body'),
|
||||||
'ok'
|
'ok'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows reserved words as route names', async () => {
|
it('allows reserved words as route names', async () => {
|
||||||
await page.goto(`${base}/const`);
|
await r.load('/const');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'reserved words are okay as routes'
|
'reserved words are okay as routes'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts value-less query string parameter on server', async () => {
|
it('accepts value-less query string parameter on server', async () => {
|
||||||
await page.goto(`${base}/echo-query?message`);
|
await r.load('/echo-query?message');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'{"message":""}'
|
'{"message":""}'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts value-less query string parameter on client', async () => {
|
it('accepts value-less query string parameter on client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('a[href="echo-query?message"]')
|
await r.page.click('a[href="echo-query?message"]');
|
||||||
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'{"message":""}'
|
'{"message":""}'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts duplicated query string parameter on server', async () => {
|
it('accepts duplicated query string parameter on server', async () => {
|
||||||
await page.goto(`${base}/echo-query?p=one&p=two`);
|
await r.load('/echo-query?p=one&p=two');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'{"p":["one","two"]}'
|
'{"p":["one","two"]}'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts duplicated query string parameter on client', async () => {
|
it('accepts duplicated query string parameter on client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('a[href="echo-query?p=one&p=two"]')
|
await r.page.click('a[href="echo-query?p=one&p=two"]')
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'{"p":["one","two"]}'
|
'{"p":["one","two"]}'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// skipped because Nightmare doesn't seem to focus the <a> correctly
|
// skipped because Nightmare doesn't seem to focus the <a> correctly
|
||||||
it('resets the active element after navigation', async () => {
|
it('resets the active element after navigation', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="a"]');
|
await r.page.click('[href="a"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.activeElement.nodeName),
|
await r.page.evaluate(() => document.activeElement.nodeName),
|
||||||
'BODY'
|
'BODY'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('replaces %sapper.xxx% tags safely', async () => {
|
it('replaces %sapper.xxx% tags safely', async () => {
|
||||||
await page.goto(`${base}/unsafe-replacement`);
|
await r.load('/unsafe-replacement');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
const html = String(await page.evaluate(() => document.body.innerHTML));
|
const html = String(await r.page.evaluate(() => document.body.innerHTML));
|
||||||
assert.equal(html.indexOf('%sapper'), -1);
|
assert.equal(html.indexOf('%sapper'), -1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates between routes with empty parts', async () => {
|
it('navigates between routes with empty parts', async () => {
|
||||||
await page.goto(`${base}/dirs/foo`);
|
await r.load('/dirs/foo');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
assert.equal(await title(), 'foo');
|
assert.equal(await r.text('h1'), 'foo');
|
||||||
|
|
||||||
await page.click('[href="dirs/bar"]');
|
await r.page.click('[href="dirs/bar"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
assert.equal(await title(), 'bar');
|
assert.equal(await r.text('h1'), 'bar');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates to ...rest', async () => {
|
it('navigates to ...rest', async () => {
|
||||||
await page.goto(`${base}/abc/xyz`);
|
await r.load('/abc/xyz');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
assert.equal(await title(), 'abc,xyz');
|
assert.equal(await r.text('h1'), 'abc,xyz');
|
||||||
|
|
||||||
await page.click('[href="xyz/abc/deep"]');
|
await r.page.click('[href="xyz/abc/deep"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
assert.equal(await title(), 'xyz,abc');
|
assert.equal(await r.text('h1'), 'xyz,abc');
|
||||||
|
|
||||||
await page.click(`[href="xyz/abc/qwe/deep.json"]`);
|
await r.page.click('[href="xyz/abc/qwe/deep.json"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.body.textContent),
|
await r.text('body'),
|
||||||
'xyz,abc,qwe'
|
'xyz,abc,qwe'
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
it('navigates between dynamic routes with same segments', async () => {
|
|
||||||
await page.goto(`${base}/dirs/bar/xyz`);
|
|
||||||
await start();
|
|
||||||
|
|
||||||
assert.equal(await title(), 'A page');
|
|
||||||
|
|
||||||
await page.click('[href="dirs/foo/xyz"]');
|
|
||||||
await wait(50);
|
|
||||||
assert.equal(await title(), 'B page');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('navigates between dynamic routes with same segments', async () => {
|
||||||
|
await r.load('/dirs/bar/xyz');
|
||||||
|
await r.sapper.start();
|
||||||
|
|
||||||
|
assert.equal(await r.text('h1'), 'A page');
|
||||||
|
|
||||||
|
await r.page.click('[href="dirs/foo/xyz"]');
|
||||||
|
await r.wait();
|
||||||
|
assert.equal(await r.text('h1'), 'B page');
|
||||||
|
});
|
||||||
|
|
||||||
it('runs server route handlers before page handlers, if they match', async () => {
|
it('runs server route handlers before page handlers, if they match', async () => {
|
||||||
const json = await get(`${base}/middleware`, {
|
const json = await get(`${r.base}/middleware`, {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
}
|
}
|
||||||
@@ -320,8 +311,26 @@ describe('basics', function() {
|
|||||||
|
|
||||||
assert.equal(json.body, '{"json":true}');
|
assert.equal(json.body, '{"json":true}');
|
||||||
|
|
||||||
const html = await get(`${base}/middleware`);
|
const html = await get(`${r.base}/middleware`);
|
||||||
|
|
||||||
assert.ok(html.body.indexOf('<h1>HTML</h1>') !== -1);
|
assert.ok(html.body.indexOf('<h1>HTML</h1>') !== -1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('invalidates page when a segment is skipped', async () => {
|
||||||
|
await r.load('/skipped/x/1');
|
||||||
|
await r.sapper.start();
|
||||||
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
|
await r.page.click('a[href="skipped/y/1"]');
|
||||||
|
await r.wait();
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
await r.text('h1'),
|
||||||
|
'y:1'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
42
test/apps/common.js
Normal file
42
test/apps/common.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
const { NODE_ENV, PORT } = process.env;
|
||||||
|
|
||||||
|
export const dev = NODE_ENV === 'development';
|
||||||
|
|
||||||
|
export function start(app) {
|
||||||
|
const port = parseInt(PORT) || 0;
|
||||||
|
|
||||||
|
app.listen(port, () => {
|
||||||
|
const address = app.server.address();
|
||||||
|
|
||||||
|
process.env.PORT = address.port;
|
||||||
|
|
||||||
|
send({
|
||||||
|
__sapper__: true,
|
||||||
|
event: 'listening',
|
||||||
|
address
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const properties = ['name', 'message', 'stack', 'code', 'lineNumber', 'fileName'];
|
||||||
|
|
||||||
|
function send(message) {
|
||||||
|
process.send && process.send(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
function send_error(error) {
|
||||||
|
send({
|
||||||
|
__sapper__: true,
|
||||||
|
event: 'error',
|
||||||
|
error: properties.reduce((object, key) => ({...object, [key]: error[key]}), {})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('unhandledRejection', (reason, p) => {
|
||||||
|
send_error(reason);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('uncaughtException', err => {
|
||||||
|
send_error(err);
|
||||||
|
process.exitCode = 1;
|
||||||
|
});
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use((req, res, next) => {
|
.use((req, res, next) => {
|
||||||
// set test cookie
|
// set test cookie
|
||||||
res.setHeader('Set-Cookie', ['a=1; Max-Age=3600', 'b=2; Max-Age=3600']);
|
res.setHeader('Set-Cookie', ['a=1; Max-Age=3600', 'b=2; Max-Age=3600']);
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware())
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,59 +1,54 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { wait } from '../../utils';
|
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
|
|
||||||
describe('credentials', function() {
|
describe('credentials', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('sends cookies when using this.fetch with credentials: "include"', async () => {
|
it('sends cookies when using this.fetch with credentials: "include"', async () => {
|
||||||
await page.goto(`${base}/credentials?creds=include`);
|
await r.load('/credentials?creds=include');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'a: 1, b: 2, max-age: undefined'
|
'a: 1, b: 2, max-age: undefined'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not send cookies when using this.fetch without credentials', async () => {
|
it('does not send cookies when using this.fetch without credentials', async () => {
|
||||||
await page.goto(`${base}/credentials`);
|
await r.load('/credentials');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'unauthorized'
|
'unauthorized'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('delegates to fetch on the client', async () => {
|
it('delegates to fetch on the client', async () => {
|
||||||
await page.goto(base)
|
await r.load('/')
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="credentials?creds=include"]');
|
await r.page.click('[href="credentials?creds=include"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'a: 1, b: 2, max-age: undefined'
|
'a: 1, b: 2, max-age: undefined'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,78 +1,61 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
|
||||||
|
|
||||||
describe('css', function() {
|
describe('css', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
let prefetch: (href: string) => Promise<void>;
|
|
||||||
let goto: (href: string) => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes, prefetch, goto, title } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('includes critical CSS with server render', async () => {
|
it('includes critical CSS with server render', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => {
|
await r.page.$eval('h1', node => getComputedStyle(node).color),
|
||||||
const h1 = document.querySelector('h1');
|
|
||||||
return getComputedStyle(h1).color;
|
|
||||||
}),
|
|
||||||
'rgb(255, 0, 0)'
|
'rgb(255, 0, 0)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads CSS when navigating client-side', async () => {
|
it('loads CSS when navigating client-side', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click(`[href="foo"]`);
|
await r.page.click(`[href="foo"]`);
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => {
|
await r.page.$eval('h1', node => getComputedStyle(node).color),
|
||||||
const h1 = document.querySelector('h1');
|
|
||||||
return getComputedStyle(h1).color;
|
|
||||||
}),
|
|
||||||
'rgb(0, 0, 255)'
|
'rgb(0, 0, 255)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads CSS for a lazily-rendered component', async () => {
|
it('loads CSS for a lazily-rendered component', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click(`[href="bar"]`);
|
await r.page.click(`[href="bar"]`);
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => {
|
await r.page.$eval('h1', node => getComputedStyle(node).color),
|
||||||
const h1 = document.querySelector('h1');
|
|
||||||
return getComputedStyle(h1).color;
|
|
||||||
}),
|
|
||||||
'rgb(0, 128, 0)'
|
'rgb(0, 128, 0)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,68 +1,63 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
|
||||||
|
|
||||||
describe('encoding', function() {
|
describe('encoding', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('encodes routes', async () => {
|
it('encodes routes', async () => {
|
||||||
await page.goto(`${base}/fünke`);
|
await r.load('/fünke');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
`I'm afraid I just blue myself`
|
`I'm afraid I just blue myself`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes req.params and req.query for server-rendered pages', async () => {
|
it('encodes req.params and req.query for server-rendered pages', async () => {
|
||||||
await page.goto(`${base}/echo/page/encöded?message=hëllö+wörld&föo=bar&=baz&tel=%2B123456789`);
|
await r.load('/echo/page/encöded?message=hëllö+wörld&föo=bar&=baz&tel=%2B123456789');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'encöded {"message":"hëllö wörld","föo":"bar","":"baz","tel":"+123456789"}'
|
'encöded {"message":"hëllö wörld","föo":"bar","":"baz","tel":"+123456789"}'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes req.params and req.query for client-rendered pages', async () => {
|
it('encodes req.params and req.query for client-rendered pages', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('a');
|
await r.page.click('a');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'encöded {"message":"hëllö wörld","föo":"bar","":"baz","tel":"+123456789"}'
|
'encöded {"message":"hëllö wörld","föo":"bar","":"baz","tel":"+123456789"}'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes req.params for server routes', async () => {
|
it('encodes req.params for server routes', async () => {
|
||||||
await page.goto(`${base}/echo/server-route/encöded`);
|
await r.load('/echo/server-route/encöded');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'encöded'
|
'encöded'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
<h1>{error ? error.message : 'No error here'}</h1>
|
<script>
|
||||||
|
export let error;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>{error ? error.message : 'No error here'}</h1>
|
||||||
|
|
||||||
<a href="enhance-your-calm">Enhance your calm</a>
|
<a href="enhance-your-calm">Enhance your calm</a>
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
import { wait } from '../../utils';
|
||||||
@@ -7,142 +6,137 @@ import { wait } from '../../utils';
|
|||||||
describe('errors', function() {
|
describe('errors', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes, title } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('handles missing route on server', async () => {
|
it('handles missing route on server', async () => {
|
||||||
await page.goto(`${base}/nope`);
|
await r.load('/nope');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'404'
|
'404'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles missing route on client', async () => {
|
it('handles missing route on client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
await page.click('[href="nope"]');
|
await r.page.click('[href="nope"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'404'
|
'404'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles explicit 4xx on server', async () => {
|
it('handles explicit 4xx on server', async () => {
|
||||||
await page.goto(`${base}/blog/nope`);
|
await r.load('/blog/nope');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'404'
|
'404'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles explicit 4xx on client', async () => {
|
it('handles explicit 4xx on client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="blog/nope"]');
|
await r.page.click('[href="blog/nope"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'404'
|
'404'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles error on server', async () => {
|
it('handles error on server', async () => {
|
||||||
await page.goto(`${base}/throw`);
|
await r.load('/throw');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'500'
|
'500'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles error on client', async () => {
|
it('handles error on client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="throw"]');
|
await r.page.click('[href="throw"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'500'
|
'500'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not serve error page for explicit non-page errors', async () => {
|
it('does not serve error page for explicit non-page errors', async () => {
|
||||||
await page.goto(`${base}/nope.json`);
|
await r.load('/nope.json');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.body.textContent),
|
await r.text('body'),
|
||||||
'nope'
|
'nope'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not serve error page for thrown non-page errors', async () => {
|
it('does not serve error page for thrown non-page errors', async () => {
|
||||||
await page.goto(`${base}/throw.json`);
|
await r.load('/throw.json');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.body.textContent),
|
await r.text('body'),
|
||||||
'oops'
|
'oops'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('execute error page hooks', async () => {
|
it('execute error page hooks', async () => {
|
||||||
await page.goto(`${base}/some-throw-page`);
|
await r.load('/some-throw-page');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await wait(50);
|
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h2', node => node.textContent),
|
await r.text('h2'),
|
||||||
'success'
|
'success'
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
it('does not serve error page for async non-page error', async () => {
|
it('does not serve error page for async non-page error', async () => {
|
||||||
await page.goto(`${base}/async-throw.json`);
|
await r.load('/async-throw.json');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.body.textContent),
|
await r.text('body'),
|
||||||
'oops'
|
'oops'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clears props.error on successful render', async () => {
|
it('clears props.error on successful render', async () => {
|
||||||
await page.goto(`${base}/no-error`);
|
await r.load('/no-error');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="enhance-your-calm"]');
|
await r.page.click('[href="enhance-your-calm"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
assert.equal(await title(), '420');
|
assert.equal(await r.text('h1'), '420');
|
||||||
|
|
||||||
await page.goBack();
|
await r.page.goBack();
|
||||||
await wait(50);
|
await r.wait();
|
||||||
assert.equal(await title(), 'No error here');
|
assert.equal(await r.text('h1'), 'No error here');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ import sirv from 'sirv';
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT, NODE_ENV } = process.env;
|
import { start, dev } from '../../common.js';
|
||||||
const dev = NODE_ENV === 'development';
|
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(
|
.use(
|
||||||
sirv('static', { dev }),
|
sirv('static', { dev }),
|
||||||
sapper.middleware()
|
sapper.middleware()
|
||||||
)
|
);
|
||||||
.listen(PORT, err => {
|
|
||||||
if (err) console.log('error', err);
|
start(app);
|
||||||
});
|
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ describe('export-webpack', function() {
|
|||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => api.build({ cwd: __dirname, bundler: 'webpack' }));
|
||||||
await api.build({ cwd: __dirname, bundler: 'webpack' });
|
before('export app', () => api.export({ cwd: __dirname }));
|
||||||
await api.export({ cwd: __dirname, bundler: 'webpack' });
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// tests
|
||||||
it('injects <link rel=preload> tags', () => {
|
it('injects <link rel=preload> tags', () => {
|
||||||
const index = fs.readFileSync(`${__dirname}/__sapper__/export/index.html`, 'utf8');
|
const index = fs.readFileSync(`${__dirname}/__sapper__/export/index.html`, 'utf8');
|
||||||
assert.ok(/rel=preload/.test(index));
|
assert.ok(/rel=preload/.test(index));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ import sirv from 'sirv';
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT, NODE_ENV } = process.env;
|
import { start, dev } from '../../common.js';
|
||||||
const dev = NODE_ENV === 'development';
|
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(
|
.use(
|
||||||
sirv('static', { dev }),
|
sirv('static', { dev }),
|
||||||
sapper.middleware()
|
sapper.middleware()
|
||||||
)
|
);
|
||||||
.listen(PORT, err => {
|
|
||||||
if (err) console.log('error', err);
|
start(app);
|
||||||
});
|
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ describe('export', function() {
|
|||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => api.build({ cwd: __dirname }));
|
||||||
await api.build({ cwd: __dirname });
|
before('export app', () => api.export({ cwd: __dirname }));
|
||||||
await api.export({ cwd: __dirname });
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// tests
|
||||||
it('crawls a site', () => {
|
it('crawls a site', () => {
|
||||||
const files = walk(`${__dirname}/__sapper__/export`);
|
const files = walk(`${__dirname}/__sapper__/export`);
|
||||||
|
|
||||||
@@ -45,4 +44,4 @@ describe('export', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// TODO test timeout, basepath
|
// TODO test timeout, basepath
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
<h1>{status}</h1>
|
<script>
|
||||||
|
export let status;
|
||||||
|
export let error;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>{status}</h1>
|
||||||
|
|
||||||
<p>{error.message}</p>
|
<p>{error.message}</p>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
const app = polka().use(sapper.middleware({
|
const app = polka().use(sapper.middleware({
|
||||||
ignore: [
|
ignore: [
|
||||||
@@ -16,4 +16,4 @@ const app = polka().use(sapper.middleware({
|
|||||||
app.get('/'+uri, (req, res) => res.end(uri));
|
app.get('/'+uri, (req, res) => res.end(uri));
|
||||||
});
|
});
|
||||||
|
|
||||||
app.listen(PORT);
|
start(app);
|
||||||
|
|||||||
@@ -1,58 +1,58 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
|
|
||||||
describe('ignore', function() {
|
describe('ignore', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('respects `options.ignore` values (RegExp)', async () => {
|
it('respects `options.ignore` values (RegExp)', async () => {
|
||||||
await page.goto(`${base}/foobar`);
|
await r.load('/foobar');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.documentElement.textContent),
|
await r.text('body'),
|
||||||
'foobar'
|
'foobar'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('respects `options.ignore` values (String #1)', async () => {
|
it('respects `options.ignore` values (String #1)', async () => {
|
||||||
await page.goto(`${base}/buzz`);
|
await r.load('/buzz');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.documentElement.textContent),
|
await r.text('body'),
|
||||||
'buzz'
|
'buzz'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('respects `options.ignore` values (String #2)', async () => {
|
it('respects `options.ignore` values (String #2)', async () => {
|
||||||
await page.goto(`${base}/fizzer`);
|
await r.load('/fizzer');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.documentElement.textContent),
|
await r.text('body'),
|
||||||
'fizzer'
|
'fizzer'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('respects `options.ignore` values (Function)', async () => {
|
it('respects `options.ignore` values (Function)', async () => {
|
||||||
await page.goto(`${base}/hello`);
|
await r.load('/hello');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => document.documentElement.textContent),
|
await r.text('body'),
|
||||||
'hello'
|
'hello'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,33 +1,25 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
|
||||||
|
|
||||||
describe('layout', function() {
|
describe('layout', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('only recreates components when necessary', async () => {
|
it('only recreates components when necessary', async () => {
|
||||||
await page.goto(`${base}/foo/bar/baz`);
|
await r.load('/foo/bar/baz');
|
||||||
|
|
||||||
const text1 = String(await page.evaluate(() => document.querySelector('#sapper').textContent));
|
const text1 = await r.text('#sapper');
|
||||||
assert.deepEqual(text1.split('\n').map(str => str.trim()).filter(Boolean), [
|
assert.deepEqual(text1.split('\n').map(str => str.trim()).filter(Boolean), [
|
||||||
'y: bar 1',
|
'y: bar 1',
|
||||||
'z: baz 1',
|
'z: baz 1',
|
||||||
@@ -35,8 +27,8 @@ describe('layout', function() {
|
|||||||
'child segment: baz'
|
'child segment: baz'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
const text2 = String(await page.evaluate(() => document.querySelector('#sapper').textContent));
|
const text2 = await r.text('#sapper');
|
||||||
assert.deepEqual(text2.split('\n').map(str => str.trim()).filter(Boolean), [
|
assert.deepEqual(text2.split('\n').map(str => str.trim()).filter(Boolean), [
|
||||||
'y: bar 1',
|
'y: bar 1',
|
||||||
'z: baz 1',
|
'z: baz 1',
|
||||||
@@ -44,10 +36,10 @@ describe('layout', function() {
|
|||||||
'child segment: baz'
|
'child segment: baz'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await page.click('[href="foo/bar/qux"]');
|
await r.page.click('[href="foo/bar/qux"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
const text3 = String(await page.evaluate(() => document.querySelector('#sapper').textContent));
|
const text3 = await r.text('#sapper');
|
||||||
assert.deepEqual(text3.split('\n').map(str => str.trim()).filter(Boolean), [
|
assert.deepEqual(text3.split('\n').map(str => str.trim()).filter(Boolean), [
|
||||||
'y: bar 1',
|
'y: bar 1',
|
||||||
'z: qux 2',
|
'z: qux 2',
|
||||||
@@ -55,4 +47,8 @@ describe('layout', function() {
|
|||||||
'child segment: qux'
|
'child segment: qux'
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { wait } from '../../utils';
|
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
|
|
||||||
declare const fulfil: () => Promise<void>;
|
declare const fulfil: () => Promise<void>;
|
||||||
@@ -9,112 +7,106 @@ declare const fulfil: () => Promise<void>;
|
|||||||
describe('preloading', function() {
|
describe('preloading', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes, title } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('serializes Set objects returned from preload', async () => {
|
it('serializes Set objects returned from preload', async () => {
|
||||||
await page.goto(`${base}/preload-values/set`);
|
await r.load('/preload-values/set');
|
||||||
|
|
||||||
assert.equal(await title(), 'true');
|
assert.equal(await r.text('h1'), 'true');
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
assert.equal(await title(), 'true');
|
assert.equal(await r.text('h1'), 'true');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prevent crash if preload return nothing', async () => {
|
it('prevent crash if preload return nothing', async () => {
|
||||||
await page.goto(`${base}/preload-nothing`);
|
await r.load('/preload-nothing');
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await wait(50);
|
|
||||||
|
|
||||||
assert.equal(await title(), 'Page loaded');
|
assert.equal(await r.text('h1'), 'Page loaded');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bails on custom classes returned from preload', async () => {
|
it('bails on custom classes returned from preload', async () => {
|
||||||
await page.goto(`${base}/preload-values/custom-class`);
|
await r.load('/preload-values/custom-class');
|
||||||
|
|
||||||
assert.equal(await title(), '42');
|
assert.equal(await r.text('h1'), '42');
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
assert.equal(await title(), '42');
|
assert.equal(await r.text('h1'), '42');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets preloading true when appropriate', async () => {
|
it('sets preloading true when appropriate', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('a[href="slow-preload"]');
|
await r.page.click('a[href="slow-preload"]');
|
||||||
|
|
||||||
assert.ok(await page.evaluate(() => !!document.querySelector('progress')));
|
assert.ok(await r.page.evaluate(() => !!document.querySelector('progress')));
|
||||||
|
|
||||||
await page.evaluate(() => fulfil());
|
await r.page.evaluate(() => fulfil());
|
||||||
assert.ok(await page.evaluate(() => !document.querySelector('progress')));
|
assert.ok(await r.page.evaluate(() => !document.querySelector('progress')));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('runs preload in root component', async () => {
|
it('runs preload in root component', async () => {
|
||||||
await page.goto(`${base}/preload-root`);
|
await r.load('/preload-root');
|
||||||
assert.equal(await title(), 'root preload function ran: true');
|
assert.equal(await r.text('h1'), 'root preload function ran: true');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('cancels navigation if subsequent navigation occurs during preload', async () => {
|
it('cancels navigation if subsequent navigation occurs during preload', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('a[href="slow-preload"]');
|
await r.page.click('a[href="slow-preload"]');
|
||||||
await wait(100);
|
await r.wait();
|
||||||
await page.click('a[href="foo"]');
|
await r.page.click('a[href="foo"]');
|
||||||
|
|
||||||
assert.equal(page.url(), `${base}/foo`);
|
assert.equal(r.page.url(), `${r.base}/foo`);
|
||||||
assert.equal(await title(), 'foo');
|
assert.equal(await r.text('h1'), 'foo');
|
||||||
|
|
||||||
await page.evaluate(() => fulfil());
|
await r.page.evaluate(() => fulfil());
|
||||||
await wait(100);
|
await r.wait();
|
||||||
assert.equal(page.url(), `${base}/foo`);
|
assert.equal(r.page.url(), `${r.base}/foo`);
|
||||||
assert.equal(await title(), 'foo');
|
assert.equal(await r.text('h1'), 'foo');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates to prefetched urls', async () => {
|
it('navigates to prefetched urls', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.hover('a[href="prefetch/qwe"]');
|
await r.page.hover('a[href="prefetch/qwe"]');
|
||||||
await wait(100);
|
await r.wait(50);
|
||||||
await page.hover('a[href="prefetch/xyz"]');
|
await r.page.hover('a[href="prefetch/xyz"]');
|
||||||
await wait(100);
|
await r.wait(50);
|
||||||
|
|
||||||
await page.click('a[href="prefetch/qwe"]');
|
await r.page.click('a[href="prefetch/qwe"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'qwe'
|
'qwe'
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.goto(`${base}/prefetch`);
|
await r.load('/prefetch');
|
||||||
await wait(50);
|
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'prefetch'
|
'prefetch'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -2,138 +2,137 @@ import * as assert from 'assert';
|
|||||||
import * as puppeteer from 'puppeteer';
|
import * as puppeteer from 'puppeteer';
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
|
||||||
|
|
||||||
describe('redirects', function() {
|
describe('redirects', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes, title } = await runner.start({
|
|
||||||
requestInterceptor: (interceptedRequest) => {
|
|
||||||
if (/example\.com/.test(interceptedRequest.url())) {
|
|
||||||
interceptedRequest.respond({
|
|
||||||
status: 200,
|
|
||||||
contentType: 'text/html',
|
|
||||||
body: `<h1>external</h1>`
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
interceptedRequest.continue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('redirects on server', async () => {
|
it('redirects on server', async () => {
|
||||||
await page.goto(`${base}/redirect-from`);
|
await r.load('/redirect-from');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`${base}/redirect-to`
|
`${r.base}/redirect-to`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'redirected'
|
'redirected'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('redirects in client', async () => {
|
it('redirects in client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="redirect-from"]');
|
await r.page.click('[href="redirect-from"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`${base}/redirect-to`
|
`${r.base}/redirect-to`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'redirected'
|
'redirected'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('redirects to root on server', async () => {
|
it('redirects to root on server', async () => {
|
||||||
await page.goto(`${base}/redirect-to-root`);
|
await r.load('/redirect-to-root');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`${base}/`
|
`${r.base}/`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'root'
|
'root'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('redirects to root in client', async () => {
|
it('redirects to root in client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="redirect-to-root"]');
|
await r.page.click('[href="redirect-to-root"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`${base}/`
|
`${r.base}/`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'root'
|
'root'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const interceptor = (request: puppeteer.Request) => {
|
||||||
|
if (/example\.com/.test(request.url())) {
|
||||||
|
request.respond({
|
||||||
|
status: 200,
|
||||||
|
contentType: 'text/html',
|
||||||
|
body: `<h1>external</h1>`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
request.continue();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
it('redirects to external URL on server', async () => {
|
it('redirects to external URL on server', async () => {
|
||||||
await page.goto(`${base}/redirect-to-external`);
|
await r.intercept_requests(interceptor, async () => {
|
||||||
|
await r.load('/redirect-to-external');
|
||||||
|
});
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`https://example.com/`
|
`https://example.com/`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'external'
|
'external'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('redirects to external URL in client', async () => {
|
it('redirects to external URL in client', async () => {
|
||||||
await page.goto(base);
|
await r.load('/');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="redirect-to-external"]');
|
await r.intercept_requests(interceptor, async () => {
|
||||||
await wait(50);
|
await r.page.click('[href="redirect-to-external"]');
|
||||||
|
await r.wait();
|
||||||
|
});
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`https://example.com/`
|
`https://example.com/`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'external'
|
'external'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,93 +1,87 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
|
||||||
|
|
||||||
describe('scroll', function() {
|
describe('scroll', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, prefetchRoutes, title } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('scrolls to active deeplink', async () => {
|
it('scrolls to active deeplink', async () => {
|
||||||
await page.goto(`${base}/tall-page#foo`);
|
await r.load('/tall-page#foo');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
const scrollY = await page.evaluate(() => window.scrollY);
|
const scrollY = await r.page.evaluate(() => window.scrollY);
|
||||||
assert.ok(scrollY > 0, String(scrollY));
|
assert.ok(scrollY > 0, String(scrollY));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('scrolls to any deeplink if it was already active', async () => {
|
it('scrolls to any deeplink if it was already active', async () => {
|
||||||
await page.goto(`${base}/tall-page#foo`);
|
await r.load('/tall-page#foo');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
|
|
||||||
let scrollY = await page.evaluate(() => window.scrollY);
|
let scrollY = await r.page.evaluate(() => window.scrollY);
|
||||||
assert.ok(scrollY > 0, String(scrollY));
|
assert.ok(scrollY > 0, String(scrollY));
|
||||||
|
|
||||||
scrollY = await page.evaluate(() => {
|
scrollY = await r.page.evaluate(() => {
|
||||||
window.scrollTo(0, 0)
|
window.scrollTo(0, 0)
|
||||||
return window.scrollY
|
return window.scrollY
|
||||||
});
|
});
|
||||||
assert.ok(scrollY === 0, String(scrollY));
|
assert.ok(scrollY === 0, String(scrollY));
|
||||||
|
|
||||||
await page.click('[href="tall-page#foo"]');
|
await r.page.click('[href="tall-page#foo"]');
|
||||||
scrollY = await page.evaluate(() => window.scrollY);
|
scrollY = await r.page.evaluate(() => window.scrollY);
|
||||||
assert.ok(scrollY > 0, String(scrollY));
|
assert.ok(scrollY > 0, String(scrollY));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resets scroll when a link is clicked', async () => {
|
it('resets scroll when a link is clicked', async () => {
|
||||||
await page.goto(`${base}/tall-page#foo`);
|
await r.load('/tall-page#foo');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="another-tall-page"]');
|
await r.page.click('[href="another-tall-page"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.evaluate(() => window.scrollY),
|
await r.page.evaluate(() => window.scrollY),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('preserves scroll when a link with sapper-noscroll is clicked', async () => {
|
it('preserves scroll when a link with sapper-noscroll is clicked', async () => {
|
||||||
await page.goto(`${base}/tall-page#foo`);
|
await r.load('/tall-page#foo');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="another-tall-page"][sapper-noscroll]');
|
await r.page.click('[href="another-tall-page"][sapper-noscroll]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
const scrollY = await page.evaluate(() => window.scrollY);
|
const scrollY = await r.page.evaluate(() => window.scrollY);
|
||||||
|
|
||||||
assert.ok(scrollY > 0);
|
assert.ok(scrollY > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('scrolls into a deeplink on a new page', async () => {
|
it('scrolls into a deeplink on a new page', async () => {
|
||||||
await page.goto(`${base}/tall-page#foo`);
|
await r.load('/tall-page#foo');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="another-tall-page#bar"]');
|
await r.page.click('[href="another-tall-page#bar"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
assert.equal(await title(), 'Another tall page');
|
assert.equal(await r.text('h1'), 'Another tall page');
|
||||||
const scrollY = await page.evaluate(() => window.scrollY);
|
const scrollY = await r.page.evaluate(() => window.scrollY);
|
||||||
assert.ok(scrollY > 0);
|
assert.ok(scrollY > 0);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use((req, res, next) => {
|
.use((req, res, next) => {
|
||||||
req.hello = 'hello';
|
req.hello = 'hello';
|
||||||
res.locals = { name: 'world' };
|
res.locals = { name: 'world' };
|
||||||
@@ -15,5 +15,6 @@ polka()
|
|||||||
title: `${req.hello} ${res.locals.name}`
|
title: `${req.hello} ${res.locals.name}`
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
)
|
);
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -1,50 +1,46 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import { build } from '../../../api';
|
import { build } from '../../../api';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
|
|
||||||
describe('session', function() {
|
describe('session', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
before('start runner', async () => {
|
||||||
|
r = await new AppRunner().start(__dirname);
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, page, start, title } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('renders session props', async () => {
|
it('renders session props', async () => {
|
||||||
await page.goto(`${base}/session`);
|
await r.load('/session');
|
||||||
|
|
||||||
assert.equal(await title(), 'hello world');
|
assert.equal(await r.text('h1'), 'hello world');
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
assert.equal(await title(), 'hello world');
|
assert.equal(await r.text('h1'), 'hello world');
|
||||||
|
|
||||||
await page.click('button');
|
await r.page.click('button');
|
||||||
assert.equal(await title(), 'changed');
|
assert.equal(await r.text('h1'), 'changed');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('preloads session props', async () => {
|
it('preloads session props', async () => {
|
||||||
await page.goto(`${base}/preloaded`);
|
await r.load('/preloaded');
|
||||||
|
|
||||||
assert.equal(await title(), 'hello world');
|
assert.equal(await r.text('h1'), 'hello world');
|
||||||
|
|
||||||
await start();
|
await r.sapper.start();
|
||||||
assert.equal(await title(), 'hello world');
|
assert.equal(await r.text('h1'), 'hello world');
|
||||||
|
|
||||||
await page.click('button');
|
await r.page.click('button');
|
||||||
assert.equal(await title(), 'changed');
|
assert.equal(await r.text('h1'), 'changed');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ import sirv from 'sirv';
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT, NODE_ENV } = process.env;
|
import { start, dev } from '../../common.js';
|
||||||
const dev = NODE_ENV === 'development';
|
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(
|
.use(
|
||||||
'custom-basepath',
|
'custom-basepath',
|
||||||
sirv('static', { dev }),
|
sirv('static', { dev }),
|
||||||
sapper.middleware()
|
sapper.middleware()
|
||||||
)
|
);
|
||||||
.listen(PORT, err => {
|
|
||||||
if (err) console.log('error', err);
|
start(app);
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,51 +1,36 @@
|
|||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as puppeteer from 'puppeteer';
|
|
||||||
import * as api from '../../../api';
|
import * as api from '../../../api';
|
||||||
import { walk } from '../../utils';
|
import { walk } from '../../utils';
|
||||||
import { AppRunner } from '../AppRunner';
|
import { AppRunner } from '../AppRunner';
|
||||||
import { wait } from '../../utils';
|
|
||||||
|
|
||||||
|
|
||||||
describe('with-basepath', function() {
|
describe('with-basepath', function() {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
let runner: AppRunner;
|
let r: AppRunner;
|
||||||
let page: puppeteer.Page;
|
|
||||||
let base: string;
|
|
||||||
|
|
||||||
// helpers
|
|
||||||
let start: () => Promise<void>;
|
|
||||||
let prefetchRoutes: () => Promise<void>;
|
|
||||||
let title: () => Promise<string>;
|
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => api.build({ cwd: __dirname }));
|
||||||
await api.build({ cwd: __dirname });
|
before('export app', () => api.export({ cwd: __dirname, basepath: '/custom-basepath' }));
|
||||||
|
before('start runner', async () => {
|
||||||
await api.export({
|
r = await new AppRunner().start(__dirname);
|
||||||
cwd: __dirname,
|
|
||||||
basepath: '/custom-basepath'
|
|
||||||
});
|
|
||||||
|
|
||||||
runner = new AppRunner(__dirname, '__sapper__/build/server/server.js');
|
|
||||||
({ base, start, page, prefetchRoutes, title } = await runner.start());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => runner.end());
|
after(() => r && r.end());
|
||||||
|
|
||||||
|
// tests
|
||||||
it('serves /custom-basepath', async () => {
|
it('serves /custom-basepath', async () => {
|
||||||
await page.goto(`${base}/custom-basepath`);
|
await r.load('/custom-basepath');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await page.$eval('h1', node => node.textContent),
|
await r.text('h1'),
|
||||||
'Great success!'
|
'Great success!'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emits a basepath message', async () => {
|
it('emits a basepath message', async () => {
|
||||||
await page.goto(`${base}/custom-basepath`);
|
await r.load('/custom-basepath');
|
||||||
|
|
||||||
assert.deepEqual(runner.messages, [{
|
assert.deepEqual(r.messages, [{
|
||||||
__sapper__: true,
|
__sapper__: true,
|
||||||
event: 'basepath',
|
event: 'basepath',
|
||||||
basepath: '/custom-basepath'
|
basepath: '/custom-basepath'
|
||||||
@@ -71,35 +56,39 @@ describe('with-basepath', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('redirects on server', async () => {
|
it('redirects on server', async () => {
|
||||||
await page.goto(`${base}/custom-basepath/redirect-from`);
|
await r.load('/custom-basepath/redirect-from');
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`${base}/custom-basepath/redirect-to`
|
`${r.base}/custom-basepath/redirect-to`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'redirected'
|
'redirected'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('redirects in client', async () => {
|
it('redirects in client', async () => {
|
||||||
await page.goto(`${base}/custom-basepath`);
|
await r.load('/custom-basepath');
|
||||||
await start();
|
await r.sapper.start();
|
||||||
await prefetchRoutes();
|
await r.sapper.prefetchRoutes();
|
||||||
|
|
||||||
await page.click('[href="redirect-from"]');
|
await r.page.click('[href="redirect-from"]');
|
||||||
await wait(50);
|
await r.wait();
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
page.url(),
|
r.page.url(),
|
||||||
`${base}/custom-basepath/redirect-to`
|
`${r.base}/custom-basepath/redirect-to`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
await title(),
|
await r.text('h1'),
|
||||||
'redirected'
|
'redirected'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('survives the tests with no server errors', () => {
|
||||||
|
assert.deepEqual(r.errors, []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ describe('with-sourcemaps-webpack', function() {
|
|||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname, bundler: 'webpack' }));
|
||||||
await build({ cwd: __dirname, bundler: 'webpack' });
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// tests
|
||||||
it('does not put sourcemap files in service worker shell', async () => {
|
it('does not put sourcemap files in service worker shell', async () => {
|
||||||
const service_worker_source = fs.readFileSync(`${__dirname}/src/node_modules/@sapper/service-worker.js`, 'utf-8');
|
const service_worker_source = fs.readFileSync(`${__dirname}/src/node_modules/@sapper/service-worker.js`, 'utf-8');
|
||||||
const shell_source = /shell = (\[[\s\S]+?\])/.exec(service_worker_source)[1];
|
const shell_source = /shell = (\[[\s\S]+?\])/.exec(service_worker_source)[1];
|
||||||
@@ -23,4 +22,4 @@ describe('with-sourcemaps-webpack', function() {
|
|||||||
const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map'));
|
const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map'));
|
||||||
assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist');
|
assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
import * as sapper from '@sapper/server';
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
const { PORT } = process.env;
|
import { start } from '../../common.js';
|
||||||
|
|
||||||
polka()
|
const app = polka()
|
||||||
.use(sapper.middleware())
|
.use(sapper.middleware());
|
||||||
.listen(PORT);
|
|
||||||
|
start(app);
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ describe('with-sourcemaps', function() {
|
|||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
before(async () => {
|
before('build app', () => build({ cwd: __dirname }));
|
||||||
await build({ cwd: __dirname });
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// tests
|
||||||
it('does not put sourcemap files in service worker shell', async () => {
|
it('does not put sourcemap files in service worker shell', async () => {
|
||||||
const service_worker_source = fs.readFileSync(`${__dirname}/src/node_modules/@sapper/service-worker.js`, 'utf-8');
|
const service_worker_source = fs.readFileSync(`${__dirname}/src/node_modules/@sapper/service-worker.js`, 'utf-8');
|
||||||
const shell_source = /shell = (\[[\s\S]+?\])/.exec(service_worker_source)[1];
|
const shell_source = /shell = (\[[\s\S]+?\])/.exec(service_worker_source)[1];
|
||||||
@@ -23,4 +22,4 @@ describe('with-sourcemaps', function() {
|
|||||||
const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map'));
|
const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map'));
|
||||||
assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist');
|
assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ describe('manifest_data', () => {
|
|||||||
|
|
||||||
assert.deepEqual(pages, [
|
assert.deepEqual(pages, [
|
||||||
{
|
{
|
||||||
pattern: /^\/?$/,
|
pattern: /^\/$/,
|
||||||
parts: [
|
parts: [
|
||||||
{ component: index, params: [] }
|
{ component: index, params: [] }
|
||||||
]
|
]
|
||||||
@@ -50,6 +50,13 @@ describe('manifest_data', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
assert.deepEqual(server_routes, [
|
assert.deepEqual(server_routes, [
|
||||||
|
{
|
||||||
|
name: 'route_index',
|
||||||
|
pattern: /^\/$/,
|
||||||
|
file: 'index.js',
|
||||||
|
params: []
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: 'route_blog_json',
|
name: 'route_blog_json',
|
||||||
pattern: /^\/blog.json$/,
|
pattern: /^\/blog.json$/,
|
||||||
@@ -167,7 +174,7 @@ describe('manifest_data', () => {
|
|||||||
file: 'foo.js',
|
file: 'foo.js',
|
||||||
name: 'route_foo',
|
name: 'route_foo',
|
||||||
params: [],
|
params: [],
|
||||||
pattern: /^\/foo$/
|
pattern: /^\/foo\/?$/
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user