1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | import slug from 'slug'
|
22 |
|
23 | import Home from 'components/Home'
|
24 | import Search from 'components/Search'
|
25 |
|
26 | import mdRoutes from 'mdRoutes'
|
27 | import jsRoutes from 'jsRoutes'
|
28 |
|
29 | import { HOME_PATH } from 'config'
|
30 |
|
31 | const generatePaths = (children, parentPath, order = []) =>
|
32 | children.map((child, rank) => {
|
33 | const path = `${parentPath}/${child.path || slug(child.name, { lower: true })}`
|
34 |
|
35 |
|
36 | const updatedOrder = [...order, rank]
|
37 | const updatedChild = { ...child, path, order: updatedOrder }
|
38 |
|
39 | return child.children
|
40 | ? { ...updatedChild, children: generatePaths(child.children, path, updatedOrder) }
|
41 | : { ...updatedChild, hasToc: true }
|
42 | })
|
43 |
|
44 | const compareOrders = (route1, route2) => {
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 | const minLength = Math.min(route1.order.length, route2.order.length)
|
53 | for (let i = 0; i < minLength; i++) {
|
54 | if (route1.order[i] < route2.order[i]) {
|
55 | return -1
|
56 | }
|
57 | if (route1.order[i] > route2.order[i]) {
|
58 | return 1
|
59 | }
|
60 | }
|
61 | return 0
|
62 | }
|
63 |
|
64 | const getNestedPath = d => (d.children ? getNestedPath(d.children[0]) : d.path)
|
65 |
|
66 | const reduction = cur =>
|
67 | cur.children
|
68 | ? [{ path: cur.path, redirect: getNestedPath(cur.children[0]) }, ...cur.children.map(reduction)]
|
69 | : cur
|
70 |
|
71 | export const trees = [...(mdRoutes || []), ...(jsRoutes || [])].reduce(
|
72 | (out, { name, path, children = [], data = [] }) => {
|
73 | out[path] = { name, tree: generatePaths([...children, ...data], path) }
|
74 | return out
|
75 | },
|
76 | {}
|
77 | )
|
78 |
|
79 | const routes = Object.keys(trees)
|
80 | .reduce((out, key) => {
|
81 | const { tree } = trees[key]
|
82 | const reduced = tree.reduce((acc, cur) => acc.concat(flatten(reduction(cur))), [])
|
83 | const final = [...reduced, reduced[0] && { path: key, redirect: reduced[0].path }].filter(
|
84 | d => d
|
85 | )
|
86 | return out.concat(final)
|
87 | }, [])
|
88 | .sort((a, b) => {
|
89 |
|
90 | if (b.redirect) {
|
91 | return -1
|
92 | }
|
93 | if (a.redirect) {
|
94 | return 1
|
95 | }
|
96 |
|
97 |
|
98 | if (a.markdown && b.markdown) {
|
99 | return compareOrders(a, b)
|
100 | }
|
101 | return 0
|
102 | })
|
103 |
|
104 | let lastRouteWithContent
|
105 | const routesPrevNext = routes.reduce((prev, route, i) => {
|
106 |
|
107 |
|
108 | prev.push(route)
|
109 | if (route.markdown || route.component) {
|
110 | if (lastRouteWithContent !== undefined) {
|
111 | prev[lastRouteWithContent].next = {
|
112 | name: route.name,
|
113 | path: route.path
|
114 | }
|
115 | prev[i].prev = {
|
116 | name: prev[lastRouteWithContent].name,
|
117 | path: prev[lastRouteWithContent].path
|
118 | }
|
119 | }
|
120 | lastRouteWithContent = i
|
121 | }
|
122 | return prev
|
123 | }, [])
|
124 |
|
125 | const flatRoutes = routesPrevNext.map(route => {
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | if (route.redirect) {
|
131 | const directRoute = routes.find(r => r.path === route.redirect)
|
132 | if (directRoute && directRoute.redirect) {
|
133 | return {
|
134 | ...route,
|
135 | redirect: directRoute.redirect
|
136 | }
|
137 | }
|
138 | }
|
139 | return route
|
140 | })
|
141 | export default [
|
142 | {
|
143 | path: '/',
|
144 | exact: true,
|
145 | component: Home,
|
146 | redirect: HOME_PATH === '/' ? null : HOME_PATH
|
147 | },
|
148 | {
|
149 | path: '/search',
|
150 | exact: true,
|
151 | component: Search
|
152 | },
|
153 | ...flatRoutes
|
154 | ]
|
155 |
|
156 | function flatten(arr) {
|
157 | if (!arr.length) {
|
158 | return arr
|
159 | }
|
160 | return arr.reduce((prev, curr) => prev.concat(Array.isArray(curr) ? flatten(curr) : curr), [])
|
161 | }
|