Skip to content

Commit 7e37fbf

Browse files
committed
feat: initial release
0 parents  commit 7e37fbf

33 files changed

+17833
-0
lines changed

.editorconfig

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
indent_style = space
7+
indent_size = 2
8+
charset = utf-8
9+
trim_trailing_whitespace = true
10+
insert_final_newline = true

.eslintrc

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"plugins": [
3+
"prettier"
4+
],
5+
"parserOptions": {
6+
"project": [
7+
"tsconfig.json"
8+
]
9+
},
10+
"extends": [
11+
"prettier",
12+
"eslint-config-airbnb",
13+
"eslint-config-airbnb-typescript",
14+
"eslint-config-prettier"
15+
],
16+
"rules": {
17+
"prettier/prettier": [
18+
"error"
19+
],
20+
"no-cond-assign": "off",
21+
"no-plusplus": "off",
22+
"no-continue": "off",
23+
"no-param-reassign": "off",
24+
"import/prefer-default-export": "off",
25+
"react/react-in-jsx-scope": "off"
26+
}
27+
}

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
node_modules
2+
dist
3+
.vscode
4+
coverage
5+
.idea
6+
.DS_Store
7+
.cache
8+
.eslintcache
9+
yarn-error.log

.npmignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.DS_Store
3+
__test__

.prettierrc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "all",
4+
"singleQuote": true,
5+
"tabWidth": 2,
6+
"printWidth": 120
7+
}

BACKERS.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## Backers
2+
3+
Thank you so much for supporting us financially! 🙏🏻😎🥳👍
4+
5+
<table>
6+
<tbody>
7+
<tr>
8+
<td align="center">
9+
<img width="150" height="150"
10+
src="https://avatars2.githubusercontent.com/u/17221813?v=4&s=150">
11+
</br>
12+
<a href="https://github.com/jsdevtom">Tom</a>
13+
</td>
14+
</tr>
15+
<tbody>
16+
</table>

CODE_OF_CONDUCT.md

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as
6+
contributors and maintainers pledge to making participation in our project and
7+
our community a harassment-free experience for everyone, regardless of age, body
8+
size, disability, ethnicity, sex characteristics, gender identity and expression,
9+
level of experience, education, socio-economic status, nationality, personal
10+
appearance, race, religion, or sexual identity and orientation.
11+
12+
## Our Standards
13+
14+
Examples of behavior that contributes to creating a positive environment
15+
include:
16+
17+
* Using welcoming and inclusive language
18+
* Being respectful of differing viewpoints and experiences
19+
* Gracefully accepting constructive criticism
20+
* Focusing on what is best for the community
21+
* Showing empathy towards other community members
22+
23+
Examples of unacceptable behavior by participants include:
24+
25+
* The use of sexualized language or imagery and unwelcome sexual attention or
26+
advances
27+
* Trolling, insulting/derogatory comments, and personal or political attacks
28+
* Public or private harassment
29+
* Publishing others' private information, such as a physical or electronic
30+
address, without explicit permission
31+
* Other conduct which could reasonably be considered inappropriate in a
32+
professional setting
33+
34+
## Our Responsibilities
35+
36+
Project maintainers are responsible for clarifying the standards of acceptable
37+
behavior and are expected to take appropriate and fair corrective action in
38+
response to any instances of unacceptable behavior.
39+
40+
Project maintainers have the right and responsibility to remove, edit, or
41+
reject comments, commits, code, wiki edits, issues, and other contributions
42+
that are not aligned to this Code of Conduct, or to ban temporarily or
43+
permanently any contributor for other behaviors that they deem inappropriate,
44+
threatening, offensive, or harmful.
45+
46+
## Scope
47+
48+
This Code of Conduct applies both within project spaces and in public spaces
49+
when an individual is representing the project or its community. Examples of
50+
representing a project or community include using an official project e-mail
51+
address, posting via an official social media account, or acting as an appointed
52+
representative at an online or offline event. Representation of a project may be
53+
further defined and clarified by project maintainers.
54+
55+
## Enforcement
56+
57+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
58+
reported by contacting the project team at [email protected]. All
59+
complaints will be reviewed and investigated and will result in a response that
60+
is deemed necessary and appropriate to the circumstances. The project team is
61+
obligated to maintain confidentiality with regard to the reporter of an incident.
62+
Further details of specific enforcement policies may be posted separately.
63+
64+
Project maintainers who do not follow or enforce the Code of Conduct in good
65+
faith may face temporary or permanent repercussions as determined by other
66+
members of the project's leadership.
67+
68+
## Attribution
69+
70+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72+
73+
[homepage]: https://www.contributor-covenant.org
74+
75+
For answers to common questions about this code of conduct, see
76+
https://www.contributor-covenant.org/faq

CONTRIBUTORS.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## Maintainers
2+
3+
SpringType is brought to you by:
4+
5+
<table>
6+
<tbody>
7+
<tr>
8+
<td align="center">
9+
<img width="150" height="150"
10+
src="https://avatars3.githubusercontent.com/u/454817?v=4&s=150">
11+
</br>
12+
<a href="https://github.com/kyr0">Aron Homberg</a>
13+
</td>
14+
<td align="center">
15+
<img width="150" height="150"
16+
src="https://avatars.githubusercontent.com/u/45510?s=150&v=4">
17+
</br>
18+
<a href="https://github.com/PaulKinlan">Paul Kinlan</a>
19+
</td>
20+
</tr>
21+
<tbody>
22+
</table>
23+
24+
### Contributors
25+
26+
We'd like to thank you for your help to support this project:
27+
28+
- Tom ([jsdevtom](https://github.com/jsdevtom))

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 - 2021 SpringType
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<h1 align="center">SpringType: st-route</h1>
2+
3+
> Nano library for client-side DOM routing
4+
5+
[![Gitter](https://badges.gitter.im/springtype-official/springtype.svg)](https://gitter.im/springtype-official/springtype?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
6+
7+
<h2 align="center">Purpose</h2>
8+
9+
This is an exremely tiny, yet powerful library for HTML5 history API based DOM routing. `st-route` makes client-side page navigation dead simple.
10+
11+
<h2 align="center">Features</h2>
12+
13+
- ✅ Abstracts the HTML5 history API
14+
- ✅ Tiny: `391 bytes` (best, brotli) - `556 bytes` (worst, umd, gz)
15+
- ✅ Zero dependencies
16+
- ✅ First class TypeScript support
17+
- ✅ 100% Unit Test coverage
18+
- ✅ TestCafé smoke tests
19+
20+
<h2 align="center">How to</h2>
21+
22+
This is how using `st-route` looks like:
23+
24+
```tsx
25+
import { tsx, render, Ref } from 'springtype';
26+
import { $ } from 'st-query';
27+
import { route, RouterRequest } from '../../../dist';
28+
29+
const HomePage = () => (
30+
<div>
31+
HomePage
32+
<br />
33+
<a href="/blog">Go to BlogPage</a>
34+
</div>
35+
);
36+
const BlogPage = () => <div>BlogPage</div>;
37+
38+
const BlogArticlePage = ({ request }: { request: RouterRequest }) => (
39+
<div>
40+
Blog / show article:
41+
{request.params.slug}
42+
</div>
43+
);
44+
45+
const RouteList = () => {
46+
const containerRef: Ref = {};
47+
const nav = route();
48+
49+
nav.get('/', () => {
50+
containerRef.current = $(containerRef.current).replaceWith(<HomePage />);
51+
});
52+
53+
nav.get('/blog', () => {
54+
containerRef.current = $(containerRef.current).replaceWith(<BlogPage />);
55+
});
56+
57+
nav.get('/blog/article/:slug', (request: Request) => {
58+
containerRef.current = $(containerRef.current).replaceWith(<BlogArticlePage request={request} />);
59+
});
60+
61+
return <div ref={containerRef}>Loading...</div>;
62+
};
63+
render(<RouteList />, document.body);
64+
```
65+
66+
<h2 align="center">API</h2>
67+
68+
The following contract is made between the webapp and `st-router`:
69+
70+
```typescript
71+
export interface API {
72+
get(path: string, handler: RouteHandler): API;
73+
match(path: string): RouteRequest | false;
74+
getRouteRegistrations(): Array<RouteRegistration>;
75+
tokenizePath(path: string): TokenizedPath;
76+
}
77+
78+
// calling route() returns the API object like:
79+
// const nav = route();
80+
// nav.get('/foo')
81+
export route = () => API;
82+
```
83+
84+
<h2 align="center">Troubleshooting</h2>
85+
86+
⚠️ Please make sure that you have a http server in place that can handle `pushState` well (re-routes all `HTTP GET` requests back to the `index.html` file serving the JavaScript). Please read about "SPA / Single Page Application routing" if you have any further questions about this.
87+
88+
<h2 align="center">Backers</h2>
89+
90+
Thank you so much for supporting us financially! 🙏🏻😎🥳👍
91+
92+
<table>
93+
<tbody>
94+
<tr>
95+
<td align="center">
96+
<img width="150" height="150"
97+
src="https://avatars2.githubusercontent.com/u/17221813?v=4&s=150">
98+
</br>
99+
<a href="https://github.com/jsdevtom">Tom</a>
100+
</td>
101+
</tr>
102+
<tbody>
103+
</table>
104+
105+
<h2 align="center">Maintainers</h2>
106+
107+
`st-route` is brought to you by:
108+
109+
<table>
110+
<tbody>
111+
<tr>
112+
<td align="center">
113+
<img width="150" height="150"
114+
src="https://avatars3.githubusercontent.com/u/454817?v=4&s=150">
115+
</br>
116+
<a href="https://github.com/kyr0">Aron Homberg</a>
117+
</td>
118+
<td align="center">
119+
<img width="150" height="150"
120+
src="https://avatars.githubusercontent.com/u/45510?s=150&v=4">
121+
</br>
122+
<a href="https://github.com/PaulKinlan">Paul Kinlan</a>
123+
</td>
124+
</tr>
125+
<tbody>
126+
</table>
127+
128+
Original implementation of the routing logic is based on ideas of <a href="https://github.com/PaulKinlan/leviroutes" target="_blank">LeviRoutes</a> developed by Paul Kinlan about 10 years ago -- however, this is a TypeScript-based clean room re-implementation which improves the original code in a few aspects.
129+
130+
<h2 align="center">Contributing</h2>
131+
132+
Please help out to make this project even better and see your name added to the list of our
133+
[CONTRIBUTORS.md](./CONTRIBUTORS.md) :tada:

e2e/smoke/.babelrc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"presets": [
3+
[
4+
"env",
5+
{
6+
"targets": {
7+
"browsers": [
8+
"last 2 Chrome versions"
9+
]
10+
}
11+
}
12+
]
13+
]
14+
}

e2e/smoke/__e2e__/smoke.test.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Selector } from 'testcafe';
2+
3+
// eslint-disable-next-line
4+
fixture`Smoke test`.page`http://localhost:1234/`;
5+
6+
test('Shows the HomePage when user navigates to path /', async (t) => {
7+
await t.wait(20);
8+
await t.expect(Selector('div').textContent).eql('HomePageGo to BlogPage');
9+
});
10+
11+
test('Shows the BlogPage when user navigates to path /blog', async (t) => {
12+
await t.navigateTo('http://localhost:1234/blog');
13+
await t.wait(20);
14+
await t.expect(Selector('div').textContent).eql('BlogPage');
15+
});
16+
17+
test('Shows the BlogArticlePage when user navigates to path /blog/article/some-article', async (t) => {
18+
await t.navigateTo('http://localhost:1234/blog/article/some-article');
19+
await t.wait(20);
20+
await t.expect(Selector('div').textContent).eql('Blog / show article:some-article');
21+
});
22+
23+
test('Jumps to BlogPage when user follows a link to /blog', async (t) => {
24+
await t.navigateTo('http://localhost:1234/');
25+
await t.click(Selector('a'));
26+
await t.wait(20);
27+
await t.expect(Selector('div').textContent).eql('BlogPage');
28+
});

0 commit comments

Comments
 (0)