UNPKG

ascaid

Version:

Hassle-free documentation generation powered by AsciiDoc

77 lines (62 loc) 2.13 kB
import { URL } from "node:url"; import fs from "node:fs/promises"; import path from "node:path"; import http from "node:http"; import browserSync from "browser-sync"; import { fileExists, invokeInDir } from "./utils.js"; import { adocConvert } from "./adoc-convert.js"; export const createAsciidocMiddleware = (rootDir, adoctorOptions = {}) => { const absoluteRootDir = path.resolve(rootDir); return async (request, res, next) => { try { const url = new URL(request.url, "http://localhost"); // https://nodejs.org/en/knowledge/file-system/security/introduction/ if (url.pathname.includes("\0")) { res.statusCode = 400; return res.end(http.STATUS_CODES[res.statusCode]); } if (/\.(adoc|asciidoc|acs)$/i.test(url.pathname)) { const adocPath = path.join(absoluteRootDir, url.pathname); const exists = await fileExists(adocPath); if (!exists || !adocPath.startsWith(absoluteRootDir)) { res.statusCode = 404; return res.end(http.STATUS_CODES[res.statusCode]); } const adoc = await fs.readFile(adocPath, { encoding: "utf8" }); let html = await invokeInDir(path.dirname(adocPath), () => { return adocConvert(adoc, adoctorOptions); }); res.setHeader("Content-Type", "text/html"); html = html.replace( /<\/head>/, `<script async src="//${request.headers.host}/browser-sync/browser-sync-client.js"></script></head>`, ); res.statusCode = 200; return res.end(html); } } catch (error) { return next(error); } next(); }; }; export const startAsciidocServer = async ( rootDir = ".", adoctorOptions = {}, ) => { const bs = browserSync.create(); bs.init({ files: "**/*.{adoc,asciidoc,acs}", server: rootDir, injectFileTypes: ["adoc", "asciidoc", "acs"], middleware: [createAsciidocMiddleware(rootDir, adoctorOptions)], directory: true, open: false, ui: false, logSnippet: true, watch: true, injectChanges: false, reloadOnRestart: true, }); return bs; };