initial breadcrumb builder
This commit is contained in:
1 parent
113fb9db77
commit
ebaebec835
5 files changed
+53
-46
No files matched your search
@@ -1,15 +1,25 @@
|
||||
import { Request, Response } from 'express'
|
||||
import Page from '../core/Page'
|
||||
import { getPathWithNoTrailingSlash } from '../lib/url'
|
||||
import { dropTrailingSlash, getPathWaterfall } from '../lib/url'
|
||||
import { encodePage } from '../factory/page'
|
||||
import { Breadcrumb } from '../types'
|
||||
|
||||
async function getBreadcrumbs(path: string): Promise<Breadcrumb> {
|
||||
const bc = getPathWaterfall(path)
|
||||
|
||||
return bc.map(href => ({
|
||||
name: href,
|
||||
href,
|
||||
}))
|
||||
}
|
||||
|
||||
export async function getItem(req: Request, res: Response) {
|
||||
const id = req.query.page
|
||||
const page = getPathWithNoTrailingSlash(id)
|
||||
const page = dropTrailingSlash(req.query.page)
|
||||
const breadcrumbs = await getBreadcrumbs(page)
|
||||
const resource = await Page.findByUrl(page)
|
||||
|
||||
|
||||
if (resource) {
|
||||
res.json(encodePage(resource))
|
||||
res.json(encodePage(resource, breadcrumbs))
|
||||
} else {
|
||||
res.status(404)
|
||||
res.json({
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { encodeImage } from './image'
|
||||
import Page from '../core/Page'
|
||||
import { Breadcrumb } from '../types'
|
||||
|
||||
export function encodePage(page) {
|
||||
export function encodePage(page: Page, breadcrumb: Breadcrumb) {
|
||||
return {
|
||||
id: page.id,
|
||||
title: page.title,
|
||||
@@ -8,5 +10,6 @@ export function encodePage(page) {
|
||||
data: page.data,
|
||||
preview: encodeImage(page.preview),
|
||||
tokens: page.tokens,
|
||||
breadcrumb,
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
function getPathWithNoTrailingSlash(path='') {
|
||||
path = path.charAt(path.length - 1) === '/'
|
||||
? path.substr(0, path.length - 1)
|
||||
: path
|
||||
return path.length === 0
|
||||
? '/'
|
||||
: path
|
||||
}
|
||||
|
||||
function isEqualPath(a, b, ignoreTrailingSlash = false) {
|
||||
return ignoreTrailingSlash
|
||||
? getPathWithNoTrailingSlash(a) === getPathWithNoTrailingSlash(b)
|
||||
: a === b
|
||||
}
|
||||
|
||||
function isMatchPathPattern(pattern, path, ignoreTrailingSlash = false) {
|
||||
const test = ignoreTrailingSlash
|
||||
? getPathWithNoTrailingSlash(path)
|
||||
: path
|
||||
return pattern.test(test)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* /article/* -> ^\/article\/[/\w\d-_]+\/?$
|
||||
*
|
||||
* @param url
|
||||
* @return {RegExp}
|
||||
*/
|
||||
function urlToPattern(url) {
|
||||
const u = url.replace('/*', '[/\\w\\d-_]+')
|
||||
const pattern = `^${u}/?$`
|
||||
|
||||
return new RegExp(pattern)
|
||||
}
|
||||
|
||||
exports.getPathWithNoTrailingSlash = getPathWithNoTrailingSlash
|
||||
exports.isMatchPathPattern = isMatchPathPattern
|
||||
exports.urlToPattern = urlToPattern
|
||||
exports.isEqualPath = isEqualPath
|
||||
@@ -0,0 +1,28 @@
|
||||
export function dropTrailingSlash(path: string) {
|
||||
if (path === '/' || path === '') {
|
||||
return '/'
|
||||
}
|
||||
|
||||
const lastChar = path.charAt(path.length - 1)
|
||||
if (lastChar === '/') {
|
||||
return path.substr(0, path.length - 1)
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
export function getPathWaterfall(path: string): string[] {
|
||||
const parts = path
|
||||
.split('/')
|
||||
.filter(Boolean)
|
||||
.reduce((acc, part, index, parts) => {
|
||||
const i = index + 1
|
||||
const item = `/${parts.slice(0, i).join('/')}`
|
||||
return [
|
||||
...acc,
|
||||
item
|
||||
]
|
||||
}, [])
|
||||
|
||||
return ['/', ...parts]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export type BreadcrumbPart = {
|
||||
name: string
|
||||
href: string
|
||||
}
|
||||
|
||||
export type Breadcrumb = BreadcrumbPart[]
|
||||
Reference in new issue
Block a user