From 77b584b6fb28128a3e62fb32a1135a4848e41c2f Mon Sep 17 00:00:00 2001
From: liujiayii
Date: Thu, 14 Nov 2024 09:38:57 +0800
Subject: [PATCH 1/2] feat: fix types
---
.devcontainer/Dockerfile | 16 -
.devcontainer/devcontainer.json | 31 -
LICENSE | 2 +-
README.en.md | 632 +++++++++++++++++
README.md | 644 +-----------------
.../react.d.ts => client-react.d.ts | 0
.../solid.d.ts => client-solid.d.ts | 0
virtual-package/vue.d.ts => client-vue.d.ts | 0
examples/react-rsbuild/env.d.ts | 1 +
examples/react/env.d.ts | 1 +
examples/remix-style/vite.config.ts | 4 +-
examples/vue-rsbuild/.gitignore | 13 +
examples/vue-rsbuild/package.json | 20 +
examples/vue-rsbuild/rsbuild.config.ts | 36 +
examples/vue-rsbuild/src/App.vue | 3 +
.../vue-rsbuild/src/admin/pages/index.vue | 22 +
examples/vue-rsbuild/src/env.d.ts | 10 +
.../src/features/admin/pages/admin.vue | 12 +
.../features/dashboard/pages/dashboard.vue | 12 +
.../src/features/dashboard/pages/welcome.vue | 12 +
examples/vue-rsbuild/src/index.css | 0
examples/vue-rsbuild/src/index.ts | 25 +
examples/vue-rsbuild/src/pages/[...all].vue | 3 +
examples/vue-rsbuild/src/pages/[sensor].vue | 4 +
.../src/pages/[sensor]/current.vue | 3 +
.../vue-rsbuild/src/pages/__test__/index.vue | 3 +
examples/vue-rsbuild/src/pages/about.vue | 11 +
examples/vue-rsbuild/src/pages/about/[id].vue | 26 +
.../vue-rsbuild/src/pages/about/[id]/more.vue | 5 +
.../src/pages/about/[id]/nested.vue | 5 +
.../vue-rsbuild/src/pages/about/index.vue | 8 +
examples/vue-rsbuild/src/pages/blog/[id].vue | 23 +
examples/vue-rsbuild/src/pages/blog/index.vue | 14 +
.../src/pages/blog/today/[...all].vue | 3 +
.../src/pages/blog/today/index.vue | 5 +
examples/vue-rsbuild/src/pages/components.vue | 8 +
examples/vue-rsbuild/src/pages/index.vue | 38 ++
examples/vue-rsbuild/src/pages/jsx.jsx | 18 +
examples/vue-rsbuild/src/pages/markdown.md | 1 +
examples/vue-rsbuild/tsconfig.json | 18 +
examples/vue/env.d.ts | 1 +
examples/vue/src/main.ts | 2 +-
examples/vue/vite.config.ts | 11 +-
package.json | 12 +-
pnpm-lock.yaml | 59 ++
src/core/context.ts | 2 +-
src/core/index.ts | 87 ---
src/core/resolvers/react.ts | 2 +-
src/core/resolvers/solid.ts | 2 +-
src/core/resolvers/vue.ts | 2 +-
src/core/types.ts | 30 +-
src/index.ts | 4 +-
52 files changed, 1111 insertions(+), 795 deletions(-)
delete mode 100644 .devcontainer/Dockerfile
delete mode 100644 .devcontainer/devcontainer.json
create mode 100644 README.en.md
rename virtual-package/react.d.ts => client-react.d.ts (100%)
rename virtual-package/solid.d.ts => client-solid.d.ts (100%)
rename virtual-package/vue.d.ts => client-vue.d.ts (100%)
create mode 100644 examples/react-rsbuild/env.d.ts
create mode 100644 examples/react/env.d.ts
create mode 100644 examples/vue-rsbuild/.gitignore
create mode 100644 examples/vue-rsbuild/package.json
create mode 100644 examples/vue-rsbuild/rsbuild.config.ts
create mode 100644 examples/vue-rsbuild/src/App.vue
create mode 100644 examples/vue-rsbuild/src/admin/pages/index.vue
create mode 100644 examples/vue-rsbuild/src/env.d.ts
create mode 100644 examples/vue-rsbuild/src/features/admin/pages/admin.vue
create mode 100644 examples/vue-rsbuild/src/features/dashboard/pages/dashboard.vue
create mode 100644 examples/vue-rsbuild/src/features/dashboard/pages/welcome.vue
create mode 100644 examples/vue-rsbuild/src/index.css
create mode 100644 examples/vue-rsbuild/src/index.ts
create mode 100644 examples/vue-rsbuild/src/pages/[...all].vue
create mode 100644 examples/vue-rsbuild/src/pages/[sensor].vue
create mode 100644 examples/vue-rsbuild/src/pages/[sensor]/current.vue
create mode 100644 examples/vue-rsbuild/src/pages/__test__/index.vue
create mode 100644 examples/vue-rsbuild/src/pages/about.vue
create mode 100644 examples/vue-rsbuild/src/pages/about/[id].vue
create mode 100644 examples/vue-rsbuild/src/pages/about/[id]/more.vue
create mode 100644 examples/vue-rsbuild/src/pages/about/[id]/nested.vue
create mode 100644 examples/vue-rsbuild/src/pages/about/index.vue
create mode 100644 examples/vue-rsbuild/src/pages/blog/[id].vue
create mode 100644 examples/vue-rsbuild/src/pages/blog/index.vue
create mode 100644 examples/vue-rsbuild/src/pages/blog/today/[...all].vue
create mode 100644 examples/vue-rsbuild/src/pages/blog/today/index.vue
create mode 100644 examples/vue-rsbuild/src/pages/components.vue
create mode 100644 examples/vue-rsbuild/src/pages/index.vue
create mode 100644 examples/vue-rsbuild/src/pages/jsx.jsx
create mode 100644 examples/vue-rsbuild/src/pages/markdown.md
create mode 100644 examples/vue-rsbuild/tsconfig.json
create mode 100644 examples/vue/env.d.ts
delete mode 100644 src/core/index.ts
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
deleted file mode 100644
index 44dfd57..0000000
--- a/.devcontainer/Dockerfile
+++ /dev/null
@@ -1,16 +0,0 @@
-# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.208.0/containers/javascript-node/.devcontainer/base.Dockerfile
-
-# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 16, 14, 12, 16-bullseye, 14-bullseye, 12-bullseye, 16-buster, 14-buster, 12-buster
-ARG VARIANT="20-bullseye"
-FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
-
-# [Optional] Uncomment this section to install additional OS packages.
-# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
-# && apt-get -y install --no-install-recommends
-
-# [Optional] Uncomment if you want to install an additional version of node using nvm
-# ARG EXTRA_NODE_VERSION=10
-# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
-
-# [Optional] Uncomment if you want to install more global node modules
-RUN su node -c "npm install -g pnpm @antfu/ni"
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
deleted file mode 100644
index fecc0ed..0000000
--- a/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,31 +0,0 @@
-// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
-// https://github.com/microsoft/vscode-dev-containers/tree/v0.208.0/containers/javascript-node
-{
- "name": "Node.js",
- "build": {
- "dockerfile": "Dockerfile",
- // Update 'VARIANT' to pick a Node version: 16, 14, 12.
- // Append -bullseye or -buster to pin to an OS version.
- // Use -bullseye variants on local arm64/Apple Silicon.
- "args": { "VARIANT": "20-bullseye" }
- },
-
- "customizations": {
- "vscode": {
- "settings": {},
- // Add the IDs of extensions you want installed when the container is created.
- "extensions": [
- "dbaeumer.vscode-eslint"
- ]
- }
- },
-
- // Use 'forwardPorts' to make a list of ports inside the container available locally.
- // "forwardPorts": [],
-
- // Use 'postCreateCommand' to run commands after the container is created.
- "postCreateCommand": "pnpm install",
-
- // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
- "remoteUser": "node"
-}
diff --git a/LICENSE b/LICENSE
index 0dedc01..e2b352b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2021 hannoeru
+Copyright (c) 2021 liujiayii
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.en.md b/README.en.md
new file mode 100644
index 0000000..a96aaee
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,632 @@
+# unplugin-convention-routes
+
+[![npm version](https://badgen.net/npm/v/unplugin-convention-routes)](https://www.npmjs.com/package/unplugin-convention-routes)
+[![monthly downloads](https://badgen.net/npm/dm/unplugin-convention-routes)](https://www.npmjs.com/package/unplugin-convention-routes)
+[![types](https://badgen.net/npm/types/unplugin-convention-routes)](https://github.com/liujiayii/unplugin-convention-routes/blob/main/src/types.ts)
+[![license](https://badgen.net/npm/license/unplugin-convention-routes)](https://github.com/liujiayii/unplugin-convention-routes/blob/main/LICENSE)
+
+> File system based routing for Vue 3 / React / Solid applications using
+> [Vite](https://github.com/vitejs/vite)
+
+## Getting Started
+
+### Vue
+
+**๐จImportant Notes๐จ**
+
+We recommend that Vue users use [unplugin-vue-router](https://github.com/posva/unplugin-vue-router) instead of this plugin.
+
+[unplugin-vue-router](https://github.com/posva/unplugin-vue-router) is a unplugin library created by [@posva](https://github.com/posva), same auther as vue-router. It provide almost same feature as [unplugin-convention-routes](https://github.com/liujiayii/unplugin-convention-routes) but better intergration with vue-router, include some cool feature like auto generate route types base on your route files to provide autocomplete for vue-router.
+
+#### Install:
+
+```bash
+npm install -D unplugin-convention-routes
+npm install vue-router
+```
+
+### React
+
+> since v0.19.0 we only support react-router v6, if you are using react-router v5 use v0.18.2.
+
+#### Install:
+
+```bash
+npm install -D unplugin-convention-routes
+npm install react-router react-router-dom
+```
+
+### Solid
+
+#### Install:
+
+```bash
+npm install -D unplugin-convention-routes
+npm install @solidjs/router
+```
+
+### Vite config
+
+Add to your `vite.config.js`:
+
+```js
+import Pages from 'unplugin-convention-routes'
+
+export default {
+ plugins: [
+ // ...
+ Pages(),
+ ],
+}
+```
+
+## Overview
+
+By default a page is a Vue component exported from a `.vue` or `.js` file in the
+`src/pages` directory.
+
+You can access the generated routes by importing the `~pages`
+module in your application.
+
+### Vue
+
+```ts
+import routes from '~pages'
+import { createRouter } from 'vue-router'
+
+const router = createRouter({
+ // ...
+ routes,
+})
+```
+
+**Type**
+
+```ts
+// vite-env.d.ts
+///
+```
+
+### React
+
+**experimental**
+
+```tsx
+import routes from '~react-pages'
+import { StrictMode, Suspense } from 'react'
+import { createRoot } from 'react-dom/client'
+
+import {
+ BrowserRouter,
+ useRoutes,
+} from 'react-router-dom'
+
+function App() {
+ return (
+ Loading...
}>
+ {useRoutes(routes)}
+
+ )
+}
+
+const app = createRoot(document.getElementById('root')!)
+
+app.render(
+
+
+
+
+ ,
+)
+```
+
+**Type**
+
+```ts
+// vite-env.d.ts
+///
+```
+
+### Solid
+
+**experimental**
+
+```tsx
+import { Router, useRoutes } from '@solidjs/router'
+import routes from '~solid-pages'
+import { render } from 'solid-js/web'
+
+render(
+ () => {
+ const Routes = useRoutes(routes)
+ return (
+
+
+
+ )
+ },
+ document.getElementById('root') as HTMLElement,
+)
+```
+
+**Type**
+
+```ts
+// vite-env.d.ts
+///
+```
+
+## Configuration
+
+To use custom configuration, pass your options to Pages when instantiating the
+plugin:
+
+```js
+// vite.config.js
+import Pages from 'unplugin-convention-routes'
+
+export default {
+ plugins: [
+ Pages({
+ dirs: 'src/views',
+ }),
+ ],
+}
+```
+
+### dirs
+
+- **Type:** `string | (string | PageOptions)[]`
+- **Default:** `'src/pages'`
+
+Paths to the pages directory. Supports globs.
+
+Can be:
+
+- single path: routes point to `/`
+- array of paths: all routes in the paths point to `/`
+- array of `PageOptions`, Check below ๐
+
+```ts
+interface PageOptions {
+ /**
+ * Page base directory.
+ * @default 'src/pages'
+ */
+ dir: string
+ /**
+ * Page base route.
+ */
+ baseRoute: string
+ /**
+ * Page file pattern.
+ * @example `**\/*.page.vue`
+ */
+ filePattern?: string
+}
+```
+
+Specifying a glob or an array of `PageOptions` allow you to use multiple
+pages folder, and specify the base route to append to the path and the route
+name.
+
+Additionally, you can specify a `filePattern` to filter the files that will be used as pages.
+
+#### Example
+
+Folder structure
+
+```bash
+src/
+ โโโ features/
+ โ โโโ dashboard/
+ โ โโโ code/
+ โ โโโ components/
+ โ โโโ pages/
+ โโโ admin/
+ โ โโโ code/
+ โ โโโ components/
+ โ โโโ pages/
+ โโโ pages/
+```
+
+Config
+
+```js
+// vite.config.js
+export default {
+ plugins: [
+ Pages({
+ dirs: [
+ // basic
+ { dir: 'src/pages', baseRoute: '' },
+ // features dir for pages
+ { dir: 'src/features/**/pages', baseRoute: 'features' },
+ // with custom file pattern
+ { dir: 'src/admin/pages', baseRoute: 'admin', filePattern: '**/*.page.*' },
+ ],
+ }),
+ ],
+}
+```
+
+### extensions
+
+- **Type:** `string[]`
+- **Default:**
+ - Vue: `['vue', 'ts', 'js']`
+ - React: `['tsx', 'jsx', 'ts', 'js']`
+ - Solid: `['tsx', 'jsx', 'ts', 'js']`
+
+An array of valid file extensions for pages. If multiple extensions match for a file, the first one is used.
+
+### exclude
+
+- **Type:** `string[]`
+- **Default:** `[]`
+
+An array of glob patterns to exclude matches.
+
+```bash
+# folder structure
+src/pages/
+ โโโ users/
+ โ โโโ components
+ โ โ โโโ form.vue
+ โ โโโ [id].vue
+ โ โโโ index.vue
+ โโโ home.vue
+```
+
+```js
+// vite.config.js
+export default {
+ plugins: [
+ Pages({
+ exclude: ['**/components/*.vue'],
+ }),
+ ],
+}
+```
+
+### importMode
+
+- **Type:** `'sync' | 'async' | (filepath: string, pluginOptions: ResolvedOptions) => 'sync' | 'async')`
+- **Default:**
+ - Top level index file: `'sync'`, others: `async`.
+
+Import mode can be set to either `async`, `sync`, or a function which returns
+one of those values.
+
+To get more fine-grained control over which routes are loaded sync/async, you
+can use a function to resolve the value based on the route path. For example:
+
+```js
+// vite.config.js
+export default {
+ plugins: [
+ Pages({
+ importMode(filepath, options) {
+ // default resolver
+ // for (const page of options.dirs) {
+ // if (page.baseRoute === '' && filepath.startsWith(`/${page.dir}/index`))
+ // return 'sync'
+ // }
+ // return 'async'
+
+ // Load about page synchronously, all other pages are async.
+ return filepath.includes('about') ? 'sync' : 'async'
+ },
+ }),
+ ],
+}
+```
+
+If you are using `async` mode with `react-router`, you will need to wrap your route components with `Suspense`:
+
+```jsx
+function App() {
+ return (
+ Loading...}>
+ {useRoutes(routes)}
+
+ )
+}
+```
+
+### importPath
+
+- **Type:** `'absolute' | 'relative'`
+- **Default:** `'relative'`
+
+Import page components from absolute or relative paths. The default behavior is to import from relative paths, but in some special cases, it can be set to `'absolute'` to import from absolute paths.
+
+For example, if your page components are located in the `app/pages` directory and you have set `base: /app/` in your `vite.config.js`, you should set `importPath` to `'absolute'` in order to correctly import the page components.
+
+```js
+// vite.config.js
+export default {
+ base: '/app/',
+ plugins: [
+ Pages({
+ dirs: 'app/pages',
+
+ // It should be set to 'absolute' in this case.
+ importPath: 'absolute',
+ }),
+ ],
+}
+```
+
+See [#492](https://github.com/liujiayii/unplugin-convention-routes/issues/492) for more details.
+
+### routeBlockLang
+
+- **Type:** `string`
+- **Default:** `'json5'`
+
+Default SFC route block parser.
+
+### routeStyle
+
+- **Type:** `'next' | 'nuxt' | 'remix'`
+- **Default:** `next`
+
+Use file system dynamic routing supporting:
+
+- [Nextjs Routing](https://nextjs.org/docs/routing/introduction)
+- [Nuxtjs Routing](https://nuxtjs.org/docs/2.x/features/file-system-routing)
+- [Remix Routing](https://remix.run/docs/en/v1/guides/routing)
+
+### routeNameSeparator
+
+- **Type:** `string`
+- **Default:** `-`
+
+Separator for generated route names.
+
+### resolver
+
+- **Type:** `'vue' | 'react' | 'solid' | PageResolver`
+- **Default:** `'auto detect'`
+
+Route resolver, support `vue`, `react`, `solid` or custom `PageResolver`.
+
+### moduleId
+
+- **Type:** `string`
+- **Default:**
+ - Vue: `'~pages'`
+ - React: `'~react-pages'`
+ - Solid: `'~solid-pages'`
+
+Module id for routes import, useful when you what to use multiple pages plugin in one project.
+
+### extendRoute
+
+- **Type:**
+ `(route: any, parent: any | undefined) => any | void`
+
+A function that takes a route and optionally returns a modified route. This is
+useful for augmenting your routes with extra data (e.g. route metadata).
+
+```js
+// vite.config.js
+export default {
+ // ...
+ plugins: [
+ Pages({
+ extendRoute(route, parent) {
+ if (route.path === '/') {
+ // Index is unauthenticated.
+ return route
+ }
+
+ // Augment the route with meta that indicates that the route requires authentication.
+ return {
+ ...route,
+ meta: { auth: true },
+ }
+ },
+ }),
+ ],
+}
+```
+
+### onRoutesGenerated
+
+- **Type:** `(routes: any[]) => Awaitable`
+
+A function that takes a generated routes and optionally returns a modified
+generated routes.
+
+### onClientGenerated
+
+- **Type:** `(clientCode: string) => Awaitable`
+
+A function that takes a generated client code and optionally returns a modified
+generated client code.
+
+### SFC custom block for Route Data
+
+Add route meta to the route by adding a `` block to the SFC. This will be
+directly added to the route after it is generated, and will override it.
+
+You can specific a parser to use using ``, or set a default
+parser using `routeBlockLang` option.
+
+- **Supported parser:** JSON, JSON5, YAML
+- **Default:** JSON5
+
+JSON/JSON5:
+
+```html
+
+{
+ name: "name-override",
+ meta: {
+ requiresAuth: false
+ }
+}
+
+```
+
+YAML:
+
+```html
+
+name: name-override
+meta:
+ requiresAuth: true
+
+```
+
+#### Syntax Highlighting ``
+
+To enable syntax highlighting `` in VS Code using [Vetur's Custom Code Blocks](https://vuejs.github.io/vetur/highlighting.html#custom-block) add the following snippet to your preferences...
+
+ 1. update setting
+
+ ```
+ "vetur.grammar.customBlocks": {
+ "route": "json"
+ }
+```
+
+ 2. Run the command in vscode
+
+ `Vetur: Generate grammar from vetur.grammar.customBlocks`
+
+ 3. Restart VS Code to get syntax highlighting for custom blocks.
+
+### JSX/TSX YAML format comments for Route Data(In Vue)
+
+Add route meta to the route by adding a comment block starts with `route` to the JSX or TSX file(In Vue). This will be directly added to the route after it is generated, and will override it.
+
+This feature only support JSX/TSX in vue, and will parse only the first block of comments which should also start with `route`.
+
+Now only `yaml` parser supported.
+
+- **Type:** `'vue'`
+- **Supported parser:** YAML
+
+```jsx
+/*
+route
+
+name: name-override
+meta:
+ requiresAuth: false
+ id: 1234
+ string: "1234"
+*/
+```
+
+## File System Routing
+
+Inspired by the routing from
+[NuxtJS](https://nuxtjs.org/guides/features/file-system-routing) ๐
+
+Pages automatically generates an array of routes for you to plug-in to your
+instance of Vue Router. These routes are determined by the structure of the
+files in your pages directory. Simply create `.vue` files in your pages
+directory and routes will automatically be created for you, no additional
+configuration required!
+
+For more advanced use cases, you can tailor Pages to fit the needs of your app
+through [configuration](#configuration).
+
+- [Basic Routing](#basic-routing)
+- [Index Routes](#index-routes)
+- [Dynamic Routes](#dynamic-routes)
+- [Nested Routes](#nested-routes)
+- [Catch-all Routes](#catch-all-routes)
+
+### Basic Routing
+
+Pages will automatically map files from your pages directory to a route with the
+same name:
+
+- `src/pages/users.vue` -> `/users`
+- `src/pages/users/profile.vue` -> `/users/profile`
+- `src/pages/settings.vue` -> `/settings`
+
+### Index Routes
+
+Files with the name `index` are treated as the index page of a route:
+
+- `src/pages/index.vue` -> `/`
+- `src/pages/users/index.vue` -> `/users`
+
+### Dynamic Routes
+
+Dynamic routes are denoted using square brackets. Both directories and pages can
+be dynamic:
+
+- `src/pages/users/[id].vue` -> `/users/:id` (`/users/one`)
+- `src/pages/[user]/settings.vue` -> `/:user/settings` (`/one/settings`)
+
+Any dynamic parameters will be passed to the page as props. For example, given
+the file `src/pages/users/[id].vue`, the route `/users/abc` will be passed the
+following props:
+
+```json
+{ "id": "abc" }
+```
+
+### Nested Routes
+
+We can make use of Vue Routers child routes to create nested layouts. The parent
+component can be defined by giving it the same name as the directory that
+contains your child routes.
+
+For example, this directory structure:
+
+```
+src/pages/
+ โโโ users/
+ โ โโโ [id].vue
+ โ โโโ index.vue
+ โโโ users.vue
+```
+
+will result in this routes configuration:
+
+```json5
+[
+ {
+ "path": "/users",
+ "component": "/src/pages/users.vue",
+ "children": [
+ {
+ "path": "",
+ "component": "/src/pages/users/index.vue",
+ "name": "users"
+ },
+ {
+ "path": ":id",
+ "component": "/src/pages/users/[id].vue",
+ "name": "users-id"
+ }
+ ]
+ }
+]
+```
+
+### Catch-all Routes
+
+Catch-all routes are denoted with square brackets containing an ellipsis:
+
+- `src/pages/[...all].vue` -> `/*` (`/non-existent-page`)
+
+The text after the ellipsis will be used both to name the route, and as the name
+of the prop in which the route parameters are passed.
+
+## Sitemap generation
+
+If you need to generate a sitemap from generated routes, you can use [unplugin-convention-routes-sitemap](https://github.com/jbaubree/unplugin-convention-routes-sitemap).
+This plugin allow you to automatically generate sitemap.xml and robots.xml files with customization.
+
+## License
+
+MIT License ยฉ 2021-PRESENT [liujiayii](https://github.com/liujiayii)
diff --git a/README.md b/README.md
index 01b2455..904ce1d 100644
--- a/README.md
+++ b/README.md
@@ -1,634 +1,30 @@
-# unplugin-convention-routes
+
+
+
+
+
+
+
+
+
-[![npm version](https://badgen.net/npm/v/unplugin-convention-routes)](https://www.npmjs.com/package/unplugin-convention-routes)
-[![monthly downloads](https://badgen.net/npm/dm/unplugin-convention-routes)](https://www.npmjs.com/package/unplugin-convention-routes)
-[![types](https://badgen.net/npm/types/unplugin-convention-routes)](https://github.com/hannoeru/unplugin-convention-routes/blob/main/src/types.ts)
-[![license](https://badgen.net/npm/license/unplugin-convention-routes)](https://github.com/hannoeru/unplugin-convention-routes/blob/main/LICENSE)
+unplugin-convention-routes
-[![Open in Visual Studio Code](https://img.shields.io/static/v1?logo=visualstudiocode&label=&message=Open%20in%20Visual%20Studio%20Code&labelColor=2c2c32&color=007acc&logoColor=007acc)](https://open.vscode.dev/hannoeru/unplugin-convention-routes)
+- ๐ฅ ๅบไบๆไปถ็ณป็ป็็บฆๅฎๅผ่ทฏ็ฑ่งฃๅณๆนๆกใ
+- ๐ฅ ๅบไบ`unplugin`ๅฏน`vite-plugin-pages`่ฟ่กไบ็งปๆค๏ผ่ฝๅๆถๆฏๆ`vite`ใ`webpack`ใ`rsbuild`ใ`farm`็ญๆๅปบๆกๆถ๏ผๅนถๅๆถๆฏๆ`react`ใ`vue`ใ`solid`ไธๅคงๆกๆถใ
+- โ ๏ธ ๅฐๅจๅผๅไธญ๏ผ่ฟไธ่ฝๆญฃๅธธไฝฟ็จ๏ผ่ฏทๅฟไฝฟ็จใไธชไบบไป
ๆต่ฏไบ`vue+vite`ใ`vue`+`rsbuild`ใ`react`+`vite`ใ`react`+`rsbuild`ใ
-> File system based routing for Vue 3 / React / Solid applications using
-> [Vite](https://github.com/vitejs/vite)
+---
-## Getting Started
+## ๅๆ
้พๆฅ
-### Vue
+- [unplugin](https://github.com/unjs/unplugin)
+- [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)
-**๐จImportant Notes๐จ**
-
-We recommend that Vue users use [unplugin-vue-router](https://github.com/posva/unplugin-vue-router) instead of this plugin.
-
-[unplugin-vue-router](https://github.com/posva/unplugin-vue-router) is a unplugin library created by [@posva](https://github.com/posva), same auther as vue-router. It provide almost same feature as [unplugin-convention-routes](https://github.com/hannoeru/unplugin-convention-routes) but better intergration with vue-router, include some cool feature like auto generate route types base on your route files to provide autocomplete for vue-router.
-
-#### Install:
-
-```bash
-npm install -D unplugin-convention-routes
-npm install vue-router
-```
-
-### React
-
-> since v0.19.0 we only support react-router v6, if you are using react-router v5 use v0.18.2.
-
-#### Install:
-
-```bash
-npm install -D unplugin-convention-routes
-npm install react-router react-router-dom
-```
-
-### Solid
-
-#### Install:
+## ๐ฆ ๅฎ่ฃ
```bash
-npm install -D unplugin-convention-routes
-npm install @solidjs/router
-```
-
-### Vite config
-
-Add to your `vite.config.js`:
-
-```js
-import Pages from 'unplugin-convention-routes'
-
-export default {
- plugins: [
- // ...
- Pages(),
- ],
-}
-```
-
-## Overview
-
-By default a page is a Vue component exported from a `.vue` or `.js` file in the
-`src/pages` directory.
-
-You can access the generated routes by importing the `~pages`
-module in your application.
-
-### Vue
-
-```ts
-import routes from '~pages'
-import { createRouter } from 'vue-router'
-
-const router = createRouter({
- // ...
- routes,
-})
-```
-
-**Type**
-
-```ts
-// vite-env.d.ts
-///
-```
-
-### React
-
-**experimental**
-
-```tsx
-import routes from '~react-pages'
-import { StrictMode, Suspense } from 'react'
-import { createRoot } from 'react-dom/client'
-
-import {
- BrowserRouter,
- useRoutes,
-} from 'react-router-dom'
-
-function App() {
- return (
- Loading...}>
- {useRoutes(routes)}
-
- )
-}
-
-const app = createRoot(document.getElementById('root')!)
-
-app.render(
-
-
-
-
- ,
-)
-```
-
-**Type**
-
-```ts
-// vite-env.d.ts
-///
-```
-
-### Solid
-
-**experimental**
-
-```tsx
-import { Router, useRoutes } from '@solidjs/router'
-import routes from '~solid-pages'
-import { render } from 'solid-js/web'
-
-render(
- () => {
- const Routes = useRoutes(routes)
- return (
-
-
-
- )
- },
- document.getElementById('root') as HTMLElement,
-)
-```
-
-**Type**
-
-```ts
-// vite-env.d.ts
-///
-```
-
-## Configuration
-
-To use custom configuration, pass your options to Pages when instantiating the
-plugin:
-
-```js
-// vite.config.js
-import Pages from 'unplugin-convention-routes'
-
-export default {
- plugins: [
- Pages({
- dirs: 'src/views',
- }),
- ],
-}
-```
-
-### dirs
-
-- **Type:** `string | (string | PageOptions)[]`
-- **Default:** `'src/pages'`
-
-Paths to the pages directory. Supports globs.
-
-Can be:
-
-- single path: routes point to `/`
-- array of paths: all routes in the paths point to `/`
-- array of `PageOptions`, Check below ๐
-
-```ts
-interface PageOptions {
- /**
- * Page base directory.
- * @default 'src/pages'
- */
- dir: string
- /**
- * Page base route.
- */
- baseRoute: string
- /**
- * Page file pattern.
- * @example `**\/*.page.vue`
- */
- filePattern?: string
-}
-```
-
-Specifying a glob or an array of `PageOptions` allow you to use multiple
-pages folder, and specify the base route to append to the path and the route
-name.
-
-Additionally, you can specify a `filePattern` to filter the files that will be used as pages.
-
-#### Example
-
-Folder structure
-
-```bash
-src/
- โโโ features/
- โ โโโ dashboard/
- โ โโโ code/
- โ โโโ components/
- โ โโโ pages/
- โโโ admin/
- โ โโโ code/
- โ โโโ components/
- โ โโโ pages/
- โโโ pages/
-```
-
-Config
-
-```js
-// vite.config.js
-export default {
- plugins: [
- Pages({
- dirs: [
- // basic
- { dir: 'src/pages', baseRoute: '' },
- // features dir for pages
- { dir: 'src/features/**/pages', baseRoute: 'features' },
- // with custom file pattern
- { dir: 'src/admin/pages', baseRoute: 'admin', filePattern: '**/*.page.*' },
- ],
- }),
- ],
-}
-```
-
-### extensions
-
-- **Type:** `string[]`
-- **Default:**
- - Vue: `['vue', 'ts', 'js']`
- - React: `['tsx', 'jsx', 'ts', 'js']`
- - Solid: `['tsx', 'jsx', 'ts', 'js']`
-
-An array of valid file extensions for pages. If multiple extensions match for a file, the first one is used.
-
-### exclude
-
-- **Type:** `string[]`
-- **Default:** `[]`
-
-An array of glob patterns to exclude matches.
-
-```bash
-# folder structure
-src/pages/
- โโโ users/
- โ โโโ components
- โ โ โโโ form.vue
- โ โโโ [id].vue
- โ โโโ index.vue
- โโโ home.vue
-```
-
-```js
-// vite.config.js
-export default {
- plugins: [
- Pages({
- exclude: ['**/components/*.vue'],
- }),
- ],
-}
-```
-
-### importMode
-
-- **Type:** `'sync' | 'async' | (filepath: string, pluginOptions: ResolvedOptions) => 'sync' | 'async')`
-- **Default:**
- - Top level index file: `'sync'`, others: `async`.
-
-Import mode can be set to either `async`, `sync`, or a function which returns
-one of those values.
-
-To get more fine-grained control over which routes are loaded sync/async, you
-can use a function to resolve the value based on the route path. For example:
-
-```js
-// vite.config.js
-export default {
- plugins: [
- Pages({
- importMode(filepath, options) {
- // default resolver
- // for (const page of options.dirs) {
- // if (page.baseRoute === '' && filepath.startsWith(`/${page.dir}/index`))
- // return 'sync'
- // }
- // return 'async'
-
- // Load about page synchronously, all other pages are async.
- return filepath.includes('about') ? 'sync' : 'async'
- },
- }),
- ],
-}
-```
-
-If you are using `async` mode with `react-router`, you will need to wrap your route components with `Suspense`:
-
-```jsx
-function App() {
- return (
- Loading...}>
- {useRoutes(routes)}
-
- )
-}
-```
-
-### importPath
-
-- **Type:** `'absolute' | 'relative'`
-- **Default:** `'relative'`
-
-Import page components from absolute or relative paths. The default behavior is to import from relative paths, but in some special cases, it can be set to `'absolute'` to import from absolute paths.
-
-For example, if your page components are located in the `app/pages` directory and you have set `base: /app/` in your `vite.config.js`, you should set `importPath` to `'absolute'` in order to correctly import the page components.
-
-```js
-// vite.config.js
-export default {
- base: '/app/',
- plugins: [
- Pages({
- dirs: 'app/pages',
-
- // It should be set to 'absolute' in this case.
- importPath: 'absolute',
- }),
- ],
-}
+pnpm i unplugin-convention-routes
```
-See [#492](https://github.com/hannoeru/unplugin-convention-routes/issues/492) for more details.
-
-### routeBlockLang
-
-- **Type:** `string`
-- **Default:** `'json5'`
-
-Default SFC route block parser.
-
-### routeStyle
-
-- **Type:** `'next' | 'nuxt' | 'remix'`
-- **Default:** `next`
-
-Use file system dynamic routing supporting:
-
-- [Nextjs Routing](https://nextjs.org/docs/routing/introduction)
-- [Nuxtjs Routing](https://nuxtjs.org/docs/2.x/features/file-system-routing)
-- [Remix Routing](https://remix.run/docs/en/v1/guides/routing)
-
-### routeNameSeparator
-
-- **Type:** `string`
-- **Default:** `-`
-
-Separator for generated route names.
-
-### resolver
-
-- **Type:** `'vue' | 'react' | 'solid' | PageResolver`
-- **Default:** `'auto detect'`
-
-Route resolver, support `vue`, `react`, `solid` or custom `PageResolver`.
-
-### moduleId
-
-- **Type:** `string`
-- **Default:**
- - Vue: `'~pages'`
- - React: `'~react-pages'`
- - Solid: `'~solid-pages'`
-
-Module id for routes import, useful when you what to use multiple pages plugin in one project.
-
-### extendRoute
-
-- **Type:**
- `(route: any, parent: any | undefined) => any | void`
-
-A function that takes a route and optionally returns a modified route. This is
-useful for augmenting your routes with extra data (e.g. route metadata).
-
-```js
-// vite.config.js
-export default {
- // ...
- plugins: [
- Pages({
- extendRoute(route, parent) {
- if (route.path === '/') {
- // Index is unauthenticated.
- return route
- }
-
- // Augment the route with meta that indicates that the route requires authentication.
- return {
- ...route,
- meta: { auth: true },
- }
- },
- }),
- ],
-}
-```
-
-### onRoutesGenerated
-
-- **Type:** `(routes: any[]) => Awaitable`
-
-A function that takes a generated routes and optionally returns a modified
-generated routes.
-
-### onClientGenerated
-
-- **Type:** `(clientCode: string) => Awaitable`
-
-A function that takes a generated client code and optionally returns a modified
-generated client code.
-
-### SFC custom block for Route Data
-
-Add route meta to the route by adding a `` block to the SFC. This will be
-directly added to the route after it is generated, and will override it.
-
-You can specific a parser to use using ``, or set a default
-parser using `routeBlockLang` option.
-
-- **Supported parser:** JSON, JSON5, YAML
-- **Default:** JSON5
-
-JSON/JSON5:
-
-```html
-
-{
- name: "name-override",
- meta: {
- requiresAuth: false
- }
-}
-
-```
-
-YAML:
-
-```html
-
-name: name-override
-meta:
- requiresAuth: true
-
-```
-
-#### Syntax Highlighting ``
-
-To enable syntax highlighting `` in VS Code using [Vetur's Custom Code Blocks](https://vuejs.github.io/vetur/highlighting.html#custom-block) add the following snippet to your preferences...
-
- 1. update setting
-
- ```
- "vetur.grammar.customBlocks": {
- "route": "json"
- }
-```
-
- 2. Run the command in vscode
-
- `Vetur: Generate grammar from vetur.grammar.customBlocks`
-
- 3. Restart VS Code to get syntax highlighting for custom blocks.
-
-### JSX/TSX YAML format comments for Route Data(In Vue)
-
-Add route meta to the route by adding a comment block starts with `route` to the JSX or TSX file(In Vue). This will be directly added to the route after it is generated, and will override it.
-
-This feature only support JSX/TSX in vue, and will parse only the first block of comments which should also start with `route`.
-
-Now only `yaml` parser supported.
-
-- **Type:** `'vue'`
-- **Supported parser:** YAML
-
-```jsx
-/*
-route
-
-name: name-override
-meta:
- requiresAuth: false
- id: 1234
- string: "1234"
-*/
-```
-
-## File System Routing
-
-Inspired by the routing from
-[NuxtJS](https://nuxtjs.org/guides/features/file-system-routing) ๐
-
-Pages automatically generates an array of routes for you to plug-in to your
-instance of Vue Router. These routes are determined by the structure of the
-files in your pages directory. Simply create `.vue` files in your pages
-directory and routes will automatically be created for you, no additional
-configuration required!
-
-For more advanced use cases, you can tailor Pages to fit the needs of your app
-through [configuration](#configuration).
-
-- [Basic Routing](#basic-routing)
-- [Index Routes](#index-routes)
-- [Dynamic Routes](#dynamic-routes)
-- [Nested Routes](#nested-routes)
-- [Catch-all Routes](#catch-all-routes)
-
-### Basic Routing
-
-Pages will automatically map files from your pages directory to a route with the
-same name:
-
-- `src/pages/users.vue` -> `/users`
-- `src/pages/users/profile.vue` -> `/users/profile`
-- `src/pages/settings.vue` -> `/settings`
-
-### Index Routes
-
-Files with the name `index` are treated as the index page of a route:
-
-- `src/pages/index.vue` -> `/`
-- `src/pages/users/index.vue` -> `/users`
-
-### Dynamic Routes
-
-Dynamic routes are denoted using square brackets. Both directories and pages can
-be dynamic:
-
-- `src/pages/users/[id].vue` -> `/users/:id` (`/users/one`)
-- `src/pages/[user]/settings.vue` -> `/:user/settings` (`/one/settings`)
-
-Any dynamic parameters will be passed to the page as props. For example, given
-the file `src/pages/users/[id].vue`, the route `/users/abc` will be passed the
-following props:
-
-```json
-{ "id": "abc" }
-```
-
-### Nested Routes
-
-We can make use of Vue Routers child routes to create nested layouts. The parent
-component can be defined by giving it the same name as the directory that
-contains your child routes.
-
-For example, this directory structure:
-
-```
-src/pages/
- โโโ users/
- โ โโโ [id].vue
- โ โโโ index.vue
- โโโ users.vue
-```
-
-will result in this routes configuration:
-
-```json5
-[
- {
- "path": "/users",
- "component": "/src/pages/users.vue",
- "children": [
- {
- "path": "",
- "component": "/src/pages/users/index.vue",
- "name": "users"
- },
- {
- "path": ":id",
- "component": "/src/pages/users/[id].vue",
- "name": "users-id"
- }
- ]
- }
-]
-```
-
-### Catch-all Routes
-
-Catch-all routes are denoted with square brackets containing an ellipsis:
-
-- `src/pages/[...all].vue` -> `/*` (`/non-existent-page`)
-
-The text after the ellipsis will be used both to name the route, and as the name
-of the prop in which the route parameters are passed.
-
-## Sitemap generation
-
-If you need to generate a sitemap from generated routes, you can use [unplugin-convention-routes-sitemap](https://github.com/jbaubree/unplugin-convention-routes-sitemap).
-This plugin allow you to automatically generate sitemap.xml and robots.xml files with customization.
-
-## License
-
-MIT License ยฉ 2021-PRESENT [hannoeru](https://github.com/hannoeru)
+## ๐จ ็คบไพ
diff --git a/virtual-package/react.d.ts b/client-react.d.ts
similarity index 100%
rename from virtual-package/react.d.ts
rename to client-react.d.ts
diff --git a/virtual-package/solid.d.ts b/client-solid.d.ts
similarity index 100%
rename from virtual-package/solid.d.ts
rename to client-solid.d.ts
diff --git a/virtual-package/vue.d.ts b/client-vue.d.ts
similarity index 100%
rename from virtual-package/vue.d.ts
rename to client-vue.d.ts
diff --git a/examples/react-rsbuild/env.d.ts b/examples/react-rsbuild/env.d.ts
new file mode 100644
index 0000000..a2c4162
--- /dev/null
+++ b/examples/react-rsbuild/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/react/env.d.ts b/examples/react/env.d.ts
new file mode 100644
index 0000000..a2c4162
--- /dev/null
+++ b/examples/react/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/remix-style/vite.config.ts b/examples/remix-style/vite.config.ts
index 1b88597..75790ec 100644
--- a/examples/remix-style/vite.config.ts
+++ b/examples/remix-style/vite.config.ts
@@ -1,11 +1,11 @@
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
-import Pages from 'unplugin-convention-routes'
+import Pages from 'unplugin-convention-routes/vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
- Pages({ routeStyle: 'remix' }),
+ Pages({ routeStyle: 'remix', resolver: 'react' }),
],
})
diff --git a/examples/vue-rsbuild/.gitignore b/examples/vue-rsbuild/.gitignore
new file mode 100644
index 0000000..38d7344
--- /dev/null
+++ b/examples/vue-rsbuild/.gitignore
@@ -0,0 +1,13 @@
+# Local
+.DS_Store
+*.local
+*.log*
+
+# Dist
+node_modules
+dist/
+
+# IDE
+.vscode/*
+!.vscode/extensions.json
+.idea
diff --git a/examples/vue-rsbuild/package.json b/examples/vue-rsbuild/package.json
new file mode 100644
index 0000000..429e266
--- /dev/null
+++ b/examples/vue-rsbuild/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "rsbuild-vue",
+ "private": true,
+ "version": "1.0.0",
+ "scripts": {
+ "dev": "rsbuild dev",
+ "build": "rsbuild build",
+ "preview": "rsbuild preview"
+ },
+ "dependencies": {
+ "vue": "^3.5.12"
+ },
+ "devDependencies": {
+ "@rsbuild/core": "^1.0.13",
+ "@rsbuild/plugin-vue": "^1.0.1",
+ "unplugin-convention-routes": "workspace:*",
+ "typescript": "^5.6.3"
+ },
+ "packageManager": "pnpm@9.12.1"
+}
\ No newline at end of file
diff --git a/examples/vue-rsbuild/rsbuild.config.ts b/examples/vue-rsbuild/rsbuild.config.ts
new file mode 100644
index 0000000..80bf36b
--- /dev/null
+++ b/examples/vue-rsbuild/rsbuild.config.ts
@@ -0,0 +1,36 @@
+import { defineConfig } from '@rsbuild/core';
+import { pluginVue } from '@rsbuild/plugin-vue';
+import Pages from 'unplugin-convention-routes/rspack'
+import {resolve} from 'path'
+
+export default defineConfig({
+ tools:{
+ rspack:{
+ plugins: [
+ Pages({
+ resolver: 'vue',
+ dirs: [
+ // issue #68
+ { dir: resolve(__dirname, './src/pages'), baseRoute: '' },
+ { dir: 'src/features/**/pages', baseRoute: 'features' },
+ { dir: 'src/admin/pages', baseRoute: 'admin' },
+ ],
+ extensions: ['vue', 'jsx'],
+ extendRoute(route: any) {
+ if (route.name === 'about')
+ route.props = (route: any) => ({ query: route.query.q })
+
+ if (route.name === 'components') {
+ return {
+ ...route,
+ beforeEnter: (route: any) => {
+ console.log(route)
+ },
+ }
+ }
+ },
+ }),]
+ }
+ },
+ plugins: [pluginVue()],
+});
diff --git a/examples/vue-rsbuild/src/App.vue b/examples/vue-rsbuild/src/App.vue
new file mode 100644
index 0000000..98240ae
--- /dev/null
+++ b/examples/vue-rsbuild/src/App.vue
@@ -0,0 +1,3 @@
+
+
+
diff --git a/examples/vue-rsbuild/src/admin/pages/index.vue b/examples/vue-rsbuild/src/admin/pages/index.vue
new file mode 100644
index 0000000..a7c073f
--- /dev/null
+++ b/examples/vue-rsbuild/src/admin/pages/index.vue
@@ -0,0 +1,22 @@
+
+
+
+ /admin/index.vue
+ located in features /admin/pages folder
+
+
+
+
+
+{
+meta: {
+ requiresAuth: false
+}
+}
+
diff --git a/examples/vue-rsbuild/src/env.d.ts b/examples/vue-rsbuild/src/env.d.ts
new file mode 100644
index 0000000..2e1d25c
--- /dev/null
+++ b/examples/vue-rsbuild/src/env.d.ts
@@ -0,0 +1,10 @@
+///
+///
+
+declare module '*.vue' {
+ import type { DefineComponent } from 'vue';
+
+ // biome-ignore lint/complexity/noBannedTypes: reason
+ const component: DefineComponent<{}, {}, any>;
+ export default component;
+}
diff --git a/examples/vue-rsbuild/src/features/admin/pages/admin.vue b/examples/vue-rsbuild/src/features/admin/pages/admin.vue
new file mode 100644
index 0000000..4c7366f
--- /dev/null
+++ b/examples/vue-rsbuild/src/features/admin/pages/admin.vue
@@ -0,0 +1,12 @@
+
+ features/admin/pages/admin.vue
+ located in features/admin/pages folder
+
+
+
+{
+ meta: {
+ requiresAuth: false
+ }
+}
+
diff --git a/examples/vue-rsbuild/src/features/dashboard/pages/dashboard.vue b/examples/vue-rsbuild/src/features/dashboard/pages/dashboard.vue
new file mode 100644
index 0000000..ad74b81
--- /dev/null
+++ b/examples/vue-rsbuild/src/features/dashboard/pages/dashboard.vue
@@ -0,0 +1,12 @@
+
+ features/dashboard/pages/dashboard.vue
+ located in features/dashboard/pages folder
+
+
+
+{
+ meta: {
+ requiresAuth: true
+ }
+}
+
diff --git a/examples/vue-rsbuild/src/features/dashboard/pages/welcome.vue b/examples/vue-rsbuild/src/features/dashboard/pages/welcome.vue
new file mode 100644
index 0000000..438486f
--- /dev/null
+++ b/examples/vue-rsbuild/src/features/dashboard/pages/welcome.vue
@@ -0,0 +1,12 @@
+
+ features/dashboard/pages/welcome.vue
+ located in features/dashboard/pages folder
+
+
+
+{
+ meta: {
+ requiresAuth: true
+ }
+}
+
diff --git a/examples/vue-rsbuild/src/index.css b/examples/vue-rsbuild/src/index.css
new file mode 100644
index 0000000..e69de29
diff --git a/examples/vue-rsbuild/src/index.ts b/examples/vue-rsbuild/src/index.ts
new file mode 100644
index 0000000..c064816
--- /dev/null
+++ b/examples/vue-rsbuild/src/index.ts
@@ -0,0 +1,25 @@
+import routes from '~unplugin-convention-routes/vue'
+import { createApp } from 'vue'
+import { createRouter, createWebHistory } from 'vue-router'
+import App from './App.vue'
+
+// @ts-expect-error no routes type
+import reactRoutes from '~admin-pages'
+import './index.css'
+
+// eslint-disable-next-line no-console
+console.log('vue:', routes)
+
+// eslint-disable-next-line no-console
+console.log('react:', reactRoutes)
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes,
+})
+
+const app = createApp(App)
+
+app.use(router)
+
+app.mount('#app')
diff --git a/examples/vue-rsbuild/src/pages/[...all].vue b/examples/vue-rsbuild/src/pages/[...all].vue
new file mode 100644
index 0000000..361b082
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/[...all].vue
@@ -0,0 +1,3 @@
+
+ ...all route
+
diff --git a/examples/vue-rsbuild/src/pages/[sensor].vue b/examples/vue-rsbuild/src/pages/[sensor].vue
new file mode 100644
index 0000000..61a094b
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/[sensor].vue
@@ -0,0 +1,4 @@
+
+ nested dynamic view:
+
+
diff --git a/examples/vue-rsbuild/src/pages/[sensor]/current.vue b/examples/vue-rsbuild/src/pages/[sensor]/current.vue
new file mode 100644
index 0000000..0b0ea7b
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/[sensor]/current.vue
@@ -0,0 +1,3 @@
+
+ /[sensor]/current.vue
+
diff --git a/examples/vue-rsbuild/src/pages/__test__/index.vue b/examples/vue-rsbuild/src/pages/__test__/index.vue
new file mode 100644
index 0000000..d58ea5d
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/__test__/index.vue
@@ -0,0 +1,3 @@
+
+ test default exclude
+
diff --git a/examples/vue-rsbuild/src/pages/about.vue b/examples/vue-rsbuild/src/pages/about.vue
new file mode 100644
index 0000000..a499293
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/about.vue
@@ -0,0 +1,11 @@
+
+
+ nested about view:
+
+
+
+
+
+meta:
+ lang: yml
+
diff --git a/examples/vue-rsbuild/src/pages/about/[id].vue b/examples/vue-rsbuild/src/pages/about/[id].vue
new file mode 100644
index 0000000..0e786d4
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/about/[id].vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+ about/[id].vue: {{ id }}
+
+
+ more deep
+
+
+
+
+
+
+{
+ name: 'about-user-id',
+ meta: {
+ requiresAuth: true,
+ },
+}
+
diff --git a/examples/vue-rsbuild/src/pages/about/[id]/more.vue b/examples/vue-rsbuild/src/pages/about/[id]/more.vue
new file mode 100644
index 0000000..7284d90
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/about/[id]/more.vue
@@ -0,0 +1,5 @@
+
+
+ deep nested: about/[id]/more.vue
+
+
diff --git a/examples/vue-rsbuild/src/pages/about/[id]/nested.vue b/examples/vue-rsbuild/src/pages/about/[id]/nested.vue
new file mode 100644
index 0000000..c1f8011
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/about/[id]/nested.vue
@@ -0,0 +1,5 @@
+
+
+ deep nested: about/[id]/nested.vue
+
+
diff --git a/examples/vue-rsbuild/src/pages/about/index.vue b/examples/vue-rsbuild/src/pages/about/index.vue
new file mode 100644
index 0000000..ee31283
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/about/index.vue
@@ -0,0 +1,8 @@
+
+
+ about/index.vue
+
+ id: 1b234bk12b3
+
+
+
diff --git a/examples/vue-rsbuild/src/pages/blog/[id].vue b/examples/vue-rsbuild/src/pages/blog/[id].vue
new file mode 100644
index 0000000..144513d
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/blog/[id].vue
@@ -0,0 +1,23 @@
+
+
+
+
+
blog/[id].vue: {{ id }}
+
+ {{ $route }}
+
+
+
+
+
+{
+ name: 'blog-id',
+ meta: {
+ requiresAuth: false,
+ },
+}
+
diff --git a/examples/vue-rsbuild/src/pages/blog/index.vue b/examples/vue-rsbuild/src/pages/blog/index.vue
new file mode 100644
index 0000000..a2602bc
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/blog/index.vue
@@ -0,0 +1,14 @@
+
+
+ blog/index.vue
+
+ id: 1b234bk12b3
+ |
+
+ today
+ |
+
+ child - not found
+
+
+
diff --git a/examples/vue-rsbuild/src/pages/blog/today/[...all].vue b/examples/vue-rsbuild/src/pages/blog/today/[...all].vue
new file mode 100644
index 0000000..3667e99
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/blog/today/[...all].vue
@@ -0,0 +1,3 @@
+
+ blog/today ...all route
+
diff --git a/examples/vue-rsbuild/src/pages/blog/today/index.vue b/examples/vue-rsbuild/src/pages/blog/today/index.vue
new file mode 100644
index 0000000..8720db9
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/blog/today/index.vue
@@ -0,0 +1,5 @@
+
+
+ blog/today/index.vue
+
+
diff --git a/examples/vue-rsbuild/src/pages/components.vue b/examples/vue-rsbuild/src/pages/components.vue
new file mode 100644
index 0000000..96ffe5b
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/components.vue
@@ -0,0 +1,8 @@
+
+ Test Components name
+
+
+
+meta:
+ lang: yaml
+
diff --git a/examples/vue-rsbuild/src/pages/index.vue b/examples/vue-rsbuild/src/pages/index.vue
new file mode 100644
index 0000000..d08e861
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/index.vue
@@ -0,0 +1,38 @@
+
+
+
index.vue
+
+ blog
+ |
+
+ about
+ |
+
+ components
+ |
+
+ markdown
+ |
+
+ not exists
+ |
+
+ features:dashboard
+ |
+
+ features:admin
+ |
+
+ admin
+
+
+
+
+
+{
+ "name": "homepage",
+ "meta": {
+ "requiresAuth": false
+ }
+}
+
diff --git a/examples/vue-rsbuild/src/pages/jsx.jsx b/examples/vue-rsbuild/src/pages/jsx.jsx
new file mode 100644
index 0000000..8e1d02a
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/jsx.jsx
@@ -0,0 +1,18 @@
+/*
+
+ route
+
+name: blog-id
+meta:
+ requiresAuth: false
+ id: 1234
+*/
+
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+ name: 'TestJSX',
+ setup() {
+ return () => TestJSX
+ },
+})
diff --git a/examples/vue-rsbuild/src/pages/markdown.md b/examples/vue-rsbuild/src/pages/markdown.md
new file mode 100644
index 0000000..f5be0b5
--- /dev/null
+++ b/examples/vue-rsbuild/src/pages/markdown.md
@@ -0,0 +1 @@
+# hello from markdown file
diff --git a/examples/vue-rsbuild/tsconfig.json b/examples/vue-rsbuild/tsconfig.json
new file mode 100644
index 0000000..be4dc60
--- /dev/null
+++ b/examples/vue-rsbuild/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "lib": ["DOM", "ES2020"],
+ "module": "ESNext",
+ "jsx": "preserve",
+ "jsxImportSource": "vue",
+ "noEmit": true,
+ "strict": true,
+ "skipLibCheck": true,
+ "isolatedModules": true,
+ "resolveJsonModule": true,
+ "moduleResolution": "bundler",
+ "useDefineForClassFields": true,
+ "allowImportingTsExtensions": true
+ },
+ "include": ["src"]
+}
diff --git a/examples/vue/env.d.ts b/examples/vue/env.d.ts
new file mode 100644
index 0000000..de0ba95
--- /dev/null
+++ b/examples/vue/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/vue/src/main.ts b/examples/vue/src/main.ts
index 072754a..c064816 100644
--- a/examples/vue/src/main.ts
+++ b/examples/vue/src/main.ts
@@ -1,4 +1,4 @@
-import routes from '~pages'
+import routes from '~unplugin-convention-routes/vue'
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
diff --git a/examples/vue/vite.config.ts b/examples/vue/vite.config.ts
index 535da4e..1f1a0df 100644
--- a/examples/vue/vite.config.ts
+++ b/examples/vue/vite.config.ts
@@ -11,6 +11,7 @@ const config = defineConfig({
include: [/\.vue$/, /\.md$/],
}),
Pages({
+ resolver: 'vue',
dirs: [
// issue #68
{ dir: resolve(__dirname, './src/pages'), baseRoute: '' },
@@ -33,11 +34,11 @@ const config = defineConfig({
},
}),
// test multiple instances
- Pages({
- dirs: '../react/src/pages',
- resolver: 'react',
- moduleId: '~admin-pages',
- }),
+ // Pages({
+ // dirs: '../react/src/pages',
+ // resolver: 'react',
+ // moduleId: '~admin-pages',
+ // }),
Markdown(),
Inspect(),
],
diff --git a/package.json b/package.json
index 3ae5a1f..2c346ec 100644
--- a/package.json
+++ b/package.json
@@ -4,14 +4,14 @@
"version": "0.0.1-alpha.1",
"packageManager": "pnpm@9.12.3",
"description": "File system base router plugin for unplugin",
- "author": "hannoeru ",
+ "author": "liujiayii@foxmail.com",
"license": "MIT",
- "homepage": "https://github.com/hannoeru/unplugin-convention-routes",
+ "homepage": "https://github.com/liujiayii/unplugin-convention-routes",
"repository": {
"type": "git",
- "url": "https://github.com/hannoeru/unplugin-convention-routes"
+ "url": "https://github.com/liujiayii/unplugin-convention-routes"
},
- "bugs": "https://github.com/hannoeru/unplugin-convention-routes/issues",
+ "bugs": "https://github.com/liujiayii/unplugin-convention-routes/issues",
"keywords": [
"vite",
"vue",
@@ -64,10 +64,6 @@
"import": "./dist/types.js",
"require": "./dist/types.cjs"
},
- "./react": {
- "import": "./react.js",
- "require": "./react.js"
- },
"./*": "./*"
},
"main": "dist/index.cjs",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e255728..4ab5e84 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -328,6 +328,25 @@ importers:
specifier: ^0.23.8
version: 0.23.8(rollup@4.25.0)(vite@5.4.11(@types/node@22.9.0)(terser@5.36.0))
+ examples/vue-rsbuild:
+ dependencies:
+ vue:
+ specifier: ^3.5.12
+ version: 3.5.12(typescript@5.6.3)
+ devDependencies:
+ '@rsbuild/core':
+ specifier: ^1.0.13
+ version: 1.1.0
+ '@rsbuild/plugin-vue':
+ specifier: ^1.0.1
+ version: 1.0.4(@rsbuild/core@1.1.0)(@vue/compiler-sfc@3.5.12)(esbuild@0.24.0)(vue@3.5.12(typescript@5.6.3))
+ typescript:
+ specifier: ^5.6.3
+ version: 5.6.3
+ unplugin-convention-routes:
+ specifier: workspace:*
+ version: link:../..
+
examples/vue-ssr:
dependencies:
vue:
@@ -1259,6 +1278,11 @@ packages:
peerDependencies:
'@rsbuild/core': 1.x
+ '@rsbuild/plugin-vue@1.0.4':
+ resolution: {integrity: sha512-5Ue3ufWUVllJG1N7GDiTIELbIZZvIzWcDjO62bIYvtcLCG19sL0PPuBge4tXl+mlW2ncJYBoUsVI5aee9qNTWw==}
+ peerDependencies:
+ '@rsbuild/core': 1.x
+
'@rspack/binding-darwin-arm64@1.1.1':
resolution: {integrity: sha512-BnvGPWObGZ2ZVnxe4K3NKwAWxYubOJvfwporXWD3NgkzeV5xJqGBFWRDnr/nfsFpgCTI8goxK5db/wb7NVzLqg==}
cpu: [arm64]
@@ -3979,6 +4003,18 @@ packages:
peerDependencies:
eslint: '>=6.0.0'
+ vue-loader@17.4.2:
+ resolution: {integrity: sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==}
+ peerDependencies:
+ '@vue/compiler-sfc': '*'
+ vue: '*'
+ webpack: ^4.1.0 || ^5.0.0-0
+ peerDependenciesMeta:
+ '@vue/compiler-sfc':
+ optional: true
+ vue:
+ optional: true
+
vue-router@4.2.5:
resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==}
peerDependencies:
@@ -4789,6 +4825,19 @@ snapshots:
'@rspack/plugin-react-refresh': 1.0.0(react-refresh@0.14.2)
react-refresh: 0.14.2
+ '@rsbuild/plugin-vue@1.0.4(@rsbuild/core@1.1.0)(@vue/compiler-sfc@3.5.12)(esbuild@0.24.0)(vue@3.5.12(typescript@5.6.3))':
+ dependencies:
+ '@rsbuild/core': 1.1.0
+ vue-loader: 17.4.2(@vue/compiler-sfc@3.5.12)(vue@3.5.12(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0))
+ webpack: 5.96.1(esbuild@0.24.0)
+ transitivePeerDependencies:
+ - '@swc/core'
+ - '@vue/compiler-sfc'
+ - esbuild
+ - uglify-js
+ - vue
+ - webpack-cli
+
'@rspack/binding-darwin-arm64@1.1.1':
optional: true
@@ -7925,6 +7974,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ vue-loader@17.4.2(@vue/compiler-sfc@3.5.12)(vue@3.5.12(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0)):
+ dependencies:
+ chalk: 4.1.2
+ hash-sum: 2.0.0
+ watchpack: 2.4.2
+ webpack: 5.96.1(esbuild@0.24.0)
+ optionalDependencies:
+ '@vue/compiler-sfc': 3.5.12
+ vue: 3.5.12(typescript@5.6.3)
+
vue-router@4.2.5(vue@3.5.12(typescript@5.6.3)):
dependencies:
'@vue/devtools-api': 6.6.4
diff --git a/src/core/context.ts b/src/core/context.ts
index 701e66d..d89347b 100644
--- a/src/core/context.ts
+++ b/src/core/context.ts
@@ -99,7 +99,7 @@ export class PageContext {
// debug.pages('add', path)
for (const p of toArray(path)) {
const pageDirPath = slash(resolve(this.root, pageDir.dir))
- const extension = this.options.extensions.find(ext => p.endsWith(`.${ext}`))
+ const extension = this.options.extensions!.find(ext => p.endsWith(`.${ext}`))
if (!extension)
continue
diff --git a/src/core/index.ts b/src/core/index.ts
deleted file mode 100644
index 0e736a2..0000000
--- a/src/core/index.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import type { Plugin } from 'vite'
-import type { UserOptions } from './types'
-import { MODULE_ID_VIRTUAL, ROUTE_BLOCK_ID_VIRTUAL, routeBlockQueryRE } from './constants'
-
-import { PageContext } from './context'
-import { parsePageRequest } from './utils'
-
-function pagesPlugin(userOptions: UserOptions = {}): Plugin {
- let ctx: PageContext
-
- return {
- name: 'unplugin-convention-routes',
- enforce: 'pre',
- async configResolved(config) {
- // auto set resolver for react project
- if (
- !userOptions.resolver
- && config.plugins.find(i => i.name.includes('vite:react'))
- ) {
- userOptions.resolver = 'react'
- }
-
- // auto set resolver for solid project
- if (
- !userOptions.resolver
- && config.plugins.find(i => i.name.includes('solid'))
- ) {
- userOptions.resolver = 'solid'
- }
-
- ctx = new PageContext(userOptions, config.root)
- ctx.setLogger(config.logger)
- await ctx.searchGlob()
- },
- api: {
- getResolvedRoutes() {
- return ctx.options.resolver.getComputedRoutes(ctx)
- },
- },
- configureServer(server) {
- ctx.setupViteServer(server)
- },
- resolveId(id) {
- if (ctx.options.moduleIds.includes(id))
- return `${MODULE_ID_VIRTUAL}?id=${id}`
-
- if (routeBlockQueryRE.test(id))
- return ROUTE_BLOCK_ID_VIRTUAL
-
- return null
- },
- async load(id) {
- const {
- moduleId,
- pageId,
- } = parsePageRequest(id)
-
- if (moduleId === MODULE_ID_VIRTUAL && pageId && ctx.options.moduleIds.includes(pageId))
- return ctx.resolveRoutes()
-
- if (id === ROUTE_BLOCK_ID_VIRTUAL) {
- return {
- code: 'export default {};',
- map: null,
- }
- }
-
- return null
- },
- }
-}
-
-export { syncIndexResolver } from './options'
-export type {
- ReactRoute,
- SolidRoute,
- VueRoute,
-} from './resolvers'
-
-export {
- reactResolver,
- solidResolver,
- vueResolver,
-} from './resolvers'
-export * from './types'
-export { PageContext }
-export default pagesPlugin
diff --git a/src/core/resolvers/react.ts b/src/core/resolvers/react.ts
index 4c5b9cc..ff0cfe5 100644
--- a/src/core/resolvers/react.ts
+++ b/src/core/resolvers/react.ts
@@ -43,7 +43,7 @@ function prepareRoutes(
}
async function computeReactRoutes(ctx: PageContext): Promise {
- const { routeStyle, caseSensitive, importPath } = ctx.options
+ const { routeStyle, caseSensitive = false, importPath } = ctx.options
const nuxtStyle = routeStyle === 'nuxt'
const pageRoutes = [...ctx.pageRouteMap.values()]
diff --git a/src/core/resolvers/solid.ts b/src/core/resolvers/solid.ts
index 657a641..64796b4 100644
--- a/src/core/resolvers/solid.ts
+++ b/src/core/resolvers/solid.ts
@@ -42,7 +42,7 @@ function prepareRoutes(
}
async function computeSolidRoutes(ctx: PageContext): Promise {
- const { routeStyle, caseSensitive, importPath } = ctx.options
+ const { routeStyle, caseSensitive = false, importPath } = ctx.options
const nuxtStyle = routeStyle === 'nuxt'
const pageRoutes = [...ctx.pageRouteMap.values()]
diff --git a/src/core/resolvers/vue.ts b/src/core/resolvers/vue.ts
index 899bd2f..9c4c0ca 100644
--- a/src/core/resolvers/vue.ts
+++ b/src/core/resolvers/vue.ts
@@ -61,7 +61,7 @@ function prepareRoutes(
}
async function computeVueRoutes(ctx: PageContext, customBlockMap: Map): Promise {
- const { routeStyle, caseSensitive, importPath, routeNameSeparator } = ctx.options
+ const { routeStyle, caseSensitive = false, importPath, routeNameSeparator } = ctx.options
const pageRoutes = [...ctx.pageRouteMap.values()]
// sort routes for HMR
diff --git a/src/core/types.ts b/src/core/types.ts
index ce343ef..a45e8b7 100644
--- a/src/core/types.ts
+++ b/src/core/types.ts
@@ -66,63 +66,63 @@ export interface Options {
* Paths to the directory to search for page components.
* @default 'src/pages'
*/
- dirs: string | (string | PageOptions)[]
+ dirs?: string | (string | PageOptions)[]
/**
* Valid file extensions for page components.
* @default ['vue', 'js']
*/
- extensions: string[]
+ extensions?: string[]
/**
* List of path globs to exclude when resolving pages.
*/
- exclude: string[]
+ exclude?: string[]
/**
* Import routes directly or as async components
* @default 'root index file => "sync", others => "async"'
*/
- importMode: ImportMode | ImportModeResolver
+ importMode?: ImportMode | ImportModeResolver
/**
* Import page components from absolute or relative paths.
* @default 'relative'
*/
- importPath: 'absolute' | 'relative'
+ importPath?: 'absolute' | 'relative'
/**
* Sync load top level index file
* @default true
* @deprecated use `importMode` instead
*/
- syncIndex: boolean
+ syncIndex?: boolean
/**
* Use Nuxt.js style route naming
* @default false
* @deprecated use `routeStyle` instead
*/
- nuxtStyle: boolean
+ nuxtStyle?: boolean
/**
* Routing style
* @default false
*/
- routeStyle: 'next' | 'nuxt' | 'remix'
+ routeStyle?: 'next' | 'nuxt' | 'remix'
/**
* Separator for generated route names.
* @default -
*/
- routeNameSeparator: string
+ routeNameSeparator?: string
/**
* Case for route paths
* @default false
*/
- caseSensitive: boolean
+ caseSensitive?: boolean
/**
* Set the default route block parser, or use `` in SFC route block
* @default 'json5'
*/
- routeBlockLang: 'json5' | 'json' | 'yaml' | 'yml'
+ routeBlockLang?: 'json5' | 'json' | 'yaml' | 'yml'
/**
* Module id for routes import
* @default '~pages'
*/
- moduleId: string
+ moduleId?: string
/**
* Generate React Route
* @default 'auto detect'
@@ -145,19 +145,19 @@ export interface Options {
* Paths to the directory to search for page components.
* @deprecated use `dirs` instead
*/
- pagesDir: string | (string | PageOptions)[]
+ pagesDir?: string | (string | PageOptions)[]
/**
* Replace '[]' to '_' in bundle filename
* @deprecated issue #122
*/
- replaceSquareBrackets: never
+ replaceSquareBrackets?: never
/**
* @name watcher
*/
watcher?: boolean
}
-export type UserOptions = Partial
+export type UserOptions = Options
export interface ResolvedOptions extends Omit {
/**
diff --git a/src/index.ts b/src/index.ts
index 1ab380c..231f7f9 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -7,7 +7,9 @@ import process from 'node:process'
import { createUnplugin } from 'unplugin'
import { PageContext } from './core/context'
-export const unpluginFactory: UnpluginFactory = (userOptions: UserOptions = {}) => {
+export const unpluginFactory: UnpluginFactory = (userOptions: UserOptions = {
+ resolver: 'vue',
+}) => {
const ctx: PageContext = new PageContext(userOptions)
// ctx.setLogger(config.logger)
return ({
From 66cc87928ff030e6364b44fee02dd133bb1e72bc Mon Sep 17 00:00:00 2001
From: liujiayii
Date: Thu, 14 Nov 2024 10:00:45 +0800
Subject: [PATCH 2/2] feat: fix types
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 904ce1d..2016df0 100644
--- a/README.md
+++ b/README.md
@@ -28,3 +28,4 @@ pnpm i unplugin-convention-routes
```
## ๐จ ็คบไพ
+- https://github.com/liujiayii/unplugin-convention-routes/tree/main/examples