From 027a7875d8d85b136ba75ae3d410a3a79a7b9f8c Mon Sep 17 00:00:00 2001 From: Hyperling Date: Mon, 2 Nov 2026 08:11:35 -0700 Subject: [PATCH] main, implement an 'assets' folder for files needed at the website's root, allows having a local favicon and images. --- main.js | 114 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 30 deletions(-) diff --git a/main.js b/main.js index e35f4ae..966fe5c 100755 --- a/main.js +++ b/main.js @@ -26,6 +26,10 @@ let pages = []; const pages_dir = "./pages/"; const file_types = ["php", "sh"]; +let assets = []; +const asset_dir = "./assets/"; +const asset_types = ['png', 'svg', 'ico', 'webmanifest', 'jpg']; + let ports = []; // Check parameters for numeric port numbers. process.argv.forEach(function (val, index, array) { @@ -46,6 +50,8 @@ const stringsToRemove = [ //// Functions //// +// Compact HTML and remove unnecessary content like comments and whitespace. +// May help with performance for slower connections. Also more professional. async function mini(html) { //console.log(`html=${html}`); const minified = await minify(html, { @@ -58,6 +64,38 @@ async function mini(html) { return minified.toString(); } +// Check extension and guess a MIME type. +function getMIME(extension) { + let mime; + switch (extension) { + case "apk": + mime = "application/vnd.android.package-archive"; + break; + case "jpg": + case "jpeg": + mime = "image/jpeg"; + break; + case "png": + mime = "image/png"; + break; + case "html": + mime = "text/html"; + break; + case "zip": + mime = "application/zip"; + break; + case "md": + case "txt": + case "csv": + mime = "text/*"; + break; + default: + mime = "application/" + extension; + break; + } + return mime; +} + /* Code exists inside a main function so that we may use async/await. */ async function main() { @@ -73,7 +111,7 @@ async function main() { next(); }); - /* Loop through all file in the pages subdirectory and add the allowed + /* Loop through all files in the pages subdirectory and add the allowed // file types into the pages array for automatic router creation. */ console.log("...Starting Main..."); @@ -94,6 +132,26 @@ async function main() { console.log(" * Pages loaded: ", pages); //return; // Stop execution FORTESTING + /* Loop through the assets folder and grab favicons, manifests, etc. and + // allow them to be accessed via the root of the website, such as a favicon + // at 'https://hyperling.com/favicon.ico'. May help with SEO! + */ + let ls_assets = await fs.promises.readdir(asset_dir); + if (DEBUG) console.log("DEBUG: Results of ls_assets, ", ls_assets); + for (let file of ls_assets) { + let file_test = file.split("."); + //let file_name = file_test[0]; // not needed (yet) + let file_type = file_test[file_test.length - 1]; + if (asset_types.includes(file_type)) { + if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added."); + assets[file] = asset_dir + file; + console.log(" * Added asset", file); + } else { + if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping."); + } + } + console.log(" * Assets loaded: ", assets); + /* Create both an XML and HTML sitemap based on these entries. XML is used for // bots like SEO scrapers. HTML will be for human users looking for a list of // all pages. Some are not in the menu. Generated an example XML sitemap at @@ -202,6 +260,30 @@ async function main() { `; + console.log(" * Creating routers for assets"); + for (let key in assets) { + console.log(" * * Adding /" + key); + router.get('/' + key, function (req, res) { + console.log("asset response to", req.socket.remoteAddress, "asking for", req.url) + + // Build variables. + const file = "./assets/" + req.path; + const extensions = req.path.split("."); + const extension = extensions[extensions.length-1]; + let mime = getMIME(extension); + + // Return the file + res.contentType(mime); + let f = fs.createReadStream(file) + .on("error", function(e) { + res.contentType("text/plain"); + res.send(404, "Asset Not Found"); + }) + .pipe(res) + ; + }); + } + // Provide sitemap.xml file for "SEO". // TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE" console.log(" * Creating router for sitemap.xml"); @@ -237,35 +319,7 @@ async function main() { const file = "." + req.path; const extensions = req.path.split("."); const extension = extensions[extensions.length-1]; - - // Check extension and guess a MIME type. - let mime; - switch (extension) { - case "apk": - mime = "application/vnd.android.package-archive"; - break; - case "jpg": - case "jpeg": - mime = "image/jpeg"; - break; - case "png": - mime = "image/png"; - break; - case "html": - mime = "text/html"; - break; - case "zip": - mime = "application/zip"; - break; - case "md": - case "txt": - case "csv": - mime = "text/*"; - break; - default: - mime = "application/" + extension; - break; - } + let mime = getMIME(extension); // Return the file res.contentType(mime);