apache-autoindex-parse
Version:
parse apache's autoindex html files
154 lines (152 loc) • 6.35 kB
JavaScript
//#region src/test-utils.ts
/**
* Generates HTML content for Apache-style directory index listings.
*
* This function creates HTML that mimics Apache's autoindex module output,
* supporting different format types (F0, F1, F2) that correspond to different
* Apache autoindex display styles.
*
* @param {Entry[]} entries - Array of directory entries to display in the listing
* @param {AutoIndexFormat} format - The Apache autoindex format type ("F0", "F1", or "F2")
* - F0: Simple unordered list format
* - F1: Preformatted text with columns and icons
* - F2: HTML table format with sortable columns
* @param {GenerateHtmlOptions} options - Configuration options for the HTML generation
* @returns {string} Complete HTML document string representing the directory index
*
* @example
* ```typescript
* import { generateAutoIndexHtml } from "apache-autoindex-parse/test-utils";
*
* const entries = [
* { type: "directory", name: "docs", path: "docs/", lastModified: Date.now() },
* { type: "file", name: "README.md", path: "README.md", lastModified: Date.now() }
* ];
*
* const html = generateAutoIndexHtml(entries, "F1", {
* title: "Index of /mydir",
* includeParent: true
* });
* ```
*/
function generateAutoIndexHtml(entries, format, options = {}) {
const { title = "Index of /", includeParent = true, headerContent } = options;
const header = `
<html>
<head>
<title>${title}</title>
</head>
<body>`;
const footer = `</body></html>`;
let content = "";
if (headerContent) content += `<div style="padding: 0.5em">${headerContent}</div>\n<hr/>\n`;
if (format === "F0") content += generateF0Content(entries, includeParent, title);
else if (format === "F1") content += generateF1Content(entries, includeParent, title);
else if (format === "F2") content += generateF2Content(entries, includeParent, title);
return header + content + footer;
}
function generateF0Content(entries, includeParent, title) {
let content = `<h1>${title}</h1>\n<ul>`;
if (includeParent) content += `<li><a href="/"> Parent Directory</a></li>\n`;
for (const entry of entries) {
const href = entry.path;
const name = entry.type === "directory" ? `${entry.name}/` : entry.name;
content += `<li><a href="${href}"> ${name}</a></li>\n`;
}
content += "</ul>";
return content;
}
function generateF1Content(entries, includeParent, title) {
let content = `<h1>${title}</h1>\n<pre>`;
content += `<img src="/icons/blank.gif" alt="Icon "> <a href="?C=N;O=D;F=1">Name</a> <a href="?C=M;O=A;F=1">Last modified</a> <a href="?C=S;O=A;F=1">Size</a> <a href="?C=D;O=A;F=1">Description</a><hr>`;
if (includeParent) content += `<img src="/icons/back.gif" alt="[PARENTDIR]"> <a href="/">Parent Directory</a> - \n`;
for (const entry of entries) {
const isDir = entry.type === "directory";
const icon = isDir ? `<img src="/icons/folder.gif" alt="[DIR]">` : `<img src="/icons/text.gif" alt="[TXT]">`;
const name = isDir ? `${entry.name}/` : entry.name;
const href = entry.path;
const date = entry.lastModified ? new Date(entry.lastModified).toISOString().slice(0, 16).replace("T", " ") : "";
const size = isDir ? "-" : "0";
content += `${icon} <a href="${href}">${name.padEnd(24)}</a> ${date.padEnd(17)} ${size.padStart(4)} \n`;
}
content += "<hr></pre>";
return content;
}
function generateF2Content(entries, includeParent, title) {
let content = `<h1>${title}</h1>\n <table>\n`;
content += ` <tr><th valign="top"> </th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>\n`;
content += ` <tr><th colspan="5"><hr></th></tr>\n`;
if (includeParent) content += `<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/">Parent Directory</a></td><td> </td><td align="right"> - </td><td> </td></tr>\n`;
for (const entry of entries) {
const isDir = entry.type === "directory";
const icon = isDir ? `<img src="/icons/folder.gif" alt="[DIR]">` : `<img src="/icons/text.gif" alt="[TXT]">`;
const name = isDir ? `${entry.name}/` : entry.name;
const href = entry.path;
const date = entry.lastModified ? new Date(entry.lastModified).toISOString().slice(0, 16).replace("T", " ") : " ";
content += `<tr><td valign="top">${icon}</td><td><a href="${href}">${name}</a></td><td align="right">${date} </td><td align="right">${isDir ? " - " : " 0 "}</td><td> </td></tr>\n`;
}
content += ` <tr><th colspan="5"><hr></th></tr>\n</table>`;
return content;
}
/**
* Creates a sample array of directory entries for testing purposes.
*
* This utility function generates a predefined set of entries that includes
* both directories and files with realistic timestamps. It's useful for
* testing the Apache autoindex parsing functionality or generating sample
* HTML outputs.
*
* @returns {Entry[]} An array of sample entries containing:
* - Two directories: "docs" and "src"
* - Two files: "README.md" and "package.json"
* Each entry includes appropriate timestamps set to different times in the past
*
* @example
* ```typescript
* import { createSampleEntries, generateAutoIndexHtml } from "apache-autoindex-parse/test-utils";
*
* const entries = createSampleEntries();
* const html = generateAutoIndexHtml(entries, "F1");
* console.log(html); // Outputs HTML with sample directory listing
* ```
*
* @example
* ```typescript
* // Use for testing parsing functionality
* import { createSampleEntries } from "apache-autoindex-parse/test-utils";
*
* const sampleData = createSampleEntries();
* // sampleData contains predefined entries for consistent testing
* ```
*/
function createSampleEntries() {
return [
{
type: "directory",
name: "docs",
path: "docs/",
lastModified: Date.now() - 864e5
},
{
type: "directory",
name: "src",
path: "src/",
lastModified: Date.now() - 36e5
},
{
type: "file",
name: "README.md",
path: "README.md",
lastModified: Date.now() - 18e5
},
{
type: "file",
name: "package.json",
path: "package.json",
lastModified: Date.now() - 72e5
}
];
}
//#endregion
exports.createSampleEntries = createSampleEntries;
exports.generateAutoIndexHtml = generateAutoIndexHtml;