generated from cms/tibi-docs
zwischenstand
This commit is contained in:
1
vendor/svelte-routing/.gitattributes
vendored
Normal file
1
vendor/svelte-routing/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.svelte linguist-language=HTML
|
||||
9
vendor/svelte-routing/.prettierrc
vendored
Normal file
9
vendor/svelte-routing/.prettierrc
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"pluginSearchDirs": ["."],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
309
vendor/svelte-routing/CHANGELOG.md
vendored
Normal file
309
vendor/svelte-routing/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
# CHANGELOG
|
||||
|
||||
# 2.11.0
|
||||
- PR Merged [#277](https://github.com/EmilTholin/svelte-routing/pull/277)
|
||||
- Update dependencies.
|
||||
|
||||
# 2.10.0
|
||||
- PR Removed [#266](https://github.com/EmilTholin/svelte-routing/pull/266)
|
||||
- Issue Fixed [#273](https://github.com/EmilTholin/svelte-routing/issues/273)
|
||||
- Update dependencies.
|
||||
|
||||
# 2.9.0
|
||||
- PR Merged [#272](https://github.com/EmilTholin/svelte-routing/pull/272).
|
||||
- Issue Fixed [#271](https://github.com/EmilTholin/svelte-routing/issues/271).
|
||||
|
||||
# 2.8.0
|
||||
- PR Merged [#267](https://github.com/EmilTholin/svelte-routing/pull/267).
|
||||
- PR Merged [#270](https://github.com/EmilTholin/svelte-routing/pull/270).
|
||||
- Issue Fixed [#268](https://github.com/EmilTholin/svelte-routing/issues/268).
|
||||
- Issue Fixed [#269](https://github.com/EmilTholin/svelte-routing/issues/269).
|
||||
- Update dependencies.
|
||||
|
||||
# 2.7.0
|
||||
- PR Merged [#266](https://github.com/EmilTholin/svelte-routing/pull/266).
|
||||
- Update dependencies.
|
||||
|
||||
# 2.6.0
|
||||
|
||||
- Issue Fixed [#262](https://github.com/EmilTholin/svelte-routing/issues/262).
|
||||
- PR Merged [#263](https://github.com/EmilTholin/svelte-routing/pull/263).
|
||||
- Update svelte version.
|
||||
|
||||
# 2.5.0
|
||||
|
||||
- Issue Fixed [#260](https://github.com/EmilTholin/svelte-routing/issues/260).
|
||||
- Update svelte version.
|
||||
|
||||
# 2.4.0
|
||||
|
||||
- Fixed viewtransition callback function error.
|
||||
|
||||
# 2.3.0
|
||||
|
||||
- Added Prettier.
|
||||
- Added View Transition (Experimental).
|
||||
|
||||
# 2.2.0
|
||||
|
||||
- PR Merged [#258](https://github.com/EmilTholin/svelte-routing/pull/258).
|
||||
|
||||
# 2.1.0
|
||||
|
||||
- PR Merged [#256](https://github.com/EmilTholin/svelte-routing/pull/256).
|
||||
- PR Merged [#257](https://github.com/EmilTholin/svelte-routing/pull/257).
|
||||
- Issue Fixed [#254](https://github.com/EmilTholin/svelte-routing/issues/254).
|
||||
- Update svelte version.
|
||||
|
||||
# 2.0.0
|
||||
|
||||
- PR Merged [#250](https://github.com/EmilTholin/svelte-routing/pull/250).
|
||||
- PR Merged [#247](https://github.com/EmilTholin/svelte-routing/pull/247).
|
||||
- Removing example folder.
|
||||
- Update svelte version.
|
||||
|
||||
# 1.11.0
|
||||
|
||||
- PR Merged [#245](https://github.com/EmilTholin/svelte-routing/pull/245).
|
||||
- Update svelte version.
|
||||
|
||||
# 1.10.0
|
||||
|
||||
- PR Merged [#243](https://github.com/EmilTholin/svelte-routing/pull/243).
|
||||
|
||||
# 1.9.0
|
||||
|
||||
- Major improvement in performance. Minimize unnecessary prefetch components.
|
||||
|
||||
# 1.8.9
|
||||
|
||||
- Fixed. Sometimes navigate return info null.
|
||||
- Issue Fixed [#132](https://github.com/EmilTholin/svelte-routing/issues/132).
|
||||
|
||||
# 1.8.8
|
||||
|
||||
- Issue Fixed [#242](https://github.com/EmilTholin/svelte-routing/issues/242).
|
||||
- PR Removed [#77](https://github.com/EmilTholin/svelte-routing/pull/77)
|
||||
Causing infinity loop in nested routes.
|
||||
|
||||
# 1.8.7
|
||||
|
||||
- Segment mismatch bug fixed.
|
||||
|
||||
# 1.8.6
|
||||
|
||||
- Issue Fixed [#242](https://github.com/EmilTholin/svelte-routing/issues/242).
|
||||
- Update svelte version.
|
||||
- Codebase improved.
|
||||
|
||||
# 1.8.5
|
||||
|
||||
- Can Use Dom function improved.
|
||||
- function & class mismatch bug fixed.
|
||||
|
||||
# 1.8.4
|
||||
|
||||
- Issue Fixed [#241](https://github.com/EmilTholin/svelte-routing/issues/241).
|
||||
|
||||
# 1.8.3
|
||||
|
||||
- Hooks & Types bugs fixed.
|
||||
|
||||
# 1.8.2
|
||||
|
||||
- Svelte dependency updated.
|
||||
- Lazyload component return type added.
|
||||
- Issue Fixed [#240](https://github.com/EmilTholin/svelte-routing/issues/240).
|
||||
|
||||
# 1.8.0
|
||||
|
||||
- Major Bugs fixed in `Router.svelte`.
|
||||
- Converted all interfaces into types.
|
||||
- Improved Lazy Loading/Async Route Import. Get much smaller chunk for every
|
||||
route. Only load files (JS & CSS module) when URL is active.
|
||||
|
||||
```jsx
|
||||
<!-- App.svelte -->
|
||||
<Route path="/" component={() => import("./Home.svelte")} />
|
||||
|
||||
<Route path="/about" component={() => import("./About.svelte")} />
|
||||
|
||||
<Route path="/user/:user" component={() => import("./User.svelte")} />
|
||||
```
|
||||
|
||||
- Added Hooks for Contexts. `useLocation`, `useRouter`, `useHistory`.
|
||||
|
||||
```html
|
||||
<!-- Page.svelte -->
|
||||
<script>
|
||||
import { useLocation } from "svelte-routing";
|
||||
const location = useLocation();
|
||||
</script>
|
||||
|
||||
<div>{JSON.stringify($location)}</div>
|
||||
```
|
||||
|
||||
# 1.7.0
|
||||
|
||||
- Added Code of Conduct.
|
||||
- Optimized the codebase.
|
||||
- Update the dependencies.
|
||||
- PR Merged [#220](https://github.com/EmilTholin/svelte-routing/pull/220).
|
||||
- PR Merged [#210](https://github.com/EmilTholin/svelte-routing/pull/210).
|
||||
- PR Merged [#206](https://github.com/EmilTholin/svelte-routing/pull/206).
|
||||
- PR Merged [#192](https://github.com/EmilTholin/svelte-routing/pull/193).
|
||||
- PR Merged [#188](https://github.com/EmilTholin/svelte-routing/pull/188).
|
||||
- PR Merged [#175](https://github.com/EmilTholin/svelte-routing/pull/175).
|
||||
- PR Merged [#173](https://github.com/EmilTholin/svelte-routing/pull/173).
|
||||
- PR Merged [#158](https://github.com/EmilTholin/svelte-routing/pull/158).
|
||||
- PR Merged [#105](https://github.com/EmilTholin/svelte-routing/pull/105).
|
||||
- PR Merged [#95](https://github.com/EmilTholin/svelte-routing/pull/95).
|
||||
- PR Merged [#85](https://github.com/EmilTholin/svelte-routing/pull/85).
|
||||
- PR Merged [#77](https://github.com/EmilTholin/svelte-routing/pull/77).
|
||||
- PR/Issue [#200](https://github.com/EmilTholin/svelte-routing/pull/200),
|
||||
Tested & it's not relevant/exists.
|
||||
- Issue Fixed [#122](https://github.com/EmilTholin/svelte-routing/issues/122),
|
||||
[#4652](https://github.com/sveltejs/svelte/issues/4652).
|
||||
|
||||
# 1.6.0
|
||||
|
||||
Added TypeScript support.
|
||||
|
||||
# 1.4.0
|
||||
|
||||
Added functionality for passing the `location` to the rendered Route `component`
|
||||
and slot.
|
||||
|
||||
```html
|
||||
<!-- App.svelte -->
|
||||
<Route path="/blog" component="{Blog}" />
|
||||
|
||||
<!-- Blog.svelte -->
|
||||
<script>
|
||||
import queryString from "query-string";
|
||||
|
||||
export let location;
|
||||
|
||||
let queryParams;
|
||||
$: queryParams = queryString.parse(location.search);
|
||||
</script>
|
||||
|
||||
<h1>Blog</h1>
|
||||
<p>{queryParams.foo}</p>
|
||||
|
||||
<!-- App.svelte -->
|
||||
<Route path="/blog" let:location>
|
||||
<h1>Blog</h1>
|
||||
<p>{location.search}</p>
|
||||
</Route>
|
||||
```
|
||||
|
||||
# 1.3.0
|
||||
|
||||
Added functionality to pass potential `Route` path parameters back to the parent
|
||||
using props, so they can be exposed to the slot template using `let:params`.
|
||||
|
||||
```html
|
||||
<Route path="/blog/:id" let:params>
|
||||
<BlogPost id="{params.id}" />
|
||||
</Route>
|
||||
```
|
||||
|
||||
# 1.2.0
|
||||
|
||||
Added functionality for passing all the extra `Route` properties to the rendered
|
||||
`component`.
|
||||
|
||||
```html
|
||||
<!-- App.svelte -->
|
||||
<Route path="/page" component="{Page}" foo="foo" bar="bar" />
|
||||
|
||||
<!-- Page.svelte -->
|
||||
<script>
|
||||
export let foo;
|
||||
export let bar;
|
||||
</script>
|
||||
|
||||
<h1>{foo} {bar}</h1>
|
||||
```
|
||||
|
||||
# 1.1.0
|
||||
|
||||
Added the ability to give `Route` path wildcards a custom name.
|
||||
|
||||
```html
|
||||
<!-- App.svelte -->
|
||||
<Route path="/page/*wildcardName" component="{Page}" />
|
||||
|
||||
<!-- Page.svelte -->
|
||||
<script>
|
||||
export let wildcardName;
|
||||
</script>
|
||||
|
||||
<h1>{wildcardName}</h1>
|
||||
```
|
||||
|
||||
# 1.0.0
|
||||
|
||||
- Moved to Svelte 3.
|
||||
- It's now required for all `Route` and `Link` components to have a `Router`
|
||||
ancestor.
|
||||
- `NavLink` was removed in favour for a more versatile `Link` component. Check
|
||||
the userland `NavLink` component in the `example` directory for an example.
|
||||
- The SSR component no longer needs to be compiled at runtime with the help of
|
||||
[esm](https://github.com/standard-things/esm) as there is no longer a
|
||||
dependency on the `history` library. You can compile a separate CJS bundle
|
||||
for the server and pass in a prop to the topmost component and use that as
|
||||
the `url` property for the `Router`, which will force the URL for all
|
||||
descendants.
|
||||
- All component filename extensions have been changed to `.svelte`.
|
||||
- Hash routing is no longer supported.
|
||||
- The entire API of the library is now exported from the `src/index.js` file,
|
||||
so importing from the library is now much more pleasant.
|
||||
|
||||
```javascript
|
||||
import { Router, Route, Link } from "svelte-routing";
|
||||
```
|
||||
|
||||
# 0.4.0
|
||||
|
||||
Moved to Svelte v2 and added the new
|
||||
[link](https://github.com/EmilTholin/svelte-routing#linkjs) and
|
||||
[links](https://github.com/EmilTholin/svelte-routing#linksjs) actions.
|
||||
|
||||
# 0.3.0
|
||||
|
||||
Split the `createHistory` function into `createBrowserHistory`,
|
||||
`createMemoryHistory`, `createHashHistory` to allow for better tree shaking of
|
||||
unused history creation code.
|
||||
|
||||
# 0.2.0
|
||||
|
||||
Added the ability to access the match object in a matched route:
|
||||
|
||||
```html
|
||||
<!-- App.html -->
|
||||
<Route path="/:myParam" bind:match>
|
||||
<h1>{{match && match.params.myParam}}</h1>
|
||||
</Route>
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```html
|
||||
<!-- App.html -->
|
||||
<Route path="/:myParam" component="{{MyComponent}}" />
|
||||
|
||||
<!-- MyComponent.html -->
|
||||
<h1>{{match.params.myParam}}</h1>
|
||||
```
|
||||
|
||||
# 0.1.0
|
||||
|
||||
Added the ability to give a component constructor to a route with the
|
||||
`component` property:
|
||||
|
||||
```html
|
||||
<!-- App.html -->
|
||||
<Route path="/:myParam" component="{{MyComponent}}" />
|
||||
```
|
||||
128
vendor/svelte-routing/CODE_OF_CONDUCT.md
vendored
Normal file
128
vendor/svelte-routing/CODE_OF_CONDUCT.md
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
- Focusing on what is best not just for us as individuals, but for the overall
|
||||
community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
- The use of sexualized language or imagery, and sexual attention or advances
|
||||
of any kind
|
||||
- Trolling, insulting or derogatory comments, and personal or political
|
||||
attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email address,
|
||||
without their explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at . All
|
||||
complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series of
|
||||
actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or permanent
|
||||
ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||
community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
20
vendor/svelte-routing/LICENSE
vendored
Normal file
20
vendor/svelte-routing/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Krishna Torque
|
||||
|
||||
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.
|
||||
234
vendor/svelte-routing/README.md
vendored
Normal file
234
vendor/svelte-routing/README.md
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
[![npm][npm]][npm-url]
|
||||
|
||||
# Svelte Routing
|
||||
|
||||
A declarative Svelte routing library with SSR support.
|
||||
|
||||
[[CHANGELOG][changelog-url]]
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm i -D svelte-routing
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```html
|
||||
<!-- App.svelte -->
|
||||
<script>
|
||||
import { Router, Link, Route } from "svelte-routing";
|
||||
import Home from "./routes/Home.svelte";
|
||||
import About from "./routes/About.svelte";
|
||||
import Blog from "./routes/Blog.svelte";
|
||||
|
||||
export let url = "";
|
||||
</script>
|
||||
|
||||
<Router {url}>
|
||||
<nav>
|
||||
<Link to="/">Home</Link>
|
||||
<Link to="/about">About</Link>
|
||||
<Link to="/blog">Blog</Link>
|
||||
</nav>
|
||||
<div>
|
||||
<Route path="/blog/:id" component={BlogPost} />
|
||||
<Route path="/blog" component={Blog} />
|
||||
<Route path="/about" component={About} />
|
||||
<Route path="/"><Home /></Route>
|
||||
</div>
|
||||
</Router>
|
||||
```
|
||||
|
||||
```javascript
|
||||
// main.js
|
||||
import App from "./App.svelte";
|
||||
|
||||
const app = new App({
|
||||
target: document.getElementById("app"),
|
||||
});
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
#### `Router`
|
||||
|
||||
The `Router` component supplies the `Link` and `Route` descendant components
|
||||
with routing information through context, so you need at least one `Router` at
|
||||
the top of your application. It assigns a score to all its `Route` descendants
|
||||
and picks the best match to render.
|
||||
|
||||
`Router` components can also be nested to allow for seamless merging of many
|
||||
smaller apps.
|
||||
|
||||
###### Properties
|
||||
|
||||
| Property | Required | Default Value | Description |
|
||||
| :--------------: | :------: | :-----------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `basepath` | | `"/"` | The `basepath` property will be added to all the `to` properties of `Link` descendants and to all `path` properties of `Route` descendants. This property can be ignored in most cases, but if you host your application on e.g. `https://example.com/my-site`, the `basepath` should be set to `/my-site`. |
|
||||
| `url` | | `""` | The `url` property is used in SSR to force the current URL of the application and will be used by all `Link` and `Route` descendants. A falsy value will be ignored by the `Router`, so it's enough to declare `export let url = "";` for your topmost component and only give it a value in SSR. |
|
||||
| `viewtransition` | | `null` | View Transition (Experimental) |
|
||||
|
||||
#### `Link`
|
||||
|
||||
A component used to navigate around the application.
|
||||
|
||||
###### Properties
|
||||
|
||||
| Property | Required | Default Value | Description |
|
||||
| :--------------: | :------: | :-----------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `to` | ✔ ️ | `"#"` | URL the component should link to. |
|
||||
| `replace` | | `false` | When `true`, clicking the `Link` will replace the current entry in the history stack instead of adding a new one. |
|
||||
| `state` | | `{}` | An object that will be pushed to the history stack when the `Link` is clicked. |
|
||||
| `getProps` | | `() => ({})` | A function that returns an object that will be spread on the underlying anchor element's attributes. The first argument given to the function is an object with the properties `location`, `href`, `isPartiallyCurrent`, `isCurrent`. |
|
||||
| `preserveScroll` | | `false` | When `true`, clicking the `Link` will not scroll the page to the top. |
|
||||
|
||||
#### `Route`
|
||||
|
||||
A component that will render its `component` property or children when its
|
||||
ancestor `Router` component decides it is the best match.
|
||||
|
||||
All properties other than `path` and `component` given to the `Route` will be
|
||||
passed to the rendered `component`.
|
||||
|
||||
Potential path parameters will be passed to the rendered `component` as
|
||||
properties. A wildcard `*` can be given a name with `*wildcardName` to pass the
|
||||
wildcard string as the `wildcardName` property instead of as the `*` property.
|
||||
|
||||
Potential path parameters are passed back to the parent using props, so they can
|
||||
be exposed to the slot template using `let:params`.
|
||||
|
||||
```html
|
||||
<Route path="/blog/:id" let:params>
|
||||
<BlogPost id="{params.id}" />
|
||||
</Route>
|
||||
```
|
||||
|
||||
The active status of link can be exposed to the slot template using
|
||||
`let:active`.
|
||||
|
||||
```html
|
||||
<Link to="/browser" let:active>
|
||||
<MenuItem active={active}>Browser</MenuItem>
|
||||
</Link>
|
||||
```
|
||||
|
||||
###### Properties
|
||||
|
||||
| Property | Required | Default Value | Description |
|
||||
| :---------: | :------: | :------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `path` | | `""` | The path for when this component should be rendered. If no `path` is given the `Route` will act as the default that matches if no other `Route` in the `Router` matches. |
|
||||
| `component` | | `null` | The component constructor that will be used for rendering when the `Route` matches. If `component` is not set, the children of `Route` will be rendered instead. |
|
||||
|
||||
#### `navigate`
|
||||
|
||||
A function that allows you to imperatively navigate around the application for
|
||||
those use cases where a `Link` component is not suitable, e.g. after submitting
|
||||
a form.
|
||||
|
||||
The first argument is a string denoting where to navigate to, and the second
|
||||
argument is an object with a `replace`, `state` and `preserveScroll` properties equivalent to those
|
||||
in the `Link` component.
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { navigate } from "svelte-routing";
|
||||
|
||||
function onSubmit() {
|
||||
login().then(() => {
|
||||
navigate("/success", { replace: true });
|
||||
});
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
#### `link`
|
||||
|
||||
An action used on anchor tags to navigate around the application. You can add an
|
||||
attribute `replace` to replace the current entry in the history stack instead of
|
||||
adding a new one and `preserveScroll` to not scroll the page to the top when clicked.
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { link } from "svelte-routing";
|
||||
</script>
|
||||
|
||||
<Router>
|
||||
<a href="/" use:link>Home</a>
|
||||
<a href="/replace" use:link replace>Replace this URL</a>
|
||||
<!-- ... -->
|
||||
</Router>
|
||||
```
|
||||
|
||||
#### `links`
|
||||
|
||||
An action used on a root element to make all relative anchor elements navigate
|
||||
around the application. You can add an attribute `replace` on any anchor to
|
||||
replace the current entry in the history stack instead of adding a new one.
|
||||
You can add an attribute `preserveScroll` on any anchor to not to scroll the page to the top when clicked. You
|
||||
can add an attribute `noroute` for this action to skip over the anchor and allow
|
||||
it to use the native browser action.
|
||||
|
||||
```html
|
||||
<!-- App.svelte -->
|
||||
<script>
|
||||
import { links } from "svelte-routing";
|
||||
</script>
|
||||
|
||||
<div use:links>
|
||||
<Router>
|
||||
<a href="/">Home</a>
|
||||
<a href="/replace" replace>Replace this URL</a>
|
||||
<a href="/native" noroute>Use the native action</a>
|
||||
<!-- ... -->
|
||||
</Router>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### `viewtransition`
|
||||
|
||||
Viewtransition for navigation (Experimental).
|
||||
|
||||
_`builtin transition`_
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { fade } from "svelte/transition";
|
||||
// ...
|
||||
</script>
|
||||
|
||||
<Router viewtransition="{() => { fn: fade, duration: 500 }}">
|
||||
<Route path="/" component="{Home}" />
|
||||
<Route path="/contact" component="{Contact}" />
|
||||
</Router>
|
||||
```
|
||||
|
||||
_`custom transition`_
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { cubicin } from "svelte/easing";
|
||||
// ...
|
||||
</script>
|
||||
|
||||
<Router
|
||||
viewtransition="{() => { duration: 500, easing: cubicin, css: (t) => `scale:${t};transform-origin:center center;` }}"
|
||||
>
|
||||
<Route path="/" component="{Home}" />
|
||||
<Route path="/contact" component="{Contact}" />
|
||||
</Router>
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
This project is licensed under the [**MIT**](LICENSE).
|
||||
|
||||
# Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for this project by you, shall be licensed as **MIT**, without any additional
|
||||
terms or conditions. [**Code of Conduct**](CODE_OF_CONDUCT.md).
|
||||
|
||||
[npm]: https://img.shields.io/npm/v/svelte-routing.svg
|
||||
[npm-url]: https://npmjs.com/package/svelte-routing
|
||||
[changelog-url]: https://github.com/EmilTholin/svelte-routing/blob/master/CHANGELOG.md
|
||||
34
vendor/svelte-routing/package.json
vendored
Normal file
34
vendor/svelte-routing/package.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "svelte-routing",
|
||||
"version": "2.11.0",
|
||||
"author": "Emil Tholin @EmilTholin",
|
||||
"license": "MIT",
|
||||
"description": "A declarative Svelte routing library with SSR support",
|
||||
"keywords": [
|
||||
"svelte routing",
|
||||
"svelte",
|
||||
"sveltejs",
|
||||
"route",
|
||||
"router",
|
||||
"routing",
|
||||
"svelte route",
|
||||
"svelte router",
|
||||
"typescript"
|
||||
],
|
||||
"repository": "EmilTholin/svelte-routing",
|
||||
"main": "./src/index.js",
|
||||
"types": "./types/index.d.ts",
|
||||
"svelte": "./src/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"main": "./src/index.js",
|
||||
"types": "./types/index.d.ts",
|
||||
"svelte": "./src/index.js"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte": "^4.2.8",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.1.2"
|
||||
}
|
||||
}
|
||||
50
vendor/svelte-routing/src/Link.svelte
vendored
Normal file
50
vendor/svelte-routing/src/Link.svelte
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<script>
|
||||
import { createEventDispatcher, getContext } from "svelte";
|
||||
import { HISTORY, LOCATION, ROUTER } from "./contexts.js";
|
||||
import { resolve, shouldNavigate } from "./utils.js";
|
||||
|
||||
export let to = "#";
|
||||
export let replace = false;
|
||||
export let state = {};
|
||||
export let getProps = () => ({});
|
||||
export let preserveScroll = false;
|
||||
|
||||
const location = getContext(LOCATION);
|
||||
const { base } = getContext(ROUTER);
|
||||
const { navigate } = getContext(HISTORY);
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let href, isPartiallyCurrent, isCurrent, props;
|
||||
$: href = resolve(to, $base.uri);
|
||||
$: isPartiallyCurrent = $location.pathname.startsWith(href);
|
||||
$: isCurrent = href === $location.pathname;
|
||||
$: ariaCurrent = isCurrent ? "page" : undefined;
|
||||
$: props = getProps({
|
||||
location: $location,
|
||||
href,
|
||||
isPartiallyCurrent,
|
||||
isCurrent,
|
||||
existingProps: $$restProps,
|
||||
});
|
||||
|
||||
const onClick = (event) => {
|
||||
dispatch("click", event);
|
||||
if (shouldNavigate(event)) {
|
||||
event.preventDefault();
|
||||
// Don't push another entry to the history stack when the user
|
||||
// clicks on a Link to the page they are currently on.
|
||||
const shouldReplace = $location.pathname === href || replace;
|
||||
navigate(href, { state, replace: shouldReplace, preserveScroll });
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<a
|
||||
{href}
|
||||
aria-current={ariaCurrent}
|
||||
on:click={onClick}
|
||||
{...props}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot active={!!ariaCurrent} />
|
||||
</a>
|
||||
59
vendor/svelte-routing/src/Route.svelte
vendored
Normal file
59
vendor/svelte-routing/src/Route.svelte
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<script>
|
||||
import { getContext, onDestroy } from "svelte";
|
||||
import { ROUTER } from "./contexts.js";
|
||||
import { canUseDOM } from "./utils.js";
|
||||
|
||||
export let path = "";
|
||||
export let component = null;
|
||||
|
||||
let routeParams = {};
|
||||
let routeProps = {};
|
||||
|
||||
const { registerRoute, unregisterRoute, activeRoute } = getContext(ROUTER);
|
||||
|
||||
const route = {
|
||||
path,
|
||||
// If no path prop is given, this Route will act as the default Route
|
||||
// that is rendered if no other Route in the Router is a match.
|
||||
default: path === "",
|
||||
};
|
||||
|
||||
$: if ($activeRoute && $activeRoute.route === route) {
|
||||
routeParams = $activeRoute.params;
|
||||
|
||||
const { component: c, path, ...rest } = $$props;
|
||||
routeProps = rest;
|
||||
|
||||
if (c) {
|
||||
// goja gives object instead of class
|
||||
if (
|
||||
c.toString().startsWith("class ") ||
|
||||
c.toString().includes("object")
|
||||
)
|
||||
component = c;
|
||||
else component = c();
|
||||
}
|
||||
|
||||
canUseDOM() && !$activeRoute.preserveScroll && window?.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
registerRoute(route);
|
||||
|
||||
onDestroy(() => {
|
||||
unregisterRoute(route);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if $activeRoute && $activeRoute.route === route}
|
||||
{#if component}
|
||||
{#await component then resolvedComponent}
|
||||
<svelte:component
|
||||
this={resolvedComponent?.default || resolvedComponent}
|
||||
{...routeParams}
|
||||
{...routeProps}
|
||||
/>
|
||||
{/await}
|
||||
{:else}
|
||||
<slot params={routeParams} />
|
||||
{/if}
|
||||
{/if}
|
||||
145
vendor/svelte-routing/src/Router.svelte
vendored
Normal file
145
vendor/svelte-routing/src/Router.svelte
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
<script>
|
||||
import { getContext, onMount, setContext } from "svelte";
|
||||
import { derived, writable } from "svelte/store";
|
||||
import { HISTORY, LOCATION, ROUTER } from "./contexts.js";
|
||||
import { globalHistory } from "./history.js";
|
||||
import { combinePaths, pick } from "./utils.js";
|
||||
|
||||
export let basepath = "/";
|
||||
export let url = null;
|
||||
export let viewtransition = null;
|
||||
export let history = globalHistory;
|
||||
|
||||
const viewtransitionFn = (node, _, direction) => {
|
||||
const vt = viewtransition(direction);
|
||||
if (typeof vt?.fn === "function") return vt.fn(node, vt);
|
||||
else return vt;
|
||||
};
|
||||
|
||||
setContext(HISTORY, history);
|
||||
|
||||
const locationContext = getContext(LOCATION);
|
||||
const routerContext = getContext(ROUTER);
|
||||
|
||||
const routes = writable([]);
|
||||
const activeRoute = writable(null);
|
||||
let hasActiveRoute = false; // Used in SSR to synchronously set that a Route is active.
|
||||
|
||||
// If locationContext is not set, this is the topmost Router in the tree.
|
||||
// If the `url` prop is given we force the location to it.
|
||||
const location =
|
||||
locationContext || writable(url ? { pathname: url } : history.location);
|
||||
|
||||
// If routerContext is set, the routerBase of the parent Router
|
||||
// will be the base for this Router's descendants.
|
||||
// If routerContext is not set, the path and resolved uri will both
|
||||
// have the value of the basepath prop.
|
||||
const base = routerContext
|
||||
? routerContext.routerBase
|
||||
: writable({
|
||||
path: basepath,
|
||||
uri: basepath,
|
||||
});
|
||||
|
||||
const routerBase = derived([base, activeRoute], ([base, activeRoute]) => {
|
||||
// If there is no activeRoute, the routerBase will be identical to the base.
|
||||
if (!activeRoute) return base;
|
||||
|
||||
const { path: basepath } = base;
|
||||
const { route, uri } = activeRoute;
|
||||
// Remove the potential /* or /*splatname from
|
||||
// the end of the child Routes relative paths.
|
||||
const path = route.default ? basepath : route.path.replace(/\*.*$/, "");
|
||||
return { path, uri };
|
||||
});
|
||||
|
||||
const registerRoute = (route) => {
|
||||
const { path: basepath } = $base;
|
||||
let { path } = route;
|
||||
|
||||
// We store the original path in the _path property so we can reuse
|
||||
// it when the basepath changes. The only thing that matters is that
|
||||
// the route reference is intact, so mutation is fine.
|
||||
route._path = path;
|
||||
route.path = combinePaths(basepath, path);
|
||||
|
||||
if (typeof window === "undefined") {
|
||||
// In SSR we should set the activeRoute immediately if it is a match.
|
||||
// If there are more Routes being registered after a match is found,
|
||||
// we just skip them.
|
||||
if (hasActiveRoute) return;
|
||||
|
||||
const matchingRoute = pick([route], $location.pathname);
|
||||
|
||||
if (matchingRoute) {
|
||||
activeRoute.set(matchingRoute);
|
||||
hasActiveRoute = true;
|
||||
}
|
||||
} else {
|
||||
routes.update((rs) => [...rs, route]);
|
||||
}
|
||||
};
|
||||
|
||||
const unregisterRoute = (route) => {
|
||||
routes.update((rs) => rs.filter((r) => r !== route));
|
||||
};
|
||||
|
||||
let preserveScroll = false;
|
||||
|
||||
// This reactive statement will update all the Routes' path when
|
||||
// the basepath changes.
|
||||
$: {
|
||||
const { path: basepath } = $base;
|
||||
routes.update((rs) =>
|
||||
rs.map((r) =>
|
||||
Object.assign(r, { path: combinePaths(basepath, r._path) })
|
||||
)
|
||||
);
|
||||
}
|
||||
// This reactive statement will be run when the Router is created
|
||||
// when there are no Routes and then again the following tick, so it
|
||||
// will not find an active Route in SSR and in the browser it will only
|
||||
// pick an active Route after all Routes have been registered.
|
||||
$: {
|
||||
const bestMatch = pick($routes, $location.pathname);
|
||||
activeRoute.set(
|
||||
bestMatch ? { ...bestMatch, preserveScroll } : bestMatch
|
||||
);
|
||||
}
|
||||
|
||||
if (!locationContext) {
|
||||
// The topmost Router in the tree is responsible for updating
|
||||
// the location store and supplying it through context.
|
||||
onMount(() => {
|
||||
const unlisten = history.listen((event) => {
|
||||
preserveScroll = event.preserveScroll || false;
|
||||
location.set(event.location);
|
||||
});
|
||||
|
||||
return unlisten;
|
||||
});
|
||||
|
||||
setContext(LOCATION, location);
|
||||
}
|
||||
|
||||
setContext(ROUTER, {
|
||||
activeRoute,
|
||||
base,
|
||||
routerBase,
|
||||
registerRoute,
|
||||
unregisterRoute,
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if viewtransition}
|
||||
{#key $location.pathname}
|
||||
<div in:viewtransitionFn out:viewtransitionFn>
|
||||
<slot
|
||||
route={$activeRoute && $activeRoute.uri}
|
||||
location={$location}
|
||||
/>
|
||||
</div>
|
||||
{/key}
|
||||
{:else}
|
||||
<slot route={$activeRoute && $activeRoute.uri} location={$location} />
|
||||
{/if}
|
||||
87
vendor/svelte-routing/src/actions.js
vendored
Normal file
87
vendor/svelte-routing/src/actions.js
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
import { navigate } from "./history.js";
|
||||
import { hostMatches, shouldNavigate } from "./utils.js";
|
||||
|
||||
/**
|
||||
* A link action that can be added to <a href=""> tags rather
|
||||
* than using the <Link> component.
|
||||
*
|
||||
* Example:
|
||||
* ```html
|
||||
* <a href="/post/{postId}" use:link>{post.title}</a>
|
||||
* ```
|
||||
*/
|
||||
const link = (node) => {
|
||||
const onClick = (event) => {
|
||||
const anchor = event.currentTarget;
|
||||
|
||||
if (
|
||||
(anchor.target === "" || anchor.target === "_self") &&
|
||||
hostMatches(anchor) &&
|
||||
shouldNavigate(event)
|
||||
) {
|
||||
event.preventDefault();
|
||||
navigate(anchor.pathname + anchor.search, {
|
||||
replace: anchor.hasAttribute("replace"),
|
||||
preserveScroll: anchor.hasAttribute("preserveScroll"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
node.addEventListener("click", onClick);
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
node.removeEventListener("click", onClick);
|
||||
},
|
||||
};
|
||||
};
|
||||
/**
|
||||
* An action to be added at a root element of your application to
|
||||
* capture all relative links and push them onto the history stack.
|
||||
*
|
||||
* Example:
|
||||
* ```html
|
||||
* <div use:links>
|
||||
* <Router>
|
||||
* <Route path="/" component={Home} />
|
||||
* <Route path="/p/:projectId/:docId?" component={ProjectScreen} />
|
||||
* {#each projects as project}
|
||||
* <a href="/p/{project.id}">{project.title}</a>
|
||||
* {/each}
|
||||
* </Router>
|
||||
* </div>
|
||||
* ```
|
||||
*/
|
||||
const links = (node) => {
|
||||
const findClosest = (tagName, el) => {
|
||||
while (el && el.tagName !== tagName) el = el.parentNode;
|
||||
return el;
|
||||
};
|
||||
|
||||
const onClick = (event) => {
|
||||
const anchor = findClosest("A", event.target);
|
||||
if (
|
||||
anchor &&
|
||||
(anchor.target === "" || anchor.target === "_self") &&
|
||||
hostMatches(anchor) &&
|
||||
shouldNavigate(event) &&
|
||||
!anchor.hasAttribute("noroute")
|
||||
) {
|
||||
event.preventDefault();
|
||||
navigate(anchor.pathname + anchor.search, {
|
||||
replace: anchor.hasAttribute("replace"),
|
||||
preserveScroll: anchor.hasAttribute("preserveScroll"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
node.addEventListener("click", onClick);
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
node.removeEventListener("click", onClick);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export { link, links };
|
||||
9
vendor/svelte-routing/src/contexts.js
vendored
Normal file
9
vendor/svelte-routing/src/contexts.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { getContext } from "svelte";
|
||||
|
||||
export const LOCATION = {};
|
||||
export const ROUTER = {};
|
||||
export const HISTORY = {};
|
||||
|
||||
export const useLocation = () => getContext(LOCATION);
|
||||
export const useRouter = () => getContext(ROUTER);
|
||||
export const useHistory = () => getContext(HISTORY);
|
||||
109
vendor/svelte-routing/src/history.js
vendored
Normal file
109
vendor/svelte-routing/src/history.js
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Adapted from https://github.com/reach/router/blob/b60e6dd781d5d3a4bdaaf4de665649c0f6a7e78d/src/lib/history.js
|
||||
* https://github.com/reach/router/blob/master/LICENSE
|
||||
*/
|
||||
import { canUseDOM } from "./utils";
|
||||
|
||||
const getLocation = (source) => {
|
||||
return {
|
||||
...source.location,
|
||||
state: source.history.state,
|
||||
key: (source.history.state && source.history.state.key) || "initial",
|
||||
};
|
||||
};
|
||||
const createHistory = (source) => {
|
||||
const listeners = [];
|
||||
let location = getLocation(source);
|
||||
|
||||
return {
|
||||
get location() {
|
||||
return location;
|
||||
},
|
||||
|
||||
listen(listener) {
|
||||
listeners.push(listener);
|
||||
|
||||
const popstateListener = () => {
|
||||
location = getLocation(source);
|
||||
listener({ location, action: "POP" });
|
||||
};
|
||||
|
||||
source.addEventListener("popstate", popstateListener);
|
||||
|
||||
return () => {
|
||||
source.removeEventListener("popstate", popstateListener);
|
||||
const index = listeners.indexOf(listener);
|
||||
listeners.splice(index, 1);
|
||||
};
|
||||
},
|
||||
|
||||
navigate(
|
||||
to,
|
||||
{
|
||||
state,
|
||||
replace = false,
|
||||
preserveScroll = false,
|
||||
blurActiveElement = true,
|
||||
} = {}
|
||||
) {
|
||||
state = { ...state, key: Date.now() + "" };
|
||||
// try...catch iOS Safari limits to 100 pushState calls
|
||||
try {
|
||||
if (replace) source.history.replaceState(state, "", to);
|
||||
else source.history.pushState(state, "", to);
|
||||
} catch (e) {
|
||||
source.location[replace ? "replace" : "assign"](to);
|
||||
}
|
||||
location = getLocation(source);
|
||||
listeners.forEach((listener) =>
|
||||
listener({ location, action: "PUSH", preserveScroll })
|
||||
);
|
||||
if (typeof document !== "undefined")
|
||||
if (blurActiveElement) document.activeElement.blur();
|
||||
},
|
||||
};
|
||||
};
|
||||
// Stores history entries in memory for testing or other platforms like Native
|
||||
const createMemorySource = (initialPathname = "/") => {
|
||||
let index = 0;
|
||||
const stack = [{ pathname: initialPathname, search: "" }];
|
||||
const states = [];
|
||||
|
||||
return {
|
||||
get location() {
|
||||
return stack[index];
|
||||
},
|
||||
addEventListener(name, fn) {},
|
||||
removeEventListener(name, fn) {},
|
||||
history: {
|
||||
get entries() {
|
||||
return stack;
|
||||
},
|
||||
get index() {
|
||||
return index;
|
||||
},
|
||||
get state() {
|
||||
return states[index];
|
||||
},
|
||||
pushState(state, _, uri) {
|
||||
const [pathname, search = ""] = uri.split("?");
|
||||
index++;
|
||||
stack.push({ pathname, search });
|
||||
states.push(state);
|
||||
},
|
||||
replaceState(state, _, uri) {
|
||||
const [pathname, search = ""] = uri.split("?");
|
||||
stack[index] = { pathname, search };
|
||||
states[index] = state;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
// Global history uses window.history as the source if available,
|
||||
// otherwise a memory history
|
||||
const globalHistory = createHistory(
|
||||
canUseDOM() ? window : createMemorySource()
|
||||
);
|
||||
const { navigate } = globalHistory;
|
||||
|
||||
export { globalHistory, navigate, createHistory, createMemorySource };
|
||||
6
vendor/svelte-routing/src/index.js
vendored
Normal file
6
vendor/svelte-routing/src/index.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export { default as Link } from "./Link.svelte";
|
||||
export { default as Route } from "./Route.svelte";
|
||||
export { default as Router } from "./Router.svelte";
|
||||
export { link, links } from "./actions.js";
|
||||
export * from "./contexts.js";
|
||||
export { navigate } from "./history.js";
|
||||
278
vendor/svelte-routing/src/utils.js
vendored
Normal file
278
vendor/svelte-routing/src/utils.js
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* Adapted from https://github.com/reach/router/blob/b60e6dd781d5d3a4bdaaf4de665649c0f6a7e78d/src/lib/utils.js
|
||||
* https://github.com/reach/router/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
const PARAM = /^:(.+)/;
|
||||
const SEGMENT_POINTS = 4;
|
||||
const STATIC_POINTS = 3;
|
||||
const DYNAMIC_POINTS = 2;
|
||||
const SPLAT_PENALTY = 1;
|
||||
const ROOT_POINTS = 1;
|
||||
|
||||
/**
|
||||
* Split up the URI into segments delimited by `/`
|
||||
* Strip starting/ending `/`
|
||||
* @param {string} uri
|
||||
* @return {string[]}
|
||||
*/
|
||||
const segmentize = (uri) => uri.replace(/(^\/+|\/+$)/g, "").split("/");
|
||||
/**
|
||||
* Strip `str` of potential start and end `/`
|
||||
* @param {string} string
|
||||
* @return {string}
|
||||
*/
|
||||
const stripSlashes = (string) => string.replace(/(^\/+|\/+$)/g, "");
|
||||
/**
|
||||
* Score a route depending on how its individual segments look
|
||||
* @param {object} route
|
||||
* @param {number} index
|
||||
* @return {object}
|
||||
*/
|
||||
const rankRoute = (route, index) => {
|
||||
const score = route.default
|
||||
? 0
|
||||
: segmentize(route.path).reduce((score, segment) => {
|
||||
score += SEGMENT_POINTS;
|
||||
|
||||
if (segment === "") {
|
||||
score += ROOT_POINTS;
|
||||
} else if (PARAM.test(segment)) {
|
||||
score += DYNAMIC_POINTS;
|
||||
} else if (segment[0] === "*") {
|
||||
score -= SEGMENT_POINTS + SPLAT_PENALTY;
|
||||
} else {
|
||||
score += STATIC_POINTS;
|
||||
}
|
||||
|
||||
return score;
|
||||
}, 0);
|
||||
|
||||
return { route, score, index };
|
||||
};
|
||||
/**
|
||||
* Give a score to all routes and sort them on that
|
||||
* If two routes have the exact same score, we go by index instead
|
||||
* @param {object[]} routes
|
||||
* @return {object[]}
|
||||
*/
|
||||
const rankRoutes = (routes) =>
|
||||
routes
|
||||
.map(rankRoute)
|
||||
.sort((a, b) =>
|
||||
a.score < b.score ? 1 : a.score > b.score ? -1 : a.index - b.index
|
||||
);
|
||||
/**
|
||||
* Ranks and picks the best route to match. Each segment gets the highest
|
||||
* amount of points, then the type of segment gets an additional amount of
|
||||
* points where
|
||||
*
|
||||
* static > dynamic > splat > root
|
||||
*
|
||||
* This way we don't have to worry about the order of our routes, let the
|
||||
* computers do it.
|
||||
*
|
||||
* A route looks like this
|
||||
*
|
||||
* { path, default, value }
|
||||
*
|
||||
* And a returned match looks like:
|
||||
*
|
||||
* { route, params, uri }
|
||||
*
|
||||
* @param {object[]} routes
|
||||
* @param {string} uri
|
||||
* @return {?object}
|
||||
*/
|
||||
const pick = (routes, uri) => {
|
||||
let match;
|
||||
let default_;
|
||||
|
||||
const [uriPathname] = uri.split("?");
|
||||
const uriSegments = segmentize(uriPathname);
|
||||
const isRootUri = uriSegments[0] === "";
|
||||
const ranked = rankRoutes(routes);
|
||||
|
||||
for (let i = 0, l = ranked.length; i < l; i++) {
|
||||
const route = ranked[i].route;
|
||||
let missed = false;
|
||||
|
||||
if (route.default) {
|
||||
default_ = {
|
||||
route,
|
||||
params: {},
|
||||
uri,
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
const routeSegments = segmentize(route.path);
|
||||
const params = {};
|
||||
const max = Math.max(uriSegments.length, routeSegments.length);
|
||||
let index = 0;
|
||||
|
||||
for (; index < max; index++) {
|
||||
const routeSegment = routeSegments[index];
|
||||
const uriSegment = uriSegments[index];
|
||||
|
||||
if (routeSegment && routeSegment[0] === "*") {
|
||||
// Hit a splat, just grab the rest, and return a match
|
||||
// uri: /files/documents/work
|
||||
// route: /files/* or /files/*splatname
|
||||
const splatName =
|
||||
routeSegment === "*" ? "*" : routeSegment.slice(1);
|
||||
|
||||
params[splatName] = uriSegments
|
||||
.slice(index)
|
||||
.map(decodeURIComponent)
|
||||
.join("/");
|
||||
break;
|
||||
}
|
||||
|
||||
if (typeof uriSegment === "undefined") {
|
||||
// URI is shorter than the route, no match
|
||||
// uri: /users
|
||||
// route: /users/:userId
|
||||
missed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
const dynamicMatch = PARAM.exec(routeSegment);
|
||||
|
||||
if (dynamicMatch && !isRootUri) {
|
||||
const value = decodeURIComponent(uriSegment);
|
||||
params[dynamicMatch[1]] = value;
|
||||
} else if (routeSegment !== uriSegment) {
|
||||
// Current segments don't match, not dynamic, not splat, so no match
|
||||
// uri: /users/123/settings
|
||||
// route: /users/:id/profile
|
||||
missed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!missed) {
|
||||
match = {
|
||||
route,
|
||||
params,
|
||||
uri: "/" + uriSegments.slice(0, index).join("/"),
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return match || default_ || null;
|
||||
};
|
||||
/**
|
||||
* Add the query to the pathname if a query is given
|
||||
* @param {string} pathname
|
||||
* @param {string} [query]
|
||||
* @return {string}
|
||||
*/
|
||||
const addQuery = (pathname, query) => pathname + (query ? `?${query}` : "");
|
||||
/**
|
||||
* Resolve URIs as though every path is a directory, no files. Relative URIs
|
||||
* in the browser can feel awkward because not only can you be "in a directory",
|
||||
* you can be "at a file", too. For example:
|
||||
*
|
||||
* browserSpecResolve('foo', '/bar/') => /bar/foo
|
||||
* browserSpecResolve('foo', '/bar') => /foo
|
||||
*
|
||||
* But on the command line of a file system, it's not as complicated. You can't
|
||||
* `cd` from a file, only directories. This way, links have to know less about
|
||||
* their current path. To go deeper you can do this:
|
||||
*
|
||||
* <Link to="deeper"/>
|
||||
* // instead of
|
||||
* <Link to=`{${props.uri}/deeper}`/>
|
||||
*
|
||||
* Just like `cd`, if you want to go deeper from the command line, you do this:
|
||||
*
|
||||
* cd deeper
|
||||
* # not
|
||||
* cd $(pwd)/deeper
|
||||
*
|
||||
* By treating every path as a directory, linking to relative paths should
|
||||
* require less contextual information and (fingers crossed) be more intuitive.
|
||||
* @param {string} to
|
||||
* @param {string} base
|
||||
* @return {string}
|
||||
*/
|
||||
const resolve = (to, base) => {
|
||||
// /foo/bar, /baz/qux => /foo/bar
|
||||
if (to.startsWith("/")) return to;
|
||||
|
||||
const [toPathname, toQuery] = to.split("?");
|
||||
const [basePathname] = base.split("?");
|
||||
const toSegments = segmentize(toPathname);
|
||||
const baseSegments = segmentize(basePathname);
|
||||
|
||||
// ?a=b, /users?b=c => /users?a=b
|
||||
if (toSegments[0] === "") return addQuery(basePathname, toQuery);
|
||||
|
||||
// profile, /users/789 => /users/789/profile
|
||||
|
||||
if (!toSegments[0].startsWith(".")) {
|
||||
const pathname = baseSegments.concat(toSegments).join("/");
|
||||
return addQuery((basePathname === "/" ? "" : "/") + pathname, toQuery);
|
||||
}
|
||||
|
||||
// ./ , /users/123 => /users/123
|
||||
// ../ , /users/123 => /users
|
||||
// ../.. , /users/123 => /
|
||||
// ../../one, /a/b/c/d => /a/b/one
|
||||
// .././one , /a/b/c/d => /a/b/c/one
|
||||
const allSegments = baseSegments.concat(toSegments);
|
||||
const segments = [];
|
||||
|
||||
allSegments.forEach((segment) => {
|
||||
if (segment === "..") segments.pop();
|
||||
else if (segment !== ".") segments.push(segment);
|
||||
});
|
||||
|
||||
return addQuery("/" + segments.join("/"), toQuery);
|
||||
};
|
||||
/**
|
||||
* Combines the `basepath` and the `path` into one path.
|
||||
* @param {string} basepath
|
||||
* @param {string} path
|
||||
*/
|
||||
const combinePaths = (basepath, path) =>
|
||||
`${stripSlashes(
|
||||
path === "/"
|
||||
? basepath
|
||||
: `${stripSlashes(basepath)}/${stripSlashes(path)}`
|
||||
)}/`;
|
||||
/**
|
||||
* Decides whether a given `event` should result in a navigation or not.
|
||||
* @param {object} event
|
||||
*/
|
||||
const shouldNavigate = (event) =>
|
||||
!event.defaultPrevented &&
|
||||
event.button === 0 &&
|
||||
!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
|
||||
|
||||
// svelte seems to kill anchor.host value in ie11, so fall back to checking href
|
||||
const hostMatches = (anchor) => {
|
||||
const host = location.host;
|
||||
return (
|
||||
anchor.host === host ||
|
||||
anchor.href.indexOf(`https://${host}`) === 0 ||
|
||||
anchor.href.indexOf(`http://${host}`) === 0
|
||||
);
|
||||
};
|
||||
|
||||
const canUseDOM = () =>
|
||||
typeof window !== "undefined" &&
|
||||
"document" in window &&
|
||||
"location" in window;
|
||||
|
||||
export {
|
||||
stripSlashes,
|
||||
pick,
|
||||
resolve,
|
||||
combinePaths,
|
||||
shouldNavigate,
|
||||
hostMatches,
|
||||
canUseDOM,
|
||||
};
|
||||
24
vendor/svelte-routing/types/Link.d.ts
vendored
Normal file
24
vendor/svelte-routing/types/Link.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { SvelteComponent } from "svelte";
|
||||
import { HTMLAnchorAttributes } from "svelte/elements";
|
||||
import { RouteLocation } from "./Route";
|
||||
|
||||
type LinkProps = {
|
||||
to: string;
|
||||
replace?: boolean;
|
||||
preserveScroll?: boolean;
|
||||
state?: {
|
||||
[k in string | number]: unknown;
|
||||
};
|
||||
getProps?: (linkParams: GetPropsParams) => Record<string, any>;
|
||||
};
|
||||
|
||||
type GetPropsParams = {
|
||||
location: RouteLocation;
|
||||
href: string;
|
||||
isPartiallyCurrent: boolean;
|
||||
isCurrent: boolean;
|
||||
};
|
||||
|
||||
export class Link extends SvelteComponent<
|
||||
Omit<LinkProps & HTMLAnchorAttributes, "href">
|
||||
> {}
|
||||
37
vendor/svelte-routing/types/Route.d.ts
vendored
Normal file
37
vendor/svelte-routing/types/Route.d.ts
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import { SvelteComponent } from "svelte";
|
||||
|
||||
type AsyncSvelteComponent = () => Promise<{
|
||||
default: typeof SvelteComponent<any>;
|
||||
}>;
|
||||
|
||||
type RouteProps = {
|
||||
path?: string;
|
||||
component?: typeof SvelteComponent<any> | AsyncSvelteComponent;
|
||||
[additionalProp: string]: unknown;
|
||||
};
|
||||
|
||||
type RouteSlots = {
|
||||
default: {
|
||||
location: RouteLocation;
|
||||
params: RouteParams;
|
||||
};
|
||||
};
|
||||
|
||||
type RouteLocation = {
|
||||
pathname: string;
|
||||
search: string;
|
||||
hash?: string;
|
||||
state: {
|
||||
[k in string | number]: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
type RouteParams = {
|
||||
[param: string]: string;
|
||||
};
|
||||
|
||||
export class Route extends SvelteComponent<
|
||||
RouteProps,
|
||||
Record<string, any>,
|
||||
RouteSlots
|
||||
> {}
|
||||
20
vendor/svelte-routing/types/Router.d.ts
vendored
Normal file
20
vendor/svelte-routing/types/Router.d.ts
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { SvelteComponent } from "svelte";
|
||||
|
||||
type Viewtransition = {
|
||||
fn?: any;
|
||||
delay?: number;
|
||||
duration?: number;
|
||||
x?: number;
|
||||
y?: number;
|
||||
opacity?: number;
|
||||
easing?: any;
|
||||
css?: (t: number) => string;
|
||||
};
|
||||
|
||||
type RouterProps = {
|
||||
basepath?: string;
|
||||
url?: string;
|
||||
viewtransition?: (direction?: string) => Viewtransition;
|
||||
};
|
||||
|
||||
export class Router extends SvelteComponent<RouterProps> {}
|
||||
2
vendor/svelte-routing/types/actions.d.ts
vendored
Normal file
2
vendor/svelte-routing/types/actions.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export const link: (node: Element) => { destroy(): void };
|
||||
export const links: (node: Element) => { destroy(): void };
|
||||
38
vendor/svelte-routing/types/ambient.d.ts
vendored
Normal file
38
vendor/svelte-routing/types/ambient.d.ts
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
declare module "svelte-routing/src/history" {
|
||||
const getLocation: (
|
||||
source: typeof window
|
||||
) => Location & { state: any; key: string };
|
||||
|
||||
type Listener = (params: {
|
||||
location: ReturnType<typeof getLocation>;
|
||||
action: "POP" | "PUSH";
|
||||
}) => void;
|
||||
|
||||
export const createHistory: (source: typeof window) => {
|
||||
readonly location: ReturnType<typeof getLocation>;
|
||||
listen: (listener: Listener) => () => void;
|
||||
navigate: (
|
||||
to?: string | null,
|
||||
options?: { replace: boolean; preserveScroll: boolean; state: any }
|
||||
) => void;
|
||||
};
|
||||
|
||||
type StackItem = { pathname: string; search: string };
|
||||
|
||||
export const createMemorySource: (initialPathname?: string) => {
|
||||
readonly location: StackItem;
|
||||
// These functions seem to have no implimentation
|
||||
// addEventListener: typeof window.addEventListener
|
||||
// removeEventListener: typeof window.removeEventListener
|
||||
history: {
|
||||
readonly entries: StackItem[];
|
||||
readonly index: number;
|
||||
readonly state: any;
|
||||
pushState: (state: any, _: unknown, uri: string) => void;
|
||||
replaceState: (state: any, _: unknown, uri: string) => void;
|
||||
};
|
||||
};
|
||||
|
||||
export const globalHistory: ReturnType<typeof createHistory>;
|
||||
export const navigate: ReturnType<typeof createHistory>["navigate"];
|
||||
}
|
||||
11
vendor/svelte-routing/types/contexts.d.ts
vendored
Normal file
11
vendor/svelte-routing/types/contexts.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { readable } from "svelte/store";
|
||||
import { RouteLocation } from "./Route";
|
||||
import { RouterProps } from "./Router";
|
||||
|
||||
type LOCATION = RouteLocation;
|
||||
type ROUTER = RouterProps;
|
||||
type HISTORY = Record<string | number, any>;
|
||||
|
||||
export const useLocation: () => ReturnType<typeof readable<LOCATION>>;
|
||||
export const useRouter: () => ReturnType<typeof readable<ROUTER>>;
|
||||
export const useHistory: () => ReturnType<typeof readable<HISTORY>>;
|
||||
14
vendor/svelte-routing/types/functions.d.ts
vendored
Normal file
14
vendor/svelte-routing/types/functions.d.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
export const navigate: (
|
||||
to: string,
|
||||
{
|
||||
replace,
|
||||
state,
|
||||
preserveScroll,
|
||||
}?: {
|
||||
replace?: boolean;
|
||||
state?: {
|
||||
[k in string | number]: unknown;
|
||||
};
|
||||
preserveScroll?: boolean;
|
||||
}
|
||||
) => void;
|
||||
8
vendor/svelte-routing/types/index.d.ts
vendored
Normal file
8
vendor/svelte-routing/types/index.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/// <reference types="./ambient" />
|
||||
|
||||
export { Link } from "./Link";
|
||||
export { Route } from "./Route";
|
||||
export { Router } from "./Router";
|
||||
export { link, links } from "./actions";
|
||||
export * from "./contexts";
|
||||
export { navigate } from "./functions";
|
||||
Reference in New Issue
Block a user