├── .eslintignore ├── .eslintrc.js ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── questions-and-help.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── .mocharc.yml ├── .netlify └── state.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── api.js ├── config ├── rollup.js └── webpack.js ├── index.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── runtime ├── index.d.ts ├── internal │ ├── error.svelte │ ├── layout.svelte │ └── shared.mjs └── src │ ├── app │ ├── app.ts │ ├── baseuri_helper.ts │ ├── goto │ │ └── index.ts │ ├── index.ts │ ├── prefetch │ │ └── index.ts │ ├── prefetchRoutes │ │ └── index.ts │ ├── router │ │ ├── find_anchor.ts │ │ └── index.ts │ ├── stores │ │ └── index.ts │ └── types.ts │ ├── common.ts │ ├── internal │ ├── App.svelte.d.ts │ ├── manifest-client.d.ts │ ├── manifest-server.d.ts │ └── shared.d.ts │ └── server │ ├── index.ts │ └── middleware │ ├── detect_client_only_references.ts │ ├── get_page_handler.ts │ ├── get_server_route_handler.ts │ ├── index.ts │ └── sourcemap_stacktrace.ts ├── sapper ├── sapper-dev-client.js ├── site ├── .eslintrc.js ├── .gitignore ├── README.md ├── appveyor.yml ├── config.js ├── content │ ├── docs │ │ ├── 00-introduction.md │ │ ├── 01-structure.md │ │ ├── 02-routing.md │ │ ├── 03-client-api.md │ │ ├── 04-preloading.md │ │ ├── 05-layouts.md │ │ ├── 06-server-side-rendering.md │ │ ├── 07-state-management.md │ │ ├── 08-link-options.md │ │ ├── 09-building.md │ │ ├── 10-exporting.md │ │ ├── 11-deploying.md │ │ ├── 12-security.md │ │ ├── 13-base-urls.md │ │ └── 14-debugging.md │ ├── faq │ │ ├── 100-version-numbers.md │ │ ├── 200-webpack-vs-rollup.md │ │ ├── 300-typescript.md │ │ └── 400-why-is-there-a-node_modules-folder-in-src.md │ └── migrating │ │ └── 01-migrating.md ├── package-lock.json ├── package.json ├── rollup.config.js ├── scripts │ └── deploy.sh ├── src │ ├── client.js │ ├── routes │ │ ├── _error.svelte │ │ ├── _layout.svelte │ │ ├── docs │ │ │ ├── index.json.js │ │ │ └── index.svelte │ │ ├── faq │ │ │ ├── _faqs.js │ │ │ ├── index.json.js │ │ │ └── index.svelte │ │ ├── index.svelte │ │ └── migrating │ │ │ ├── index.json.js │ │ │ └── index.svelte │ ├── server.js │ ├── service-worker.js │ ├── template.html │ └── utils │ │ ├── generate_docs.js │ │ ├── highlight.js │ │ └── slug.js └── static │ ├── CNAME │ ├── favicon.png │ ├── fonts │ ├── fira-mono │ │ └── fira-mono-latin-400.woff2 │ ├── overpass │ │ ├── overpass-latin-100.woff2 │ │ ├── overpass-latin-300.woff2 │ │ ├── overpass-latin-400.woff2 │ │ ├── overpass-latin-600.woff2 │ │ └── overpass-latin-700.woff2 │ └── roboto │ │ ├── roboto-latin-400.woff2 │ │ ├── roboto-latin-400italic.woff2 │ │ ├── roboto-latin-500.woff2 │ │ └── roboto-latin-500italic.woff2 │ ├── global.css │ ├── icons │ ├── arrow-right.svg │ ├── check.svg │ ├── chevron.svg │ ├── collapse.svg │ ├── download.svg │ ├── dropdown.svg │ ├── edit.svg │ ├── expand.svg │ ├── flip.svg │ ├── fork.svg │ ├── link.svg │ ├── loading.svg │ └── save.svg │ ├── images │ ├── sapper-android-chrome-192.png │ ├── sapper-android-chrome-512.png │ ├── sapper-apple-touch-icon.png │ └── sapper-mstile-150.png │ ├── manifest.json │ ├── prism.css │ ├── sapper-logo-horizontal.svg │ ├── sapper-logo-outline.svg │ ├── sapper-logo-vertical.svg │ ├── sapper-logo.svg │ └── sapper-logotype.svg ├── src ├── api.ts ├── api │ ├── build.ts │ ├── dev.ts │ ├── export.ts │ ├── find_page.ts │ └── utils │ │ ├── Deferred.ts │ │ ├── clean_html.ts │ │ ├── copy_runtime.ts │ │ ├── copy_shimport.ts │ │ ├── export_queue.ts │ │ ├── fs_utils.ts │ │ ├── minify_html.ts │ │ ├── noop.ts │ │ └── validate_bundler.ts ├── cli.ts ├── config │ ├── env.ts │ ├── rollup.ts │ └── webpack.ts ├── core.ts ├── core │ ├── create_app.ts │ ├── create_compilers │ │ ├── RollupCompiler.ts │ │ ├── RollupResult.ts │ │ ├── WebpackCompiler.ts │ │ ├── WebpackResult.ts │ │ ├── index.ts │ │ └── interfaces.ts │ ├── create_manifest_data.ts │ └── read_template.ts ├── interfaces.ts ├── types.d.ts └── utils.ts ├── test ├── apps │ ├── .eslintrc.js │ ├── AppRunner.ts │ ├── basics │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── [...rest] │ │ │ │ │ ├── deep.json.js │ │ │ │ │ ├── deep.svelte │ │ │ │ │ └── index.svelte │ │ │ │ ├── [id([0-9]+)].svelte │ │ │ │ ├── [slug].svelte │ │ │ │ ├── _error.svelte │ │ │ │ ├── a.svelte │ │ │ │ ├── ambiguous │ │ │ │ │ ├── [slug].json.js │ │ │ │ │ └── [slug].svelte │ │ │ │ ├── b │ │ │ │ │ ├── index.json.js │ │ │ │ │ └── index.svelte │ │ │ │ ├── client │ │ │ │ │ ├── bar │ │ │ │ │ │ ├── b.svelte │ │ │ │ │ │ └── index.svelte │ │ │ │ │ └── foo.svelte │ │ │ │ ├── const.svelte │ │ │ │ ├── delete-test │ │ │ │ │ ├── [id].json.js │ │ │ │ │ └── index.svelte │ │ │ │ ├── dirs │ │ │ │ │ ├── bar │ │ │ │ │ │ ├── [a].svelte │ │ │ │ │ │ └── index.svelte │ │ │ │ │ └── foo │ │ │ │ │ │ ├── [b].svelte │ │ │ │ │ │ └── index.svelte │ │ │ │ ├── echo-query │ │ │ │ │ └── index.svelte │ │ │ │ ├── host.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── middleware │ │ │ │ │ ├── index.js │ │ │ │ │ └── index.svelte │ │ │ │ ├── prefetch-timing │ │ │ │ │ ├── prefetched │ │ │ │ │ │ └── index.svelte │ │ │ │ │ └── prefetcher │ │ │ │ │ │ └── index.svelte │ │ │ │ ├── regexp │ │ │ │ │ └── [id([0-9]+)].svelte │ │ │ │ ├── skipped │ │ │ │ │ └── [one] │ │ │ │ │ │ └── [two].svelte │ │ │ │ ├── store │ │ │ │ │ ├── index.svelte │ │ │ │ │ └── result.svelte │ │ │ │ └── unsafe-replacement.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── common.js │ ├── credentials │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── credentials │ │ │ │ │ ├── authorization.json.js │ │ │ │ │ ├── cookie.json.js │ │ │ │ │ └── index.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── csp-nonce │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── cspnonce │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── css-inlined │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── css │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _components │ │ │ │ │ ├── NestedRouteTest.svelte │ │ │ │ │ └── Title.svelte │ │ │ │ ├── _error.svelte │ │ │ │ ├── bar.svelte │ │ │ │ ├── foo.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── index2.svelte │ │ │ │ ├── nested │ │ │ │ │ ├── _layout.svelte │ │ │ │ │ └── index.svelte │ │ │ │ └── title.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── custom-extension │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── [slug].mdx │ │ │ │ ├── _error.svelte │ │ │ │ ├── a.svelte │ │ │ │ ├── const.whokilledthemuffinman │ │ │ │ ├── ide-friendly.route.svelte │ │ │ │ ├── index.jesuslivesineveryone │ │ │ │ └── unsafe-replacement.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── encoding │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── echo │ │ │ │ │ ├── page │ │ │ │ │ │ └── [slug].html │ │ │ │ │ └── server-route │ │ │ │ │ │ └── [slug].js │ │ │ │ ├── fünke.html │ │ │ │ ├── fünke.json.js │ │ │ │ └── index.html │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── errors │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── _layout.svelte │ │ │ │ ├── _trace.js │ │ │ │ ├── access_document.svelte │ │ │ │ ├── async-throw.json.js │ │ │ │ ├── blog │ │ │ │ │ ├── [slug].html │ │ │ │ │ └── [slug].json.js │ │ │ │ ├── enhance-your-calm.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── no-error.svelte │ │ │ │ ├── nope.json.js │ │ │ │ ├── preload-reject.svelte │ │ │ │ ├── throw.json.js │ │ │ │ ├── throw.svelte │ │ │ │ └── trace.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── export-multiple-entry │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── about.svelte │ │ │ │ ├── blog │ │ │ │ │ ├── [slug].html │ │ │ │ │ ├── [slug].json.js │ │ │ │ │ ├── _posts.js │ │ │ │ │ ├── index.html │ │ │ │ │ └── index.json.js │ │ │ │ ├── boom │ │ │ │ │ ├── [a] │ │ │ │ │ │ ├── [b].svelte │ │ │ │ │ │ └── index.svelte │ │ │ │ │ └── index.svelte │ │ │ │ ├── contact.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ ├── static │ │ │ └── global.css │ │ └── test.ts │ ├── export-queue │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── a-[x].svelte │ │ │ │ ├── b-[x].svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ ├── static │ │ │ └── global.css │ │ └── test.ts │ ├── export-webpack │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── blog │ │ │ │ │ ├── [slug].html │ │ │ │ │ ├── [slug].json.js │ │ │ │ │ ├── _posts.js │ │ │ │ │ ├── index.html │ │ │ │ │ └── index.json.js │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ ├── static │ │ │ └── global.css │ │ ├── test.ts │ │ └── webpack.config.js │ ├── export-without-serviceworker │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ └── template.html │ │ ├── static │ │ │ └── global.css │ │ └── test.ts │ ├── export │ │ ├── content │ │ │ ├── example-192.png │ │ │ ├── example-512.png │ │ │ └── test.pdf │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── blog │ │ │ │ │ ├── [slug].html │ │ │ │ │ ├── [slug].json.js │ │ │ │ │ ├── _posts.js │ │ │ │ │ ├── index.html │ │ │ │ │ └── index.json.js │ │ │ │ ├── boom │ │ │ │ │ ├── [a] │ │ │ │ │ │ ├── [b].html.svelte │ │ │ │ │ │ ├── [b].svelte │ │ │ │ │ │ └── index.svelte │ │ │ │ │ └── index.svelte │ │ │ │ ├── img │ │ │ │ │ └── [slug].png.js │ │ │ │ ├── index.svelte │ │ │ │ ├── manifest.json.js │ │ │ │ └── pdfs │ │ │ │ │ └── [slug].pdf.js │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ ├── static │ │ │ ├── global.css │ │ │ ├── test.html │ │ │ └── test.pdf │ │ └── test.ts │ ├── ignore │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── [slug].svelte │ │ │ │ ├── _error.svelte │ │ │ │ ├── a.svelte │ │ │ │ ├── b │ │ │ │ │ ├── index.html │ │ │ │ │ └── index.json.js │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── layout │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── [x] │ │ │ │ │ ├── [y] │ │ │ │ │ │ ├── [z].svelte │ │ │ │ │ │ └── _layout.svelte │ │ │ │ │ └── _counts.js │ │ │ │ ├── _error.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── preloading │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── _layout.svelte │ │ │ │ ├── echo │ │ │ │ │ └── index.svelte │ │ │ │ ├── foo.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── prefetch │ │ │ │ │ ├── [slug] │ │ │ │ │ │ └── index.svelte │ │ │ │ │ └── index.svelte │ │ │ │ ├── preload-nothing │ │ │ │ │ └── index.svelte │ │ │ │ ├── preload-root │ │ │ │ │ └── index.svelte │ │ │ │ ├── preload-values │ │ │ │ │ ├── custom-class.svelte │ │ │ │ │ ├── host.svelte │ │ │ │ │ └── set.svelte │ │ │ │ └── slow-preload.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── redirects │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── redirect-from.svelte │ │ │ │ ├── redirect-to-external.svelte │ │ │ │ ├── redirect-to-root.svelte │ │ │ │ └── redirect-to.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── scroll │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── a-third-tall-page.svelte │ │ │ │ ├── another-tall-page.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── redirect.svelte │ │ │ │ ├── search-form.svelte │ │ │ │ ├── search-page.svelte │ │ │ │ └── tall-page.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── session │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── preloaded.svelte │ │ │ │ └── session.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ └── test.ts │ ├── with-basepath │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ ├── index.svelte │ │ │ │ ├── redirect-from.svelte │ │ │ │ └── redirect-to.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ ├── static │ │ │ └── global.css │ │ └── test.ts │ ├── with-sourcemaps-webpack │ │ ├── src │ │ │ ├── client.js │ │ │ ├── routes │ │ │ │ ├── _error.svelte │ │ │ │ └── index.svelte │ │ │ ├── server.js │ │ │ ├── service-worker.js │ │ │ └── template.html │ │ ├── test.ts │ │ └── webpack.config.js │ └── with-sourcemaps │ │ ├── rollup.config.js │ │ ├── src │ │ ├── client.js │ │ ├── routes │ │ │ ├── _error.svelte │ │ │ └── index.svelte │ │ ├── server.js │ │ ├── service-worker.js │ │ └── template.html │ │ └── test.ts ├── unit │ ├── baseuri_helper │ │ └── test.ts │ ├── clean_html │ │ ├── samples │ │ │ ├── removes-cdata │ │ │ │ ├── .actual.html │ │ │ │ ├── input.html │ │ │ │ └── output.html │ │ │ ├── removes-comments │ │ │ │ ├── .actual.html │ │ │ │ ├── input.html │ │ │ │ └── output.html │ │ │ └── removes-script-contents │ │ │ │ ├── .actual.html │ │ │ │ ├── input.html │ │ │ │ └── output.html │ │ └── test.ts │ ├── create_manifest_data │ │ ├── samples │ │ │ ├── basic │ │ │ │ ├── about.html │ │ │ │ ├── blog │ │ │ │ │ ├── [slug].html │ │ │ │ │ ├── [slug].json.js │ │ │ │ │ ├── _default.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── index.json.js │ │ │ │ ├── index.html │ │ │ │ └── index.js │ │ │ ├── clash-pages │ │ │ │ ├── [bar] │ │ │ │ │ └── index.html │ │ │ │ ├── [foo].html │ │ │ │ └── index.html │ │ │ ├── clash-routes │ │ │ │ ├── [bar] │ │ │ │ │ └── index.js │ │ │ │ ├── [foo].js │ │ │ │ └── index.html │ │ │ ├── custom-extension │ │ │ │ ├── about.jazz │ │ │ │ ├── blog │ │ │ │ │ ├── [slug].beebop │ │ │ │ │ ├── [slug].json.js │ │ │ │ │ ├── _default.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── index.json.js │ │ │ │ └── index.funk │ │ │ ├── encoding │ │ │ │ └── #.html │ │ │ ├── hidden-dot │ │ │ │ ├── .unknown │ │ │ │ │ └── foo.txt.js │ │ │ │ └── .well-known │ │ │ │ │ └── dnt-policy.txt.js │ │ │ ├── hidden-underscore │ │ │ │ ├── _foo.js │ │ │ │ ├── a │ │ │ │ │ └── _b │ │ │ │ │ │ └── c │ │ │ │ │ │ └── d.js │ │ │ │ ├── e │ │ │ │ │ └── f │ │ │ │ │ │ └── g │ │ │ │ │ │ └── h.js │ │ │ │ ├── i │ │ │ │ │ └── _j.js │ │ │ │ ├── index.html │ │ │ │ └── index.js │ │ │ ├── invalid-params │ │ │ │ └── [foo][bar].js │ │ │ ├── invalid-qualifier │ │ │ │ └── [foo([a-z]([0-9]))].js │ │ │ ├── lockfiles │ │ │ │ ├── foo.js │ │ │ │ └── foo.js_tmp │ │ │ ├── multiple-slugs │ │ │ │ └── [file].[ext].js │ │ │ ├── nested-square-brackets │ │ │ │ └── [file([a-z]+)].[ext([a-z]+)].js │ │ │ ├── qualifiers │ │ │ │ ├── [slug([0-9-a-z]{3,})].html │ │ │ │ ├── [slug([a-z]{2})].html │ │ │ │ └── [slug].html │ │ │ └── sorting │ │ │ │ ├── [...spread] │ │ │ │ ├── abc.html │ │ │ │ ├── deep │ │ │ │ │ ├── [...deep_spread] │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── xyz.html │ │ │ │ │ └── index.html │ │ │ │ └── index.html │ │ │ │ ├── [wildcard].html │ │ │ │ ├── _layout.html │ │ │ │ ├── about.html │ │ │ │ ├── index.html │ │ │ │ └── post │ │ │ │ ├── [id([0-9-a-z]{3,})].html │ │ │ │ ├── [id].html │ │ │ │ ├── _default.html │ │ │ │ ├── bar.html │ │ │ │ ├── f[xx].html │ │ │ │ ├── foo.html │ │ │ │ └── index.html │ │ └── test.ts │ ├── srcset │ │ └── test.ts │ └── utils.test.ts └── utils.ts ├── tsconfig.json ├── webpack.js └── webpack ├── [slug].svelte └── config.js /.eslintignore: -------------------------------------------------------------------------------- 1 | **/_actual.js 2 | **/expected.js 3 | _output 4 | test/*/samples/*/output.js 5 | node_modules 6 | __sapper__ 7 | /runtime/app.mjs 8 | /runtime/server.mjs 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@sveltejs', 4 | plugins: ['import'], 5 | settings: { 6 | 'import/resolver': { 7 | typescript: {} // this loads /tsconfig.json to eslint 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: svelte 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ------ 2 | Before filing an issue we'd appreciate it if you could take a moment to ensure 3 | there isn't already an open issue or pull-request. 4 | ----- 5 | 6 | If there's an existing issue, please add a :+1: reaction to the description of 7 | the issue. One way we prioritize issues is by the number of :+1: reactions on 8 | their descriptions. Please DO NOT add `+1` or :+1: comments. 9 | 10 | ### Feature requests and proposals 11 | We're excited to hear how we can make Sapper better. Please add as much detail 12 | as you can on your use case. To propose an implementation of a large feature or 13 | change, please create an [RFC](https://github.com/sveltejs/rfcs). 14 | 15 | ### Bugs 16 | If you're filing an issue about a bug please include as much information 17 | as you can, including the following. 18 | 19 | - The output of `npx envinfo --system --npmPackages svelte,sapper,rollup,webpack --binaries --browsers` 20 | - Your browser 21 | - Your hosting environment (i.e. Local, GCP/AWS/Azure, Vercel/Begin, etc...) 22 | - If it is an exported (`npm run export`) or dynamic application 23 | 24 | - *Repeatable steps to reproduce the issue* 25 | 26 | * We recommend creating a small repo that illustrates the problem. 27 | * Reproductions should be small, self-contained, correct examples – http://sscce.org. 28 | 29 | Thanks for being part of Sapper! 30 | ------- 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'New Feature' 6 | assignees: '' 7 | 8 | --- 9 | 10 | NOTE: All development is currently focused on Sapper's successor, SvelteKit: https://kit.svelte.dev/ 11 | We are not adding new features to Sapper. Please see whether SvelteKit has the feature you need and 12 | if not consider filing your feature request there instead. 13 | 14 | 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/questions-and-help.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Questions and help 3 | about: If you think you need help with something related to Sapper 4 | title: '' 5 | labels: 'Question' 6 | assignees: '' 7 | 8 | --- 9 | 10 | This issue tracker is intended to collect bug reports and feature requests. 11 | 12 | For help with installation, information on how features work, or questions about specific features of Sapper, please come and join us in the [Svelte Discord](https://svelte.dev/chat), or ask your question on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte). Any issues open for help requests will be closed to keep from clogging up the issue tracker. 13 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | NOTE: All development is currently focused on Sapper's successor, SvelteKit: https://kit.svelte.dev/ 2 | We are not adding new features to Sapper. While we might fix some particularly pressing or easy to 3 | address bugs, it's highly unlikely that most PRs will be reviewed. 4 | 5 | ### Before submitting the PR, please make sure you do the following 6 | - [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs 7 | - [ ] This message body should clearly illustrate what problems it solves. 8 | - [ ] Ideally, include a test that fails without this PR but passes with it. 9 | 10 | ### Tests 11 | - [ ] Run the tests with `npm test` and lint the project with `npm run lint` 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | Tests: 5 | runs-on: ${{ matrix.os }} 6 | timeout-minutes: 30 7 | strategy: 8 | matrix: 9 | node-version: [10, 12, 14] 10 | os: [ubuntu-latest, windows-latest, macOS-latest] 11 | steps: 12 | - run: git config --global core.autocrlf false 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v2 15 | with: 16 | node-version: ${{ matrix.node-version }} 17 | cache: npm 18 | - run: npm install 19 | - run: npm test 20 | env: 21 | CI: true 22 | Lint: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: actions/setup-node@v2 27 | with: 28 | cache: npm 29 | - run: 'npm i && npm run lint' 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | /test/**/node_modules 4 | __sapper__ 5 | dist 6 | /runtime/app.mjs 7 | /runtime/server.mjs 8 | /.vscode/settings.json -------------------------------------------------------------------------------- /.mocharc.yml: -------------------------------------------------------------------------------- 1 | recursive: true 2 | require: 3 | - 'source-map-support/register' 4 | - 'ts-node/register' 5 | spec: 'test/**/*test.ts' 6 | -------------------------------------------------------------------------------- /.netlify/state.json: -------------------------------------------------------------------------------- 1 | { 2 | "siteId": "a6a3cfed-c34e-42f7-9616-07ad2eedb15f" 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-present [these people](https://github.com/sveltejs/sapper/graphs/contributors) 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sapper 2 | 3 | [Sapper](https://sapper.svelte.dev) is deprecated in favor of its successor, [SvelteKit](https://kit.svelte.dev/), which we recommend using instead. 4 | 5 | ## Financial Support 6 | 7 | To support Sapper, SvelteKit, and the rest of the Svelte ecosystem, please consider [contributing via OpenCollective](https://opencollective.com/svelte). 8 | 9 | ## License 10 | 11 | [MIT](LICENSE) 12 | -------------------------------------------------------------------------------- /api.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./dist/api.js'); -------------------------------------------------------------------------------- /config/rollup.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../dist/rollup.js'); -------------------------------------------------------------------------------- /config/webpack.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../dist/webpack.js'); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | throw new Error(`As of Sapper 0.22, you should not import 'sapper' directly. See https://sapper.svelte.technology/guide#0-21-to-0-22 for more information`); -------------------------------------------------------------------------------- /runtime/internal/error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 | {#if process.env.NODE_ENV === 'development'} 11 |
{error.stack}
12 | {/if} -------------------------------------------------------------------------------- /runtime/internal/layout.svelte: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /runtime/internal/shared.mjs: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | 3 | export const CONTEXT_KEY = {}; 4 | 5 | export const preload = () => ({}); -------------------------------------------------------------------------------- /runtime/src/app/baseuri_helper.ts: -------------------------------------------------------------------------------- 1 | export function get_base_uri(window_document) { 2 | let baseURI = window_document.baseURI; 3 | 4 | if (!baseURI) { 5 | const baseTags = window_document.getElementsByTagName('base'); 6 | baseURI = baseTags.length ? baseTags[0].href : window_document.URL; 7 | } 8 | 9 | return baseURI; 10 | } 11 | -------------------------------------------------------------------------------- /runtime/src/app/goto/index.ts: -------------------------------------------------------------------------------- 1 | import { cid, history, navigate, select_target } from '../router'; 2 | import { get_base_uri } from '../baseuri_helper'; 3 | 4 | export default function goto( 5 | href: string, 6 | opts: { noscroll?: boolean; replaceState?: boolean } = { noscroll: false, replaceState: false } 7 | ): Promise { 8 | const target = select_target(new URL(href, get_base_uri(document))); 9 | 10 | if (target) { 11 | const res = navigate(target, null, opts.noscroll); 12 | history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href); 13 | return res; 14 | } 15 | 16 | location.href = href; 17 | return new Promise(() => { 18 | /* never resolves */ 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /runtime/src/app/index.ts: -------------------------------------------------------------------------------- 1 | import { getContext } from 'svelte'; 2 | import { CONTEXT_KEY } from '@sapper/internal/shared'; 3 | 4 | export const stores = () => getContext(CONTEXT_KEY); 5 | 6 | export { default as start } from './app'; 7 | export { default as goto } from './goto/index'; 8 | export { default as prefetch } from './prefetch/index'; 9 | export { default as prefetchRoutes } from './prefetchRoutes/index'; 10 | -------------------------------------------------------------------------------- /runtime/src/app/prefetchRoutes/index.ts: -------------------------------------------------------------------------------- 1 | import { components, routes } from '@sapper/internal/manifest-client'; 2 | 3 | export default function prefetchRoutes(pathnames: string[]): Promise { 4 | return routes 5 | .filter(pathnames 6 | ? route => pathnames.some(pathname => route.pattern.test(pathname)) 7 | : () => true 8 | ) 9 | .reduce((promise: Promise, route) => promise.then(() => { 10 | return Promise.all(route.parts.map(part => part && components[part.i].js())); 11 | }), Promise.resolve()); 12 | } 13 | -------------------------------------------------------------------------------- /runtime/src/app/router/find_anchor.ts: -------------------------------------------------------------------------------- 1 | export default function find_anchor(node: Node) { 2 | while (node && node.nodeName.toUpperCase() !== 'A') node = node.parentNode; // SVG elements have a lowercase name 3 | return node; 4 | } 5 | -------------------------------------------------------------------------------- /runtime/src/app/stores/index.ts: -------------------------------------------------------------------------------- 1 | import { writable, Readable } from 'svelte/store'; 2 | 3 | /** Callback to inform of a value updates. */ 4 | type Subscriber = (value: T) => void; 5 | 6 | /** Unsubscribes from value updates. */ 7 | type Unsubscriber = () => void; 8 | 9 | /** Writable interface for both updating and subscribing. */ 10 | interface PageStore extends Readable { 11 | /** 12 | * Inform subscribers. 13 | */ 14 | notify(): void; 15 | 16 | /** 17 | * Set value without informing subscribers. 18 | * @param value to set 19 | */ 20 | set(value: T): void; 21 | } 22 | 23 | export function page_store(value: T): PageStore { 24 | const store = writable(value); 25 | let ready = true; 26 | 27 | function notify(): void { 28 | ready = true; 29 | store.update(val => val); 30 | } 31 | 32 | function set(new_value: T): void { 33 | ready = false; 34 | store.set(new_value); 35 | } 36 | 37 | function subscribe(run: Subscriber): Unsubscriber { 38 | let old_value; 39 | return store.subscribe((new_value) => { 40 | if (old_value === undefined || (ready && new_value !== old_value)) { 41 | run(old_value = new_value); 42 | } 43 | }); 44 | } 45 | 46 | return { notify, set, subscribe }; 47 | } 48 | -------------------------------------------------------------------------------- /runtime/src/app/types.ts: -------------------------------------------------------------------------------- 1 | import { DOMComponentConstructor, Route } from '@sapper/internal/manifest-client'; 2 | 3 | export interface HydratedTarget { 4 | redirect?: Redirect; 5 | preload_error?: any; 6 | props: any; 7 | branch: Branch; 8 | } 9 | 10 | export type Branch = Array<{ 11 | segment: string; 12 | match?: RegExpExecArray; 13 | component?: DOMComponentConstructor; 14 | part?: number; 15 | }>; 16 | 17 | export type InitialData = { 18 | session: any; 19 | preloaded?: object[]; 20 | status: number; 21 | error: Error; 22 | baseUrl: string; 23 | } 24 | 25 | export interface ScrollPosition { 26 | x: number; 27 | y: number; 28 | } 29 | 30 | export interface Target { 31 | href: string; 32 | route: Route; 33 | match: RegExpExecArray; 34 | page: Page; 35 | } 36 | 37 | export interface Redirect { 38 | statusCode: number; 39 | location: string; 40 | } 41 | 42 | export interface Page { 43 | host: string; 44 | path: string; 45 | params: Record; 46 | query: Record; 47 | } 48 | -------------------------------------------------------------------------------- /runtime/src/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file exists to avoid errors on references to @sapper/common from inside Sapper. 3 | * (@sapper/common is a namespace defined in index.d.ts) 4 | */ 5 | 6 | export default null; 7 | -------------------------------------------------------------------------------- /runtime/src/internal/App.svelte.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ComponentConstructor, 3 | SSRComponent 4 | } from './shared'; 5 | 6 | declare const App: ComponentConstructor & SSRComponent; 7 | 8 | export default App; 9 | -------------------------------------------------------------------------------- /runtime/src/internal/manifest-client.d.ts: -------------------------------------------------------------------------------- 1 | import { PageParams, Preload } from '@sapper/common'; 2 | 3 | export interface DOMComponentModule { 4 | default: DOMComponentConstructor; 5 | preload?: Preload; 6 | } 7 | 8 | export interface DOMComponent { 9 | $set: (data: any) => void; 10 | $destroy: () => void; 11 | } 12 | 13 | export interface DOMComponentConstructor { 14 | new(options: { target: Element, props: unknown, hydrate: boolean }): DOMComponent; 15 | } 16 | 17 | export interface DOMComponentLoader { 18 | js: () => Promise 19 | } 20 | 21 | export interface Route { 22 | pattern: RegExp; 23 | parts: Array<{ 24 | i: number; 25 | params?: (match: RegExpExecArray) => PageParams; 26 | }>; 27 | } 28 | 29 | export const ErrorComponent: DOMComponentConstructor; 30 | export const components: DOMComponentLoader[]; 31 | export const ignore: RegExp[]; 32 | export const root_comp: { preload: Preload }; 33 | export const routes: Route[]; 34 | -------------------------------------------------------------------------------- /runtime/src/internal/manifest-server.d.ts: -------------------------------------------------------------------------------- 1 | import { Preload } from '@sapper/common'; 2 | import { SapperRequest, SapperResponse } from '@sapper/server'; 3 | 4 | export const src_dir: string; 5 | export const build_dir: string; 6 | export const dev: boolean; 7 | export const manifest: Manifest; 8 | 9 | export type { SapperRequest, SapperResponse }; 10 | 11 | export interface SSRComponentModule { 12 | default: SSRComponent; 13 | preload?: Preload; 14 | } 15 | 16 | export interface SSRComponent { 17 | render(props: unknown): { 18 | html: string 19 | head: string 20 | css: { code: string, map: unknown }; 21 | } 22 | } 23 | 24 | export interface Manifest { 25 | server_routes: ServerRoute[]; 26 | ignore: RegExp[]; 27 | root_comp: SSRComponentModule 28 | error: SSRComponent 29 | pages: ManifestPage[] 30 | } 31 | 32 | export interface ManifestPage { 33 | pattern: RegExp | null; 34 | parts: ManifestPagePart[]; 35 | } 36 | 37 | export interface ManifestPagePart { 38 | name: string | null; 39 | file?: string; 40 | component: SSRComponentModule; 41 | params?: (match: RegExpMatchArray | null) => Record; 42 | } 43 | 44 | export type Handler = (req: SapperRequest, res: SapperResponse, next: () => void) => void; 45 | 46 | export interface ServerRoute { 47 | pattern: RegExp; 48 | handlers: Record; 49 | params: (match: RegExpMatchArray) => Record; 50 | } 51 | -------------------------------------------------------------------------------- /runtime/src/internal/shared.d.ts: -------------------------------------------------------------------------------- 1 | export const CONTEXT_KEY: unknown; 2 | -------------------------------------------------------------------------------- /runtime/src/server/index.ts: -------------------------------------------------------------------------------- 1 | export { default as middleware } from './middleware/index'; 2 | -------------------------------------------------------------------------------- /runtime/src/server/middleware/detect_client_only_references.ts: -------------------------------------------------------------------------------- 1 | function convertThrownError(fn: () => T, convertError: (error: any) => Error): T { 2 | try { 3 | const result = fn(); 4 | 5 | if (result instanceof Promise) { 6 | return result.catch(e => { 7 | throw convertError(e); 8 | }) as any; 9 | } else { 10 | return result; 11 | } 12 | } catch (e) { 13 | throw convertError(e); 14 | } 15 | } 16 | 17 | /** 18 | * If the code executing in fn() tries to access `window` or `document`, throw 19 | * an explanatory error. Also works if fn() is async. 20 | */ 21 | export default function detectClientOnlyReferences(fn: () => T): T { 22 | return convertThrownError(fn, e => { 23 | const m = e.message.match('(document|window) is not defined'); 24 | 25 | if (m && e.name === 'ReferenceError') { 26 | e.message = `Server-side code is attempting to access the global variable "${m[1]}", which is client only. See https://sapper.svelte.dev/docs/#Server-side_rendering`; 27 | } 28 | 29 | return e; 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /sapper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('./dist/cli.js'); -------------------------------------------------------------------------------- /sapper-dev-client.js: -------------------------------------------------------------------------------- 1 | let source; 2 | 3 | function check() { 4 | if (typeof module === 'undefined') return; 5 | 6 | if (module.hot.status() === 'idle') { 7 | module.hot.check(true).then(modules => { 8 | console.log(`[SAPPER] applied HMR update`); 9 | }); 10 | } 11 | } 12 | 13 | export function connect(port) { 14 | if (source || !window.EventSource) return; 15 | 16 | source = new EventSource(`http://${window.location.hostname}:${port}/__sapper__`); 17 | 18 | window.source = source; 19 | 20 | source.onopen = function(event) { 21 | console.log(`[SAPPER] dev client connected`); 22 | }; 23 | 24 | source.onerror = function(error) { 25 | console.error(error); 26 | }; 27 | 28 | source.onmessage = function(event) { 29 | const data = JSON.parse(event.data); 30 | if (!data) return; // just a heartbeat 31 | 32 | if (data.action === 'reload') { 33 | window.location.reload(); 34 | } 35 | 36 | if (data.status === 'completed') { 37 | check(); 38 | } 39 | }; 40 | 41 | // Close the event source before the window is unloaded to prevent an error 42 | // ("The connection was interrupted while the page was loading.") in Firefox 43 | // when the page is reloaded. 44 | window.addEventListener('beforeunload', function() { 45 | source.close(); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /site/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | /* The dependencies haven't been installed on CI when lint is run. This should be fixed. */ 4 | 'import/no-unresolved': 'off' 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /site/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | yarn-error.log 4 | /cypress/screenshots/ 5 | /__sapper__/ 6 | -------------------------------------------------------------------------------- /site/README.md: -------------------------------------------------------------------------------- 1 | ## Running locally 2 | 3 | Set up the project: 4 | 5 | ```bash 6 | git clone https://github.com/sveltejs/sapper.git 7 | cd sapper/site 8 | npm ci 9 | ``` 10 | 11 | Start the server with `npm run dev`, and navigate to [localhost:3000](http://localhost:3000). 12 | 13 | ## Translating the API docs 14 | 15 | Anchors are automatically generated using headings in the documentation and by default (for the english language) they are latinised to make sure the URL is always conforming to RFC3986. 16 | 17 | If we need to translate the API documentation to a language using unicode chars, we can setup this app to export the correct anchors by setting up `SLUG_PRESERVE_UNICODE` to `true` in `config.js`. 18 | -------------------------------------------------------------------------------- /site/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | shallow_clone: true 4 | 5 | init: 6 | - git config --global core.autocrlf false 7 | 8 | build: off 9 | 10 | environment: 11 | matrix: 12 | # node.js 13 | - nodejs_version: stable 14 | 15 | install: 16 | - ps: Install-Product node $env:nodejs_version 17 | - npm install 18 | -------------------------------------------------------------------------------- /site/config.js: -------------------------------------------------------------------------------- 1 | export const SLUG_PRESERVE_UNICODE = false; 2 | export const SLUG_SEPARATOR = '_'; 3 | export const SLUG_LANG = 'en'; 4 | -------------------------------------------------------------------------------- /site/content/docs/13-base-urls.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Base URLs 3 | --- 4 | 5 | Ordinarily, the root of your Sapper app is served at `/`. But in some cases, your app may need to be served from a different base path — for example, if Sapper only controls part of your domain, or if you have multiple Sapper apps living side-by-side. 6 | 7 | This can be done like so: 8 | 9 | ```js 10 | // app/server.js 11 | 12 | express() // or Polka, or a similar framework 13 | .use( 14 | '/my-base-path', // /gm, ''); 7 | } 8 | -------------------------------------------------------------------------------- /src/api/utils/copy_runtime.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | import { mkdirp } from './fs_utils'; 4 | 5 | const runtime = [ 6 | 'index.d.ts', 7 | 'app.mjs', 8 | 'server.mjs', 9 | 'internal/shared.mjs', 10 | 'internal/layout.svelte', 11 | 'internal/error.svelte' 12 | ].map(file => ({ 13 | file, 14 | source: fs.readFileSync(path.join(__dirname, `../runtime/${file}`), 'utf-8') 15 | })); 16 | 17 | export function copy_runtime(output: string) { 18 | runtime.forEach(({ file, source }) => { 19 | mkdirp(path.dirname(`${output}/${file}`)); 20 | fs.writeFileSync(`${output}/${file}`, source); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /src/api/utils/copy_shimport.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import { version as shimport_version } from 'shimport/package.json'; 3 | 4 | export function copy_shimport(dest: string) { 5 | fs.writeFileSync( 6 | `${dest}/client/shimport@${shimport_version}.js`, 7 | fs.readFileSync(require.resolve('shimport/index.js')) 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src/api/utils/fs_utils.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | 4 | export function mkdirp(dir: string) { 5 | const parent = path.dirname(dir); 6 | if (parent === dir) return; 7 | 8 | mkdirp(parent); 9 | 10 | try { 11 | fs.mkdirSync(dir); 12 | } catch (err) { 13 | // ignore 14 | } 15 | } 16 | 17 | export function rimraf(thing: string) { 18 | if (!fs.existsSync(thing)) return; 19 | 20 | const stats = fs.statSync(thing); 21 | 22 | if (stats.isDirectory()) { 23 | fs.readdirSync(thing).forEach(file => { 24 | rimraf(path.join(thing, file)); 25 | }); 26 | 27 | fs.rmdirSync(thing); 28 | } else { 29 | fs.unlinkSync(thing); 30 | } 31 | } 32 | 33 | export function copy(from: string, to: string) { 34 | if (!fs.existsSync(from)) return; 35 | 36 | const stats = fs.statSync(from); 37 | 38 | if (stats.isDirectory()) { 39 | fs.readdirSync(from).forEach(file => { 40 | copy(path.join(from, file), path.join(to, file)); 41 | }); 42 | } else { 43 | mkdirp(path.dirname(to)); 44 | fs.writeFileSync(to, fs.readFileSync(from)); 45 | fs.utimesSync(to, stats.atime, stats.mtime); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/api/utils/minify_html.ts: -------------------------------------------------------------------------------- 1 | import { minify } from 'html-minifier'; 2 | 3 | export default function minify_html(html: string) { 4 | return minify(html, { 5 | collapseBooleanAttributes: true, 6 | collapseWhitespace: true, 7 | conservativeCollapse: true, 8 | decodeEntities: true, 9 | html5: true, 10 | ignoreCustomComments: [/^#/], 11 | minifyCSS: true, 12 | minifyJS: false, 13 | removeAttributeQuotes: true, 14 | removeComments: true, 15 | removeOptionalTags: true, 16 | removeRedundantAttributes: true, 17 | removeScriptTypeAttributes: true, 18 | removeStyleLinkTypeAttributes: true, 19 | sortAttributes: true, 20 | sortClassName: true 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /src/api/utils/noop.ts: -------------------------------------------------------------------------------- 1 | export function noop() {} 2 | -------------------------------------------------------------------------------- /src/api/utils/validate_bundler.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | 3 | export default function validate_bundler(bundler?: 'rollup' | 'webpack') { 4 | if (!bundler) { 5 | bundler = ( 6 | fs.existsSync('rollup.config.js') || fs.existsSync('rollup.config.ts') ? 'rollup' : 7 | fs.existsSync('webpack.config.js') || fs.existsSync('webpack.config.ts') ? 'webpack' : null 8 | ); 9 | 10 | if (!bundler) { 11 | // TODO remove in a future version 12 | deprecate_dir('rollup'); 13 | deprecate_dir('webpack'); 14 | 15 | throw new Error('Could not find a configuration file for rollup or webpack'); 16 | } 17 | } 18 | 19 | if (bundler !== 'rollup' && bundler !== 'webpack') { 20 | throw new Error(`'${bundler}' is not a valid option for --bundler — must be either 'rollup' or 'webpack'`); 21 | } 22 | 23 | return bundler; 24 | } 25 | 26 | function deprecate_dir(bundler: 'rollup' | 'webpack') { 27 | try { 28 | const stats = fs.statSync(bundler); 29 | if (!stats.isDirectory()) return; 30 | } catch (err) { 31 | // do nothing 32 | return; 33 | } 34 | 35 | // TODO link to docs, once those docs exist 36 | throw new Error(`As of Sapper 0.21, build configuration should be placed in a single ${bundler}.config.js file`); 37 | } 38 | -------------------------------------------------------------------------------- /src/config/env.ts: -------------------------------------------------------------------------------- 1 | export let dev: boolean; 2 | export let src: string; 3 | export let dest: string; 4 | export let module: boolean; 5 | 6 | export const set_dev = (_: boolean) => dev = _; 7 | export const set_src = (_: string) => src = _; 8 | export const set_dest = (_: string) => dest = _; 9 | export const set_module = (_: boolean) => module = _; 10 | -------------------------------------------------------------------------------- /src/config/rollup.ts: -------------------------------------------------------------------------------- 1 | import { dev, src, dest, module } from './env'; 2 | import { InputOption, OutputOptions } from 'rollup'; 3 | 4 | const sourcemap = dev ? 'inline' : false; 5 | 6 | export default { 7 | dev, 8 | 9 | client: { 10 | input: (): InputOption => { 11 | return `${src}/client.js`; 12 | }, 13 | 14 | output: (): OutputOptions => { 15 | let dir = `${dest}/client`; 16 | if (process.env.SAPPER_LEGACY_BUILD) dir += '/legacy'; 17 | 18 | return { 19 | dir, 20 | entryFileNames: '[name].[hash].js', 21 | chunkFileNames: '[name].[hash].js', 22 | format: 'esm', 23 | sourcemap 24 | }; 25 | } 26 | }, 27 | 28 | server: { 29 | input: (): InputOption => { 30 | return { 31 | server: `${src}/server.js` 32 | }; 33 | }, 34 | 35 | output: (): OutputOptions => { 36 | return { 37 | dir: `${dest}/server`, 38 | format: module ? 'esm' : 'cjs', 39 | sourcemap 40 | }; 41 | } 42 | }, 43 | 44 | serviceworker: { 45 | input: (): InputOption => { 46 | return `${src}/service-worker.js`; 47 | }, 48 | 49 | output: (): OutputOptions => { 50 | return { 51 | file: `${dest}/service-worker.js`, 52 | format: 'iife', 53 | sourcemap 54 | }; 55 | } 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /src/config/webpack.ts: -------------------------------------------------------------------------------- 1 | import { dev, src, dest } from './env'; 2 | 3 | export default { 4 | dev, 5 | 6 | client: { 7 | entry: () => { 8 | return { 9 | main: `${src}/client` 10 | }; 11 | }, 12 | 13 | output: () => { 14 | return { 15 | path: `${dest}/client`, 16 | filename: '[hash]/[name].js', 17 | chunkFilename: '[hash]/[name].[id].js', 18 | publicPath: 'client/' 19 | }; 20 | } 21 | }, 22 | 23 | server: { 24 | entry: () => { 25 | return { 26 | server: `${src}/server` 27 | }; 28 | }, 29 | 30 | output: () => { 31 | return { 32 | path: `${dest}/server`, 33 | filename: '[name].js', 34 | chunkFilename: '[hash]/[name].[id].js', 35 | publicPath: 'client/', 36 | libraryTarget: 'commonjs2' 37 | }; 38 | } 39 | }, 40 | 41 | serviceworker: { 42 | entry: () => { 43 | return { 44 | 'service-worker': `${src}/service-worker` 45 | }; 46 | }, 47 | 48 | output: () => { 49 | return { 50 | path: dest, 51 | filename: '[name].js', 52 | chunkFilename: '[name].[id].[hash].js' 53 | }; 54 | } 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /src/core.ts: -------------------------------------------------------------------------------- 1 | export * from './core/create_app'; 2 | export { default as create_compilers } from './core/create_compilers/index'; 3 | export { default as create_manifest_data } from './core/create_manifest_data'; 4 | -------------------------------------------------------------------------------- /src/core/create_compilers/WebpackCompiler.ts: -------------------------------------------------------------------------------- 1 | import relative from 'require-relative'; 2 | import { CompileResult } from './interfaces'; 3 | import WebpackResult from './WebpackResult'; 4 | 5 | let webpack: any; 6 | 7 | export class WebpackCompiler { 8 | _: any; 9 | 10 | constructor(config: any) { 11 | if (!webpack) webpack = relative('webpack', process.cwd()); 12 | this._ = webpack(config); 13 | } 14 | 15 | oninvalid(cb: (filename: string) => void) { 16 | this._.hooks.invalid.tap('sapper', cb); 17 | } 18 | 19 | compile(): Promise { 20 | return new Promise((fulfil, reject) => { 21 | this._.run((err: Error, stats: any) => { 22 | if (err) { 23 | reject(err); 24 | process.exit(1); 25 | } 26 | 27 | const result = new WebpackResult(stats); 28 | 29 | if (result.errors.length) { 30 | console.error(stats.toString({ colors: true })); 31 | reject(new Error('Encountered errors while building app')); 32 | } else { 33 | fulfil(result); 34 | } 35 | }); 36 | }); 37 | } 38 | 39 | watch(cb: (err?: Error, stats?: any) => void) { 40 | this._.watch({}, (err?: Error, stats?: any) => { 41 | cb(err, stats && new WebpackResult(stats)); 42 | }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/core/create_compilers/interfaces.ts: -------------------------------------------------------------------------------- 1 | import { ManifestData, Dirs } from '../../interfaces'; 2 | 3 | export type Chunk = { 4 | file: string; 5 | imports: string[]; 6 | modules: string[]; 7 | } 8 | 9 | export type CssFile = { 10 | id: string; 11 | code: string; 12 | }; 13 | 14 | export class CompileError { 15 | file: string; 16 | message: string; 17 | } 18 | 19 | export interface CompileResult { 20 | duration: number; 21 | errors: CompileError[]; 22 | warnings: CompileError[]; 23 | chunks: Chunk[]; 24 | assets: Record; 25 | print: () => void; 26 | 27 | to_json: (manifest_data: ManifestData, dirs: Dirs) => BuildInfo; 28 | } 29 | 30 | export type BuildInfo = { 31 | bundler: string; 32 | shimport: string; 33 | assets: Record; 34 | dependencies?: Record; 35 | legacy_assets?: Record; 36 | css: { 37 | main: string[] | null; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /src/core/read_template.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | 3 | export default function read_template(dir: string) { 4 | try { 5 | return fs.readFileSync(`${dir}/template.html`, 'utf-8'); 6 | } catch (err) { 7 | if (fs.existsSync('app/template.html')) { 8 | throw new Error(`As of Sapper 0.21, the default folder structure has been changed: 9 | app/ --> src/ 10 | routes/ --> src/routes/ 11 | assets/ --> static/`); 12 | } 13 | 14 | throw err; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'svelte/compiler'; 2 | -------------------------------------------------------------------------------- /test/apps/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | /* The @sapper/service-worker dependency is missing in all the tests if they haven't been built yet. */ 4 | 'import/no-unresolved': 'off' 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /test/apps/basics/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/basics/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/[...rest]/deep.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.end(req.params.rest.join(',')); 3 | } 4 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/[...rest]/deep.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 |

{$page.params.rest.join(',')}

15 |

{rest.join(',')}

16 | 17 |
deep 18 | back 19 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/[...rest]/index.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 |

{$page.params.rest.join(',')}

15 |

{rest.join(',')}

16 | 17 | deep 18 | deep 19 | deep 20 | deep 21 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/[id([0-9]+)].svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

Regexp page {$page.params.id}

7 | 8 | nested regexp route 9 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/[slug].svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{$page.params.slug}

7 | 8 | regexp route 9 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/a.svelte: -------------------------------------------------------------------------------- 1 |

a

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/ambiguous/[slug].json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.end(req.params.slug); 3 | } 4 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/ambiguous/[slug].svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/apps/basics/src/routes/ambiguous/[slug].svelte -------------------------------------------------------------------------------- /test/apps/basics/src/routes/b/index.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.end(JSON.stringify('b')); 3 | } 4 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/b/index.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{letter}

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/client/bar/b.svelte: -------------------------------------------------------------------------------- 1 |

b

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/client/bar/index.svelte: -------------------------------------------------------------------------------- 1 |

bar

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/client/foo.svelte: -------------------------------------------------------------------------------- 1 |

foo

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/const.svelte: -------------------------------------------------------------------------------- 1 |

reserved words are okay as routes

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/delete-test/[id].json.js: -------------------------------------------------------------------------------- 1 | export function del(req, res) { 2 | res.writeHead(200, { 3 | 'Content-Type': 'application/json' 4 | }); 5 | 6 | res.end(JSON.stringify({ 7 | id: req.params.id 8 | })); 9 | } 10 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/delete-test/index.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/dirs/bar/[a].svelte: -------------------------------------------------------------------------------- 1 |

A page

2 | 3 | same segment 4 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/dirs/bar/index.svelte: -------------------------------------------------------------------------------- 1 |

bar

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/dirs/foo/[b].svelte: -------------------------------------------------------------------------------- 1 |

B page

2 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/dirs/foo/index.svelte: -------------------------------------------------------------------------------- 1 |

foo

2 | bar -------------------------------------------------------------------------------- /test/apps/basics/src/routes/echo-query/index.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{JSON.stringify($page.query)}

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/host.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{$page.host.replace(/:\d+$/, '')}

7 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | a 4 | ok 5 | ok 6 | ok 7 | 8 |
-------------------------------------------------------------------------------- /test/apps/basics/src/routes/middleware/index.js: -------------------------------------------------------------------------------- 1 | export function get(req, res, next) { 2 | if (req.headers.accept === 'application/json') { 3 | res.end('{"json":true}'); 4 | return; 5 | } 6 | 7 | next(); 8 | } 9 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/middleware/index.svelte: -------------------------------------------------------------------------------- 1 |

HTML

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/prefetch-timing/prefetched/index.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 31 | 32 |

Prefetched

33 | 34 | prefetcher 35 | prefetched 36 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/prefetch-timing/prefetcher/index.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |

Prefetcher

12 | 13 | prefetched 14 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/regexp/[id([0-9]+)].svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

Nested regexp page {$page.params.id}

7 | -------------------------------------------------------------------------------- /test/apps/basics/src/routes/skipped/[one]/[two].svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 |

{one}:{two}

13 | 14 | skipped/y/1 -------------------------------------------------------------------------------- /test/apps/basics/src/routes/store/index.svelte: -------------------------------------------------------------------------------- 1 | 21 | 22 |

Test

23 |

Called {call_count} time

24 | results -------------------------------------------------------------------------------- /test/apps/basics/src/routes/store/result.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |

Result

15 |

Called {call_count} time

-------------------------------------------------------------------------------- /test/apps/basics/src/routes/unsafe-replacement.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | $& -------------------------------------------------------------------------------- /test/apps/basics/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/basics/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/common.js: -------------------------------------------------------------------------------- 1 | const { NODE_ENV, PORT } = process.env; 2 | 3 | export const dev = NODE_ENV === 'development'; 4 | 5 | export function start(app) { 6 | const port = parseInt(PORT) || 0; 7 | 8 | app.listen(port, () => { 9 | const address = app.server.address(); 10 | 11 | process.env.PORT = address.port; 12 | 13 | send({ 14 | __sapper__: true, 15 | event: 'listening', 16 | address 17 | }); 18 | }); 19 | } 20 | 21 | const properties = ['name', 'message', 'stack', 'code', 'lineNumber', 'fileName']; 22 | 23 | function send(message) { 24 | process.send && process.send(message); 25 | } 26 | 27 | function send_error(error) { 28 | send({ 29 | __sapper__: true, 30 | event: 'error', 31 | error: properties.reduce((object, key) => ({...object, [key]: error[key]}), {}) 32 | }); 33 | } 34 | 35 | process.on('unhandledRejection', (reason, p) => { 36 | send_error(reason); 37 | }); 38 | 39 | process.on('uncaughtException', err => { 40 | send_error(err); 41 | process.exitCode = 1; 42 | }); 43 | -------------------------------------------------------------------------------- /test/apps/credentials/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/credentials/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/credentials/src/routes/credentials/authorization.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | if (req.headers.authorization) { 3 | res.writeHead(200); 4 | res.end(JSON.stringify({ 5 | message: req.headers.authorization 6 | })); 7 | } else { 8 | res.writeHead(200); 9 | res.end(JSON.stringify({ 10 | message: 'unauthorized' 11 | })); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/apps/credentials/src/routes/credentials/cookie.json.js: -------------------------------------------------------------------------------- 1 | import { parse } from 'cookie'; 2 | 3 | export function get(req, res) { 4 | if (req.headers.cookie) { 5 | const cookies = parse(req.headers.cookie); 6 | res.writeHead(200); 7 | res.end(JSON.stringify({ 8 | message: `a: ${cookies.a}, b: ${cookies.b}, max-age: ${cookies['max-age']}` 9 | })); 10 | } else { 11 | res.writeHead(200); 12 | res.end(JSON.stringify({ 13 | message: 'unauthorized' 14 | })); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/apps/credentials/src/routes/credentials/index.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{message}

-------------------------------------------------------------------------------- /test/apps/credentials/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | link -------------------------------------------------------------------------------- /test/apps/credentials/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use((req, res, next) => { 8 | // set test cookie 9 | res.setHeader('Set-Cookie', ['a=1; Max-Age=3600', 'b=2; Max-Age=3600']); 10 | next(); 11 | }) 12 | .use(sapper.middleware()); 13 | 14 | start(app); 15 | -------------------------------------------------------------------------------- /test/apps/credentials/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/csp-nonce/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: false 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/csp-nonce/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/csp-nonce/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

-------------------------------------------------------------------------------- /test/apps/csp-nonce/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

Great success!

8 | -------------------------------------------------------------------------------- /test/apps/csp-nonce/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use((req, res, next) => { 8 | res.locals = { nonce: 'nonce'}; 9 | next(); 10 | }) 11 | .use(sapper.middleware()); 12 | 13 | start(app); 14 | -------------------------------------------------------------------------------- /test/apps/csp-nonce/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | 10 | 11 |
%sapper.html%
12 | %sapper.scripts% 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/csp-nonce/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { build } from '../../../api'; 3 | import { AppRunner } from '../AppRunner'; 4 | 5 | describe('csp-nonce', function() { 6 | this.timeout(10000); 7 | 8 | let r: AppRunner; 9 | 10 | // hooks 11 | before('build app', () => build({ cwd: __dirname })); 12 | before('start runner', async () => { 13 | r = await new AppRunner().start(__dirname); 14 | }); 15 | 16 | after(() => r && r.end()); 17 | 18 | it('includes a script nonce', async () => { 19 | await r.load('/'); 20 | 21 | assert.strictEqual( 22 | await r.page.$eval('script:not([src])', node => node.getAttribute('nonce')), 23 | 'nonce' 24 | ); 25 | }); 26 | 27 | it('includes a style nonce', async () => { 28 | await r.load('/'); 29 | 30 | assert.strictEqual( 31 | await r.page.$eval('style', node => node.getAttribute('nonce')), 32 | 'nonce' 33 | ); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/apps/cspnonce/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/cspnonce/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/cspnonce/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

-------------------------------------------------------------------------------- /test/apps/cspnonce/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

-------------------------------------------------------------------------------- /test/apps/cspnonce/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use((req, res, next) => { 8 | res.locals = { nonce: 'rAnd0m123'}; 9 | next(); 10 | }) 11 | .use(sapper.middleware()); 12 | 13 | start(app); 14 | -------------------------------------------------------------------------------- /test/apps/cspnonce/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | 10 | 11 |
%sapper.html%
12 | 13 | 14 | 15 | %sapper.scripts% 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/apps/cspnonce/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { build } from '../../../api'; 3 | import { AppRunner } from '../AppRunner'; 4 | 5 | describe('cspnonce', function() { 6 | this.timeout(10000); 7 | 8 | let r: AppRunner; 9 | 10 | // hooks 11 | before('build app', () => build({ cwd: __dirname })); 12 | before('start runner', async () => { 13 | r = await new AppRunner().start(__dirname); 14 | }); 15 | 16 | after(() => r && r.end()); 17 | 18 | it('sapper.cspnonce replaced with CSP nonce \'rAnd0m123\' injected via \'res.locals.nonce\'', async () => { 19 | await r.load('/'); 20 | 21 | assert.equal( 22 | await r.page.$eval('#hasNonce', node => node.getAttribute('nonce')), 'rAnd0m123' 23 | ); 24 | assert.equal( 25 | await r.page.$eval('#hasNonceAgain', node => node.getAttribute('nonce')), 'rAnd0m123' 26 | ); 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /test/apps/css-inlined/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/css-inlined/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 |

This is an error page

13 | 14 |

{status}

15 | 16 |

{error.message}

17 | 18 |
{error.stack}
19 | -------------------------------------------------------------------------------- /test/apps/css-inlined/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | foo 4 | bar 5 | 6 | -------------------------------------------------------------------------------- /test/apps/css-inlined/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/css-inlined/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/css-inlined/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { build } from '../../../api'; 3 | import { AppRunner } from '../AppRunner'; 4 | 5 | describe('css inlined', function() { 6 | this.timeout(10000); 7 | 8 | let r: AppRunner; 9 | 10 | // hooks 11 | before('build app', () => build({ cwd: __dirname })); 12 | before('start runner', async () => { 13 | r = await new AppRunner().start(__dirname); 14 | }); 15 | 16 | after(() => r && r.end()); 17 | 18 | // tests 19 | it('includes critical CSS with server render', async () => { 20 | await r.load('/'); 21 | 22 | assert((await r.page.content()).includes('color:red')); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/apps/css/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/_components/NestedRouteTest.svelte: -------------------------------------------------------------------------------- 1 |

This is content defined in a component imported by a layout in a nested routes.

2 | 3 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/_components/Title.svelte: -------------------------------------------------------------------------------- 1 |

Title

2 | 3 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 |

This is an error page

13 | 14 |

{status}

15 | 16 |

{error.message}

17 | 18 |
{error.stack}
19 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/bar.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/foo.svelte: -------------------------------------------------------------------------------- 1 |

Foo

2 | 3 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | foo 4 | bar 5 | 6 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/index2.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/nested/_layout.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

This is content defined in a layout in a nested route. It should have a green background.

6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/apps/css/src/routes/nested/index.svelte: -------------------------------------------------------------------------------- 1 |

This is slotted page content in a nested routes.

-------------------------------------------------------------------------------- /test/apps/css/src/routes/title.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/apps/css/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/css/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/custom-extension/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/custom-extension/src/routes/[slug].mdx: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{$page.params.slug.toUpperCase()}

-------------------------------------------------------------------------------- /test/apps/custom-extension/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 |

hi

2 | 3 |

hi

4 | -------------------------------------------------------------------------------- /test/apps/custom-extension/src/routes/a.svelte: -------------------------------------------------------------------------------- 1 |

a

-------------------------------------------------------------------------------- /test/apps/custom-extension/src/routes/const.whokilledthemuffinman: -------------------------------------------------------------------------------- 1 |

Tremendous!

-------------------------------------------------------------------------------- /test/apps/custom-extension/src/routes/ide-friendly.route.svelte: -------------------------------------------------------------------------------- 1 |

Great success, IDE friendly custom extensions!

2 | 3 | -------------------------------------------------------------------------------- /test/apps/custom-extension/src/routes/index.jesuslivesineveryone: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | a 4 | ok 5 | ok 6 | ok 7 | 8 |
-------------------------------------------------------------------------------- /test/apps/custom-extension/src/routes/unsafe-replacement.svelte: -------------------------------------------------------------------------------- 1 |

Bazooom!

-------------------------------------------------------------------------------- /test/apps/custom-extension/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/custom-extension/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/encoding/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/encoding/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/encoding/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/encoding/src/routes/echo/page/[slug].html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | 17 |

{slug} {JSON.stringify($page.query)}

-------------------------------------------------------------------------------- /test/apps/encoding/src/routes/echo/server-route/[slug].js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.writeHead(200, { 3 | 'Content-Type': 'text/html' 4 | }); 5 | 6 | res.end(` 7 | 8 | 9 | 10 | 11 |

${req.params.slug}

12 | 13 | 14 | `); 15 | } 16 | -------------------------------------------------------------------------------- /test/apps/encoding/src/routes/fünke.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{phrase}

-------------------------------------------------------------------------------- /test/apps/encoding/src/routes/fünke.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.writeHead(200, { 3 | 'Content-Type': 'application/json' 4 | }); 5 | 6 | res.end(JSON.stringify( 7 | "I'm afraid I just blue myself" 8 | )); 9 | } 10 | -------------------------------------------------------------------------------- /test/apps/encoding/src/routes/index.html: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | link -------------------------------------------------------------------------------- /test/apps/encoding/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/encoding/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/errors/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |

{status}

14 | 15 |

{mounted}

16 | 17 |

{error.message}

18 | 19 | {error.stack} 20 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/_layout.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/_trace.js: -------------------------------------------------------------------------------- 1 | export function oops() { 2 | throw new Error('oops'); 3 | } 4 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/access_document.svelte: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/async-throw.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | return Promise.reject(new Error('oops')); 3 | } 4 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/blog/[slug].html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 20 | 21 |

{post.title}

-------------------------------------------------------------------------------- /test/apps/errors/src/routes/blog/[slug].json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.writeHead(404, { 3 | 'Content-Type': 'application/json' 4 | }); 5 | 6 | res.end(JSON.stringify({ 7 | message: 'not found' 8 | })); 9 | } 10 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/enhance-your-calm.svelte: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

root

2 | 3 | nope 4 | blog/nope 5 | throw 6 | preload-reject 7 | trace 8 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/no-error.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

{error ? error.message : 'No error here'}

6 | 7 | Enhance your calm -------------------------------------------------------------------------------- /test/apps/errors/src/routes/nope.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.writeHead(500); 3 | res.end('nope'); 4 | } 5 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/preload-reject.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

Test has failed

8 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/throw.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | throw new Error('oops'); 3 | } 4 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/throw.svelte: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/apps/errors/src/routes/trace.svelte: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /test/apps/errors/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/errors/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/about.svelte: -------------------------------------------------------------------------------- 1 |

I am an about page

2 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/blog/[slug].html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{post.title}

-------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/blog/[slug].json.js: -------------------------------------------------------------------------------- 1 | import posts from './_posts.js'; 2 | 3 | export function get(req, res) { 4 | const post = posts.find(post => post.slug === req.params.slug); 5 | 6 | if (post) { 7 | res.writeHead(200, { 8 | 'Content-Type': 'application/json' 9 | }); 10 | 11 | res.end(JSON.stringify(post)); 12 | } else { 13 | res.writeHead(404, { 14 | 'Content-Type': 'application/json' 15 | }); 16 | 17 | res.end(JSON.stringify({ message: 'not found' })); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/blog/_posts.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { slug: 'foo', title: 'once upon a foo' }, 3 | { slug: 'bar', title: 'a bar is born' }, 4 | { slug: 'baz', title: 'bazzily ever after' } 5 | ]; 6 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/blog/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

blog

14 | 15 | {#each posts as post} 16 |

{post.title}

17 | {/each} -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/blog/index.json.js: -------------------------------------------------------------------------------- 1 | import posts from './_posts.js'; 2 | 3 | export function get(req, res) { 4 | res.writeHead(200, { 5 | 'Content-Type': 'application/json' 6 | }); 7 | 8 | res.end(JSON.stringify(posts)); 9 | } 10 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/boom/[a]/[b].svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 |

{a}/{b}

-------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/boom/[a]/index.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | {#each list as b} 14 | {a}/{b} 15 | {/each} -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/boom/index.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | {#each list as a} 6 | {a} 7 | {/each} -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/contact.svelte: -------------------------------------------------------------------------------- 1 |

I am a contact page

2 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | 4 | empty anchor 5 | 6 | empty anchor #2 7 | 8 | empty anchor #3 9 | 10 | empty anchor #4 11 | empty anchor #5 12 | 13 | empty anchor #6 14 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/server.js: -------------------------------------------------------------------------------- 1 | import sirv from 'sirv'; 2 | import polka from 'polka'; 3 | import * as sapper from '@sapper/server'; 4 | 5 | import { start, dev } from '../../common.js'; 6 | 7 | const app = polka() 8 | .use( 9 | sirv('static', { dev }), 10 | sapper.middleware() 11 | ); 12 | 13 | start(app); 14 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/export-multiple-entry/static/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Comic Sans MS'; 3 | } -------------------------------------------------------------------------------- /test/apps/export-queue/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/export-queue/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/export-queue/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/export-queue/src/routes/a-[x].svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 14 | 15 | b-{x} 16 | -------------------------------------------------------------------------------- /test/apps/export-queue/src/routes/b-[x].svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

b-{x}

6 | -------------------------------------------------------------------------------- /test/apps/export-queue/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 | 2 | 1 3 | 2 4 | -------------------------------------------------------------------------------- /test/apps/export-queue/src/server.js: -------------------------------------------------------------------------------- 1 | import sirv from 'sirv'; 2 | import polka from 'polka'; 3 | import * as sapper from '@sapper/server'; 4 | 5 | import { start, dev } from '../../common.js'; 6 | 7 | const app = polka() 8 | .use( 9 | sirv('static', { dev }), 10 | sapper.middleware() 11 | ); 12 | 13 | start(app); 14 | -------------------------------------------------------------------------------- /test/apps/export-queue/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/export-queue/static/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Comic Sans MS'; 3 | } -------------------------------------------------------------------------------- /test/apps/export-queue/test.ts: -------------------------------------------------------------------------------- 1 | import * as api from '../../../api'; 2 | 3 | describe('export-queue', function() { 4 | this.timeout(20000); 5 | 6 | // hooks 7 | before('build app', () => api.build({ cwd: __dirname })); 8 | 9 | // tests 10 | it('exports a site with inconsistent load time', async () => { 11 | await api.export({ cwd: __dirname }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/apps/export-webpack/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/export-webpack/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/export-webpack/src/routes/blog/[slug].html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{post.title}

-------------------------------------------------------------------------------- /test/apps/export-webpack/src/routes/blog/[slug].json.js: -------------------------------------------------------------------------------- 1 | import posts from './_posts.js'; 2 | 3 | export function get(req, res) { 4 | const post = posts.find(post => post.slug === req.params.slug); 5 | 6 | if (post) { 7 | res.writeHead(200, { 8 | 'Content-Type': 'application/json' 9 | }); 10 | 11 | res.end(JSON.stringify(post)); 12 | } else { 13 | res.writeHead(404, { 14 | 'Content-Type': 'application/json' 15 | }); 16 | 17 | res.end(JSON.stringify({ message: 'not found' })); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/apps/export-webpack/src/routes/blog/_posts.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { slug: 'foo', title: 'once upon a foo' }, 3 | { slug: 'bar', title: 'a bar is born' }, 4 | { slug: 'baz', title: 'bazzily ever after' } 5 | ]; 6 | -------------------------------------------------------------------------------- /test/apps/export-webpack/src/routes/blog/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

blog

14 | 15 | {#each posts as post} 16 |

{post.title}

17 | {/each} -------------------------------------------------------------------------------- /test/apps/export-webpack/src/routes/blog/index.json.js: -------------------------------------------------------------------------------- 1 | import posts from './_posts.js'; 2 | 3 | export function get(req, res) { 4 | res.writeHead(200, { 5 | 'Content-Type': 'application/json' 6 | }); 7 | 8 | res.end(JSON.stringify(posts)); 9 | } 10 | -------------------------------------------------------------------------------- /test/apps/export-webpack/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | blog 4 | 5 | empty anchor -------------------------------------------------------------------------------- /test/apps/export-webpack/src/server.js: -------------------------------------------------------------------------------- 1 | import sirv from 'sirv'; 2 | import polka from 'polka'; 3 | import * as sapper from '@sapper/server'; 4 | 5 | import { start, dev } from '../../common.js'; 6 | 7 | const app = polka() 8 | .use( 9 | sirv('static', { dev }), 10 | sapper.middleware() 11 | ); 12 | 13 | start(app); 14 | -------------------------------------------------------------------------------- /test/apps/export-webpack/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/export-webpack/static/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Comic Sans MS'; 3 | } -------------------------------------------------------------------------------- /test/apps/export-webpack/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import * as api from '../../../api'; 3 | import * as fs from 'fs'; 4 | 5 | describe('export-webpack', function() { 6 | this.timeout(20000); 7 | 8 | // hooks 9 | before('build app', () => api.build({ cwd: __dirname, bundler: 'webpack' })); 10 | before('export app', () => api.export({ cwd: __dirname })); 11 | 12 | // tests 13 | it('injects tags', () => { 14 | const index = fs.readFileSync(`${__dirname}/__sapper__/export/index.html`, 'utf8'); 15 | assert.ok(/rel=preload/.test(index)); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

-------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | -------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/src/server.js: -------------------------------------------------------------------------------- 1 | import sirv from 'sirv'; 2 | import polka from 'polka'; 3 | import * as sapper from '@sapper/server'; 4 | 5 | import { start, dev } from '../../common.js'; 6 | 7 | const app = polka() 8 | .use( 9 | sirv('static', { dev }), 10 | sapper.middleware() 11 | ); 12 | 13 | start(app); 14 | -------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | 10 | 11 |
%sapper.html%
12 | %sapper.scripts% 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/static/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Comic Sans MS'; 3 | } -------------------------------------------------------------------------------- /test/apps/export-without-serviceworker/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { walk } from '../../utils'; 3 | import * as api from '../../../api'; 4 | 5 | describe('export w/o serviceworker', function() { 6 | this.timeout(10000); 7 | 8 | // hooks 9 | before('build app', () => api.build({ cwd: __dirname })); 10 | before('export app', () => api.export({ cwd: __dirname })); 11 | 12 | // tests 13 | it('do not create service-worker-index.html', () => { 14 | const files = walk(`${__dirname}/__sapper__/export`); 15 | 16 | const client_assets = files.filter(file => file.startsWith('client/')); 17 | const non_client_assets = files.filter(file => !file.startsWith('client/')).sort(); 18 | 19 | assert.ok(client_assets.length > 0); 20 | 21 | assert.deepStrictEqual(non_client_assets.sort(), [ 22 | 'global.css', 23 | 'index.html' 24 | ].sort()); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/apps/export/content/example-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/apps/export/content/example-192.png -------------------------------------------------------------------------------- /test/apps/export/content/example-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/apps/export/content/example-512.png -------------------------------------------------------------------------------- /test/apps/export/content/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/apps/export/content/test.pdf -------------------------------------------------------------------------------- /test/apps/export/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/export/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/blog/[slug].html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{post.title}

14 | 15 | {#if post.src} 16 | 17 | 18 | 19 | 20 | {/if} 21 | 22 | {#if post.pdf} 23 | {post.pdf} 24 | {/if} 25 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/blog/[slug].json.js: -------------------------------------------------------------------------------- 1 | import posts from './_posts.js'; 2 | 3 | export function get(req, res) { 4 | const post = posts.find(post => post.slug === req.params.slug); 5 | 6 | if (post) { 7 | res.writeHead(200, { 8 | 'Content-Type': 'application/json' 9 | }); 10 | 11 | res.end(JSON.stringify(post)); 12 | } else { 13 | res.writeHead(404, { 14 | 'Content-Type': 'application/json' 15 | }); 16 | 17 | res.end(JSON.stringify({ message: 'not found' })); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/blog/_posts.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { slug: 'foo', title: 'once upon a foo', src: 'img/example-512.png', srcset: 'img/example-512.png 512w, img/example-192.png 192w', pdf: 'pdfs/test.pdf' }, 3 | { slug: 'bar', title: 'a bar is born' }, 4 | { slug: 'baz', title: 'bazzily ever after' } 5 | ]; 6 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/blog/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

blog

14 | 15 | {#each posts as post} 16 |

{post.title}

17 | {/each} -------------------------------------------------------------------------------- /test/apps/export/src/routes/blog/index.json.js: -------------------------------------------------------------------------------- 1 | import posts from './_posts.js'; 2 | 3 | export function get(req, res) { 4 | res.writeHead(200, { 5 | 'Content-Type': 'application/json' 6 | }); 7 | 8 | res.end(JSON.stringify(posts)); 9 | } 10 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/boom/[a]/[b].html.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 |

{a}/{b}.html

-------------------------------------------------------------------------------- /test/apps/export/src/routes/boom/[a]/[b].svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 |

{a}/{b}

-------------------------------------------------------------------------------- /test/apps/export/src/routes/boom/[a]/index.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | {#each list as b} 14 | {a}/{b} 15 | {a}/{b}.html 16 | {/each} -------------------------------------------------------------------------------- /test/apps/export/src/routes/boom/index.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | {#each list as a} 6 | {a} 7 | {/each} -------------------------------------------------------------------------------- /test/apps/export/src/routes/img/[slug].png.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const cwd = process.cwd(); 4 | 5 | export function get(req, res) { 6 | 7 | const { slug } = req.params; 8 | const image = path.join(cwd, `/content/${slug}.png`); 9 | 10 | const s = fs.createReadStream(image); 11 | s.on('open', () => { 12 | res.writeHead(200, { 'Content-Type': 'image/png' }); 13 | s.pipe(res); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Great success!

6 | 7 | blog 8 | 9 | empty anchor 10 | 11 | empty anchor #2 12 | 13 | empty anchor #3 14 | 15 | empty anchor #4 16 | empty anchor #5 17 | 18 | empty anchor #6 19 | boom 20 | html file 21 | pdf file -------------------------------------------------------------------------------- /test/apps/export/src/routes/manifest.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.writeHead(200, { 'Content-Type': 'application/json' }); 3 | res.end('{}'); 4 | } 5 | -------------------------------------------------------------------------------- /test/apps/export/src/routes/pdfs/[slug].pdf.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const cwd = process.cwd(); 4 | 5 | export function get(req, res, next) { 6 | 7 | const { slug } = req.params; 8 | const image = path.join(cwd, `/content/${slug}.pdf`); 9 | 10 | const s = fs.createReadStream(image); 11 | s.on('open', () => { 12 | res.writeHead(200, { 'Content-Type': 'application/pdf' }); 13 | s.pipe(res); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /test/apps/export/src/server.js: -------------------------------------------------------------------------------- 1 | import sirv from 'sirv'; 2 | import polka from 'polka'; 3 | import * as sapper from '@sapper/server'; 4 | 5 | import { start, dev } from '../../common.js'; 6 | 7 | const app = polka() 8 | .use( 9 | sirv('static', { dev }), 10 | sapper.middleware() 11 | ); 12 | 13 | start(app); 14 | -------------------------------------------------------------------------------- /test/apps/export/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/export/static/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Comic Sans MS'; 3 | } -------------------------------------------------------------------------------- /test/apps/export/static/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 |

Test Heading

10 |

Test Paragraph.

11 | 12 | 13 | -------------------------------------------------------------------------------- /test/apps/export/static/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/apps/export/static/test.pdf -------------------------------------------------------------------------------- /test/apps/ignore/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/ignore/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/ignore/src/routes/[slug].svelte: -------------------------------------------------------------------------------- 1 |

Svelte template rendered

-------------------------------------------------------------------------------- /test/apps/ignore/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/ignore/src/routes/a.svelte: -------------------------------------------------------------------------------- 1 |

a

-------------------------------------------------------------------------------- /test/apps/ignore/src/routes/b/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{letter}

-------------------------------------------------------------------------------- /test/apps/ignore/src/routes/b/index.json.js: -------------------------------------------------------------------------------- 1 | export function get(req, res) { 2 | res.end(JSON.stringify('b')); 3 | } 4 | -------------------------------------------------------------------------------- /test/apps/ignore/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | a -------------------------------------------------------------------------------- /test/apps/ignore/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka().use(sapper.middleware({ 7 | ignore: [ 8 | /foobar/i, 9 | '/buzz', 10 | 'fizz', 11 | x => x === '/hello' 12 | ] 13 | })); 14 | 15 | ['foobar', 'buzz', 'fizzer', 'hello'].forEach(uri => { 16 | app.get('/'+uri, (req, res) => res.end(uri)); 17 | }); 18 | 19 | start(app); 20 | -------------------------------------------------------------------------------- /test/apps/ignore/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/ignore/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { build } from '../../../api'; 3 | import { AppRunner } from '../AppRunner'; 4 | 5 | describe('ignore', function() { 6 | this.timeout(20000); 7 | 8 | let r: AppRunner; 9 | 10 | // hooks 11 | before('build app', () => build({ cwd: __dirname })); 12 | before('start runner', async () => { 13 | r = await new AppRunner().start(__dirname); 14 | }); 15 | 16 | after(() => r && r.end()); 17 | 18 | // tests 19 | it('respects `options.ignore` values (RegExp)', async () => { 20 | await r.load('/foobar'); 21 | 22 | assert.strictEqual( 23 | await r.text('body'), 24 | 'foobar' 25 | ); 26 | }); 27 | 28 | it('respects `options.ignore` values (String #1)', async () => { 29 | await r.load('/buzz'); 30 | 31 | assert.strictEqual( 32 | await r.text('body'), 33 | 'buzz' 34 | ); 35 | }); 36 | 37 | it('respects `options.ignore` values (String #2)', async () => { 38 | await r.load('/fizzer'); 39 | 40 | assert.strictEqual( 41 | await r.text('body'), 42 | 'fizzer' 43 | ); 44 | }); 45 | 46 | it('respects `options.ignore` values (Function)', async () => { 47 | await r.load('/hello'); 48 | 49 | assert.strictEqual( 50 | await r.text('body'), 51 | 'hello' 52 | ); 53 | }); 54 | 55 | it('survives the tests with no server errors', () => { 56 | assert.deepStrictEqual(r.errors, []); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /test/apps/layout/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/layout/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/layout/src/routes/[x]/[y]/[z].svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | z: {$page.params.z} {count} 19 | goto foo/bar/qux 20 | goto foo/abc/def -------------------------------------------------------------------------------- /test/apps/layout/src/routes/[x]/[y]/_layout.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | 19 | y: {$page.params.y} {count} 20 | 21 | 22 | child segment: {segment} -------------------------------------------------------------------------------- /test/apps/layout/src/routes/[x]/_counts.js: -------------------------------------------------------------------------------- 1 | export default { 2 | x: process.browser ? 1 : 0, 3 | y: process.browser ? 1 : 0, 4 | z: process.browser ? 1 : 0 5 | }; 6 | -------------------------------------------------------------------------------- /test/apps/layout/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/layout/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

-------------------------------------------------------------------------------- /test/apps/layout/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/layout/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/preloading/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/preloading/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/_layout.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | {#if $preloading} 21 | 22 | {/if} 23 | 24 | -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/echo/index.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |
{JSON.stringify(query)}
14 | 15 | foo=1 16 | foo=2 17 | foo=3 -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/foo.svelte: -------------------------------------------------------------------------------- 1 |

foo

-------------------------------------------------------------------------------- /test/apps/preloading/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 | slow preload 4 | foo 5 | prefetch qwe 6 | prefetch xyz 7 | -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/prefetch/[slug]/index.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{$page.params.slug}

7 | -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/prefetch/index.svelte: -------------------------------------------------------------------------------- 1 |

prefetch

2 | -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/preload-nothing/index.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

Page loaded

6 | -------------------------------------------------------------------------------- /test/apps/preloading/src/routes/preload-root/index.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

root preload function ran: {rootPreloadFunctionRan}

-------------------------------------------------------------------------------- /test/apps/preloading/src/routes/preload-values/custom-class.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 18 | 19 |

{foo.bar()}

-------------------------------------------------------------------------------- /test/apps/preloading/src/routes/preload-values/host.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{host.replace(/:\d+$/, '')}

-------------------------------------------------------------------------------- /test/apps/preloading/src/routes/preload-values/set.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 |

{set.has('x')}

-------------------------------------------------------------------------------- /test/apps/preloading/src/routes/slow-preload.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |

This page should never render

-------------------------------------------------------------------------------- /test/apps/preloading/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/preloading/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/redirects/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/redirects/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/redirects/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/redirects/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

root

2 | 3 | redirect from 4 | redirect to root 5 | redirect to external -------------------------------------------------------------------------------- /test/apps/redirects/src/routes/redirect-from.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

unredirected

-------------------------------------------------------------------------------- /test/apps/redirects/src/routes/redirect-to-external.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

unredirected

-------------------------------------------------------------------------------- /test/apps/redirects/src/routes/redirect-to-root.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

unredirected

-------------------------------------------------------------------------------- /test/apps/redirects/src/routes/redirect-to.svelte: -------------------------------------------------------------------------------- 1 |

redirected

-------------------------------------------------------------------------------- /test/apps/redirects/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/redirects/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/scroll/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/scroll/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/scroll/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/scroll/src/routes/a-third-tall-page.svelte: -------------------------------------------------------------------------------- 1 |

A third tall page

2 | 3 | link 4 |
5 | link 6 | -------------------------------------------------------------------------------- /test/apps/scroll/src/routes/another-tall-page.svelte: -------------------------------------------------------------------------------- 1 |

Another tall page

2 | 3 |
4 |

element

-------------------------------------------------------------------------------- /test/apps/scroll/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

-------------------------------------------------------------------------------- /test/apps/scroll/src/routes/redirect.svelte: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /test/apps/scroll/src/routes/search-form.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |

A search form

14 | 15 |
16 | 17 | 21 | -------------------------------------------------------------------------------- /test/apps/scroll/src/routes/search-page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

A search form

9 | 10 |
11 | 12 | 15 | 16 |
17 | 18 |
19 | 20 |
-------------------------------------------------------------------------------- /test/apps/scroll/src/routes/tall-page.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |

A tall page

12 | 13 | scroll to foo 14 |
15 | 16 |
17 | link 18 | link 19 | {#if barLink} 20 | link 21 | {/if} 22 | redirected link 23 |
-------------------------------------------------------------------------------- /test/apps/scroll/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/scroll/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/session/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/session/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/session/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/session/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

-------------------------------------------------------------------------------- /test/apps/session/src/routes/preloaded.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 |

{title}

15 | 16 | -------------------------------------------------------------------------------- /test/apps/session/src/routes/session.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{$session.title}

7 | 8 | -------------------------------------------------------------------------------- /test/apps/session/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use((req, res, next) => { 8 | req.hello = 'hello'; 9 | res.locals = { name: 'world' }; 10 | next(); 11 | }) 12 | .use( 13 | sapper.middleware({ 14 | session: async (req, res) => { 15 | if (req.url === '/error') { 16 | throw new Error('error'); 17 | } 18 | return { title: `${req.hello} ${res.locals.name}` }; 19 | } 20 | }) 21 | ); 22 | 23 | start(app); 24 | -------------------------------------------------------------------------------- /test/apps/session/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/with-basepath/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import replace from '@rollup/plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = require('../../../config/rollup.js'); 9 | 10 | export default { 11 | client: { 12 | input: config.client.input(), 13 | output: config.client.output(), 14 | plugins: [ 15 | replace({ 16 | 'process.browser': true, 17 | 'process.env.NODE_ENV': JSON.stringify(mode) 18 | }), 19 | svelte({ 20 | dev, 21 | hydratable: true, 22 | emitCss: true 23 | }), 24 | resolve() 25 | ] 26 | }, 27 | 28 | server: { 29 | input: config.server.input(), 30 | output: config.server.output(), 31 | plugins: [ 32 | replace({ 33 | 'process.browser': false, 34 | 'process.env.NODE_ENV': JSON.stringify(mode) 35 | }), 36 | svelte({ 37 | generate: 'ssr', 38 | dev 39 | }), 40 | resolve({ 41 | preferBuiltins: true 42 | }) 43 | ], 44 | external: ['sirv', 'polka'] 45 | }, 46 | 47 | serviceworker: { 48 | input: config.serviceworker.input(), 49 | output: config.serviceworker.output(), 50 | plugins: [ 51 | resolve(), 52 | replace({ 53 | 'process.browser': true, 54 | 'process.env.NODE_ENV': JSON.stringify(mode) 55 | }) 56 | ] 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /test/apps/with-basepath/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/with-basepath/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/with-basepath/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | redirect from 3 | -------------------------------------------------------------------------------- /test/apps/with-basepath/src/routes/redirect-from.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

unredirected

-------------------------------------------------------------------------------- /test/apps/with-basepath/src/routes/redirect-to.svelte: -------------------------------------------------------------------------------- 1 |

redirected

-------------------------------------------------------------------------------- /test/apps/with-basepath/src/server.js: -------------------------------------------------------------------------------- 1 | import sirv from 'sirv'; 2 | import polka from 'polka'; 3 | import * as sapper from '@sapper/server'; 4 | 5 | import { start, dev } from '../../common.js'; 6 | 7 | const app = polka() 8 | .use( 9 | 'custom-basepath', 10 | sirv('static', { dev }), 11 | sapper.middleware() 12 | ); 13 | 14 | start(app); 15 | 16 | -------------------------------------------------------------------------------- /test/apps/with-basepath/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/with-basepath/static/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Comic Sans MS'; 3 | } -------------------------------------------------------------------------------- /test/apps/with-sourcemaps-webpack/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps-webpack/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps-webpack/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 |

Woot!

-------------------------------------------------------------------------------- /test/apps/with-sourcemaps-webpack/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps-webpack/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps-webpack/test.ts: -------------------------------------------------------------------------------- 1 | import { build } from '../../../api'; 2 | import * as assert from 'assert'; 3 | import * as fs from 'fs'; 4 | import * as path from 'path'; 5 | 6 | describe('with-sourcemaps-webpack', function() { 7 | this.timeout(10000); 8 | 9 | // hooks 10 | before('build app', () => build({ cwd: __dirname, bundler: 'webpack' })); 11 | 12 | // tests 13 | it('does not put sourcemap files in service worker shell', async () => { 14 | const service_worker_source = fs.readFileSync(`${__dirname}/src/node_modules/@sapper/service-worker.js`, 'utf-8'); 15 | const shell_source = /shell = (\[[\s\S]+?\])/.exec(service_worker_source)[1]; 16 | const shell = JSON.parse(shell_source); 17 | 18 | assert.strictEqual(shell.filter(_ => _.endsWith('.map')).length, 0, 19 | 'sourcemap files are not cached in SW'); 20 | 21 | const clientShellDir = path.resolve(`${__dirname}/__sapper__/build`, path.dirname(shell[0]).replace(/^\//, '')); 22 | const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map')); 23 | assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | window.start = () => sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); 6 | 7 | window.prefetchRoutes = () => sapper.prefetchRoutes(); 8 | window.prefetch = href => sapper.prefetch(href); 9 | window.goto = href => sapper.goto(href); 10 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |

{status}

7 | 8 |

{error.message}

9 | 10 |
{error.stack}
11 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps/src/routes/index.svelte: -------------------------------------------------------------------------------- 1 |

Great success!

2 | 3 |

Woot!

-------------------------------------------------------------------------------- /test/apps/with-sourcemaps/src/server.js: -------------------------------------------------------------------------------- 1 | import polka from 'polka'; 2 | import * as sapper from '@sapper/server'; 3 | 4 | import { start } from '../../common.js'; 5 | 6 | const app = polka() 7 | .use(sapper.middleware()); 8 | 9 | start(app); 10 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %sapper.base% 7 | %sapper.styles% 8 | %sapper.head% 9 | %sapper.scripts% 10 | 11 | 12 |
%sapper.html%
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/apps/with-sourcemaps/test.ts: -------------------------------------------------------------------------------- 1 | import { build } from '../../../api'; 2 | import * as assert from 'assert'; 3 | import * as fs from 'fs'; 4 | import * as path from 'path'; 5 | 6 | describe('with-sourcemaps', function() { 7 | this.timeout(10000); 8 | 9 | // hooks 10 | before('build app', () => build({ cwd: __dirname })); 11 | 12 | // tests 13 | it('does not put sourcemap files in service worker shell', async () => { 14 | const service_worker_source = fs.readFileSync(`${__dirname}/src/node_modules/@sapper/service-worker.js`, 'utf-8'); 15 | const shell_source = /shell = (\[[\s\S]+?\])/.exec(service_worker_source)[1]; 16 | const shell = JSON.parse(shell_source); 17 | 18 | assert.equal(shell.filter(_ => _.endsWith('.map')).length, 0, 19 | 'sourcemap files are not cached in SW'); 20 | 21 | const clientShellDir = path.resolve(`${__dirname}/__sapper__/build`, path.dirname(shell[0]).replace(/^\//, '')); 22 | const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map')); 23 | assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/unit/baseuri_helper/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { get_base_uri } from '../../../runtime/src/app/baseuri_helper'; 3 | 4 | describe('get_base_uri', () => { 5 | it('document.baseURI exists', () => { 6 | const baseUri = 'https://baseuri.example.com'; 7 | const document = { 8 | baseURI: baseUri 9 | }; 10 | assert.strictEqual(get_base_uri(document), baseUri); 11 | }); 12 | 13 | it('document.baseURI does not exist, with tag', () => { 14 | const baseUri = 'https://bytag.example.com'; 15 | const document = { 16 | getElementsByTagName: () => [ 17 | { href: baseUri } 18 | ] 19 | }; 20 | assert.strictEqual(get_base_uri(document), baseUri); 21 | }); 22 | 23 | it('document.baseURI does not exist, with multiple tag', () => { 24 | const baseUri = 'https://fromtag.example.com'; 25 | const document = { 26 | getElementsByTagName: () => [ 27 | { href: baseUri }, 28 | { href: 'https://ignoreme.example.com' } 29 | ] 30 | }; 31 | assert.strictEqual(get_base_uri(document), baseUri); 32 | }); 33 | 34 | it('document.baseURI does not exist, without tag', () => { 35 | const baseUri = 'https://byurl.example.com'; 36 | const document = { 37 | getElementsByTagName: () => [], 38 | URL: baseUri 39 | }; 40 | assert.strictEqual(get_base_uri(document), baseUri); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-cdata/.actual.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + 9 | 3 10 | = 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-cdata/input.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | x<y 8 | + 9 | 3 10 | = 11 | x<y3 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-cdata/output.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + 9 | 3 10 | = 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-comments/.actual.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | keep me 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-comments/input.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | keep me 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-comments/output.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | keep me 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-script-contents/.actual.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-script-contents/input.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/unit/clean_html/samples/removes-script-contents/output.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/unit/clean_html/test.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | import * as assert from 'assert'; 4 | import clean_html from '../../../src/api/utils/clean_html'; 5 | 6 | describe('clean_html', () => { 7 | const samples = path.join(__dirname, 'samples'); 8 | 9 | fs.readdirSync(samples).forEach(dir => { 10 | if (dir[0] === '.') return; 11 | 12 | it(dir, () => { 13 | const input = fs.readFileSync(`${samples}/${dir}/input.html`, 'utf-8'); 14 | const expected = fs.readFileSync(`${samples}/${dir}/output.html`, 'utf-8'); 15 | 16 | const actual = clean_html(input); 17 | 18 | fs.writeFileSync(`${samples}/${dir}/.actual.html`, actual); 19 | 20 | assert.equal( 21 | actual.replace(/\s+$/gm, ''), 22 | expected.replace(/\s+$/gm, '') 23 | ); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/about.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/about.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/blog/[slug].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/blog/[slug].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/blog/[slug].json.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/blog/[slug].json.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/blog/_default.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/blog/_default.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/blog/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/blog/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/blog/index.json.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/blog/index.json.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/basic/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/basic/index.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/clash-pages/[bar]/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/clash-pages/[bar]/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/clash-pages/[foo].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/clash-pages/[foo].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/clash-pages/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/clash-pages/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/clash-routes/[bar]/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/clash-routes/[bar]/index.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/clash-routes/[foo].js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/clash-routes/[foo].js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/clash-routes/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/clash-routes/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/custom-extension/about.jazz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/custom-extension/about.jazz -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/custom-extension/blog/[slug].beebop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/custom-extension/blog/[slug].beebop -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/custom-extension/blog/[slug].json.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/custom-extension/blog/[slug].json.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/custom-extension/blog/_default.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/custom-extension/blog/_default.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/custom-extension/blog/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/custom-extension/blog/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/custom-extension/blog/index.json.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/custom-extension/blog/index.json.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/custom-extension/index.funk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/custom-extension/index.funk -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/encoding/#.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/encoding/#.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-dot/.unknown/foo.txt.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-dot/.unknown/foo.txt.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-dot/.well-known/dnt-policy.txt.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-dot/.well-known/dnt-policy.txt.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-underscore/_foo.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-underscore/_foo.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-underscore/a/_b/c/d.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-underscore/a/_b/c/d.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-underscore/e/f/g/h.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-underscore/e/f/g/h.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-underscore/i/_j.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-underscore/i/_j.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-underscore/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-underscore/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/hidden-underscore/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/hidden-underscore/index.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/invalid-params/[foo][bar].js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/invalid-params/[foo][bar].js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/invalid-qualifier/[foo([a-z]([0-9]))].js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/invalid-qualifier/[foo([a-z]([0-9]))].js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/lockfiles/foo.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/lockfiles/foo.js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/lockfiles/foo.js_tmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/lockfiles/foo.js_tmp -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/multiple-slugs/[file].[ext].js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/multiple-slugs/[file].[ext].js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/nested-square-brackets/[file([a-z]+)].[ext([a-z]+)].js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/nested-square-brackets/[file([a-z]+)].[ext([a-z]+)].js -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/qualifiers/[slug([0-9-a-z]{3,})].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/qualifiers/[slug([0-9-a-z]{3,})].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/qualifiers/[slug([a-z]{2})].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/qualifiers/[slug([a-z]{2})].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/qualifiers/[slug].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/qualifiers/[slug].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/[...spread]/abc.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/[...spread]/abc.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/[...spread]/deep/[...deep_spread]/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/[...spread]/deep/[...deep_spread]/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/[...spread]/deep/[...deep_spread]/xyz.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/[...spread]/deep/[...deep_spread]/xyz.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/[...spread]/deep/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/[...spread]/deep/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/[...spread]/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/[...spread]/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/[wildcard].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/[wildcard].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/_layout.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/_layout.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/about.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/about.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/index.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/post/[id([0-9-a-z]{3,})].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/post/[id([0-9-a-z]{3,})].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/post/[id].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/post/[id].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/post/_default.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/post/_default.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/post/bar.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/post/bar.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/post/f[xx].html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/post/f[xx].html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/post/foo.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/post/foo.html -------------------------------------------------------------------------------- /test/unit/create_manifest_data/samples/sorting/post/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper/45ccb4dbbf31ba7ad8a7a634b1f01a0bb8e7260f/test/unit/create_manifest_data/samples/sorting/post/index.html -------------------------------------------------------------------------------- /test/unit/srcset/test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { get_srcset_urls } from '../../../src/api/export'; 3 | 4 | describe('get_srcset_urls', () => { 5 | it('should parse single entry without descriptor', () => { 6 | const result = get_srcset_urls(''); 7 | assert.deepEqual(result, ['assets/image/1.jpg']); 8 | }); 9 | 10 | it('should parse single entry with width descriptor', () => { 11 | const result = get_srcset_urls(''); 12 | assert.deepEqual(result, ['assets/image/1.jpg']); 13 | }); 14 | 15 | it('should parse single entry with density descriptor', () => { 16 | const result = get_srcset_urls(''); 17 | assert.deepEqual(result, ['assets/image/1.jpg']); 18 | }); 19 | 20 | it('should parse multiple entries with different descriptors', () => { 21 | const result = get_srcset_urls(''); 22 | assert.deepEqual(result, [ 23 | 'assets/image/1.jpg', 24 | 'assets/image/2.jpg', 25 | 'assets/image/3.jpg', 26 | 'assets/image/4.jpg', 27 | 'assets/image/5.jpg' 28 | ]); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/unit/utils.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { normalize_path } from '../../src/utils'; 3 | 4 | describe('normalize_path', () => { 5 | it('lowercases the first letter', () => { 6 | assert.equal(normalize_path('C:\\Users\\simon\\Source\\my-app\\src\\routes\\index.svelte'), 7 | 'c:\\Users\\simon\\Source\\my-app\\src\\routes\\index.svelte'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/utils.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | 4 | export function wait(ms: number) { 5 | return new Promise(fulfil => setTimeout(fulfil, ms)); 6 | } 7 | 8 | export function walk(cwd: string, dir = cwd, files: string[] = []) { 9 | fs.readdirSync(dir).forEach(file => { 10 | const resolved = path.resolve(dir, file); 11 | if (fs.statSync(resolved).isDirectory()) { 12 | walk(cwd, resolved, files); 13 | } else { 14 | files.push(posixify(path.relative(cwd, resolved))); 15 | } 16 | }); 17 | 18 | return files; 19 | } 20 | 21 | function posixify(str: string) { 22 | return str.replace(/\\/g, '/'); 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitThis": true, 4 | "noEmitOnError": true, 5 | "allowJs": true, 6 | "allowSyntheticDefaultImports": true, 7 | "moduleResolution": "Node", 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "lib": ["es5", "es6", "dom", "dom.iterable"], 11 | "importHelpers": true, 12 | "target": "ES6", 13 | "baseUrl": ".", 14 | "paths": { 15 | "@sapper/*": ["runtime/src/*"] 16 | } 17 | }, 18 | "include": [ 19 | "src", 20 | "runtime" 21 | ], 22 | "exclude": [ 23 | "node_modules" 24 | ], 25 | "types": [ 26 | "@sapper" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /webpack.js: -------------------------------------------------------------------------------- 1 | console.error(`[DEPRECATION] As of Sapper 0.18, webpack config should be loaded from sapper/config/webpack.js`); 2 | module.exports = require('./dist/webpack.js'); -------------------------------------------------------------------------------- /webpack/[slug].svelte: -------------------------------------------------------------------------------- 1 |

{params.slug.toUpperCase()}

-------------------------------------------------------------------------------- /webpack/config.js: -------------------------------------------------------------------------------- 1 | console.error(`[DEPRECATION] As of Sapper 0.18, webpack config should be loaded from sapper/config/webpack.js`); 2 | module.exports = require('../dist/webpack.js'); --------------------------------------------------------------------------------