diff --git a/modules/hudozka-api/src/controllers/page.ts b/modules/hudozka-api/src/controllers/page.ts index 242b7040..3e043ea9 100644 --- a/modules/hudozka-api/src/controllers/page.ts +++ b/modules/hudozka-api/src/controllers/page.ts @@ -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 { + 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({ diff --git a/modules/hudozka-api/src/factory/page.ts b/modules/hudozka-api/src/factory/page.ts index ef6bb38d..7d0fee31 100644 --- a/modules/hudozka-api/src/factory/page.ts +++ b/modules/hudozka-api/src/factory/page.ts @@ -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, } } diff --git a/modules/hudozka-api/src/lib/url.js b/modules/hudozka-api/src/lib/url.js deleted file mode 100644 index d68c640d..00000000 --- a/modules/hudozka-api/src/lib/url.js +++ /dev/null @@ -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 diff --git a/modules/hudozka-api/src/lib/url.ts b/modules/hudozka-api/src/lib/url.ts new file mode 100644 index 00000000..f6c2bd5f --- /dev/null +++ b/modules/hudozka-api/src/lib/url.ts @@ -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] +} diff --git a/modules/hudozka-api/src/types.ts b/modules/hudozka-api/src/types.ts new file mode 100644 index 00000000..238157c9 --- /dev/null +++ b/modules/hudozka-api/src/types.ts @@ -0,0 +1,6 @@ +export type BreadcrumbPart = { + name: string + href: string +} + +export type Breadcrumb = BreadcrumbPart[]