Skip to content

Commit

Permalink
Merge branch 'master' into adapter-static-output
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Jan 10, 2022
2 parents a42b187 + fb08d55 commit 2e8d472
Show file tree
Hide file tree
Showing 21 changed files with 186 additions and 50 deletions.
5 changes: 5 additions & 0 deletions .changeset/heavy-moons-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

url hash is now properly reflected in page store
3 changes: 3 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@
"healthy-vans-build",
"heavy-humans-check",
"heavy-lamps-explode",
"heavy-moons-admire",
"heavy-papayas-smile",
"heavy-turkeys-report",
"heavy-ways-agree",
Expand Down Expand Up @@ -402,6 +403,7 @@
"red-cooks-fix",
"red-papayas-prove",
"rich-clocks-chew",
"rich-ligers-smash",
"rich-pumpkins-applaud",
"rich-seahorses-walk",
"rotten-cats-pump",
Expand Down Expand Up @@ -444,6 +446,7 @@
"shy-jeans-fly",
"shy-mails-share",
"shy-oranges-sin",
"silly-ants-battle",
"silly-grapes-cover",
"silly-jokes-hug",
"silly-phones-worry",
Expand Down
5 changes: 5 additions & 0 deletions .changeset/rich-ligers-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Strip hash fragments from URLs during prerendering
5 changes: 5 additions & 0 deletions .changeset/silly-ants-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Allow prefixes and suffixes around rest parameters
10 changes: 10 additions & 0 deletions packages/kit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# @sveltejs/kit

## 1.0.0-next.220

### Patch Changes

- url hash is now properly reflected in page store ([#3273](https://github.com/sveltejs/kit/pull/3273))

* Strip hash fragments from URLs during prerendering ([#3251](https://github.com/sveltejs/kit/pull/3251))

- Allow prefixes and suffixes around rest parameters ([#3240](https://github.com/sveltejs/kit/pull/3240))

## 1.0.0-next.219

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sveltejs/kit",
"version": "1.0.0-next.219",
"version": "1.0.0-next.220",
"repository": {
"type": "git",
"url": "https://github.com/sveltejs/kit",
Expand Down
7 changes: 6 additions & 1 deletion packages/kit/src/core/adapt/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,12 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a
if (element === 'a' || element === 'link') {
if (is_rel_external(attrs)) continue;

hrefs.push(get_href(attrs));
let href = get_href(attrs);
if (!href) continue;

const i = href.indexOf('#');
href = i < 0 ? href : href.substring(0, i);
hrefs.push(href);
} else {
if (element === 'img') {
hrefs.push(get_src(attrs));
Expand Down
60 changes: 31 additions & 29 deletions packages/kit/src/core/create_manifest_data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,6 @@ export default function create_manifest_data({ config, output, cwd = process.cwd
throw new Error(`Invalid route ${file} — brackets are unbalanced`);
}

if (/.+\[\.\.\.[^\]]+\]/.test(segment) || /\[\.\.\.[^\]]+\].+/.test(segment)) {
throw new Error(`Invalid route ${file} — rest parameter must be a standalone segment`);
}

const parts = get_parts(segment, file);
const is_index = is_dir ? false : basename.startsWith('index.');
const is_page = config.extensions.indexOf(ext) !== -1;
Expand Down Expand Up @@ -367,31 +363,37 @@ function get_parts(part, file) {
function get_pattern(segments, add_trailing_slash) {
const path = segments
.map((segment) => {
return segment[0].rest
? '(?:\\/(.*))?'
: '\\/' +
segment
.map((part) => {
return part.dynamic
? '([^/]+?)'
: // allow users to specify characters on the file system in an encoded manner
part.content
.normalize()
// We use [ and ] to denote parameters, so users must encode these on the file
// system to match against them. We don't decode all characters since others
// can already be epressed and so that '%' can be easily used directly in filenames
.replace(/%5[Bb]/g, '[')
.replace(/%5[Dd]/g, ']')
// '#', '/', and '?' can only appear in URL path segments in an encoded manner.
// They will not be touched by decodeURI so need to be encoded here, so
// that we can match against them.
// We skip '/' since you can't create a file with it on any OS
.replace(/#/g, '%23')
.replace(/\?/g, '%3F')
// escape characters that have special meaning in regex
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
})
.join('');
if (segment.length === 1 && segment[0].rest) {
// special case — `src/routes/foo/[...bar]/baz` matches `/foo/baz`
// so we need to make the leading slash optional
return '(?:\\/(.*))?';
}

const parts = segment.map((part) => {
if (part.rest) return '(.*?)';
if (part.dynamic) return '([^/]+?)';

return (
part.content
// allow users to specify characters on the file system in an encoded manner
.normalize()
// We use [ and ] to denote parameters, so users must encode these on the file
// system to match against them. We don't decode all characters since others
// can already be epressed and so that '%' can be easily used directly in filenames
.replace(/%5[Bb]/g, '[')
.replace(/%5[Dd]/g, ']')
// '#', '/', and '?' can only appear in URL path segments in an encoded manner.
// They will not be touched by decodeURI so need to be encoded here, so
// that we can match against them.
// We skip '/' since you can't create a file with it on any OS
.replace(/#/g, '%23')
.replace(/\?/g, '%3F')
// escape characters that have special meaning in regex
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
);
});

return '\\/' + parts.join('');
})
.join('');

Expand Down
40 changes: 30 additions & 10 deletions packages/kit/src/core/create_manifest_data/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,18 +215,38 @@ test('sorts routes with rest correctly', () => {
});

test('disallows rest parameters inside segments', () => {
assert.throws(
() => {
create('samples/invalid-rest');
const { routes } = create('samples/rest-prefix-suffix');

assert.equal(routes, [
{
type: 'page',
segments: [
{
dynamic: true,
rest: true,
content: 'prefix-[...rest]'
}
],
pattern: /^\/prefix-(.*?)\/?$/,
params: ['...rest'],
path: '',
a: ['components/layout.svelte', 'samples/rest-prefix-suffix/prefix-[...rest].svelte'],
b: ['components/error.svelte']
},
/** @param {Error} e */
(e) => {
return (
e.message ===
'Invalid route samples/invalid-rest/foo-[...rest]-bar.svelte — rest parameter must be a standalone segment'
);
{
type: 'endpoint',
segments: [
{
dynamic: true,
rest: true,
content: '[...rest].json'
}
],
pattern: /^\/(.*?)\.json$/,
file: 'samples/rest-prefix-suffix/[...rest].json.js',
params: ['...rest']
}
);
]);
});

test('ignores files and directories with leading underscores', () => {
Expand Down
5 changes: 1 addition & 4 deletions packages/kit/src/core/dev/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import path from 'path';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import amp_validator from 'amphtml-validator';
import vite from 'vite';
import { rimraf } from '../../utils/filesystem.js';
import { deep_merge } from '../../utils/object.js';
Expand All @@ -27,8 +26,6 @@ export async function dev({ cwd, port, host, https, config }) {
rimraf(output);
copy_assets(output);

process.env.VITE_SVELTEKIT_AMP = config.kit.amp ? 'true' : '';

const [vite_config] = deep_merge(
{
server: {
Expand Down Expand Up @@ -76,7 +73,7 @@ export async function dev({ cwd, port, host, https, config }) {
hydratable: !!config.kit.hydrate
}
}),
create_plugin(config, output, cwd, config.kit.amp && (await amp_validator.getInstance()))
await create_plugin(config, output, cwd)
],
publicDir: config.kit.files.assets,
base: '/'
Expand Down
13 changes: 10 additions & 3 deletions packages/kit/src/core/dev/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@ import { load_template } from '../config/index.js';
* @param {import('types/config').ValidatedConfig} config
* @param {string} output
* @param {string} cwd
* @param {import('amphtml-validator').Validator | false} amp
* @returns {import('vite').Plugin}
* @returns {Promise<import('vite').Plugin>}
*/
export function create_plugin(config, output, cwd, amp) {
export async function create_plugin(config, output, cwd) {
/** @type {import('amphtml-validator').Validator} */
let amp;

if (config.kit.amp) {
process.env.VITE_SVELTEKIT_AMP = 'true';
amp = await (await import('amphtml-validator')).getInstance();
}

return {
name: 'vite-plugin-svelte-kit',

Expand Down
3 changes: 3 additions & 0 deletions packages/kit/src/runtime/client/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ export class Renderer {

let error_args;

// url.hash is empty when coming from the server
url.hash = window.location.hash;

try {
for (let i = 0; i < nodes.length; i += 1) {
const is_leaf = i === nodes.length - 1;
Expand Down
4 changes: 4 additions & 0 deletions packages/kit/src/runtime/client/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ export class Router {
// Call `pushState` to add url to history so going back works.
// Also make a delay, otherwise the browser default behaviour would not kick in
setTimeout(() => history.pushState({}, '', url.href));
const info = this.parse(url);
if (info) {
return this.renderer.update(info, [], false);
}
return;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/kit/test/apps/amp/playwright.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { config } from '../../utils.js';

config.webServer && (config.webServer.timeout = 15000); // AMP validator needs a long time to get moving

// remove any projects with javaScriptEnabled
const projects = config.projects || [];
for (let i = projects.length - 1; i >= 0; i--) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script>
import { page } from '$app/stores';
import { onMount } from 'svelte';
/** @type {string} */
let curWindowHash;
onMount(() => setHashVar());
function setHashVar() {
curWindowHash = window.location.hash;
}
</script>

<svelte:window on:hashchange={setHashVar} />

<h1 id="window-hash">{curWindowHash}</h1>
<h1 id="page-url-hash">{$page.url.hash}</h1>

<a href="#target">Nav to #ing with anchor tag</a>
<div id="target">Target</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('@sveltejs/kit').RequestHandler} */
export function get({ params }) {
return {
body: {
parts: params.parts
}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script context="module">
/** @type {import('@sveltejs/kit').Load} */
export async function load({ fetch, params }) {
const res = await fetch(`/routing/rest/complex/${params.parts}.json`);
const { parts } = await res.json();
return {
props: { parts }
};
}
</script>

<script>
/** @type {string} */
export let parts;
</script>

<h1>parts: {parts}</h1>
24 changes: 24 additions & 0 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,25 @@ test.describe.parallel('Routing', () => {
).toBe('rgb(255, 0, 0)');
});

test('$page.url.hash is correctly set on page load', async ({ page, javaScriptEnabled }) => {
if (javaScriptEnabled) {
await page.goto('/routing/hashes/pagestore#target');
expect(await page.textContent('#window-hash')).toBe('#target');
expect(await page.textContent('#page-url-hash')).toBe('#target');
}
});

test('$page.url.hash is correctly set on navigation', async ({ page, javaScriptEnabled }) => {
if (javaScriptEnabled) {
await page.goto('/routing/hashes/pagestore');
expect(await page.textContent('#window-hash')).toBe('');
expect(await page.textContent('#page-url-hash')).toBe('');
await page.click('[href="#target"]');
expect(await page.textContent('#window-hash')).toBe('#target');
expect(await page.textContent('#page-url-hash')).toBe('#target');
}
});

test('fallthrough', async ({ page }) => {
await page.goto('/routing/fallthrough-simple/invalid');
expect(await page.textContent('h1')).toBe('Page');
Expand Down Expand Up @@ -1618,6 +1637,11 @@ test.describe.parallel('Routing', () => {
await clicknav('[href="/routing/rest/path/three"]');
expect(await page.textContent('h1')).toBe('path: /routing/rest/path/three');
});

test('allows rest routes to have prefixes and suffixes', async ({ page }) => {
await page.goto('/routing/rest/complex/prefix-one/two/three');
expect(await page.textContent('h1')).toBe('parts: one/two/three');
});
});

test.describe.parallel('Session', () => {
Expand Down
3 changes: 1 addition & 2 deletions packages/kit/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ export const config = {
timeout: process.env.CI ? (process.platform === 'win32' ? 45000 : 30000) : 10000,
webServer: {
command: process.env.DEV ? 'npm run dev' : 'npm run build && npm run preview',
port: 3000,
timeout: 15000 // AMP validator needs a long time to get moving
port: 3000
},
workers: 8,
retries: process.env.CI ? 5 : 0,
Expand Down

0 comments on commit 2e8d472

Please sign in to comment.