diff --git a/deno.json b/deno.json index 179a6c5..f9d47ee 100644 --- a/deno.json +++ b/deno.json @@ -16,12 +16,9 @@ }, "imports": { "@astral/astral": "jsr:@astral/astral@^0.4.5", - "@hono/hono": "jsr:@hono/hono@^4.5.5", "@std/assert": "jsr:@std/assert@^1.0.2", - "@std/cli": "jsr:@std/cli@1.0.6", - "@std/fmt": "jsr:@std/fmt@^1.0.0", - "@std/fs": "jsr:@std/fs@^1.0.1", - "@std/http": "jsr:@std/http@^1.0.11", + "@std/cli": "jsr:@std/cli@1.0.7", + "@std/fmt": "jsr:@std/fmt@^1", "md4w": "npm:md4w@^0.2.6" }, "exclude": [".gitattributes", ".github", "src/testdata", "**/*/*_test.ts"] diff --git a/deno.lock b/deno.lock index 792812b..5881b2e 100644 --- a/deno.lock +++ b/deno.lock @@ -3,26 +3,15 @@ "specifiers": { "jsr:@astral/astral@~0.4.5": "0.4.9", "jsr:@deno-library/progress@^1.5.1": "1.5.1", - "jsr:@hono/hono@^4.5.5": "4.6.12", "jsr:@std/assert@^1.0.2": "1.0.8", "jsr:@std/async@1": "1.0.9", - "jsr:@std/cli@1.0.6": "1.0.6", - "jsr:@std/cli@^1.0.6": "1.0.6", - "jsr:@std/encoding@^1.0.5": "1.0.5", + "jsr:@std/cli@1.0.7": "1.0.7", "jsr:@std/fmt@1": "1.0.3", "jsr:@std/fmt@1.0.3": "1.0.3", - "jsr:@std/fmt@^1.0.3": "1.0.3", "jsr:@std/fs@1": "1.0.6", - "jsr:@std/fs@^1.0.1": "1.0.6", - "jsr:@std/html@^1.0.3": "1.0.3", - "jsr:@std/http@^1.0.11": "1.0.11", "jsr:@std/internal@^1.0.5": "1.0.5", "jsr:@std/io@0.225.0": "0.225.0", - "jsr:@std/media-types@^1.1.0": "1.1.0", - "jsr:@std/net@^1.0.4": "1.0.4", "jsr:@std/path@1": "1.0.8", - "jsr:@std/path@^1.0.8": "1.0.8", - "jsr:@std/streams@^1.0.8": "1.0.8", "jsr:@zip-js/zip-js@^2.7.52": "2.7.53", "npm:md4w@~0.2.6": "0.2.6" }, @@ -32,8 +21,8 @@ "dependencies": [ "jsr:@deno-library/progress", "jsr:@std/async", - "jsr:@std/fs@1", - "jsr:@std/path@1", + "jsr:@std/fs", + "jsr:@std/path", "jsr:@zip-js/zip-js" ] }, @@ -44,9 +33,6 @@ "jsr:@std/io" ] }, - "@hono/hono@4.6.12": { - "integrity": "fa0b97fa7c3292f0d9957109ac07a475fe485868795b71b8e3114c284152cdb5" - }, "@std/assert@1.0.8": { "integrity": "ebe0bd7eb488ee39686f77003992f389a06c3da1bbd8022184804852b2fa641b", "dependencies": [ @@ -56,36 +42,14 @@ "@std/async@1.0.9": { "integrity": "c6472fd0623b3f3daae023cdf7ca5535e1b721dfbf376562c0c12b3fb4867f91" }, - "@std/cli@1.0.6": { - "integrity": "d22d8b38c66c666d7ad1f2a66c5b122da1704f985d3c47f01129f05abb6c5d3d" - }, - "@std/encoding@1.0.5": { - "integrity": "ecf363d4fc25bd85bd915ff6733a7e79b67e0e7806334af15f4645c569fefc04" + "@std/cli@1.0.7": { + "integrity": "98359df9df586a69015ba570305183b0cb9e7d53c05ea2016ef9a3e77e82c7cd" }, "@std/fmt@1.0.3": { "integrity": "97765c16aa32245ff4e2204ecf7d8562496a3cb8592340a80e7e554e0bb9149f" }, "@std/fs@1.0.6": { - "integrity": "42b56e1e41b75583a21d5a37f6a6a27de9f510bcd36c0c85791d685ca0b85fa2", - "dependencies": [ - "jsr:@std/path@^1.0.8" - ] - }, - "@std/html@1.0.3": { - "integrity": "7a0ac35e050431fb49d44e61c8b8aac1ebd55937e0dc9ec6409aa4bab39a7988" - }, - "@std/http@1.0.11": { - "integrity": "f1928e69e7dcf1664e22d153934cb866bf31e1bbe4bc59f8ac1b4d0e98cb7558", - "dependencies": [ - "jsr:@std/cli@^1.0.6", - "jsr:@std/encoding", - "jsr:@std/fmt@^1.0.3", - "jsr:@std/html", - "jsr:@std/media-types", - "jsr:@std/net", - "jsr:@std/path@^1.0.8", - "jsr:@std/streams" - ] + "integrity": "42b56e1e41b75583a21d5a37f6a6a27de9f510bcd36c0c85791d685ca0b85fa2" }, "@std/internal@1.0.5": { "integrity": "54a546004f769c1ac9e025abd15a76b6671ddc9687e2313b67376125650dc7ba" @@ -93,18 +57,9 @@ "@std/io@0.225.0": { "integrity": "c1db7c5e5a231629b32d64b9a53139445b2ca640d828c26bf23e1c55f8c079b3" }, - "@std/media-types@1.1.0": { - "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" - }, - "@std/net@1.0.4": { - "integrity": "2f403b455ebbccf83d8a027d29c5a9e3a2452fea39bb2da7f2c04af09c8bc852" - }, "@std/path@1.0.8": { "integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be" }, - "@std/streams@1.0.8": { - "integrity": "b41332d93d2cf6a82fe4ac2153b930adf1a859392931e2a19d9fabfb6f154fb3" - }, "@zip-js/zip-js@2.7.53": { "integrity": "acea5bd8e01feb3fe4c242cfbde7d33dd5e006549a4eb1d15283bc0c778ed672" } @@ -117,12 +72,9 @@ "workspace": { "dependencies": [ "jsr:@astral/astral@~0.4.5", - "jsr:@hono/hono@^4.5.5", "jsr:@std/assert@^1.0.2", - "jsr:@std/cli@1.0.6", + "jsr:@std/cli@1.0.7", "jsr:@std/fmt@1", - "jsr:@std/fs@^1.0.1", - "jsr:@std/http@^1.0.11", "npm:md4w@~0.2.6" ] } diff --git a/src/cli.ts b/src/cli.ts index c7a7eb2..fa5fbad 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -21,7 +21,6 @@ import { underline, yellow, } from "@std/fmt/colors"; -import { exists } from "@std/fs/exists"; import { mdToPdf } from "./md-to-pdf.ts"; import { getFilename } from "./utils/filename.ts"; import type { MdToPdfOptions } from "./types.ts"; @@ -31,8 +30,10 @@ async function validateArgs( css?: string; }, ): Promise { - if (typeof args.css === "string") { - if (!(await exists(args.css, { isFile: true, isReadable: true }))) { + if (args.css) { + try { + await Deno.lstat(args.css); + } catch (_e) { console.error( `${brightRed("error")}: Set CSS file is not found: ${args.css}`, ); @@ -97,14 +98,13 @@ const paths: Array = []; if (args._) { for await (const path of args._) { if (typeof path !== "string") continue; - if (await exists(path, { isFile: true })) { + try { + await Deno.lstat(path); paths.push(path); - } else { - if (await exists(path)) { - console.error("md2pdf: " + path + ": Is not a file"); - } else { - console.error("md2pdf: " + path + ": Not found"); - } + } catch (e) { + console.error( + `${brightRed("error")}: ${e}`, + ); } } } diff --git a/src/utils/server.ts b/src/utils/server.ts index 3a090d4..7b3ad14 100644 --- a/src/utils/server.ts +++ b/src/utils/server.ts @@ -1,8 +1,5 @@ -import { Hono } from "@hono/hono/tiny"; -import { LinearRouter } from "@hono/hono/router/linear-router"; import { init as initMd4w, mdToHtml } from "md4w"; import type { MdToPdfOptions } from "../types.ts"; -import { serveFile } from "@std/http/file-server"; import { getFilename } from "./filename.ts"; export const DEFAULT_PORT = 33433; @@ -18,38 +15,52 @@ export function launchHttpServer( path: string, options?: MdToPdfOptions, ): Deno.HttpServer { - const decoder = new TextDecoder("utf-8"); - const app = new Hono({ router: new LinearRouter() }); - app.get("/", async (c) => { - const css = options?.css - ? await decoder.decode(await Deno.readFile(options?.css)) - : ""; - const content = mdToHtml( - decoder.decode(await Deno.readFile(path)), - ); - const title = getFilename(path.split("/").at(-1) || "") || "Untitled"; - return c.html( - ` - - ${title} - - - - ${content} - - `, - ); - }); - app.get("*", async (c) => { - const filePath = "." + decodeURI(c.req.path); - try { - const fileInfo = await Deno.lstat(filePath); - if (fileInfo.isFile) { - return serveFile(c.req.raw, filePath); + const handler: Deno.ServeHandler = async (req) => { + const url = new URL(req.url); + + if (url.pathname === "/") { + const decoder = new TextDecoder("utf-8"); + const css = options?.css + ? decoder.decode(await Deno.readFile(options?.css)) + : ""; + const content = mdToHtml( + decoder.decode(await Deno.readFile(path)), + ); + const title = getFilename(path.split("/").at(-1) || "") || "Untitled"; + return new Response( + ` + + ${title} + + + + ${content} + + `, + { headers: { "Content-Type": "text/html" } }, + ); + } else { + const filePath = "." + decodeURI(url.pathname); + try { + const fileInfo = await Deno.lstat(filePath); + if (fileInfo.isFile) { + const file = await Deno.open(filePath); + return new Response(file.readable); + } + } catch (_e) { + return notFound(); } - } catch (_e) { - return c.notFound(); } - }); - return Deno.serve({ onListen: () => "", port: DEFAULT_PORT }, app.fetch); + return notFound(); + }; + + return Deno.serve({ onListen: () => "", port: DEFAULT_PORT }, handler); +} + +/** + * A response for 404 Not Found. + * @internal + */ +function notFound(): Response { + return new Response("Not Found", { status: 404 }); }