diff --git a/packages/adapter-static/README.md b/packages/adapter-static/README.md index 7d7ed7ecf54a5..d6350da0cbccc 100644 --- a/packages/adapter-static/README.md +++ b/packages/adapter-static/README.md @@ -38,6 +38,25 @@ The directory to write static assets (the contents of `static`, plus client-side Specify a fallback page for SPA mode, e.g. `index.html` or `200.html` or `404.html`. +### outputFileName + +A optional function that is called per entry to return the destination to write to. + +Default value: + +```javascript +/** @type {(opts: {path: string, is_html: boolean}) => string} */ +function default_output_file_name({ path, is_html }) { + if (!is_html) return path; + + const parts = path.split('/'); + if (parts[parts.length - 1] === 'index.html') return path; + + parts.push('index.html'); + return parts.join('/'); +} +``` + ## SPA mode You can use `adapter-static` to create a single-page app or SPA by specifying a **fallback page**. diff --git a/packages/adapter-static/index.d.ts b/packages/adapter-static/index.d.ts index 1f298a4a6f389..92e3475640aa8 100644 --- a/packages/adapter-static/index.d.ts +++ b/packages/adapter-static/index.d.ts @@ -4,6 +4,7 @@ interface AdapterOptions { pages?: string; assets?: string; fallback?: string; + outputFileName?: (opts: { path: string, is_html: boolean }) => string; } declare function plugin(options?: AdapterOptions): Adapter; diff --git a/packages/adapter-static/index.js b/packages/adapter-static/index.js index e1cc80ce042f3..756bf824029b2 100644 --- a/packages/adapter-static/index.js +++ b/packages/adapter-static/index.js @@ -1,8 +1,17 @@ -/** @type {import('.')} */ -export default function ({ pages = 'build', assets = pages, fallback } = {}) { +/** + * @param {{ + * pages?: string; + * assets?: string; + * fallback?: string; + * outputFileName?: (opts: {path: string, is_html: boolean}) => string; + * }} [opts] + */ +export default function({ pages = 'build', assets = pages, fallback, outputFileName } = {}) { + /** @type {import('@sveltejs/kit').Adapter} */ return { name: '@sveltejs/adapter-static', + /** @type {import('@sveltejs/kit').Adapter['adapt']} */ async adapt({ utils }) { utils.rimraf(assets); utils.rimraf(pages); @@ -13,7 +22,8 @@ export default function ({ pages = 'build', assets = pages, fallback } = {}) { await utils.prerender({ fallback, all: !fallback, - dest: pages + dest: pages, + output_file_name: outputFileName }); } }; diff --git a/packages/adapter-static/test/apps/spa-entry-name/.gitignore b/packages/adapter-static/test/apps/spa-entry-name/.gitignore new file mode 100644 index 0000000000000..0a4623184983b --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +node_modules +/.svelte-kit +/build +/functions diff --git a/packages/adapter-static/test/apps/spa-entry-name/.npmrc b/packages/adapter-static/test/apps/spa-entry-name/.npmrc new file mode 100644 index 0000000000000..b6f27f1359546 --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/packages/adapter-static/test/apps/spa-entry-name/README.md b/packages/adapter-static/test/apps/spa-entry-name/README.md new file mode 100644 index 0000000000000..82510ca06f504 --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/README.md @@ -0,0 +1,38 @@ +# create-svelte + +Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte); + +## Creating a project + +If you're seeing this, you've probably already done this step. Congrats! + +```bash +# create a new project in the current directory +npm init svelte@next + +# create a new project in my-app +npm init svelte@next my-app +``` + +> Note: the `@next` is temporary + +## Developing + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: + +```bash +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +## Building + +Before creating a production version of your app, install an [adapter](https://kit.svelte.dev/docs#adapters) for your target environment. Then: + +```bash +npm run build +``` + +> You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production. diff --git a/packages/adapter-static/test/apps/spa-entry-name/jsconfig.json b/packages/adapter-static/test/apps/spa-entry-name/jsconfig.json new file mode 100644 index 0000000000000..893781f65ca0c --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/jsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "$lib/*": ["src/lib/*"] + } + }, + "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/packages/adapter-static/test/apps/spa-entry-name/package.json b/packages/adapter-static/test/apps/spa-entry-name/package.json new file mode 100644 index 0000000000000..c39d2a71cee10 --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/package.json @@ -0,0 +1,15 @@ +{ + "name": "~TODO~", + "version": "0.0.1", + "scripts": { + "dev": "../../../../kit/svelte-kit.js dev", + "build": "../../../../kit/svelte-kit.js build", + "start": "../../../../kit/svelte-kit.js start" + }, + "devDependencies": { + "@sveltejs/adapter-node": "next", + "@sveltejs/kit": "workspace:*", + "svelte": "^3.40.0" + }, + "type": "module" +} diff --git a/packages/adapter-static/test/apps/spa-entry-name/src/app.html b/packages/adapter-static/test/apps/spa-entry-name/src/app.html new file mode 100644 index 0000000000000..ab9a75726ecc6 --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/src/app.html @@ -0,0 +1,11 @@ + + + + + + %svelte.head% + + +
%svelte.body%
+ + diff --git a/packages/adapter-static/test/apps/spa-entry-name/src/global.d.ts b/packages/adapter-static/test/apps/spa-entry-name/src/global.d.ts new file mode 100644 index 0000000000000..63908c66cfd4a --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/src/global.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/adapter-static/test/apps/spa-entry-name/src/routes/__layout.svelte b/packages/adapter-static/test/apps/spa-entry-name/src/routes/__layout.svelte new file mode 100644 index 0000000000000..2633c3c802ca3 --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/src/routes/__layout.svelte @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/packages/adapter-static/test/apps/spa-entry-name/src/routes/about.html.svelte b/packages/adapter-static/test/apps/spa-entry-name/src/routes/about.html.svelte new file mode 100644 index 0000000000000..eaafdd9c712ae --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/src/routes/about.html.svelte @@ -0,0 +1,7 @@ + + +

This page was prerendered

+ +

about

\ No newline at end of file diff --git a/packages/adapter-static/test/apps/spa-entry-name/src/routes/index.svelte b/packages/adapter-static/test/apps/spa-entry-name/src/routes/index.svelte new file mode 100644 index 0000000000000..913f0784cbb66 --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/src/routes/index.svelte @@ -0,0 +1 @@ +

This page was not prerendered

\ No newline at end of file diff --git a/packages/adapter-static/test/apps/spa-entry-name/src/routes/page.svelte b/packages/adapter-static/test/apps/spa-entry-name/src/routes/page.svelte new file mode 100644 index 0000000000000..73a4c7838d16f --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/src/routes/page.svelte @@ -0,0 +1,7 @@ + + +

This page was prerendered

+ +

page

\ No newline at end of file diff --git a/packages/adapter-static/test/apps/spa-entry-name/svelte.config.js b/packages/adapter-static/test/apps/spa-entry-name/svelte.config.js new file mode 100644 index 0000000000000..82874d4bb4492 --- /dev/null +++ b/packages/adapter-static/test/apps/spa-entry-name/svelte.config.js @@ -0,0 +1,23 @@ +import { format, parse } from 'path'; +import adapter from '../../../index.js'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + adapter: adapter({ + fallback: '200.html', + outputFileName: ({ path, is_html }) => { + if (!is_html) return path; + + let { root, dir, name, ext } = parse(path); + + if (!ext) ext = '.html'; + + return format({ root, dir, name, ext }); + } + }), + target: '#svelte' + } +}; + +export default config; diff --git a/packages/adapter-static/test/test.js b/packages/adapter-static/test/test.js index 16629cfa9469c..8fbb52f5e83c5 100644 --- a/packages/adapter-static/test/test.js +++ b/packages/adapter-static/test/test.js @@ -36,3 +36,28 @@ run('spa', (test) => { assert.equal(await page.textContent('h1'), '404'); }); }); + +run('spa-entry-name', (test) => { + test('generates a fallback page', ({ cwd }) => { + assert.ok(fs.existsSync(`${cwd}/build/200.html`)); + }); + + test('does not prerender pages without prerender=true', ({ cwd }) => { + assert.ok(!fs.existsSync(`${cwd}/build/index.html`)); + }); + + test('prerenders page with prerender=true', ({ cwd }) => { + assert.ok(fs.existsSync(`${cwd}/build/about.html`)); + assert.ok(fs.existsSync(`${cwd}/build/page.html`)); + }); + + test('renders content in fallback page when JS runs', async ({ base, page }) => { + await page.goto(base); + assert.equal(await page.textContent('h1'), 'This page was not prerendered'); + }); + + test('renders error page for missing page', async ({ base, page }) => { + await page.goto(`${base}/nosuchpage`); + assert.equal(await page.textContent('h1'), '404'); + }); +});