VSCode Extension to generate a router based on a file structure and returning the correct nested layouts.
There can be optional loader function to return data to the component before the build is done.
You can check out the examples for more details.
Inspired by https://remix.run
- File based routing (with regex)
- Nested layouts
- Works on https://vscode.dev
- Flutter (.dart)
- Lit (.js, .ts)
- React (.tsx, .jsx)
- JSON (.json)
Generate JSON for Routes
This will generate a json file at the route containing all the metadata found after crawling the routes
directory.
{
"routes": {
"/projects/:id": {
"hasLoader": true,
"name": "ProjectDetails",
"route": "/projects/:id",
"args": ["id"],
"ext": "tsx",
"alias": "route1",
"relativePath": "routes/projects/:id",
"implicitIndex": false,
"parentRoute": "/projects"
},
"/projects/": {
"hasLoader": true,
"name": "ProjectList",
"route": "/projects/",
"args": [],
"ext": "tsx",
"alias": "route2",
"relativePath": "routes/projects/index",
"parentRoute": "/projects"
},
"/projects": {
"hasLoader": false,
"name": "ProjectBase",
"route": "/projects",
"args": [],
"ext": "tsx",
"alias": "route3",
"relativePath": "routes/projects",
"implicitIndex": true,
"parentRoute": ""
},
"/": {
"hasLoader": false,
"name": "Home",
"route": "/",
"args": [],
"ext": "tsx",
"alias": "route0",
"relativePath": "routes/index",
"parentRoute": ""
},
"": {
"hasLoader": false,
"name": "Root",
"route": "",
"args": [],
"ext": "tsx",
"alias": "route4",
"relativePath": "routes/root"
}
}
}
Generate Lit Router
Generates a router that can be used both server side and browser side.
@customElement("router-outlet")
export class RouterOutlet extends LitElement {
router = createRouter(this);
override render() {
return this.router.outlet();
}
}
Also generates a Lit web component that can consume the generated router and listen for hash changes.
<body>
<router-outlet> </router-outlet>
<script type="module" src="/src/router.ts"></script>
</body>
Generate Flutter Router
Generates a Flutter MaterialApp with a router using Navigator 2.0 and will listen for hash changes and return the correct layout for the route.
import 'package:flutter/material.dart';
import 'router.dart';
void main() {
runApp(MaterialApp.router(
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.system,
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
routerDelegate: router.routerDelegate,
routeInformationParser: router.routeInformationParser,
));
}
Create a widget with the exact properties in the url params and a child if you nest the content in a route:
import 'package:flutter/material.dart';
class AccountPage extends StatelessWidget {
const AccountPage({
Key? key,
required this.id,
}) : super(key: key);
final String id;
@override
Widget build(BuildContext context) {
return Center(
child: Text('ID: $id'),
);
}
}
To update the route in a widget just dispatch the following:
RoutingRequest('ROUTE_HERE').dispatch(context)
Generate React Router
Generates a async React component that can be used to render a layout based on the url.
You can import the generated router and run it at the top level index.js:
import * as ReactDOM from "react-dom";
import App from "./router";
const root = document.getElementById("root");
async function loadApp() {
const AppRoot = await App();
ReactDOM.render(AppRoot, root);
}
window.addEventListener("hashchange", () => {
loadApp();
});
loadApp();
You can define a layout and an optional loader for a given page:
import * as React from "react";
export function loader(route: string, args: { [key: string]: any }) {
const id = args["id"];
return {
id: `${id}`,
name: `Project ${id}`,
};
}
export default function ProjectDetails({
data,
children,
}: {
id: string,
data: Project,
children?: React.ReactNode,
}) {
const project = data;
return (
<div>
<h3>{project.name}</h3>
{children}
</div>
);
}
interface Project {
id: string;
name: string;
}
To build with nested layouts you can use the children from the props to pass down the tree:
import * as React from "react";
import Header from "../components/Header";
export default function ProjectBase({
children,
}: {
children?: React.ReactNode,
}) {
return (
<div>
<Header title="Projects" />
<section
style={{
padding: "1rem",
}}
>
{children}
</section>
</div>
);
}