roxiness / routify Goto Github PK
View Code? Open in Web Editor NEWAutomated Svelte routes
Home Page: https://routify.dev
Automated Svelte routes
Home Page: https://routify.dev
Hi
I downloaded the starter template and changed package.json
to enable the code splitting:
"watch:routify": "routify --dynamic-imports",
This yields an error:
[routify] Watching C:\Gebruikers\Developer\Src\routify-starter\src\pages
(node:17644) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'component' of undefined
at C:\Gebruikers\Developer\Src\routify-starter\node_modules\@sveltech\routify\lib\services\_template.js:27:57
at Array.map (<anonymous>)
at C:\Gebruikers\Developer\Src\routify-starter\node_modules\@sveltech\routify\lib\services\_template.js:21:26
at Array.map (<anonymous>)
at template (C:\Gebruikers\Developer\Src\routify-starter\node_modules\@sveltech\routify\lib\services\_template.js:16:8)
at build (C:\Gebruikers\Developer\Src\routify-starter\node_modules\@sveltech\routify\lib\services\interface.js:30:25)
(node:17644) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:17644) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
What should I do to test the code splitting?
By the way, the config documentation shows duplicate shortcode flag -d
. One for debug --debug
and one for code splitting --dynamic-imports
. You may want to disambigue this?
Hi @jakobrosenberg I am interested in using this router. I see though that it has a devdependency on a rollup plugin , how does that impact usage with svelte webpack or parcel-bundler-svelte ?
In case some url is not hit by a file.
If you switch pages on a website, you would expect to end up at the top (scroll position 0). This is currently not the case, the scroll position remains.
After the first time you enter a page onMount always is fired twice.
Simple test scenario:
src/page/index.svelte (add link to /about)
src/page/about.svelte (add link to index and console.log something inside onMount)
go to your index and click /about link, then click /index link and now everytime you enter /about again onMount will be fired twice
I navigate to: /org/1234
It loads the _layout which is in org/[orgid] folder + the index.svelte. In the index it has availability of orgid while in _layout it hasn't.
I would expect it to be available to _layout's in the 'dynamic' folder??
I get this error: Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
It is a spa application, I have a few routes and a lot of components but this error makes me thing that they are not the problem.
rollup.config.js
import commonjs from "rollup-plugin-commonjs";
import livereload from "rollup-plugin-livereload";
import postcss from "rollup-plugin-postcss";
import resolve from "@rollup/plugin-node-resolve";
import { routify } from "@sveltech/routify";
import svelte from "rollup-plugin-svelte";
import { terser } from "rollup-plugin-terser";
const production = !process.env.ROLLUP_WATCH;
export default {
input: "src/main.js",
output: {
sourcemap: true,
format: "esm",
name: "app",
//file: "public/build/bundle.js"
dir: "public/build"
},
plugins: [
routify({ dynamicImports: true }),
postcss({
plugins: require("./postcss.config.js")(production),
extract: true
}),
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file — better for performance
emitCss: true,
css: css => {
css.write("public/build/bundle.css");
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration —
// consult the documentation for details:
// https://github.com/rollup/rollup-plugin-commonjs
resolve({
browser: true,
dedupe: importee =>
importee === "svelte" || importee.startsWith("svelte/")
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload("public"),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require("child_process").spawn("npm", ["run", "start", "--", "--dev"], {
stdio: ["ignore", "inherit", "inherit"],
shell: true
});
}
}
};
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Svelte app</title>
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="stylesheet" href="/global.css" />
<link rel="stylesheet" href="/build/main.css" />
<script type="module" defer src="/bundle/main.js"></script>
</head>
<body></body>
</html>
Hi I'm trying to follow some docs examples:
https://routify.now.sh/docs/authentication
and exactly on this line:
let show = $routifyContext.component.path === '/login'
I'm getting the error:
Error: 'routifyContext' is not exported by node_modules/@sveltech/routify/runtime/index.js
maybe it changed on latest version and we need to update the docs?
Best Regards.
Hi, I'm using version: ^1.0.1-8
and a _layout.svelte like this:
<script>
import { goto } from '@sveltech/routify'
import { user } from '../store.js'
if (user === null) {
$goto('/login')
}
</script>
{#if user !== null}
<h2 data-focus>Home yeah!</h2>
{/if}
However, I can see that it redirect into url as expected to /login but it does not re-rendering the /login page contents, so the result is a blank page. if I hit F5 is the only way to get /login page rendered
Any thought?
Regards.
I am using Routify as a router on my project https://bestof2019.johanronsse.be/
I used the active state example from https://routify.now.sh/docs/helpers .
Now, the problem was that my active state stayed stuck on the intro page, because the component was not refreshed.
I fixed it with afterUpdate
import { isActive, url } from '@sveltech/routify'
import { afterUpdate } from 'svelte';
let links = [];
function setup() {
links = [
['/index', 'Intro'],
['/albums', 'Albums'],
['/films', 'Films'],
['/games', 'Games'],
['/series', 'Series']
].map(([path, name]) => {
return {
name,
href: $url(path),
active: $isActive(path)
}
})
}
setup();
afterUpdate(() => {
setup();
});
Possibly this would be good as an addition/change to the docs?
With all the new features of the v1.4.x-beta, I think it might be time to move on to a new major release. 1.4 features listed below:
I have some thoughts and ideas outlined below. Nothing is set in stone and all feedback welcome.
Name: Routify
I never liked the name svelte-filerouter much. It was just a quick name for an ad hoc project. The project has since grown and I think it deserves a "proper" name now.
Home: github.com/grottolabs (or something more svelt'ish?)
Helpers:
Make the url helper context aware to support relational routes based on current file. Can this be done through import without adding extra boilerplate? If not, restrict the url so it's only accessible as a prop -This would also sort circular dependency warnings.
Page props
We currently have route
, routes
, url
, _routeOptions
, scoped
and components
"poluting" every page. Should we combine them all in one object, prefix them or do both?
"scoped" prop
I'm not sure how I feel about this one. Should page props be passed as any other prop instead? Can it be done programmatically? Route.svelte I'm looking at you.
Separate rollup/webpack plugins
#18
Does Rollup/Webpack/Parcel still serve a purpose for this project?
Custom routes
There's technically nothing in the way of being able to pass custom routes to . Would this be a good feature though?
Query parameters in route object
#5
Hash based routing
#22
Since the file-router maps resources to paths like a traditional router, I don't see much point in hash based routing. However, it would be a nice feature to have for those who prefer.
EDIT: Added hash based routing suggestion.
That's for it now. What do you think?
I enter a page at http://localhost:5000
I navigate with a <a href="/org/1234">
' in my base layout to a component.
When I use a <a href="structure">
to now go deeper in the hierarchy it strips the param (1234) from the resulting url. Is this normal behaviour? Hence I end up in: http://localhost:5000/org/structure in stead of http://localhost:5000/org/1234/structure
It would be useful to me to be able to see when the user is trying to leave the page.
Notice that when you click a link to another nav item on this Games page: https://bestof2019.johanronsse.be/games you will have to wait for the transition of the slider component to run before the page is left.
I would like to intercept that animation call and check whether you are leaving the page, and then in case you are leaving the page disable that “out” transition.
As far as I know, Routify doesn't have any option to capture this, is this correct?
Any other ideas on how to solve this would be helpful, if it can be worked around that is also useful.
Hi
Additional elements in App.svelte
do not seem to animate.
If I take the starter template and replace App.svelte
with the following:
<script>
import { Router } from "@sveltech/routify";
import { routes } from "@sveltech/routify/tmp/routes";
import { fade } from "svelte/transition";
</script>
<!-- src/App.svelte -->
<Router {routes} />
<div transition:fade={{ duration: 1500 }}>
This is not animating, but showing
</div>
Then the additional div is not animating, but showing.
I was trying this case for a cookie warning that should animate into the screen for the user, irrespective of the route the user enters the app. Either way, strange it shows, but not animates.
Animations work in other parts of the app (within the routes, so it seems).
pages/ <-- blank page
--> _layout.svelte
--> index.svelte
pages/[org] <-- blank page
--> _layout.svelte
--> index.svelte
pages/[org]/[group] <-- only deepest level is showing
--> _layout.svelte
--> index.svelte
I found that in order to install npm i -d @sveltech/routify@next
on my Mac I had to do a
npm i --no-bin-links @sveltech/routify@next
and manually link npm-cli.js to routify as I was getting this error with the wrong kinda slash for unix:
npm ERR! code ENOENT
npm ERR! syscall chmod
npm ERR! path /Users/me/repos/testapp/node_modules/@sveltech/routify/plugins\cli.js
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, chmod '/Users/me/repos/testapp/node_modules/@sveltech/routify/plugins\cli.js'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent
After that step I ended up doing a
dos2unix node_modules/@sveltech/routify/plugins/cli.js
because of this error
env: node\r: No such file or directory
Not sure if this would be in scope for this library (feel free to close if not) but it would be nice to have an option to use hash-based routing for SPAs.
Lets say you have the following files:
/pages/_fallback.svelte
/pages/[foo]/index.svelte
/pages/[foo]/_fallback.svelte
As I understand it these will map to the follow regex strings:
"^/"
"^/([^/]+)/index"
"^/([^/]+)/"
And here's what my intuition suggests about various input paths:
"/" => /pages/_fallback.svelte
"/bar" => /pages/[foo]/index.svelte
"/bar/baz" => /pages/[foo]/_fallback.svelte
So now what SHOULD happen if I delete /pages/[foo]/index.svelte
? My intuition would suggest that /pages/[foo]/_fallback.svelte
should be the match however currently it does not.
I am just curious what the intended mappings ought to be, I can open PR's to help fix bugs but I don't want to deviate from expected behavior.
maybe a feature?
I created a breadcrumb from a nested path. The breadrumb shows the different parts when route.params.XXX is present. When a deeper path is visited, and navigating back to a less deep path, the navigation is ok but the breadcrumb also shows the deeper path as route rembered this value.
<a href="#jump">Jump</a>
<div style="padding-bottom: 2000px"></div>
<div id="jump">Jump</div>
Clicking the a
tag will not snap the window to the div
with the id.
But reloading while the hash is in the url will snap.
What does the run-p
command refer to? I was trying to use this router but got stuck on the installation. First on having to install sirv
(should it not be a devDependency?) and then on
> run-p watch:routify watch:rollup
sh: run-p: command not found
Does this refer to this project? https://github.com/mysticatea/npm-run-all
@jakobrosenberg - It looks like you have some local setup that I do not have.
rollup.config.js
fileRouter({
appFile: './src/app/Hello.svelte',
pages: './src/routes'
}),
got:
Error: Could not resolve './src/pages/index.svelte' from generatedRoutes.js`
seems it hardcoded at /src/files-to-routes.js
Apologies in advance if I am asking at the wrong place.
I was planning to try svelte+sapper for my new app(s). However, I'd like to use same codebase for both web app and Cordova based app for the same project.
Is this something supported by Sapper.js itself or I have to use a project like routify
to make use of the same codebase for SSR and Cordova app?
Thanks for any help in advance
Error when using Routify on a templated project, it always errors out when trying to create the pages
directory that already exists in my src directory
If I comment the line out that tries to make it in /lib/services/monitor.js:20:6
, everything works fine. I assume it should gracefully fail, but why would it not for me?
routify
fs.js:885
return binding.mkdir(pathModule._makeLong(path),
^
Error: EEXIST: file already exists, mkdir '/home/j/code/tmp/newappy/src/pages'
at Object.fs.mkdirSync (fs.js:885:18)
at monitor (/home/j/code/tmp/newappy/node_modules/@sveltech/routify/lib/services/monitor.js:20:6)
at start (/home/j/code/tmp/newappy/node_modules/@sveltech/routify/lib/services/interface.js:34:34)
at Object.<anonymous> (/home/j/code/tmp/newappy/node_modules/@sveltech/routify/plugins/cli.js:25:1)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Function.Module.runMain (module.js:694:10)
You get this console output when you run a production build with 1.0.1-9:
src/main.js → public/build/bundle.js...
(!) Plugin svelte: Empty block
node_modules/@sveltech/routify/runtime/Route.svelte
35: </script>
36:
37: {#await layout.component()}
^
38: {:then component}
39: <svelte:component
@jakobrosenberg following the instructions here https://routify.now.sh/docs/codesplitting and using the starter template, i am only able to hit 404 (_fallback.svelte) page and cannot get the links to work. I might be doing something wrong i cant say , my rollup.config file is
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import {routify} from '@sveltech/routify'
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'esm',
name: 'app',
dir: 'public/build/bundle'
},
plugins: [
routify({ dynamicImports: true }),
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file — better for performance
css: css => {
css.write('public/build/bundle.css');
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration —
// consult the documentation for details:
// https://github.com/rollup/rollup-plugin-commonjs
resolve({
browser: true,
dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/'),
mainFields: ['main', 'module']
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}
and index.html is
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
</head>
<script type="module" defer src='/build/bundle/main.js'></script>
<body>
</body>
</html>
Can you have a look please. Thanks a lot
In the svelte-filerouter we got the reactive route property. Is there also something to use in routify??
when using $goto my page refreshes, is using a the preferred way to do a local redirect?
For whatever reason, only the first component passed to the Router is being displayed. I'm a little confused because obviously this isn't a problem with the example site you have up.
For example, the Router
receives the [Layout, Index]
components but then the internal Route
component used by Router
only renders Layout
.
I did a bit of investigating but I'm really not sure what's happening.
Inside of Route.svelte
was the only potential problem area I found
The component
prop seems to only ever be the first component in the components
array and never changes.
If I get rid of the component
prop and instead add the following the the markup it seems to render all components properly:
{#each components as component}
<svelte:component this={component} {...props} let:scoped={layoutScope}>
{#if components.length && demandObject(layoutScope)}
<svelte:self {...childProps} {layoutScope} />
{/if}
</svelte:component>
{/each}
Hi
not an issue, but banging my head getting this done:
import { goto } from '@sveltech/routify'
function navigate(url) {
console.log("Navigate url", url);
$goto("./some/where/else");
}
Giving error: index.mjs:89 Uncaught TypeError: Cannot read property 'subscribe' of undefined
Where the location of the error (and callstack) does not link to the actual $goto statement which gives the error (unless commented out).
What am I doing wrong (the goto statements in the example are working).
Hope you can help.
Tom
Not sure if there's a redirect feature or way to programmatically navigate to another route.
https://svelte.dev/tutorial/named-slots
src/routes/app/_reset.svelte
<div>
<div>
<slot name=card_header_title>
...
</div>
<div>
<slot name=card_body_title>
...
<slot name=card_body_content>
</div>
</div>
src/routes/app/signin.svelte
<small slot="card_header_title">Sign in with</small>
<small slot="card_body_title">Or sign in with credentials</small>
<form slot="card_body_content">
...
</form>
src/routes/app/signup.svelte
<small slot="card_header_title">Sign up with</small>
<small slot="card_body_title">Or sign up with credentials</small>
<form slot="card_body_content">
...
</form>
output
bundles src/main.js → public/build/bundle.js...
[!] (plugin svelte) ValidationError: Element with a slot='...' attribute must be a descendant of a component or custom element
src/routes/app/signin.svelte
10: <small slot="card_header_title">Or sign in with credentials</small>-->
11:
12: <form slot="card_body_content"
^
When upgrading from 1.0.1-20 to 1.0.1-27
Error:
Uncaught ReferenceError: routes is not defined
<!-- src/App.svelte -->
<script>
import { Router } from "@sveltech/routify";
import { routes } from "@sveltech/routify/tmp/routes";
</script>
<Router {routes} />
Code is exactly like in the reference template: https://github.com/sveltech/routify-starter/blob/master/src/App.svelte
Did the implementation logic change?
I tried a simple project where one would have 4 links that would lead to 4 tabs.
App.svelte needs the following content
<script>
import { Router } from "@sveltech/routify";
import { routes } from "@sveltech/routify/tmp/routes";
</script>
<Router {routes} />
Then, every route should be .svelte file in pages; with a possibility of inheriting a global layout (_layout.svelte
) and a specific template for the 404 (_fallback.svelte
).
Now, be careful, because the scripts
in package.json also need to be updated:
Use this if you use rollup:
"scripts": {
"build": "rollup -c",
"dev": "run-p watch:routify watch:rollup",
"watch:rollup": "rollup -c -w",
"watch:routify": "routify",
"start": "sirv public --single"
},
Use this for webpack:
"build": "cross-env NODE_ENV=production webpack",
"dev": "run-p watch:routify watch:webpack",
"watch:webpack": "webpack-dev-server --content-base public",
"watch:routify": "routify"
},
You can find my project at https://github.com/Wolfr/routify-tabs .
There's no issue with it, I wanted to make an issue, but then I solved the problem myself.
Just wanted to show some activity ;) and appreciation for building a file-based router.
When I was on 1.0.1-15 I was having an issue with isActive returning true if the current path ended with something that matched the test, eg .../.../index returned true as did .../index at the same time.
This can be seen at this preserved container:
https://frontend-debug-avzcrpvnta-uc.a.run.app/cars
and this commit:
https://github.com/ptone/firerest-demo/tree/4cd2d8c947892f3b81931192d9b04e62163835f3
HOWEVER, when going back to that commit and deleting package-lock and node_modules and re-installing, I can't reproduce this :(
With this commit
ptone/firerest-demo@e5cd4e4
I updated to v23
And I first saw the "null" behavior
(but note the caveat above about being unable to revert and reproduce the "simultaneous active" issue)
The current nav component:
https://github.com/ptone/firerest-demo/blob/16e85cd4eb88238df211c5b7ba64090b38bda78c/webapp/src/pages/_components/AppNav.svelte
It would be useful to be able to match a URL and adjust something based on the current URL. This could be useful to switch layouts in a centralized _layout.svelte
:
Example code:
<script>
import { currentPageUrl } from '@sveltech/routify' // Pseudo code, function does not exist!
</script>
{#if currentPageUrl.match(/intro/)}
<!-- Render special layout -->
{:else}
<!-- Render standard layout -->
{/if}
How would I test for page URLs with the current implementation?
I am interested in assisting with this if it's something you'd like to do, please let me know @jakobrosenberg
would it be nice to have the queryparameters in the route object similarly to parameters?
/:path1/ --> /hello/?name=world
route.parameters.path1 = hello
route.queryparameters.name = world
TypeError: regexUrl.match(...) is nullnavigator.js:82:13
urlToRoute navigator.js:82
updatePage navigator.js:24
instance$1 Router.svelte:14
init index.mjs:1350
Router bundle.js:1394
create_fragment$8 bundle.js:2797
init index.mjs:1364
App bundle.js:2839
app main.js:3
bundle.js:2856
--> would expect it to hit the fallback?
This may just be a docs issue, but I got stuck for a while in trying to use the helpers from a component that wasn't a page.
I am using material, and have a nav drawer component used in my app.svelte
I can use the helpers from a page, or component reference from a page, but not from a component directly referenced from app.svelte - I get a Uncaught TypeError: Cannot read property 'subscribe' of undefined
Do we have any lifecycle hooks at all for authn / authz?
I'm trying to import the params
helper util but it doesn't seem to be working
Error: 'params' is not exported by node_modules/@sveltech/routify/runtime/index.js
I'm thinking about adding an option for page/layout configurations inside the respective component files.
Example
src/pages/admin/_layout.svelte
<!--ROUTIFY:{"cache": {"order": 1, "bundle": true}}-->
The idea for precaching so far is:
Order: The order in which to precache files. Leave empty for no precaching.
Bundle: Bundle self and nested files in one file.
Preload: Don't do code splitting on this file/folder.
Recursive: Apply precache settings to siblings and nested files/dirs. (Only available in layout and reset files). Can be overwritten further down the tree if needed.
Proximity: Precache if there's a link showing for this page.
Other options:
Name: Name the page. (Ie. name the page 'crud' and navigate to it with $url('crud')
)
Reset: Same as _reset.svelte. Simplifies resets in many scenarios.
Catchall/Fallback: Same as fallback. Simplifies fallback in many scenarios.
If I link to a (sub)route on a deployed site,
https://bestof2019.johanronsse.be/series
I will get a 404.
However, if I go from https://bestof2019.johanronsse.be/ to /series, it works.
Does this have to do with sirv
?
Should I somehow redirect every request to index.html? Any suggestions on how to this? This might not have much to do with Routify but maybe how SPA's should work in general.
Feel free to close if you feel this is not relevant to Routify.
If you try to import { url } from 'svelte-filerouter'; inside of any sub component of a routed component you get circular dependency warnings due to the way the generated route file works. This makes building components like difficult to do presently. I am filing this issue because honestly I am not sure what the best approach ought to be to avoid this in a clean way.
Sidenote: Awesome project so far!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.