diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/index.ts | 8 | ||||
| -rw-r--r-- | app/middlewares/blogs.ts | 28 | ||||
| -rw-r--r-- | app/middlewares/index.ts | 26 | ||||
| -rw-r--r-- | app/pages.ts | 112 | ||||
| -rw-r--r-- | app/routes/blog/router.ts | 5 | ||||
| -rw-r--r-- | app/routes/page/router.ts | 3 |
6 files changed, 108 insertions, 74 deletions
diff --git a/app/index.ts b/app/index.ts index 664a751..7d73eb4 100644 --- a/app/index.ts +++ b/app/index.ts @@ -4,6 +4,8 @@ import * as page from './routes/page/router.js'; import * as blog from './routes/blog/router.js'; import { logger } from './logger.js' import { PageDirectory } from './pages.js'; +import { directory } from './middlewares/index.js'; +import { blogs } from './middlewares/blogs.js'; dotenv.config() @@ -16,6 +18,10 @@ app.use(express.static('static', { maxAge: '1d' })); +const pageDirectory = new PageDirectory(process.env.PAGES_DIR); +app.use(directory(pageDirectory)); +app.use(blogs(pageDirectory)); + app.use(blog.router); app.use(page.router); @@ -36,7 +42,7 @@ const exit = () => { }) } -PageDirectory.rebuild('pages'); +pageDirectory.loadFromDisk(); process.on('SIGINT', exit); process.on('SIGTERM', exit); diff --git a/app/middlewares/blogs.ts b/app/middlewares/blogs.ts index 8fd07c6..e1f5433 100644 --- a/app/middlewares/blogs.ts +++ b/app/middlewares/blogs.ts @@ -1,17 +1,19 @@ import { PageDirectory } from "../pages.js"; -export const blogs = ((req, res, next) => { - let blogs = []; - for (const page of Object.values(PageDirectory.pages)) { - if (page.route.startsWith('blog/')) { - blogs.push(page); +export const blogs = (pageDirectory: PageDirectory) => { + return ((req, res, next) => { + let blogs = []; + for (const page of Object.values(pageDirectory.pages)) { + if (page.route.startsWith('blog/')) { + blogs.push(page); + } } - } - - blogs.sort((a, b) => { - return b.metadata.date.getTime() - a.metadata.date.getTime(); + + blogs.sort((a, b) => { + return b.metadata.date.getTime() - a.metadata.date.getTime(); + }); + + res.locals.blogs = blogs; + next(); }); - - res.locals.blogs = blogs; - next(); -}); +} diff --git a/app/middlewares/index.ts b/app/middlewares/index.ts index 81431ca..b5fcd34 100644 --- a/app/middlewares/index.ts +++ b/app/middlewares/index.ts @@ -1,16 +1,18 @@ import { PageDirectory } from "../pages.js"; -export const page = ((req, res, next) => { - const path = req.originalUrl == "/" ? 'index' : req.originalUrl.substring(1); - res.locals.path = path; - - const page = PageDirectory.get(path); +export const directory = (pageDirectory: PageDirectory) => { + return ((req, res, next) => { + const path = req.originalUrl == "/" ? 'index' : req.originalUrl.substring(1); + res.locals.path = path; + + const page = pageDirectory.get(path); + + if (!page) { + next(); + return; + } - if (!page) { + res.locals.page = page; next(); - return; - } - - res.locals.page = page; - next(); -}); + }); +} diff --git a/app/pages.ts b/app/pages.ts index 3bef4a9..a7057da 100644 --- a/app/pages.ts +++ b/app/pages.ts @@ -3,9 +3,9 @@ import glob from 'glob'; import { logger } from './logger.js' import { marked } from 'marked'; import matter from 'gray-matter'; +import chokidar from 'chokidar'; export function buildPage(page: Page) { - logger.info(`Building ${page.path}`); try { const result = matter(page.raw); const metadata = result.data; @@ -19,61 +19,93 @@ export function buildPage(page: Page) { } } -export namespace PageDirectory { - export const pages: Record<string, Page> = {}; - export let lastBuild: number; +function loadRaw(path: string): string { + return readFileSync(`${path}`, 'utf-8'); +} + +export class PageDirectory { + private pagesPath: string; + + public pages: Record<string, Page> = {}; + public lastFullBuild: number; - export const rebuild = (pagePath: string): boolean => { - for (const page in pages) { - delete pages[page]; + constructor(pagesPath: string) { + this.pagesPath = pagesPath; + } + + public loadFromDisk = () => { + for (const page in this.pages) { + delete this.pages[page]; } - const localPages = glob.sync(`**/*.{md,html}`, { cwd: pagePath }) + const localPages = glob.sync(`**/*.{md,html}`, { cwd: this.pagesPath }) - // Load page content - localPages.forEach(page => { - let route = page.replace(/\.[^.]*$/,'') - let name = /[^/]*$/.exec(route)[0]; - let path = `${pagePath}/${page}` - let raw: string; - try { - raw = loadRaw(path); - } catch (e) { - logger.error(`Failed to read page ${path}: ${e.message}`); - return; - } + localPages.forEach(this.loadPage); - pages[route] = { - route: route, - name: name, - path: path, - raw: raw, - buildTime: 0, - metadata: { - title: "A Page" - } - } + this.lastFullBuild = Date.now(); + + const watcher = chokidar.watch('.', { + persistent: true, + cwd: this.pagesPath, + ignoreInitial: true, }); - // Build pages - Object.values(pages).forEach(page => buildPage(page)); + const onPageChange = (page: string) => { + logger.info(`File ${page} has been modified`); + this.loadPage(page); + } + + const onPageRemoval = (page: string) => { + logger.info(`File ${page} has been removed`); + this.removePage(page); + } + + watcher.on('add', onPageChange); + watcher.on('change', onPageChange); + watcher.on('unlink', onPageRemoval); + } + + public loadPage = (page: string): void => { + logger.info(`Building page ${page}`); + let route = page.replace(/\.[^.]*$/,'') + let name = /[^/]*$/.exec(route)[0]; + let path = `${this.pagesPath}/${page}` + let raw: string; + try { + raw = loadRaw(path); + } catch (e) { + logger.error(`Failed to read page ${path}: ${e.message}`); + return; + } - lastBuild = Date.now(); - return true; + this.pages[route] = { + route: route, + name: name, + path: path, + raw: raw, + buildTime: 0, + metadata: { + title: "A Page" + } + } + + buildPage(this.pages[route]); + } + + public removePage = (page: string): void => { + logger.info(`Unloading page ${page}`); + let route = page.replace(/\.[^.]*$/,'') + delete this.pages[route]; } - export function get(name: string): Page { - const page = pages[name]; + public get(name: string): Page { + const page = this.pages[name]; if (!page) { return undefined; } return page; } - - function loadRaw(path: string): string { - return readFileSync(`${path}`, 'utf-8'); - } } export type Page = { diff --git a/app/routes/blog/router.ts b/app/routes/blog/router.ts index bbd09d5..933946b 100644 --- a/app/routes/blog/router.ts +++ b/app/routes/blog/router.ts @@ -1,12 +1,7 @@ import express from 'express'; -import { page } from '../../middlewares/index.js'; -import { blogs } from '../../middlewares/blogs.js'; export const router = express.Router({ mergeParams: true }); -router.use('/blog/:page?', page); -router.use('/blog/:page?', blogs); - router.get('/blog/:page?', (req, res, next) => { let page = res.locals.page; let index = !page || res.locals.path === 'blog'; diff --git a/app/routes/page/router.ts b/app/routes/page/router.ts index 5c0a39b..b1b9bc1 100644 --- a/app/routes/page/router.ts +++ b/app/routes/page/router.ts @@ -1,10 +1,7 @@ import express from 'express'; -import { page } from '../../middlewares/index.js'; export const router = express.Router({ mergeParams: true }); -router.use('/:page?', page); - router.get('/:page?', (req, res, next) => { let page = res.locals.page; if (!page) { |
