зеркало из https://github.com/github/docs.git
82 строки
2.9 KiB
JavaScript
82 строки
2.9 KiB
JavaScript
import path from 'path'
|
|
import { existsSync } from 'fs'
|
|
|
|
import { ROOT } from '../lib/constants.js'
|
|
import Page from '../lib/page.js'
|
|
import { languagePrefixPathRegex } from '../lib/languages.js'
|
|
|
|
const englishPrefixRegex = /^\/en(\/|$)/
|
|
const CONTENT_ROOT = path.join(ROOT, 'content')
|
|
|
|
export default async function findPage(
|
|
req,
|
|
res,
|
|
next,
|
|
// Express won't execute these but it makes it easier to unit test
|
|
// the middleware.
|
|
{ isDev = process.env.NODE_ENV === 'development', contentRoot = CONTENT_ROOT } = {},
|
|
) {
|
|
// Filter out things like `/will/redirect` or `/_next/data/...`
|
|
if (!languagePrefixPathRegex.test(req.pagePath)) {
|
|
return next()
|
|
}
|
|
|
|
let page = req.context.pages[req.pagePath]
|
|
if (page && isDev && englishPrefixRegex.test(req.pagePath)) {
|
|
page = await rereadByPath(req.pagePath, contentRoot, req.context.currentVersion)
|
|
|
|
// This can happen if the page we just re-read has changed which
|
|
// versions it's available in (the `versions` frontmatter) meaning
|
|
// it might no longer be available on the current URL.
|
|
if (!page.applicableVersions.includes(req.context.currentVersion)) {
|
|
return res
|
|
.status(404)
|
|
.send(
|
|
`After re-reading the page, '${req.context.currentVersion}' is no longer an applicable version. ` +
|
|
'A restart is required.',
|
|
)
|
|
}
|
|
}
|
|
|
|
if (page) {
|
|
req.context.page = page
|
|
req.context.page.version = req.context.currentVersion
|
|
|
|
// We can't depend on `page.hidden` because the dedicated search
|
|
// results page is a hidden page but it needs to offer all possible
|
|
// languages.
|
|
if (page.relativePath.startsWith('early-access')) {
|
|
// Override the languages to be only English
|
|
req.context.languages = {
|
|
en: req.context.languages.en,
|
|
}
|
|
}
|
|
}
|
|
|
|
return next()
|
|
}
|
|
|
|
async function rereadByPath(uri, contentRoot, currentVersion) {
|
|
const languageCode = uri.match(languagePrefixPathRegex)[1]
|
|
const withoutLanguage = uri.replace(languagePrefixPathRegex, '/')
|
|
const withoutVersion = withoutLanguage.replace(`/${currentVersion}`, '')
|
|
// TODO: Support loading translations the same way.
|
|
// NOTE: No one is going to test translations like this in development
|
|
// but perhaps one day we can always and only do these kinds of lookups
|
|
// at runtime.
|
|
const possible = path.join(contentRoot, withoutVersion)
|
|
const filePath = existsSync(possible) ? path.join(possible, 'index.md') : possible + '.md'
|
|
const relativePath = path.relative(contentRoot, filePath)
|
|
const basePath = contentRoot
|
|
|
|
// Remember, the Page.init() can return a Promise that resolves to falsy
|
|
// if it can't read the file in from disk. E.g. a request for /en/non/existent.
|
|
// In other words, it's fine if it can't be read from disk. It'll get
|
|
// handled and turned into a nice 404 message.
|
|
return await Page.init({
|
|
basePath,
|
|
relativePath,
|
|
languageCode,
|
|
})
|
|
}
|