Skip to content

Commit

Permalink
Internal: Refactor Vue playground (#1864)
Browse files Browse the repository at this point in the history
* Add dynamic routes to Vue playground

* Simplify

* Upgrade to Vite 3.0

* Use TypeScript
  • Loading branch information
thecrypticace authored Sep 19, 2022
1 parent dd2feef commit b267ce3
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 300 deletions.
2 changes: 1 addition & 1 deletion packages/playground-vue/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
</head>
<body class="h-full w-full font-sans text-gray-900 antialiased">
<div class="h-full w-full" id="app"></div>
<script type="module" src="/src/main.js"></script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions packages/playground-vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"vue-router": "^4.0.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.0.1",
"vite": "^2.7.13"
"@vitejs/plugin-vue": "^3.0.3",
"vite": "^3.0.0"
}
}
74 changes: 35 additions & 39 deletions packages/playground-vue/src/components/Home.vue
Original file line number Diff line number Diff line change
@@ -1,46 +1,42 @@
<script setup>
import { defineComponent } from 'vue'
import { useRouter } from 'vue-router'
let Examples = defineComponent({
props: ['routes'],
setup:
(props, { slots }) =>
() =>
slots.default({ routes: props.routes, slots }),
})
let router = useRouter()
let routes = router
.getRoutes()
.filter((example) => example.path !== '/')
.filter((route) => route.meta.isRoot)
</script>

<template>
<div class="container mx-auto my-24">
<div class="prose">
<h2>Examples</h2>
<Examples :examples="examples" />
<Examples :routes="routes" v-slot="{ routes, slots }">
<ul>
<li v-for="{ children, meta, path } in routes">
<template v-if="children.length > 0">
<h3 class="text-xl">{{ meta.name }}</h3>
<!-- This is a bit cursed but it works -->
<component v-for="vnode in slots.default({ routes: children, slots })" :is="vnode" />
</template>
<template v-else>
<router-link :key="path" :to="path">
{{ meta.name }}
</router-link>
</template>
</li>
</ul>
</Examples>
</div>
</div>
</template>

<script>
import { defineComponent, h } from 'vue'
import { RouterLink } from 'vue-router'
import routes from '../routes.json'
let Examples = defineComponent({
props: ['examples'],
setup(props) {
return () => {
return h(
'ul',
props.examples
.filter((example) => example.path !== '/')
.map((example) =>
h(
'li',
{ key: example.path },
example.children
? h('h3', { class: 'text-xl' }, example.name)
: [h(RouterLink, { to: example.path }, () => example.name)],
example.children && h(Examples, { examples: example.children })
)
)
)
}
},
})
export default {
components: { Examples },
setup() {
return {
examples: routes,
}
},
}
</script>
File renamed without changes.
23 changes: 0 additions & 23 deletions packages/playground-vue/src/router.js

This file was deleted.

83 changes: 83 additions & 0 deletions packages/playground-vue/src/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { createWebHistory, createRouter, RouterView } from 'vue-router'

type Component = import('vue').Component

function buildRoutes() {
function titleCase(str) {
return str
.toLocaleLowerCase()
.split('-')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
}

// 1. Get all the components in the src/components directory
let files = Object.entries(
import.meta.glob('./components/**/*.vue', {
eager: true,
import: 'default',
})
) as [string, Component][]

// 2.a. Swap the file names for route urls
// 2.b. Resolve the default import for each component
files = files.map(([file, component]) => [
file
.replace('./components/', '/')
.replace(/\.vue$/, '')
.toLocaleLowerCase()
.replace(/^\/home$/g, '/'),
component,
])

let alreadyAdded = new Set()

// 3. Add a route for each directory (if not already added)
files = files.flatMap((entry) => {
let dirs = entry[0].split('/').slice(1, -1)

let paths: [string, Component][] = []

for (const [idx] of dirs.entries()) {
let path = `/` + dirs.slice(0, idx + 1).join('/')
if (alreadyAdded.has(path)) {
continue
}

paths.push([path, RouterView])
alreadyAdded.add(path)
}

return [...paths, entry]
})

// 4. Sort the routes alphabetically and by length
files.sort((a, b) => a[0].localeCompare(b[0]))

// 5. Create the nested routes
let routes = []
let routesByPath = {}

for (let [path, component] of files) {
let prefix = path.split('/').slice(0, -1).join('/')
let parent = routesByPath[prefix]?.children ?? routes
let route = {
path,
component: component,
children: [],
meta: {
name: titleCase(path.match(/[^/]+$/)?.[0] ?? 'Home'),
isRoot: parent === routes,
},
}

parent.push((routesByPath[path] = route))
}

return routes
}

export default createRouter({
history: createWebHistory(),
routes: buildRoutes(),
})
188 changes: 0 additions & 188 deletions packages/playground-vue/src/routes.json

This file was deleted.

Loading

0 comments on commit b267ce3

Please sign in to comment.