67 lines
2.9 KiB
TypeScript
67 lines
2.9 KiB
TypeScript
/* Route-shape helpers for the reader experience.
|
|
|
|
An article route is a page of the open book drawn by ArticleBookStack —
|
|
pages laid out side by side, older ones parked with their spines showing —
|
|
while the article edit page and the new-article page remain plain,
|
|
full-height pages. Every language version of an article has an address of
|
|
its own — /wiki/<lang>/<identity>, English no different from the rest, so
|
|
/wiki/en/bayes-theorem and /wiki/fr/bayes-theorem sit side by side. The one
|
|
short form, /wiki/<slug> (what a wiki link to [[Bayes Theorem]] writes, and
|
|
what an old bookmark holds), names no language: the open-article middleware
|
|
reads which document the slug speaks and turns the address into that
|
|
version's own. */
|
|
|
|
const READER_PATH = /^\/wiki\/([^/]+?)\/?$/
|
|
const VERSION_READER_PATH = /^\/wiki\/([a-z]{2})\/([^/]+?)\/?$/
|
|
const WIKI_SUB_PATH = /^\/wiki\/[^/]+\/[^/]+/
|
|
|
|
/** What a reader address names: the article's identity, and which language
|
|
* version the address asks for (null for the short form, which asks for
|
|
* whichever version the slug itself speaks). */
|
|
export interface ReaderLocation {
|
|
identity: string
|
|
lang: string | null
|
|
}
|
|
|
|
export function parseReaderPath(path: string): ReaderLocation | null {
|
|
const version = VERSION_READER_PATH.exec(path)
|
|
// /wiki/<x>/edit is the editor whatever <x> is — never a version address
|
|
if (version && version[2]!.toLowerCase() !== 'edit') {
|
|
return { identity: decodeURIComponent(version[2]!), lang: version[1]! }
|
|
}
|
|
const plain = READER_PATH.exec(path)
|
|
if (plain) return { identity: decodeURIComponent(plain[1]!), lang: null }
|
|
return null
|
|
}
|
|
|
|
export function isReaderPath(path: string): boolean {
|
|
return parseReaderPath(path) !== null
|
|
}
|
|
|
|
export function wikiSlugFromPath(path: string): string | null {
|
|
return parseReaderPath(path)?.identity ?? null
|
|
}
|
|
|
|
/**
|
|
* The address one language version lives at: /wiki/<lang>/<identity>, the
|
|
* article's identity being the canonical version's slug — so every version of
|
|
* one article shares the last part of its address and differs only by the
|
|
* language in front. Documents carry their own stored slug, which no address
|
|
* needs: the wiki finds a version by (identity, language).
|
|
*/
|
|
export function versionHref(identity: string, language?: string): string {
|
|
const code = language?.trim().toLowerCase() || DEFAULT_LANGUAGE
|
|
return `/wiki/${encodeURIComponent(code)}/${encodeURIComponent(identity)}`
|
|
}
|
|
|
|
/**
|
|
* The "reading surface": the reader itself plus the edit/new-article pages —
|
|
* the pages that belong to the open book. The stack of open pages survives the
|
|
* whole session either way; this marks the pages outside it (the list, the
|
|
* graph, home), which are the places worth returning to once the last page is
|
|
* closed.
|
|
*/
|
|
export function isReadingSurface(path: string): boolean {
|
|
return isReaderPath(path) || WIKI_SUB_PATH.test(path) || path === '/new'
|
|
}
|