class RouterPath { name = ''; path = ''; children: Array | null = null; component: null | Function = null; props = false; } function getNearestBranch(tree: Array, url: string, root = '', name = ''): { branch: Array, path: string, leaf: string, name: string } { let path = ''; const parts = url.split(/\//g).filter(a => a); for (const part of parts) { if (path.length > 0) { path += '/'; } if (name.length > 0) { name += '-'; } if (/_parent$/i.test(part)) { // path name += 'root'; path = path.slice(0, path.length - 1); } else if (/^_/.test(part)) { path += ':' + part.slice(1); name += name.length !== 0 ? 'detail' : part.slice(1); } else { const clean = part.toLowerCase().replace(/_/g, '-'); path += clean; name += clean; } // console.log(url, parts, part); const leaf = url.slice(path.length + 1); const branch = tree.find((b) => { if (!root) { return b.path.slice(1) === path; } return b.path === path; }); if (branch && branch.children) { return getNearestBranch(branch.children, leaf, path, name); } } return { branch: tree, path: root, leaf: (root ? '' : '/') + path, name }; } function insertLeaf(tree: Array, url: string, leaf: RouterPath): RouterPath { const nearest = getNearestBranch(tree, url); leaf.path = nearest.leaf; leaf.name = nearest.name; if (/_parent$/i.test(url)) { leaf.children = []; console.log(' -> branch', leaf.path, leaf.name); } else { console.log(' -> leaf', leaf.path, leaf.name); } nearest.branch.push(leaf); return leaf; } function sortKey(path: string) { let cleaned = path; const decomment = /(.*)(__.*?)(.vue)$/; const match = decomment.exec(cleaned); if (match) { cleaned = match[1] + match[3]; } return cleaned.length - (/\/_parent.vue$/.test(cleaned) ? 1000 : 0); } class Sorter { key = ''; sort = 0; } // Import all of the resource routes files. export default function loadRoutes(tree: Array = []) { let keys: Array = []; let routes: Record = {}; try { routes = import.meta.glob(`@/routes/**/**.vue`); keys = Object.keys(routes); } catch (ex) { const context = require.context('@/routes/', true, /\.vue$/i); keys = Object.keys(context); keys.forEach((key) => { routes[key] = () => import(/* @vite-ignore */`@/routes/${key.slice(2)}`); }); } let sorting: Array = keys.map((key: string) => ({ key, sort: sortKey(key) })); sorting.sort((a: Sorter, b: Sorter) => a.sort - b.sort); keys = sorting.map((key) => key.key); keys.map((key) => { let path = key.slice(0, -4).replace(/^.*\/routes\//, ''); // remove index path = path.replace(/__.*/i, ''); path = path.replace(/(^|\/)index$/i, ''); const rp = new RouterPath() rp.component = routes[key]; rp.props = true; insertLeaf(tree, path, rp); }); return tree; }