diff --git a/src/runTest.ts b/src/runTest.ts new file mode 100644 index 0000000..ec0522d --- /dev/null +++ b/src/runTest.ts @@ -0,0 +1,209 @@ +import { type TestInput, type TestOutput } from "./types"; + +function h(unsafe: string): string { + if (unsafe == null) { + return ""; + } + + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +export function runTest(input: TestInput): TestOutput { + if (input.regex == null || input.regex.length == 0) { + return { success: false, message: "No regex to test!" }; + } + + const options = input.option ? input.option.join("") : undefined; + + const html = []; + html.push( + '\n' + ); + + html.push("\t\n"); + html.push("\t\t\n"); + html.push("\t\t\n"); + html.push("\t\n"); + + html.push("\t\n"); + html.push("\t\t\n"); + html.push("\t\t\n"); + + html.push("\t\n"); + html.push("\t\t\n"); + html.push("\t\t\n"); + html.push("\t\n"); + html.push("
Regular Expression"); + html.push(h(input.regex)); + html.push("
Replacement"); + html.push(h(input.replacement)); + html.push("
Options"); + html.push(options ? h(options) : "(none)"); + html.push("
\n"); + + let compileTest: RegExp; + + try { + compileTest = new RegExp(input.regex, options); + } catch (err) { + const message = err instanceof Error ? err.message : `unknown error ${err}`; + return { + success: false, + message: `unable to create RegExp object: ${message}`, + html: html.join(""), + }; + } + + try { + html.push('\n'); + + html.push("\t"); + html.push("\t\t\n"); + html.push('\t\t\t\n'); + html.push("\t\t\t"); + html.push("\t\t\t"); + html.push("\t\t\t"); + html.push("\t\t\t"); + html.push("\t\t\t"); + html.push("\t\t\t"); + html.push("\t\t\t"); + html.push("\t\t\t"); + html.push("\t\t\n"); + html.push("\t\n"); + html.push("\t\n"); + + var count = 0; + + if (input.inputs != null) { + for (var loop = 0; loop < input.inputs.length; loop++) { + var target = input.inputs[loop]; + + if (target.length == 0) { + continue; + } + html.push("\t\t\n"); + + html.push('\t\t\t\n"); + + html.push("\t\t\t\n"); + + html.push("\t\t\t\n"); + + html.push("\t\t\t\n"); + + html.push("\t\t\t\n"); + + html.push("\t\t\t\n"); + + var regex = new RegExp(input.regex, options); + var result = regex.exec(target); + if (result == null) { + html.push('\t\t\t\n'); + } else { + var first = true; + + while (result != null) { + if (first == true) { + first = false; + } else { + html.push("\n"); + html.push('\t\t\t\n"); + } + + html.push("\t\t\t\n"); + + html.push("\t\t\t\n"); + + html.push("\t\t\t\n"); + + result = global ? regex.exec(target) : null; + } + } + html.push("\t\t\n"); + count++; + } + } + + if (count == 0) { + html.push("\t\t\n"); + html.push('\t\t\n"); + html.push("\t\t\n"); + } + + html.push("\t\n"); + html.push("
TestInputregex.test()input.replace()input.replaceAll()input.split()[]regex.exec().indexregex.exec()[]regex.lastIndex
'); + html.push(loop + 1); + html.push(""); + html.push(h(target)); + html.push(""); + html.push( + new RegExp(input.regex, options).test(target) ? "true" : "false" + ); + html.push(""); + html.push( + h(target.replace(new RegExp(input.regex, options), input.replacement)) + ); + html.push(""); + try { + html.push( + h( + target.replaceAll( + new RegExp(input.regex, options), + input.replacement + ) + ) + ); + } catch (replaceAllErr) { + const message = + replaceAllErr instanceof Error + ? replaceAllErr.message + : `unknown error ${replaceAllErr}`; + html.push(`${message}`); + } + html.push(""); + var splits = target.split(new RegExp(input.regex, options)); + for (var split = 0; split < splits.length; split++) { + html.push("["); + html.push(split); + html.push("]: "); + html.push(splits[split] == null ? "(null)" : h(splits[split])); + html.push("
"); + } + html.push("
(null)
'); + html.push("regex.exec()"); + html.push(""); + html.push(result.index); + html.push(""); + for (var capture = 0; capture < result.length; capture++) { + html.push("["); + html.push(capture); + html.push("]: "); + html.push( + result[capture] == null ? "(null)" : h(result[capture]) + ); + html.push("
"); + } + html.push("
"); + html.push(regex.lastIndex); + html.push("
'); + html.push("(no input to test)"); + html.push("
\n"); + } catch (err) { + const message = err instanceof Error ? err.message : `unknown error ${err}`; + return { + success: false, + message: `unable to run tests: ${message}`, + html: html.join(""), + }; + } + + return { + success: true, + html: html.join(""), + }; +} diff --git a/src/server.ts b/src/server.ts index 1b517b3..bcc3556 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,4 +1,6 @@ import type { Server } from "bun"; +import type { TestInput } from "./types"; +import { runTest } from "./runTest"; Bun.serve({ development: process.env.NODE_ENV !== "production", @@ -43,7 +45,7 @@ Bun.serve({ return handleJsonp(req, { success: false, - code: 'ENOTFOUND', + code: "ENOTFOUND", statusCode: 404, message: `Not Found: ${pathname}`, }); @@ -69,26 +71,56 @@ function handleJsonp(req: Request, data: Object): Response { }); } -function testJson(req: Request, server: Server): Response { - const body = req.body; +async function testJson(req: Request, server: Server): Promise { + let testInput: TestInput; - return handleJsonp(req, { - sucess: false, - html: ``, - }); + if (req.method === "POST") { + if (req.headers.get("content-type") === "application/json") { + testInput = await req.json(); + } else { + const data = await req.formData(); + console.log("formData", data); + + testInput = { + engine: "bun", + regex: data.get("regex") as string, + replacement: data.get("replacement") as string, + option: data.getAll("option") as string[], + inputs: data.getAll("input") as string[], + }; + } + } else { + const searchParams = new URL(req.url).searchParams; + testInput = { + engine: searchParams.get("engine") || "bun", + regex: searchParams.get("regex") || "", + replacement: searchParams.get("replacement") || "", + option: searchParams.getAll("option") as string[], + inputs: searchParams.getAll("input") as string[], + }; + console.log("searchParams", searchParams); + } + + console.log("testInput", testInput); + + const retVal = runTest(testInput); + + console.log("testOutput", retVal); + + return handleJsonp(req, retVal); } function statusJson(req: Request, server: Server): Response { const retVal = { success: true, tech: `Bun v${Bun.version}`, - lastmod: process.env.LASTMOD || '(not set)', - commit: process.env.COMMIT || '(not set)', + lastmod: process.env.LASTMOD || "(not set)", + commit: process.env.COMMIT || "(not set)", timestamp: new Date().toISOString(), version: `${Bun.version}`, revision: `${Bun.revision}`, - 'process.arch': process.arch, - 'process.platform': process.platform, + "process.arch": process.arch, + "process.platform": process.platform, }; return handleJsonp(req, retVal); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..c892e4b --- /dev/null +++ b/src/types.ts @@ -0,0 +1,16 @@ + + +export type TestInput = { + engine: string; + regex: string; + replacement: string; + extras?: string[]; + option: string[]; + inputs: string[]; +}; + +export type TestOutput = { + success: boolean; + html?: string; + message?: string; +}; \ No newline at end of file