From 014d0e56c8544df4f21acc859ce0fd00f3ed0511 Mon Sep 17 00:00:00 2001 From: Andy Burke Date: Mon, 26 Jan 2026 23:32:51 -0800 Subject: [PATCH] feature: allow for fallback includes --- README.md | 9 +- deno.json | 2 +- handlers/html.ts | 132 ++++++++++-------- tests/www/includes/index.html | 4 +- tests/www/includes/test_include.html | 2 +- tests/www/includes/with_lots_of_includes.html | 8 +- tests/www/includes/with_markdown.html | 2 +- tests/www/includes/with_text.html | 2 +- 8 files changed, 93 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 6c0ea6e..4c47374 100644 --- a/README.md +++ b/README.md @@ -37,14 +37,17 @@ The default handlers are: ``` - + - + diff --git a/deno.json b/deno.json index da044ae..3e6e490 100644 --- a/deno.json +++ b/deno.json @@ -1,7 +1,7 @@ { "name": "@andyburke/serverus", "description": "A flexible HTTP server for mixed content. Throw static files, markdown, Typescript and (hopefully, eventually) more into a directory and serverus can serve it up a bit more like old-school CGI.", - "version": "0.15.0", + "version": "0.16.0", "license": "MIT", "exports": { ".": "./serverus.ts", diff --git a/handlers/html.ts b/handlers/html.ts index 111c170..c161283 100644 --- a/handlers/html.ts +++ b/handlers/html.ts @@ -3,11 +3,16 @@ * @module */ -import * as path from '@std/path'; -import { md_to_html } from './markdown.ts'; +import * as fs from "@std/fs"; +import * as path from "@std/path"; +import { md_to_html } from "./markdown.ts"; // https://stackoverflow.com/a/75205316 -const replaceAsync = async (str: string, regex: RegExp, asyncFn: (match: any, ...args: any) => Promise) => { +const replaceAsync = async ( + str: string, + regex: RegExp, + asyncFn: (match: any, ...args: any) => Promise, +) => { const promises: Promise[] = []; str.replace(regex, (match, ...args) => { promises.push(asyncFn(match, ...args)); @@ -17,53 +22,69 @@ const replaceAsync = async (str: string, regex: RegExp, asyncFn: (match: any, .. return str.replace(regex, () => data.shift()); }; -const SSI_REGEX: RegExp = /\<\!--\s+#include\s+(?.*?)\s*=\s*["'](?.*?)['"]\s+-->/mg; export async function load_html_with_ssi(html_file: string): Promise { + const directory = path.dirname(html_file); const html_file_content: string = await Deno.readTextFile(html_file); const processed: string = await replaceAsync( html_file_content, - SSI_REGEX, - async (_match, type, location, index): Promise => { - switch (type) { - case 'file': { - const directory = path.dirname(html_file); - const resolved = path.resolve(path.join(directory, location)); - if (!resolved.startsWith(Deno.cwd())) { - console.error( - `Cannot include files above the working directory (${Deno.cwd()}): ${location} ${html_file}:${index}` - ); - break; - } + /\<\!--\s+#include\s+(?.*?)\s*-->/gm, + async (_match, directive, index): Promise => { + const file_include_options = Array.from( + directive.matchAll(/(?