Repository: kazzkiq/svero
Branch: master
Commit: e27f95048097
Files: 24
Total size: 29.4 KB
Directory structure:
gitextract_dvw8sfi4/
├── .gitattributes
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── nightwatch.json
├── package.json
├── rollup.config.js
├── src/
│ ├── Link.svelte
│ ├── Route.svelte
│ ├── Router.svelte
│ ├── main.js
│ └── utils.js
└── test/
├── About.svelte
├── App.svelte
├── Index.svelte
├── User.svelte
├── e2e/
│ ├── link.js
│ ├── navigateTo.js
│ ├── route.js
│ └── router.js
├── main.js
└── public/
├── 404.html
└── index.html
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
package-lock.json -diff
build/* -diff
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
yarn.lock
chromedriver.log
*.xml
dist
tests_output
test/public/test.js
test/public/test.js.map
================================================
FILE: .travis.yml
================================================
sudo: required
addons:
chrome: stable
language: node_js
node_js:
- "lts/*"
deploy:
provider: npm
email: $NPM_EMAIL
api_key: $NPM_TOKEN
on:
tags: true
notifications:
email: false
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Claudio Holanda
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
================================================
FILE: README.md
================================================
⚠️⚠️ THIS LIBRARY IS DEPRECATED AND SHOULD NOT BE USED IN NEW PROJECTS ⚠️⚠️
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
<br>⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
⚠️⚠️ MORE DETAILS [HERE](https://github.com/kazzkiq/svero/issues/68). ⚠️⚠️
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
<br>⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
[](https://www.npmjs.com/package/svero)
[](https://travis-ci.org/kazzkiq/svero)
<p align="center">
svero (<b>Sve</b>lte <b>Ro</b>uter): A simple router for Svelte 3.
</p>
## First things first
svero is intented to be used in SPA (Single Page Applications) making usage of `pushState` and History API. We're assuming that you already know how to configure your front-end server (being it dev or production) to serve all path requests to `index.html`.
If you're not familiar with the terms SPA, `pushState` or History API, you should probably be reading these first:
<small>http://krasimirtsonev.com/blog/article/deep-dive-into-client-side-routing-navigo-pushstate-hash</small><br>
<small>https://css-tricks.com/using-the-html5-history-api/</small><br>
<small>https://diveinto.html5doctor.com/history.html</small><br>
<small>https://developer.mozilla.org/pt-BR/docs/Web/API/History</small><br>
## Installation
Since it's exported in CommonJS format, you should be using it with a module bundler such as [Rollup](https://github.com/sveltejs/template/tree/v3) or Webpack.
You can install svero via npm:
```
npm install --save svero
```
## Usage
The usage is super simple:
```html
<!-- ./App.svelte -->
<script>
import { Router, Route } from 'svero';
import Index from './pages/Index.svelte';
import About from './pages/About.svelte';
import Employees from './pages/Employees.svelte';
let employees = [{ id: 1, name: 'Bill'}, { id:2, name: 'Sven' }];
</script>
<Router>
<Route path="*" component={Index} />
<Route path="/about" component={About} />
<Route path="/about/:who/123/:where" component={About} />
<Route path="/employees">
<Employees {employees}/>
</Route>
</Router>
```
The `*` wildcard simply works as a fallback. If a route fails to meet any other path, it then loads the path with the `*`. If there is no wildcard route and the route did not meet any other path, nothing is loaded.
Your custom props can be passed by putting your component in the Route `slot` (Employees example above).
Paths with parameters (`:param`) are passed to components via props: `router.params`.
> Parameters like `*param` will capture the rest of segments. You can access them as `router.params._` like other params.
A component loaded by `<Route>` receives a property with route details:
```html
<!-- ./pages/About.svelte -->
<script>
export let router = {};
// Those contains useful information about current route status
router.path; // /test
router.route; // Route Object
router.params; // /about/bill/123/kansas { who: 'bill', where: 'kansas' }
</script>
```
Additional properties are passed to the mounted component, e.g.
```html
<Route component={Test} title="Some description" />
```
Also, you can pass an object:
```html
<Route component={Test} props={myProps} />
```
> `Route` props are omitted, but all remaining ones are passed to `Test`.
Routes can also render any given markup when they're active, e.g.
```html
<Route path="/static-path">
<h1>It works!</h1>
</Route>
```
> You can access `router` within `<slot />` renders by declaring `let:router` on `<Router />` or `<Route />` components (see below).
If you're building an SPA or simply want to leverage on hash-based routing for certain components try the following:
```html
<Route path="#g/:gistId/*filePath" let:router>
<p>Info: {JSON.stringify(router.params)}</p>
</Route>
```
Standard anchors and `<Link />` components will work as usual:
```html
<a href="#g/1acf21/path/to/README.md">View README.md</a>
```
Declaring a component `<Route path="#" />` will serve as fallback when `location.hash` is empty.
### Nesting
You can render `svero` components inside anything, e.g.
```html
<Router nofallback path="/sub">
<Route>
<fieldset>
<legend>Routing:</legend>
<Router nofallback path="/sub/:bar">
<Route let:router>{router.params.bar}!</Route>
</Router>
<Route path="/foo">Foo</Route>
<Route fallback path="*" let:router>
<summary>
<p>Not found: {router.params._}</p>
<details>{router.failure}</details>
</summary>
</Route>
<Router nofallback path="/sub/nested">
<Route>
[...]
<Route fallback path="*">not found?</Route>
<Route path="/a">A</Route>
<Route path="/b/:c">C</Route>
<Route path="/:value" let:router>{JSON.stringify(router.params)}</Route>
</Route>
</Router>
</fieldset>
</Route>
</Router>
```
Properties determine how routing will match and render routes:
- Use the `nofallback` prop for telling `<Router />` to disable the _fallback_ mechanism by default
- Any route using the `fallback` prop will catch unmatched routes or potential look-up errors
- Use the `exact` prop to skip this route from render just in case it does not matches
- A `<Route />` without `path` will render only if `<Router path="..." />` is active!
> Note that all `<Router />` paths MUST begin from the root as `/sub` and `/sub/nested` in the example.
### Redirects
Sometimes you just want a route to send user to another place. You can use the `redirect` attribute for that.
A redirect should always be a string with a path. It uses the same pattern as `path` attribute. For a redirect to run, there must be a Route with the equivalent path.
```html
<Router>
<Route path="/company" redirect="/about-us">
<Route path="/about-us" component={AboutUs}>
</Router>
```
### Conditions
If you need to meet a condition in order to run a route, you can use the `condition` attribute. Conditions can also be used with `redirect` for graceful route fallback.
A condition should be either `boolean` or a function returning `boolean`. There is no support for asynchronous conditions at the moment (so keep it simple).
```html
<Router>
<Route path="/admin/settings" condition={isAdminLogged} redirect="/admin/login">
</Router>
```
Think of it as a simpler middleware. A condition will run *before* the route loads your component, so there is no wasteful component mounting, and no screen blinking the unwanted view.
### Link Component
There is also an useful `<Link>` component that overrides `<a>` elements:
```html
<Link href="path/here" className="btn">Hello!</Link>
```
The difference between `<Link>` and `<a>` is that it uses `pushState` whenever possible, with fallback to `<a>` behavior. This means that when you use `<Link>`, svero can update the view based on your URL trigger, without reloading the entire page.
> Given `href` values will be normalized (on-click) if they don't start with a slash, e.g. when `location.pathname === '/foo'` then `#bar` would become `/foo#bar` as result.
### navigateTo()
In some cases you want to navigate to routes programatically instead of letting user click on links. For this scenario we have `navigateto()` which takes a route as parameter and navigates imediatelly to said route.
`navigateTo()` receives the same treatment as `<Link>`: It will always try to use `pushState` for better performance, fallbacking to a full page redirect if it isn't supported.
Usage:
```html
<script>
import { onMount } from 'svelte';
import { navigateTo } from 'svero';
onMount(() => {
if (localStorage.getItem('logged')) {
navigateTo('/admin');
}
});
</script>
```
### Webpack issues
If you're having trouble with Webpack failing to load svero, please replace the following rule (in Svelte rule):
```js
exclude: /node_modules/,
```
with:
```js
exclude: /node_modules\/(?!(svero)\/).*/,
```
More information [here](https://github.com/kazzkiq/svero/issues/23).
================================================
FILE: nightwatch.json
================================================
{
"src_folders" : ["test/e2e"],
"webdriver" : {
"start_process": true,
"server_path": "node_modules/.bin/chromedriver",
"port": 9515
},
"test_settings" : {
"default" : {
"desiredCapabilities": {
"browserName": "chrome",
"chromeOptions": {
"args": [
"--headless"
]
}
}
}
}
}
================================================
FILE: package.json
================================================
{
"name": "svero",
"version": "1.0.0",
"description": "Simple Router for Svelte 3",
"main": "dist/svero.js",
"svelte": "src/main.js",
"module": "dist/svero.es.js",
"browser": "dist/svero.min.js",
"files": [
"src/**",
"dist/*"
],
"peerDependencies": {
"svelte": "3.x"
},
"devDependencies": {
"chromedriver": "^78.0.1",
"http-server": "^0.11.1",
"kill-port": "^1.3.2",
"nightwatch": "^1.0.19",
"rollup": "^1.14.4",
"rollup-plugin-commonjs": "^10.0.0",
"rollup-plugin-node-resolve": "^5.0.1",
"rollup-plugin-svelte": "^5.0.3",
"rollup-plugin-terser": "^5.0.0",
"svelte": "^3.4.4"
},
"dependencies": {
"abstract-nested-router": "^0.1.3"
},
"scripts": {
"test": "kill-port 5001 && npm run test:server & npm run test:build && npm run test:run",
"debug": "kill-port 5001 && npm run test:build && npm run test:server",
"test:server": "http-server test/public -s -p 5001",
"test:build": "NODE_ENV=test rollup -c",
"test:run": "nightwatch",
"build": "NODE_ENV=production rollup -c",
"prepublishOnly": "npm run test && npm run build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/kazzkiq/svero.git"
},
"keywords": [
"router",
"svelte",
"svelte3"
],
"author": "Claudio Holanda",
"license": "MIT",
"bugs": {
"url": "https://github.com/kazzkiq/svero/issues"
},
"homepage": "https://github.com/kazzkiq/svero"
}
================================================
FILE: rollup.config.js
================================================
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
const isDev = process.env.ROLLUP_WATCH;
const isProd = process.env.NODE_ENV === 'production';
function bundle(file, format) {
return {
sourcemap: false,
name: 'svero',
format,
file,
};
}
export default {
input: isProd ? 'src/main.js' : 'test/main.js',
output: isProd ? [
bundle('dist/svero.js', 'cjs'),
bundle('dist/svero.es.js', 'es'),
bundle('dist/svero.min.js', 'umd'),
] : bundle('test/public/test.js', 'iife'),
external: isProd ? ['svelte', 'svelte/store', 'svelte/internal'] : [],
plugins: [
svelte({
dev: isDev,
}),
resolve(),
commonjs(),
isProd && terser(),
],
};
================================================
FILE: src/Link.svelte
================================================
<script>
import { onMount, createEventDispatcher } from 'svelte';
import { navigateTo } from './utils';
let cssClass = '';
export let href = '/';
export let className = '';
export let title = '';
export { cssClass as class };
onMount(() => {
className = className || cssClass;
});
const dispatch = createEventDispatcher();
// this will enable `<Link on:click={...} />` calls
function onClick(e) {
let fixedHref = href;
// this will rebase anchors to avoid location changes
if (fixedHref.charAt() !== '/') {
fixedHref = window.location.pathname + fixedHref;
}
navigateTo(fixedHref);
dispatch('click', e);
}
</script>
<a {href} class={className} title={title} on:click|preventDefault={onClick}><slot></slot></a>
================================================
FILE: src/Route.svelte
================================================
<script>
import { onDestroy, getContext } from 'svelte';
import { CTX_ROUTER } from './utils';
export let key = null;
export let path = '';
export let props = null;
export let exact = undefined;
export let fallback = undefined;
export let component = undefined;
export let condition = undefined;
export let redirect = undefined;
const { assignRoute, unassignRoute, routeInfo } = getContext(CTX_ROUTER);
let activeRouter = null;
let activeProps = {};
let fullpath;
function getProps(given, required) {
const { props, ...others } = given;
// prune all declared props from this component
required.forEach(k => {
delete others[k];
});
return {
...props,
...others,
};
}
[key, fullpath] = assignRoute(key, path, { condition, redirect, fallback, exact });
$: {
activeRouter = $routeInfo[key];
activeProps = getProps($$props, arguments[0]['$$'].props);
}
onDestroy(() => {
unassignRoute(fullpath);
});
</script>
{#if activeRouter}
{#if component}
<svelte:component this={component} router={activeRouter} {...activeProps} />
{:else}
<slot router={activeRouter} props={activeProps} />
{/if}
{/if}
================================================
FILE: src/Router.svelte
================================================
<script context="module">
import Router from 'abstract-nested-router';
import { CTX_ROUTER, navigateTo } from './utils';
const router = new Router();
</script>
<script>
import { writable } from 'svelte/store';
import { onMount, getContext, setContext } from 'svelte';
let t;
let failure;
let fallback;
export let path = '/';
export let nofallback = null;
const routeInfo = writable({});
const routerContext = getContext(CTX_ROUTER);
const basePath = routerContext ? routerContext.basePath : writable(path);
function cleanPath(route) {
return route.replace(/\?[^#]*/, '').replace(/(?!^)\/#/, '#').replace('/#', '#').replace(/\/$/, '');
}
function fixPath(route) {
if (route === '/#*' || route === '#*') return '#*_';
if (route === '/*' || route === '*') return '/*_';
return route;
}
function handleRoutes(map) {
const params = map.reduce((prev, cur) => {
prev[cur.key] = Object.assign(prev[cur.key] || {}, cur.params);
return prev;
}, {});
let skip;
let routes = {};
map.some(x => {
if (typeof x.condition === 'boolean' || typeof x.condition === 'function') {
const ok = typeof x.condition === 'function' ? x.condition() : x.condition;
if (ok === false && x.redirect) {
navigateTo(x.redirect);
skip = true;
return true;
}
}
if (x.key && !routes[x.key]) {
if (x.exact && !x.matches) return false;
routes[x.key] = { ...x, params: params[x.key] };
}
return false;
});
if (!skip) {
$routeInfo = routes;
}
}
function doFallback(e, path) {
$routeInfo[fallback] = { failure: e, params: { _: path.substr(1) || undefined } };
}
function resolveRoutes(path) {
const segments = path.split('#')[0].split('/');
const prefix = [];
const map = [];
segments.forEach(key => {
const sub = prefix.concat(`/${key}`).join('');
if (key) prefix.push(`/${key}`);
try {
const next = router.find(sub);
handleRoutes(next);
map.push(...next);
} catch (e_) {
doFallback(e_, path);
}
});
return map;
}
function handlePopState() {
const fullpath = cleanPath(`/${location.href.split('/').slice(3).join('/')}`);
try {
const found = resolveRoutes(fullpath);
if (fullpath.includes('#')) {
const next = router.find(fullpath);
const keys = {};
// override previous routes to avoid non-exact matches
handleRoutes(found.concat(next).reduce((prev, cur) => {
if (typeof keys[cur.key] === 'undefined') {
keys[cur.key] = prev.length;
}
prev[keys[cur.key]] = cur;
return prev;
}, []));
}
} catch (e) {
if (!fallback) {
failure = e;
return;
}
doFallback(e, fullpath);
}
}
function _handlePopState() {
clearTimeout(t);
t = setTimeout(handlePopState, 100);
}
function assignRoute(key, route, detail) {
key = key || Math.random().toString(36).substr(2);
const fixedRoot = $basePath !== path && $basePath !== '/'
? `${$basePath}${path}`
: path;
const handler = { key, ...detail };
let fullpath;
router.mount(fixedRoot, () => {
fullpath = router.add(fixPath(route), handler);
fallback = (handler.fallback && key) || fallback;
});
_handlePopState();
return [key, fullpath];
}
function unassignRoute(route) {
router.rm(fixPath(route));
_handlePopState();
}
setContext(CTX_ROUTER, {
basePath,
routeInfo,
assignRoute,
unassignRoute,
});
</script>
<svelte:window on:popstate={handlePopState}></svelte:window>
{#if failure && !nofallback}
<fieldset>
<legend>Router failure: {path}</legend>
<pre>{failure}</pre>
</fieldset>
{/if}
<slot />
================================================
FILE: src/main.js
================================================
import Router from './Router.svelte';
import Route from './Route.svelte';
import Link from './Link.svelte';
import { navigateTo } from './utils';
export {
Router,
Route,
Link,
navigateTo
};
================================================
FILE: src/utils.js
================================================
export const CTX_ROUTER = {};
export function navigateTo(path) {
// If path empty or no string, throws error
if (!path || typeof path !== 'string') {
throw Error(`svero expects navigateTo() to have a string parameter. The parameter provided was: ${path} of type ${typeof path} instead.`);
}
if (path[0] !== '/' && path[0] !== '#') {
throw Error(`svero expects navigateTo() param to start with slash or hash, e.g. "/${path}" or "#${path}" instead of "${path}".`);
}
// If no History API support, fallbacks to URL redirect
if (!history.pushState || !window.dispatchEvent) {
window.location.href = path;
return;
}
// If has History API support, uses it
history.pushState({}, '', path);
window.dispatchEvent(new Event('popstate'));
}
================================================
FILE: test/About.svelte
================================================
<script>
export let description = '';
export let router = null;
</script>
<h1>Hello from About!</h1>
{#if description}
<p>{description}</p>
{/if}
================================================
FILE: test/App.svelte
================================================
<script>
import { Router, Route, Link } from '../src/main';
import Index from './Index.svelte';
import About from './About.svelte';
import User from './User.svelte';
</script>
<main>
<Router>
<Route fallback path="*"><h1>Not found</h1></Route>
<Route exact path="/" component={Index} />
<Route path="/company" redirect="/about" />
<Route path="/about" description="Company and such." component={About} />
<Route path="/user/:name/:age" component={User} />
<Route path="/admin-false" condition={false} component={User} redirect="/" />
<Route path="/admin-true" condition={true} component={User} redirect="/" />
<Route path="/slot"><h3>It works!</h3></Route>
<Router nofallback path="/nested">
<Route>
<a href="#abc/def/ghi">Show params</a> | <Link href="#test">Static test</Link> | <Link href="#">Reset hash</Link>
<p>
<Route path="#:any/*path" let:router>Params: {JSON.stringify(router.params)}</Route>
<Route path="#test">Static placeholder is shown</Route>
<Route path="#">No hash is present</Route>
</p>
</Route>
</Router>
<Route path="#*" let:router>
<p><b>Anchored</b>. {router.params._}</p>
</Route>
</Router>
</main>
<Router nofallback path="/sub">
<Route>
<fieldset>
<legend>Routing:</legend>
<Router nofallback path="/:bar">
<Route let:router>{router.params.bar}!</Route>
</Router>
<Route path="/foo">Foo</Route>
<Route fallback path="*" let:router>
<summary>
<p>Not found: {router.params._}</p>
<details>{router.failure}</details>
</summary>
</Route>
<Router nofallback path="/nested">
<Route>
[...]
<Route fallback path="*">not found?</Route>
<Route path="/a">A</Route>
<Route path="/b/:c">C</Route>
<Route path="/:value" let:router>{JSON.stringify(router.params)}</Route>
</Route>
</Router>
</fieldset>
</Route>
</Router>
================================================
FILE: test/Index.svelte
================================================
<h1>Hello from Index!</h1>
================================================
FILE: test/User.svelte
================================================
<script>
import { Link, navigateTo } from '../src/main';
export let router = {};
</script>
{#if router.params.age}
<h1>Hello {router.params.name}, {router.params.age}yo!</h1>
{:else}
<h1>Hello {router.params.name}!</h1>
{/if}
{#if window.location.pathname === '/admin-true'}
<h2>Admin Panel</h2>
{/if}
{#if router.params.name === 'Classious'}
<Link class="purple" href="/about">Go to About</Link>
{:else}
<Link className="red" href="/about">Go to About</Link>
{/if}
<br>
<button on:click={() => { navigateTo('/about') }}>Goto /about</button>
<br>
<em on:click={() => { navigateTo('') }}>Does nothing</em>
<br>
<strong on:click={() => { navigateTo('about') }}>Does nothing</strong>
<br>
<Link href="/test-no-class">No Class Link</Link>
================================================
FILE: test/e2e/link.js
================================================
module.exports = {
'<Link> Href Attribute Tests': (browser) => {
browser
.url('http://localhost:5001/user/Amanda')
.waitForElementVisible('a')
.click('a')
.pause(100)
.assert.containsText('h1', 'Hello from About!')
.assert.urlContains('/about')
.end();
},
'<Link> ClassName Attribute Tests': (browser) => {
browser
.url('http://localhost:5001/user/Amanda')
.waitForElementVisible('a.red')
.end();
},
'<Link> Class Attribute Tests': (browser) => {
browser
.url('http://localhost:5001/user/Classious')
.waitForElementVisible('a.purple')
.end();
},
'<Link> Empty Class Attribute Shouldn\'t be "undefined"': (browser) => {
browser
.url('http://localhost:5001/user/Josh')
.waitForElementVisible('a[href="/test-no-class"]:not(.undefined)')
.end();
},
'<Link> <slot> Text Tests': (browser) => {
browser
.url('http://localhost:5001/user/Amanda')
.waitForElementVisible('a.red')
.assert.containsText('a.red', 'Go to About')
.end();
},
};
================================================
FILE: test/e2e/navigateTo.js
================================================
module.exports = {
'navigateTo(path) navigate to new path': (browser) => {
browser
.url('http://localhost:5001/user/Jon')
.waitForElementVisible('button')
.click('button')
.pause(100)
.assert.containsText('h1', 'Hello from About!')
.assert.urlContains('/about')
.end();
},
'navigateTo(path) empty parameter does nothing': (browser) => {
browser
.url('http://localhost:5001/user/Jon')
.waitForElementVisible('em')
.click('em')
.pause(100)
.assert.containsText('h1', 'Hello Jon!')
.assert.urlContains('/user/Jon')
.end();
},
'navigateTo(path) parameter not starting with slash (/) does nothing': (browser) => {
browser
.url('http://localhost:5001/user/Jon')
.waitForElementVisible('strong')
.click('strong')
.pause(100)
.assert.containsText('h1', 'Hello Jon!')
.assert.urlContains('/user/Jon')
.end();
}
};
================================================
FILE: test/e2e/route.js
================================================
module.exports = {
'<Route> Wildcard (*) Tests': (browser) => {
browser
// Checking if "/" Route loads Index Component
.url('http://localhost:5001')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Hello from Index!')
// Checking if non-existent route redirects to About Page
.url('http://localhost:5001/does-not-exists')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Not found')
.end();
},
'<Route> Slot rendering (/slot) Tests': (browser) => {
browser
.url('http://localhost:5001/slot')
.waitForElementVisible('h3')
.assert.containsText('h3', 'It works!')
.end();
},
'<Route> Basic path (/{name}) Tests': (browser) => {
browser
.url('http://localhost:5001/about')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Hello from About!')
.end();
},
'<Route> Single param (/:name) Tests': (browser) => {
browser
.url('http://localhost:5001/user/Amanda')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Hello Amanda!')
.end();
},
'<Route> Multiple params (/:name/:age) Tests': (browser) => {
browser
.url('http://localhost:5001/user/Amanda/30')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Hello Amanda, 30yo!')
.end();
},
'<Route> Redirect Attribute Tests': (browser) => {
browser
.url('http://localhost:5001/company')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Hello from About!')
.assert.urlContains('/about')
.end();
},
'<Route> Redirect Attribute Tests': (browser) => {
browser
// Check if /admin-false redirects to index
.url('http://localhost:5001/admin-false')
.pause(100)
.waitForElementVisible('h1')
.assert.containsText('h1', 'Hello from Index!')
.assert.urlContains('/')
// Check if /admin-true redirects to the right page
.url('http://localhost:5001/admin-true')
.waitForElementVisible('h2')
.assert.containsText('h2', 'Admin Panel')
.assert.urlContains('/admin-true')
.end();
},
'<Route> should work with hash-based routes': (browser) => {
browser
.url('http://localhost:5001/nested#')
.waitForElementVisible('p')
.assert.containsText('p', 'No hash is present')
.click('a[href="#abc/def/ghi"]')
.assert.containsText('p', 'Params: {"any":"abc","path":"def/ghi"}')
.click('a[href="#test"]')
.assert.containsText('p', 'Static placeholder is shown')
.end();
},
'<Route> use fallback for unreachable nested-routes': (browser) => {
browser
.url('http://localhost:5001/nested/im_not_exists')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Not found')
.end();
},
'<Route> hash-based paths can all catch-all': (browser) => {
browser
.url('http://localhost:5001/#whatever')
.waitForElementVisible('h1')
.assert.containsText('h1', 'Hello from Index!')
.waitForElementVisible('p')
.assert.containsText('p', 'Anchored. whatever')
.end();
},
'<Route> can receive additional props': (browser) => {
browser
.url('http://localhost:5001/about')
.waitForElementVisible('p')
.assert.containsText('p', 'Company and such.')
.end();
},
};
================================================
FILE: test/e2e/router.js
================================================
module.exports = {
'<Router> Render inside elements': (browser) => {
browser
.url('http://localhost:5001')
.waitForElementVisible('main h1')
.assert.containsText('main h1', 'Hello from Index!')
.url('http://localhost:5001/does-not-exists')
.waitForElementVisible('main h1')
.assert.containsText('main h1', 'Not found')
.end();
},
'<Router> can be nested indefinitely': (browser) => {
browser
.url('http://localhost:5001/sub')
.waitForElementVisible('fieldset')
.url('http://localhost:5001/sub/val')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', 'val!')
.url('http://localhost:5001/sub/foo')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', 'Foo')
.url('http://localhost:5001/sub/im/not/exists')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', 'im!')
.assert.containsText('fieldset', 'Not found: sub/im/not/exists')
.url('http://localhost:5001/sub/nested')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', '[...]')
.url('http://localhost:5001/sub/nested/a')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', '[...] A')
.url('http://localhost:5001/sub/nested/b')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', '[...] C')
.url('http://localhost:5001/sub/nested/b/d')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', '[...] C')
.url('http://localhost:5001/sub/nested/b/c/d')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', '[...] not found? C')
.assert.containsText('fieldset', 'Not found: sub/nested/b/c/d')
.url('http://localhost:5001/sub/nested/something')
.waitForElementVisible('fieldset')
.assert.containsText('fieldset', '[...] {"value":"something"}')
.end();
},
};
================================================
FILE: test/main.js
================================================
import App from './App.svelte';
document.addEventListener('DOMContentLoaded', () => {
new App({
target: document.body
});
});
================================================
FILE: test/public/404.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Svero Testing Page</title>
<script src="/test.js"></script>
</head>
<body>
</body>
</html>
================================================
FILE: test/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Svero Testing Page</title>
<script src="/test.js"></script>
</head>
<body>
</body>
</html>
gitextract_dvw8sfi4/
├── .gitattributes
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── nightwatch.json
├── package.json
├── rollup.config.js
├── src/
│ ├── Link.svelte
│ ├── Route.svelte
│ ├── Router.svelte
│ ├── main.js
│ └── utils.js
└── test/
├── About.svelte
├── App.svelte
├── Index.svelte
├── User.svelte
├── e2e/
│ ├── link.js
│ ├── navigateTo.js
│ ├── route.js
│ └── router.js
├── main.js
└── public/
├── 404.html
└── index.html
SYMBOL INDEX (3 symbols across 2 files)
FILE: rollup.config.js
function bundle (line 9) | function bundle(file, format) {
FILE: src/utils.js
constant CTX_ROUTER (line 1) | const CTX_ROUTER = {};
function navigateTo (line 3) | function navigateTo(path) {
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (33K chars).
[
{
"path": ".gitattributes",
"chars": 38,
"preview": "package-lock.json -diff\nbuild/* -diff\n"
},
{
"path": ".gitignore",
"chars": 118,
"preview": ".DS_Store\nnode_modules\nyarn.lock\nchromedriver.log\n*.xml\ndist\ntests_output\ntest/public/test.js\ntest/public/test.js.map\n"
},
{
"path": ".travis.yml",
"chars": 192,
"preview": "sudo: required\naddons:\n chrome: stable\nlanguage: node_js\nnode_js:\n - \"lts/*\"\ndeploy:\n provider: npm\n email: $NPM_EMAI"
},
{
"path": "LICENSE",
"chars": 1072,
"preview": "MIT License\n\nCopyright (c) 2019 Claudio Holanda\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "README.md",
"chars": 8019,
"preview": "⚠️⚠️ THIS LIBRARY IS DEPRECATED AND SHOULD NOT BE USED IN NEW PROJECTS ⚠️⚠️\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n<br>⚠️⚠️⚠️⚠️⚠️⚠️"
},
{
"path": "nightwatch.json",
"chars": 373,
"preview": "{\n \"src_folders\" : [\"test/e2e\"],\n\n \"webdriver\" : {\n \"start_process\": true,\n \"server_path\": \"node_modules/.bin/ch"
},
{
"path": "package.json",
"chars": 1475,
"preview": "{\n \"name\": \"svero\",\n \"version\": \"1.0.0\",\n \"description\": \"Simple Router for Svelte 3\",\n \"main\": \"dist/svero.js\",\n \""
},
{
"path": "rollup.config.js",
"chars": 832,
"preview": "import svelte from 'rollup-plugin-svelte';\nimport resolve from 'rollup-plugin-node-resolve';\nimport commonjs from 'rollu"
},
{
"path": "src/Link.svelte",
"chars": 778,
"preview": "<script>\n import { onMount, createEventDispatcher } from 'svelte';\n import { navigateTo } from './utils';\n\n let cssCl"
},
{
"path": "src/Route.svelte",
"chars": 1208,
"preview": "<script>\n import { onDestroy, getContext } from 'svelte';\n import { CTX_ROUTER } from './utils';\n\n export let key = n"
},
{
"path": "src/Router.svelte",
"chars": 3905,
"preview": "<script context=\"module\">\n import Router from 'abstract-nested-router';\n import { CTX_ROUTER, navigateTo } from './uti"
},
{
"path": "src/main.js",
"chars": 199,
"preview": "import Router from './Router.svelte';\nimport Route from './Route.svelte';\nimport Link from './Link.svelte';\nimport { nav"
},
{
"path": "src/utils.js",
"chars": 772,
"preview": "export const CTX_ROUTER = {};\n\nexport function navigateTo(path) {\n // If path empty or no string, throws error\n if (!p"
},
{
"path": "test/About.svelte",
"chars": 154,
"preview": "<script>\n export let description = '';\n export let router = null;\n</script>\n\n<h1>Hello from About!</h1>\n\n{#if descript"
},
{
"path": "test/App.svelte",
"chars": 2038,
"preview": "<script>\n import { Router, Route, Link } from '../src/main';\n import Index from './Index.svelte';\n import About from "
},
{
"path": "test/Index.svelte",
"chars": 26,
"preview": "<h1>Hello from Index!</h1>"
},
{
"path": "test/User.svelte",
"chars": 753,
"preview": "<script>\n import { Link, navigateTo } from '../src/main';\n\n export let router = {};\n</script>\n\n{#if router.params.age}"
},
{
"path": "test/e2e/link.js",
"chars": 1088,
"preview": "module.exports = {\n '<Link> Href Attribute Tests': (browser) => {\n browser\n .url('http://localhost:5001/user/Am"
},
{
"path": "test/e2e/navigateTo.js",
"chars": 954,
"preview": "module.exports = {\n 'navigateTo(path) navigate to new path': (browser) => {\n browser\n .url('http://localhost:50"
},
{
"path": "test/e2e/route.js",
"chars": 3371,
"preview": "module.exports = {\n '<Route> Wildcard (*) Tests': (browser) => {\n browser\n // Checking if \"/\" Route loads Index"
},
{
"path": "test/e2e/router.js",
"chars": 1978,
"preview": "module.exports = {\n '<Router> Render inside elements': (browser) => {\n browser\n .url('http://localhost:5001')\n "
},
{
"path": "test/main.js",
"chars": 135,
"preview": "import App from './App.svelte';\n\ndocument.addEventListener('DOMContentLoaded', () => {\n new App({\n target: document."
},
{
"path": "test/public/404.html",
"chars": 298,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, in"
},
{
"path": "test/public/index.html",
"chars": 298,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, in"
}
]
About this extraction
This page contains the full source code of the kazzkiq/svero GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (29.4 KB), approximately 8.7k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.