@@ -15,7 +15,7 @@ This library is a work in progress and in active development.
1515
1616- [ ] generic route parsing function with options to cover major filesystem routing patterns
1717 - [x] [ Nuxt] ( https://github.com/nuxt/nuxt )
18- - [ ] [ unplugin-vue-router] ( https://github.com/posva/unplugin-vue-router )
18+ - [x ] [ unplugin-vue-router] ( https://github.com/posva/unplugin-vue-router ) (does not include dot-syntax nesting support )
1919- [ ] export capability for framework routers
2020 - [x] RegExp patterns
2121 - [x] [ ` vue-router ` ] ( https://router.vuejs.org/ ) routes
@@ -50,7 +50,7 @@ console.log(result.segments)
5050// [{ type: 'dynamic', value: 'id' }],
5151// [{ type: 'static', value: 'profile' }]
5252// ]
53- console .log (result .modes ) // undefined (no modes detected)
53+ console .log (result .meta ) // undefined (no metadata detected)
5454```
5555
5656### Mode Detection
@@ -63,17 +63,43 @@ const result = parsePath('app.server.vue', {
6363 modes: [' server' , ' client' ]
6464})
6565
66- console .log (result .modes ) // ['server']
66+ console .log (result .meta ? . modes ) // ['server']
6767console .log (result .segments ) // [[{ type: 'static', value: 'app' }]]
6868
6969// Multiple modes
7070const result2 = parsePath (' api.server.edge.js' , {
7171 modes: [' server' , ' client' , ' edge' ]
7272})
73- console .log (result2 .modes ) // ['server', 'edge']
73+ console .log (result2 .meta ? . modes ) // ['server', 'edge']
7474console .log (result2 .segments ) // [[{ type: 'static', value: 'api' }]]
7575` ` `
7676
77+ ### Named Views
78+
79+ ` ` ` js
80+ import { parsePath } from ' unrouting'
81+
82+ // Named views with @ suffix (for Vue Router named views)
83+ const result = parsePath (' dashboard@sidebar.vue' )
84+ console .log (result .meta ? .name ) // 'sidebar'
85+ console .log (result .segments ) // [[{ type: 'static', value: 'dashboard' }]]
86+
87+ // Named views with modes
88+ const result2 = parsePath (' admin@main.client.vue' , {
89+ modes: [' client' , ' server' ]
90+ })
91+ console .log (result2 .meta ) // { name: 'main', modes: ['client'] }
92+
93+ // Nested named views
94+ const result3 = parsePath (' users/[id]@profile.vue' )
95+ console .log (result3 .meta ? .name ) // 'profile'
96+ console .log (result3 .segments )
97+ // [
98+ // [{ type: 'static', value: 'users' }],
99+ // [{ type: 'dynamic', value: 'id' }]
100+ // ]
101+ ` ` `
102+
77103### Convert to Router Formats
78104
79105` ` ` js
@@ -99,20 +125,39 @@ console.log(regexpRoute.keys) // ['id', 'slug']
99125### Advanced Examples
100126
101127` ` ` js
102- import { parsePath } from ' unrouting'
128+ import { parsePath , toRegExp , toVueRouter4 } from ' unrouting'
103129
104- // Group segments (ignored in final path)
105- const result = parsePath (' (admin)/(dashboard)/users/[id].vue' )
106- console .log (result .segments )
107- // Groups are parsed but skipped in path generation
130+ // Repeatable parameters ([slug]+.vue -> one or more segments)
131+ const repeatable = parsePath (' posts/[slug]+.vue' )
132+ console .log (toVueRouter4 (repeatable .segments ).path ) // '/posts/:slug+'
133+
134+ // Optional repeatable parameters ([[slug]]+.vue -> zero or more segments)
135+ const optionalRepeatable = parsePath (' articles/[[slug]]+.vue' )
136+ console .log (toVueRouter4 (optionalRepeatable .segments ).path ) // '/articles/:slug*'
137+
138+ // Group segments (ignored in final path, useful for organization)
139+ const grouped = parsePath (' (admin)/(dashboard)/users/[id].vue' )
140+ console .log (toVueRouter4 (grouped .segments ).path ) // '/users/:id()'
141+ // Groups are parsed but excluded from path generation
108142
109- // Catchall routes
143+ // Catchall routes ([...slug].vue -> captures remaining path)
110144const catchall = parsePath (' docs/[...slug].vue' )
111- // catchall.segments converts to /docs/:slug(.*)*
145+ console . log ( toVueRouter4 ( catchall .segments ). path ) // ' /docs/:slug(.*)*'
112146
113- // Optional parameters
147+ // Optional parameters ([[param]].vue -> parameter is optional)
114148const optional = parsePath (' products/[[category]]/[[id]].vue' )
115- // optional.segments converts to /products/:category?/:id?
149+ console .log (toVueRouter4 (optional .segments ).path ) // '/products/:category?/:id?'
150+
151+ // Complex mixed patterns
152+ const complex = parsePath (' shop/[category]/product-[id]-[[variant]].vue' )
153+ console .log (toVueRouter4 (complex .segments ).path )
154+ // '/shop/:category()/product-:id()-:variant?'
155+
156+ // Proper regex matching with anchoring (fixes partial match issues)
157+ const pattern = toRegExp (' [slug].vue' )
158+ console .log (pattern .pattern ) // /^\/(?<slug>[^/]+)\/?$/
159+ console .log (' /file' .match (pattern .pattern )) // ✅ matches
160+ console .log (' /test/thing' .match (pattern .pattern )) // ❌ null (properly rejected)
116161` ` `
117162
118163## API
@@ -132,7 +177,10 @@ Parse a file path into route segments with mode detection.
132177` ` ` ts
133178interface ParsedPath {
134179 segments: ParsedPathSegment[]
135- modes? : string []
180+ meta?: {
181+ modes?: string[] // Detected mode suffixes (e.g., ['client', 'server'])
182+ name?: string // Named view from @name suffix
183+ }
136184}
137185` ` `
138186
0 commit comments