-
-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathsanitize.ts
82 lines (71 loc) · 2.33 KB
/
sanitize.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import type { EntryRoute, RouteManifest } from "@remix-run/react/dist/routes.js"
type Route = Pick<EntryRoute, "path" | "parentId" | "id" | "hasErrorBoundary">
/**
* Helper method used to convert remix route conventions to url segments
* @param chunk Chunk to convert
* @returns Returns the converted chunk
*/
export const convertRemixPathToUrl = (routes: RouteManifest<Route>, route: Route) => {
let currentRoute: Route | null = route
const path = []
while (currentRoute) {
path.push(currentRoute.path)
if (!currentRoute.parentId) break
if (!routes[currentRoute.parentId]) break
currentRoute = routes[currentRoute.parentId]
}
const output = path.reverse().filter(Boolean).join("/")
return output === "" ? "/" : output
}
export const findParentErrorBoundary = (routes: RouteManifest<Route>, route: Route) => {
let currentRoute: Route | null = route
while (currentRoute) {
const hasErrorBoundary = currentRoute.hasErrorBoundary
if (hasErrorBoundary) return { hasErrorBoundary, errorBoundaryId: currentRoute.id }
if (!currentRoute.parentId) break
if (!routes[currentRoute.parentId]) break
currentRoute = routes[currentRoute.parentId]
}
return { hasErrorBoundary: false, errorBoundaryId: null }
}
export const tryParseJson = <T>(json: string | null): T | undefined => {
if (!json) return undefined
try {
return JSON.parse(json)
} catch (e) {
return undefined
}
}
interface RawNodeDatum {
name: string
attributes?: Record<string, string | number | boolean>
children?: RawNodeDatum[]
errorBoundary: { hasErrorBoundary: boolean; errorBoundaryId: string | null }
}
const constructTree = (routes: Record<string, Route>, parentId?: string): RawNodeDatum[] => {
const nodes: RawNodeDatum[] = []
const routeKeys = Object.keys(routes)
for (const key of routeKeys) {
const route = routes[key]
if (route.parentId === parentId) {
const url = convertRemixPathToUrl(routes, route)
const node: RawNodeDatum = {
name: url,
attributes: {
...route,
url,
},
errorBoundary: findParentErrorBoundary(routes, route),
children: constructTree(routes, route.id),
}
nodes.push(node)
}
}
return nodes
}
export const createRouteTree = (routes: RouteManifest<Route>) => {
return constructTree(routes)
}
export const uppercaseFirstLetter = (str: string) => {
return str.charAt(0).toUpperCase() + str.slice(1)
}