├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── babel.config.js ├── build └── index.html ├── example ├── App.svelte ├── components │ ├── button.svelte │ ├── header.svelte │ └── menu.svelte ├── docs │ ├── Installation.md │ ├── Introduction.md │ ├── component │ │ └── Link.md │ └── guide │ │ ├── API.md │ │ ├── BasicUsage.md │ │ └── PassingProps.md ├── main.js ├── pages │ ├── Installation.svelte │ ├── Introduction.svelte │ ├── NotFound.svelte │ ├── component │ │ └── Link.svelte │ └── guide │ │ ├── API.svelte │ │ ├── BasicUsage.svelte │ │ └── PassingProps.svelte └── routes.js ├── package-lock.json ├── package.json ├── rollup.config.js └── src ├── components └── Link.svelte ├── index.js └── router.js /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | public 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "ecmaVersion": 6 6 | }, 7 | "env": { 8 | "browser": true, 9 | "node": true 10 | }, 11 | "plugins": [ 12 | "svelte3" 13 | ], 14 | "overrides": [{ 15 | "files": ["**/*.svelte"], 16 | "processor": "svelte3/svelte3" 17 | }], 18 | "extends": "standard", 19 | "parser": "babel-eslint", 20 | "rules": { 21 | "no-console": 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | public 3 | lib 4 | .vscode 5 | 6 | *.log 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | src 3 | example 4 | build 5 | 6 | .DS_Store 7 | babel.config.js 8 | .eslintignore 9 | *.log 10 | rollup.config.js 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 - present Jikkai Xiao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Svelte Router 2 | 3 | ![version](https://img.shields.io/npm/v/svelte-router.svg) 4 | ![license](https://img.shields.io/github/license/mashape/apistatus.svg) 5 | 6 | > Router component for Svelte 7 | 8 | This branch is for Svelte v3.0.0+. For usage with Svelte v1.8.0+, see the [v2 branch](https://github.com/jikkai/svelte-router/tree/v2). For usage with Svelte v1.8.0-, see the [0.1.x branch](https://github.com/jikkai/svelte-router/tree/0.1.x). 9 | 10 | ## Installation 11 | 12 | Using npm: 13 | 14 | ```bash 15 | npm install --save svelte-router 16 | ``` 17 | 18 | Using yarn: 19 | 20 | ```bash 21 | yarn add svelte-router 22 | ``` 23 | 24 | ## Examples 25 | 26 | ```html 27 |
28 | Home 29 | Welcome 30 |
31 |
32 | 33 | 58 | 59 | 64 | ``` 65 | 66 | ## API 67 | 68 | ### SvelteRouter 69 | 70 | * `push(path: string)` 71 | * `replace(path: string)` 72 | * `go(n: number)` 73 | * `goBack()` 74 | * `goForward()` 75 | * `listen(fn: function)` 76 | 77 | ### Link 78 | 79 | * `to`: string 80 | * `replace`: boolean 81 | * `className`: string 82 | * `activeClassName`: string 83 | 84 | ## Contributors 85 | 86 | * [@rumpytim](https://github.com/rumpytim) 87 | * [@RobBrazier](https://github.com/RobBrazier) 88 | * [@stalkerg](https://github.com/stalkerg) 89 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['@babel/preset-env', { 4 | modules: false, 5 | targets: { 6 | browsers: [ 7 | '> 1%', 8 | 'last 2 versions', 9 | 'not ie <= 8' 10 | ] 11 | } 12 | }] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Svelte Router 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /example/App.svelte: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |
6 |
7 |
8 |
9 | 10 | 38 | 39 | 71 | -------------------------------------------------------------------------------- /example/components/button.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /example/components/header.svelte: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | Svelte Router 5 | {version} 6 |

7 | 8 | 9 | Github 10 |
11 | 12 | 22 | 23 | 49 | -------------------------------------------------------------------------------- /example/components/menu.svelte: -------------------------------------------------------------------------------- 1 | 37 | 38 | 41 | 42 | 83 | -------------------------------------------------------------------------------- /example/docs/Installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## npm 4 | 5 | Installing with npm is recommended and it works seamlessly with webpack. 6 | 7 | ```sh 8 | npm install svelte-router 9 | ``` 10 | 11 | ## yarn 12 | 13 | Long live Yarn. 14 | 15 | ```sh 16 | yarn add svelte-router 17 | ``` 18 | 19 | ## CDN 20 | 21 | ```html 22 | 23 | ``` 24 | -------------------------------------------------------------------------------- /example/docs/Introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Svelte Router is an unofficial router for [Svelte](https://svelte.technology). 4 | 5 | Just for fun :) 6 | -------------------------------------------------------------------------------- /example/docs/component/Link.md: -------------------------------------------------------------------------------- 1 | # Link 2 | 3 | `` is the component for enabling user navigation in a router-enabled app. 4 | 5 | ## Props 6 | 7 | | name | type | default | 8 | | --- | --- | --- | 9 | | to | `string` | - | 10 | | replace | `boolean` | `false` | 11 | | className | `string` | `''` | 12 | | activeClassName | `string` | `'router-link-active'` | 13 | 14 | ## Example 15 | 16 | ```html 17 | go Foo 18 | 19 | 22 | ``` 23 | -------------------------------------------------------------------------------- /example/docs/guide/API.md: -------------------------------------------------------------------------------- 1 | # API 2 | 3 | ## Router Construction Options 4 | 5 | ### target 6 | 7 | * type: `string` | `HTMLElement` 8 | 9 | ### mode 10 | 11 | * type: `string` 12 | * enum: `'hash' | 'history'` 13 | * default: `'hash'` 14 | 15 | ### routes 16 | 17 | * type: `array` 18 | 19 | ```javascript 20 | const router = new SvelteRouter({ 21 | target: '#app', 22 | mode: 'hash', 23 | routes: [{ 24 | path: '/', 25 | component: Home 26 | }, { 27 | path: '/welcome', 28 | component: Welcome 29 | }, { 30 | path: '(.*)', 31 | component: NotFound 32 | }] 33 | }) 34 | ``` 35 | 36 | ## Router Instance Methods 37 | 38 | ### destroy 39 | 40 | ```javascript 41 | router.destroy() 42 | ``` 43 | 44 | ## Router Methods 45 | 46 | ### push 47 | 48 | ```javascript 49 | SvelteRouter.push(path: string) 50 | ``` 51 | 52 | ### replace 53 | 54 | ```javascript 55 | SvelteRouter.replace(path: string) 56 | ``` 57 | 58 | ### go 59 | 60 | ```javascript 61 | SvelteRouter.go(n: number) 62 | ``` 63 | 64 | ### goBack 65 | 66 | ```javascript 67 | SvelteRouter.goBack() 68 | ``` 69 | 70 | ### goForward 71 | 72 | ```javascript 73 | SvelteRouter.goForward() 74 | ``` 75 | 76 | ### listen 77 | 78 | ```javascript 79 | SvelteRouter.listen(fn: function) 80 | ``` 81 | -------------------------------------------------------------------------------- /example/docs/guide/BasicUsage.md: -------------------------------------------------------------------------------- 1 | # Basic Usage 2 | 3 | It is the first step that is troublesome. 4 | 5 | ## Foo.svelte 6 | 7 | ```html 8 |

Foo

9 | ``` 10 | 11 | ## Bar.svelte 12 | 13 | ```html 14 |

Bar

15 | ``` 16 | 17 | ## App.svelte 18 | 19 | ```html 20 |
21 | Foo 22 | Bar 23 |
24 |
25 | 26 | 54 | 55 | 60 | ``` 61 | 62 | ## main.js 63 | 64 | ```javascript 65 | import App from './App.svelte' 66 | 67 | new App({ 68 | target: document.querySelector('#main') 69 | }) 70 | ``` 71 | -------------------------------------------------------------------------------- /example/docs/guide/PassingProps.md: -------------------------------------------------------------------------------- 1 | # Passing Props 2 | 3 | Passing props to route components by using `props`. 4 | 5 | ## Foo.svelte 6 | 7 | ```html 8 |

Hello {title}

9 | 10 | 13 | ``` 14 | 15 | ## App.svelte 16 | 17 | ```html 18 |
19 |
20 |
21 | 22 | 45 | ``` 46 | -------------------------------------------------------------------------------- /example/main.js: -------------------------------------------------------------------------------- 1 | import App from './App' 2 | import 'alius' 3 | import 'prismjs/themes/prism-okaidia.css' 4 | 5 | // eslint-disable-next-line 6 | new App({ 7 | target: document.querySelector('#example') 8 | }) 9 | -------------------------------------------------------------------------------- /example/pages/Installation.svelte: -------------------------------------------------------------------------------- 1 |
2 | {@html content} 3 |
4 | 5 | 8 | -------------------------------------------------------------------------------- /example/pages/Introduction.svelte: -------------------------------------------------------------------------------- 1 |
2 | {@html content} 3 | 4 | 5 |
6 | 7 | 16 | -------------------------------------------------------------------------------- /example/pages/NotFound.svelte: -------------------------------------------------------------------------------- 1 |

404 Not Found

2 | 3 | 4 | 12 | -------------------------------------------------------------------------------- /example/pages/component/Link.svelte: -------------------------------------------------------------------------------- 1 |
2 | {@html content} 3 |
4 | 5 | 8 | -------------------------------------------------------------------------------- /example/pages/guide/API.svelte: -------------------------------------------------------------------------------- 1 |
2 | {@html content} 3 |
4 | 5 | 8 | -------------------------------------------------------------------------------- /example/pages/guide/BasicUsage.svelte: -------------------------------------------------------------------------------- 1 |
2 | {@html content} 3 |
4 | 5 | 8 | -------------------------------------------------------------------------------- /example/pages/guide/PassingProps.svelte: -------------------------------------------------------------------------------- 1 |
2 | {@html content} 3 |
4 | 5 | 8 | -------------------------------------------------------------------------------- /example/routes.js: -------------------------------------------------------------------------------- 1 | import Introduction from './pages/Introduction' 2 | import Installation from './pages/Installation' 3 | import BasicUsage from './pages/guide/BasicUsage' 4 | import PassingProps from './pages/guide/PassingProps' 5 | import API from './pages/guide/API' 6 | import Link from './pages/component/Link' 7 | import NotFound from './pages/NotFound' 8 | 9 | export default [{ 10 | path: '/', 11 | component: Introduction 12 | }, { 13 | path: '/installation', 14 | component: Installation 15 | }, { 16 | path: '/guide/basic-usage', 17 | component: BasicUsage 18 | }, { 19 | path: '/guide/passing-props', 20 | component: PassingProps, 21 | props: { 22 | foo: 'bar' 23 | } 24 | }, { 25 | path: '/guide/api', 26 | component: API 27 | }, { 28 | path: '/component/link', 29 | component: Link 30 | }, { 31 | path: '(.*)', 32 | component: NotFound 33 | }] 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-router", 3 | "version": "3.0.0-alpha.2", 4 | "description": "A simple router for Svelte", 5 | "main": "lib/svelte-router.js", 6 | "author": "Jikkai Xiao ", 7 | "license": "MIT", 8 | "scripts": { 9 | "prebuild:js": "rimraf ./lib", 10 | "build:js": "cross-env NODE_ENV=production APP_ENV=js rollup -c", 11 | "prebuild:docs": "rimraf ./public", 12 | "dev": "cross-env NODE_ENV=development rollup -c -w", 13 | "build:docs": "cross-env NODE_ENV=production APP_ENV=docs rollup -c", 14 | "deploy": "npm run build:docs && gh-pages -d ./public", 15 | "prepublishOnly": "npm run build:js" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/jikkai/svelte-router.git" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/jikkai/svelte-router/issues" 23 | }, 24 | "homepage": "https://jikkai.github.io/svelte-router", 25 | "keywords": [ 26 | "svelte", 27 | "router", 28 | "plugins" 29 | ], 30 | "peerDependencies": { 31 | "svelte": "^3.0.0" 32 | }, 33 | "dependencies": { 34 | "history": "^4.9.0", 35 | "path-to-regexp": "^3.0.0" 36 | }, 37 | "devDependencies": { 38 | "@babel/core": "^7.5.5", 39 | "@babel/preset-env": "^7.5.5", 40 | "alius": "0.0.1", 41 | "babel-eslint": "^10.0.2", 42 | "cross-env": "^5.2.0", 43 | "eslint": "^6.1.0", 44 | "eslint-config-standard": "^13.0.1", 45 | "eslint-friendly-formatter": "^4.0.1", 46 | "eslint-plugin-import": "^2.18.2", 47 | "eslint-plugin-node": "^9.1.0", 48 | "eslint-plugin-promise": "^4.2.1", 49 | "eslint-plugin-standard": "^4.0.0", 50 | "eslint-plugin-svelte3": "^2.7.3", 51 | "gh-pages": "^2.1.1", 52 | "prismjs": "^1.17.1", 53 | "rimraf": "^2.7.0", 54 | "rollup": "^1.19.4", 55 | "rollup-plugin-babel": "^4.3.3", 56 | "rollup-plugin-commonjs": "^10.0.2", 57 | "rollup-plugin-copy": "^3.1.0", 58 | "rollup-plugin-eslint": "^7.0.0", 59 | "rollup-plugin-livereload": "^1.0.1", 60 | "rollup-plugin-md": "0.0.7", 61 | "rollup-plugin-node-resolve": "^5.2.0", 62 | "rollup-plugin-postcss": "^2.0.3", 63 | "rollup-plugin-replace": "^2.2.0", 64 | "rollup-plugin-serve": "^1.0.1", 65 | "rollup-plugin-svelte": "^5.1.0", 66 | "rollup-plugin-uglify": "^6.0.2", 67 | "svelte": "^3.8.0" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import serve from 'rollup-plugin-serve' 2 | import livereload from 'rollup-plugin-livereload' 3 | import { eslint } from 'rollup-plugin-eslint' 4 | import postcss from 'rollup-plugin-postcss' 5 | import md from 'rollup-plugin-md' 6 | import svelte from 'rollup-plugin-svelte' 7 | import babel from 'rollup-plugin-babel' 8 | import commonjs from 'rollup-plugin-commonjs' 9 | import resolve from 'rollup-plugin-node-resolve' 10 | import replace from 'rollup-plugin-replace' 11 | import { uglify } from 'rollup-plugin-uglify' 12 | import copy from 'rollup-plugin-copy' 13 | 14 | import pkg from './package.json' 15 | 16 | const config = { 17 | output: { 18 | file: pkg.main, 19 | format: 'umd', 20 | name: 'SvelteRouter', 21 | exports: 'named' 22 | }, 23 | context: 'window', 24 | plugins: [ 25 | eslint({ 26 | include: './src/**/*.js' 27 | }), 28 | postcss(), 29 | replace({ 30 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 31 | 'process.env.APP_VERSION': JSON.stringify(pkg.version) 32 | }), 33 | resolve({ 34 | extensions: ['.js', '.svelte', '.md'] 35 | }), 36 | svelte(), 37 | commonjs(), 38 | babel({ 39 | externalHelpers: true, 40 | extensions: ['.js', '.mjs', '.svelte'] 41 | }) 42 | ] 43 | } 44 | 45 | if (process.env.NODE_ENV === 'production') { 46 | config.plugins.push( 47 | uglify() 48 | ) 49 | if (process.env.APP_ENV === 'js') { 50 | config.input = './src/index.js' 51 | } else if (process.env.APP_ENV === 'docs') { 52 | config.input = './example/main.js' 53 | config.output = { 54 | file: 'public/svelte-router.js', 55 | format: 'iife' 56 | } 57 | config.plugins.unshift( 58 | md(), 59 | copy({ 60 | targets: [{ 61 | src: './build/index.html', 62 | dest: './public' 63 | }] 64 | }) 65 | ) 66 | } 67 | } else if (process.env.NODE_ENV === 'development') { 68 | config.input = './example/main.js' 69 | config.plugins.unshift( 70 | serve({ 71 | historyApiFallback: true, 72 | contentBase: ['lib', 'build'] 73 | }), 74 | livereload('release'), 75 | md() 76 | ) 77 | } 78 | 79 | export default config 80 | -------------------------------------------------------------------------------- /src/components/Link.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 41 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Link from './components/Link' 2 | import Router from './router' 3 | 4 | export { Link } 5 | 6 | export default Router 7 | -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import { createBrowserHistory, createHashHistory } from 'history' 2 | import pathToRegexp from 'path-to-regexp' 3 | 4 | class SvelteRouter { 5 | constructor ({ target, mode = 'hash', routes = [] }) { 6 | let history 7 | switch (mode) { 8 | case 'hash': 9 | history = createHashHistory() 10 | break 11 | case 'history': 12 | history = createBrowserHistory() 13 | break 14 | default: 15 | history = createHashHistory() 16 | break 17 | } 18 | 19 | SvelteRouter.__VERSION__ = process.env.APP_VERSION 20 | SvelteRouter.mode = mode 21 | SvelteRouter.history = history 22 | SvelteRouter.push = path => history.push(path) 23 | SvelteRouter.replace = path => history.replace(path) 24 | SvelteRouter.go = n => history.go(n) 25 | SvelteRouter.goBack = () => history.goBack() 26 | SvelteRouter.goForward = () => history.goForward() 27 | SvelteRouter.listen = fn => history.listen(fn) 28 | 29 | this.$content = null 30 | this.target = typeof target === 'string' ? document.querySelector(target) : target 31 | this.routes = routes 32 | this.$listener = history.listen(this.handleRouteChange.bind(this)) 33 | 34 | this.handleRouteChange(history.location) 35 | } 36 | 37 | destroy () { 38 | if (this.$listener) { 39 | this.$listener() 40 | this.$listener = null 41 | } 42 | } 43 | 44 | handleRouteChange ({ pathname }) { 45 | let matchedRoute 46 | 47 | for (const route of this.routes) { 48 | const regexp = pathToRegexp(route.path) 49 | if (regexp.test(pathname)) { 50 | matchedRoute = route 51 | break 52 | } 53 | } 54 | 55 | if (matchedRoute && matchedRoute.component) { 56 | if (this.$content) this.$content.$destroy() 57 | const { component: Component, props } = matchedRoute 58 | 59 | this.$content = new Component({ 60 | target: this.target, 61 | props 62 | }) 63 | } 64 | } 65 | } 66 | 67 | export default SvelteRouter 68 | --------------------------------------------------------------------------------