- routes.js is now config.json - routes and siteglobals have been merged into one singular object inside config.json - globals are pulled in during main.ts initialization
161 lines
5.5 KiB
TypeScript
161 lines
5.5 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { type RouteLocationNormalizedLoaded, type RouteRecordRaw } from 'vue-router'
|
|
import type {
|
|
GalleryListDefinition,
|
|
HeaderEntry,
|
|
Link,
|
|
ArticleListDefinition,
|
|
RouteDefinition,
|
|
SiteGlobals,
|
|
TemplateType,
|
|
} from '@goldenwere/mackenzii-types'
|
|
|
|
const markdownBody = () => import ('./views/markdown/markdown.vue')
|
|
const articleViewBody = () => import ('./views/article/article-view.vue')
|
|
const galleryViewBody = () => import ('./views/gallery/gallery-view.vue')
|
|
const mediaListBody = () => import ('./views/shared/media-list.vue')
|
|
|
|
export const templates: Record<TemplateType, () => Promise<any>> = {
|
|
'markdown': markdownBody,
|
|
'article-list': mediaListBody,
|
|
'gallery-list': mediaListBody,
|
|
}
|
|
|
|
export const createRoutes = (globals: SiteGlobals): RouteRecordRaw[] => {
|
|
const routeRecord: RouteRecordRaw[] = []
|
|
|
|
Object.keys(globals.routes).forEach(route => {
|
|
const toPush: RouteRecordRaw = {
|
|
name: globals.routes[route].id,
|
|
path: route,
|
|
component: templates[globals.routes[route].template],
|
|
}
|
|
|
|
if (globals.routes[route].template === 'article-list') {
|
|
routeRecord.push({
|
|
name: `${globals.routes[route].id}: View Article`,
|
|
path: `${route}/view`,
|
|
component: articleViewBody,
|
|
props: route => ({ id: route.query.id }),
|
|
})
|
|
} else if (globals.routes[route].template === 'gallery-list') {
|
|
toPush.props = route => ({ variants: (route.query.v as string || '').split(';') })
|
|
|
|
routeRecord.push({
|
|
name: `${globals.routes[route].id}: View Entry`,
|
|
path: `${route}/view`,
|
|
component: galleryViewBody,
|
|
props: route => ({ variants: (route.query.v as string || '').split(';') }),
|
|
})
|
|
}
|
|
|
|
routeRecord.push(toPush)
|
|
})
|
|
|
|
return routeRecord
|
|
}
|
|
|
|
export const useRouteStore = defineStore('routeStore', {
|
|
state: () => ({
|
|
_header: [] as HeaderEntry[],
|
|
_routes: {} as Record<string, RouteRecordRaw & RouteDefinition>,
|
|
_globals: {} as SiteGlobals,
|
|
|
|
_routesAlreadyWarned: {} as Record<string, boolean>,
|
|
_breadcrumbs: [] as Link[],
|
|
_cachedFiles: {} as { [path: string]: any },
|
|
}),
|
|
actions: {
|
|
/**
|
|
* Adds a file to the cache
|
|
* @param path the path to the file to cache
|
|
* @param result the parsed file to cache
|
|
*/
|
|
cacheFile<T>(path: string, result: T) {
|
|
this._cachedFiles[path] = result
|
|
},
|
|
/**
|
|
* Retrieves a file from the cache if it is defined
|
|
* @param path the path to the file to retrieve
|
|
* @returns the parsed and cached file or undefined
|
|
*/
|
|
getFile<T>(path: string) {
|
|
return this._cachedFiles[path] as T | undefined
|
|
},
|
|
/**
|
|
* Determines whether a route has showed a warning or not
|
|
* @param route the route to check
|
|
* @returns `true` if previously warned, `false` otherwise
|
|
*/
|
|
doesRouteRememberWarning(route: string) {
|
|
return this._routesAlreadyWarned[route]
|
|
},
|
|
|
|
/**
|
|
* Remembers whether a route showed a warning or not
|
|
* @param route the route to remember
|
|
*/
|
|
rememberRouteWarning(route: string) {
|
|
this._routesAlreadyWarned[route] = true
|
|
},
|
|
|
|
/**
|
|
* Sets the breadcrumbs array in the store
|
|
* @param route the current route
|
|
* @param resolvedTitle a title related to dynamic content loaded from a list-based template when in the view for that list
|
|
*/
|
|
setBreadcrumbs(route: RouteLocationNormalizedLoaded, resolvedTitle?: string) {
|
|
// breadcrumb shouldn't show on home page
|
|
if (route.path === '/') {
|
|
this._breadcrumbs = []
|
|
return
|
|
}
|
|
|
|
// split '/my/path' into '', 'my', 'path'
|
|
const split = route.path.split('/')
|
|
// adjust for root; '', 'my', 'path' becomes '/', 'my', 'path'
|
|
split[0] = '/'
|
|
// compile paths from the split through some array functions
|
|
const paths = [] as string[]
|
|
split.forEach((val, i) => {
|
|
// get the paths leading up to the current index plus the next one
|
|
const sliced = split.slice(0, i + 1)
|
|
// reduce converts '/', 'my', 'path' to a breadcrumb trail '/', '/my', '/my/path'
|
|
// the conditional '/' check prevents accidentally prepending '//' to each breadcrumb
|
|
paths.push(sliced.reduce((prev, curr) => prev === '/' ? `/${curr}` : `${prev}/${curr}`))
|
|
})
|
|
// map paths into breadcrumb info
|
|
this._breadcrumbs = paths.map((path, index) => {
|
|
return {
|
|
href: path,
|
|
// the tail end should be the resolvedTitle from a view route if specified,
|
|
// otherwise use the title in the route definition
|
|
caption: index === paths.length - 1 && !!resolvedTitle ? resolvedTitle : this._routes[path]?.title,
|
|
}
|
|
})
|
|
}
|
|
},
|
|
})
|
|
|
|
export const initializeRouteStore = (routerRoutes: readonly RouteRecordRaw[], globals: SiteGlobals) => {
|
|
const routeStore = useRouteStore()
|
|
Object.keys(globals.routes).forEach(route => {
|
|
routeStore._routes[route] = {
|
|
...routerRoutes.find(other => other.path === route) as RouteRecordRaw,
|
|
...globals.routes[route] as RouteDefinition,
|
|
}
|
|
if (globals.routes[route].template === 'article-list' || globals.routes[route].template === 'gallery-list') {
|
|
routeStore._routes[`${route}/view`] = {
|
|
...routerRoutes.find(other => other.path === `${route}/view`) as RouteRecordRaw,
|
|
...(globals.routes[route] as ArticleListDefinition | GalleryListDefinition).view,
|
|
} as any
|
|
}
|
|
})
|
|
routeStore._globals = globals
|
|
}
|
|
|
|
export type RouteStoreDefinition = Omit<
|
|
ReturnType<typeof useRouteStore>,
|
|
keyof ReturnType<typeof defineStore>
|
|
>
|
|
|