| author | |
| committer | |
| log | 6832e061d3ab21c081e593dc308f5087eacf377d |
| tree | 1d5a07d4463a1df48d1c827a82b9ccdbb992faa6 |
| parent | 8f9a9d4e99fa9e1b759ae0f7a63151deae720585 |
| signature | Commit is signed but in an unrecognized format. |
12 files changed, 153 insertions(+), 40 deletions(-)
deno.jsonc+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | { |
| 2 | 2 | "lint": { |
| 3 | "exclude": ["framework/meta"], // OLD | |
| 3 | "exclude": ["src"], // OLD | |
| 4 | 4 | "rules": { |
| 5 | 5 | "exclude": [ |
| 6 | 6 | "no-explicit-any" // TODO |
framework/assets.ts+1| ... | ... | @@ -97,3 +97,4 @@ import * as fs from "./fs.ts"; |
| 97 | 97 | import type { Context, Next } from "hono"; |
| 98 | 98 | import type { StatusCode } from "hono/utils/http-status"; |
| 99 | 99 | import type { BuiltAsset, BuiltAssetMap, View } from "./incremental.ts"; |
| 100 | import { Buffer } from "node:buffer"; |
framework/bundle.ts+2-2| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | // This file implements client-side bundling, mostly wrapping esbuild. |
| 2 | import process from "node:process"; | |
| 3 | 2 | const plugins: esbuild.Plugin[] = [ |
| 4 | 3 | // There are currently no plugins needed by 'paperclover.net' |
| 5 | 4 | ]; |
| ... | ... | @@ -80,6 +79,7 @@ export async function bundleClientJavaScript( |
| 80 | 79 | } |
| 81 | 80 | } |
| 82 | 81 | |
| 83 | import * as path from "node:path"; | |
| 84 | 82 | import * as esbuild from "esbuild"; |
| 83 | import * as path from "node:path"; | |
| 84 | import process from "node:process"; | |
| 85 | 85 | import { Incremental } from "./incremental.ts"; |
framework/engine/jsx-runtime.ts+1-1| ... | ... | @@ -35,7 +35,7 @@ declare global { |
| 35 | 35 | [name: string]: Record<string, unknown>; |
| 36 | 36 | } |
| 37 | 37 | interface ElementChildrenAttribute { |
| 38 | children: {}; | |
| 38 | children: unknown; | |
| 39 | 39 | } |
| 40 | 40 | type Element = engine.Node; |
| 41 | 41 | type ElementType = keyof IntrinsicElements | engine.Component; |
framework/hot.ts+4-2| ... | ... | @@ -157,11 +157,13 @@ function loadMarko(module: NodeJS.Module, filepath: string) { |
| 157 | 157 | // bare client import statements to it's own usage. |
| 158 | 158 | if (src.match(/^\s*client\s+import\s+["']/m)) { |
| 159 | 159 | src = src.replace( |
| 160 | /^\s*client\s+import\s+("[^"]+|'[^']+)[^\n]+/m, | |
| 160 | /^\s*client\s+import\s+("[^"]+"|'[^']+')[^\n]+/m, | |
| 161 | 161 | "<CloverScriptInclude src=$1 />", |
| 162 | ) + '\nimport { Script as CloverScriptInclude } from "#sitegen";'; | |
| 162 | ) + '\nimport { Script as CloverScriptInclude } from "#sitegen";\n'; | |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | console.log(src); | |
| 166 | console.log("---"); | |
| 165 | 167 | src = marko.compileSync(src, filepath).code; |
| 166 | 168 | src = src.replace("marko/debug/html", "#ssr/marko"); |
| 167 | 169 | return loadEsbuildCode(module, filepath, src); |
framework/mime.ts+19-18| ... | ... | @@ -1,29 +1,30 @@ |
| 1 | const db = new Map( | |
| 2 | fs.readFileSync(path.join(import.meta.dirname, "mime.txt"), "utf8") | |
| 3 | .split("\n").filter(Boolean).map((line) => | |
| 4 | line.split(/\s+/) as [string, string] | |
| 5 | ), | |
| 6 | ); | |
| 1 | const entries = fs.readFileSync( | |
| 2 | path.join(import.meta.dirname, "mime.txt"), | |
| 3 | "utf8", | |
| 4 | ) | |
| 5 | .split("\n") | |
| 6 | .map((line) => line.trim()) | |
| 7 | .filter((line) => line && !line.startsWith("#")) | |
| 8 | .map((line) => line.split(/\s+/, 2) as [string, string]); | |
| 9 | const extensions = new Map(entries.filter((x) => x[0].startsWith("."))); | |
| 10 | const fullNames = new Map(entries.filter((x) => !x[0].startsWith("."))); | |
| 7 | 11 | |
| 8 | 12 | /** |
| 9 | 13 | * Accepts: |
| 10 | * - Full file path | |
| 14 | * - Full file path or basename | |
| 11 | 15 | * - Extension (with or without dot) |
| 12 | 16 | */ |
| 13 | 17 | export function contentTypeFor(file: string) { |
| 14 | if (file.includes("/") || file.includes("\\")) { | |
| 15 | // Some file names are special cased. | |
| 16 | switch (path.basename(file)) { | |
| 17 | case "rss.xml": | |
| 18 | return "application/rss+xml"; | |
| 19 | } | |
| 20 | ||
| 21 | file = path.extname(file); | |
| 22 | } | |
| 18 | const slash = file.indexOf("/"); | |
| 19 | if (slash !== -1) file = file.slice(slash + 1); | |
| 23 | 20 | const dot = file.indexOf("."); |
| 24 | 21 | if (dot === -1) file = "." + file; |
| 25 | else if (dot > 0) file = file.slice(dot); | |
| 26 | return db.get(file) ?? "application/octet-stream"; | |
| 22 | else if (dot > 0) { | |
| 23 | let entry = fullNames.get(file); | |
| 24 | if (entry) return entry; | |
| 25 | file = file.slice(dot); | |
| 26 | } | |
| 27 | return extensions.get(file) ?? "application/octet-stream"; | |
| 27 | 28 | } |
| 28 | 29 | |
| 29 | 30 | import * as fs from "./fs.ts"; |
framework/mime.txt created+99| ... | ... | @@ -0,0 +1,99 @@ |
| 1 | # media types | |
| 2 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types | |
| 3 | .aac audio/x-aac | |
| 4 | .aif audio/x-aiff | |
| 5 | .aifc audio/x-aiff | |
| 6 | .aiff audio/x-aiff | |
| 7 | .asm text/x-asm | |
| 8 | .avi video/x-msvideo | |
| 9 | .bat application/x-msdownload | |
| 10 | .c text/x-c | |
| 11 | .chat text/x-clover-chatlog | |
| 12 | .class application/java-vm | |
| 13 | .cmd application/x-msdownload | |
| 14 | .com application/x-msdownload | |
| 15 | .conf text/plain | |
| 16 | .cpp text/x-c | |
| 17 | .css text/css | |
| 18 | .csv text/csv | |
| 19 | .cxx text/x-c | |
| 20 | .def text/plain | |
| 21 | .diff text/plain | |
| 22 | .dll application/x-msdownload | |
| 23 | .dmg application/octet-stream | |
| 24 | .doc application/msword | |
| 25 | .docx application/vnd.openxmlformats-officedocument.wordprocessingml.document | |
| 26 | .epub application/epub+zip | |
| 27 | .exe application/x-msdownload | |
| 28 | .flv video/x-flv | |
| 29 | .fbx application/fbx | |
| 30 | .gz application/x-gzip | |
| 31 | .h text/x-c | |
| 32 | .h264 video/h264 | |
| 33 | .hh text/x-c | |
| 34 | .htm text/html;charset=utf-8 | |
| 35 | .html text/html;charset=utf-8 | |
| 36 | .ico image/x-icon | |
| 37 | .ics text/calendar | |
| 38 | .in text/plain | |
| 39 | .jar application/java-archive | |
| 40 | .java text/x-java-source | |
| 41 | .jpeg image/jpeg | |
| 42 | .jpg image/jpeg | |
| 43 | .jpgv video/jpeg | |
| 44 | .jxl image/jxl | |
| 45 | .js application/javascript | |
| 46 | .json application/json | |
| 47 | .latex application/x-latex | |
| 48 | .list text/plain | |
| 49 | .log text/plain | |
| 50 | .m4a audio/mp4 | |
| 51 | .man text/troff | |
| 52 | .mid audio/midi | |
| 53 | .midi audio/midi | |
| 54 | .mov video/quicktime | |
| 55 | .mp3 audio/mpeg | |
| 56 | .mp4 video/mp4 | |
| 57 | .msh model/mesh | |
| 58 | .msi application/x-msdownload | |
| 59 | .obj application/octet-stream | |
| 60 | .ogg audio/ogg | |
| 61 | .otf application/x-font-otf | |
| 62 | .pdf application/pdf | |
| 63 | .png image/png | |
| 64 | .ppt application/vnd.ms-powerpoint | |
| 65 | .pptx application/vnd.openxmlformats-officedocument.presentationml.presentation | |
| 66 | .psd image/vnd.adobe.photoshop | |
| 67 | .py text/x-python | |
| 68 | .rar application/x-rar-compressed | |
| 69 | .rss application/rss+xml | |
| 70 | .rtf application/rtf | |
| 71 | .rtx text/richtext | |
| 72 | .s text/x-asm | |
| 73 | .pem application/x-pem-file" | |
| 74 | .ser application/java-serialized-object | |
| 75 | .sh application/x-sh | |
| 76 | .sig application/pgp-signature | |
| 77 | .silo model/mesh | |
| 78 | .svg image/svg+xml | |
| 79 | .t text/troff | |
| 80 | .tar application/x-tar | |
| 81 | .text text/plain | |
| 82 | .tgz application/x-gzip | |
| 83 | .tif image/tiff | |
| 84 | .tiff image/tiff | |
| 85 | .torrent application/x-bittorrent | |
| 86 | .ttc application/x-font-ttf | |
| 87 | .ttf application/x-font-ttf | |
| 88 | .txt text/plain | |
| 89 | .urls text/uri-list | |
| 90 | .v text/x-v | |
| 91 | .wav audio/x-wav | |
| 92 | .wmv video/x-ms-wmv | |
| 93 | .xls application/vnd.ms-excel | |
| 94 | .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | |
| 95 | .xml application/xml | |
| 96 | .xps application/vnd.ms-xpsdocument | |
| 97 | ||
| 98 | # special cased based on file name | |
| 99 | rss.xml application/rss+xml |
framework/queue.ts+5-5| ... | ... | @@ -1,8 +1,3 @@ |
| 1 | import { Progress } from "@paperclover/console/Progress"; | |
| 2 | import { Spinner } from "@paperclover/console/Spinner"; | |
| 3 | import * as path from "node:path"; | |
| 4 | import process from "node:process"; | |
| 5 | ||
| 6 | 1 | interface QueueOptions<T, R> { |
| 7 | 2 | name: string; |
| 8 | 3 | fn: (item: T, spin: Spinner) => Promise<R>; |
| ... | ... | @@ -204,3 +199,8 @@ export class OnceMap<T> { |
| 204 | 199 | return result; |
| 205 | 200 | } |
| 206 | 201 | } |
| 202 | ||
| 203 | import { Progress } from "@paperclover/console/Progress"; | |
| 204 | import { Spinner } from "@paperclover/console/Spinner"; | |
| 205 | import * as path from "node:path"; | |
| 206 | import process from "node:process"; |
package-lock.json+3-3| ... | ... | @@ -1027,9 +1027,9 @@ |
| 1027 | 1027 | "license": "ISC" |
| 1028 | 1028 | }, |
| 1029 | 1029 | "node_modules/acorn": { |
| 1030 | "version": "8.14.1", | |
| 1031 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", | |
| 1032 | "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", | |
| 1030 | "version": "8.15.0", | |
| 1031 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", | |
| 1032 | "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", | |
| 1033 | 1033 | "license": "MIT", |
| 1034 | 1034 | "bin": { |
| 1035 | 1035 | "acorn": "bin/acorn" |
package.json+3-4| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | { |
| 2 | "private": true, | |
| 3 | 2 | "type": "module", |
| 4 | 3 | "dependencies": { |
| 5 | 4 | "@hono/node-server": "^1.14.3", |
| ... | ... | @@ -23,9 +22,9 @@ |
| 23 | 22 | "#ssr/jsx-runtime": "./framework/engine/jsx-runtime.ts", |
| 24 | 23 | "#ssr/marko": "./framework/engine/marko-runtime.ts", |
| 25 | 24 | "#marko/html": { |
| 26 | "development": "marko/debug/html", | |
| 27 | "production": "marko/html", | |
| 28 | "types": "marko/html" | |
| 25 | "types": "marko/html", | |
| 26 | "production": "marko/production", | |
| 27 | "node": "marko/debug/html" | |
| 29 | 28 | }, |
| 30 | 29 | "#hono/platform": { |
| 31 | 30 | "bun": "hono/bun", |
repl.js+1-1| ... | ... | @@ -18,7 +18,7 @@ hot.load("node:repl").start({ |
| 18 | 18 | .catch((err) => { |
| 19 | 19 | // TODO: improve @paperclover/console's ability to print AggregateError |
| 20 | 20 | // and errors with extra random properties |
| 21 | console.error(inspect(err)); | |
| 21 | console.error(util.inspect(err)); | |
| 22 | 22 | }) |
| 23 | 23 | .then((result) => done(null, result)); |
| 24 | 24 | }, |
run.js+14-3| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | // This file allows using Node.js in combination with |
| 2 | 2 | // all available plugins. Usage: "node run <script>" |
| 3 | import * as path from "node:path"; | |
| 4 | 3 | import * as util from "node:util"; |
| 5 | 4 | import process from "node:process"; |
| 6 | 5 | |
| ... | ... | @@ -47,9 +46,21 @@ if (process.argv[1].startsWith(import.meta.filename.slice(0, -".js".length))) { |
| 47 | 46 | console.error("usage: node run <script> [...args]"); |
| 48 | 47 | process.exit(1); |
| 49 | 48 | } |
| 50 | const file = path.resolve(process.argv[2]); | |
| 49 | let found; | |
| 50 | for (const dir of ["./", "./src/", "./framework/"]) { | |
| 51 | try { | |
| 52 | found = hot.resolveFrom(import.meta.filename, dir + process.argv[2]); | |
| 53 | break; | |
| 54 | } catch (e) { | |
| 55 | continue; | |
| 56 | } | |
| 57 | } | |
| 58 | if (!found) { | |
| 59 | console.error("Cannot find script: " + process.argv[2]); | |
| 60 | process.exit(1); | |
| 61 | } | |
| 51 | 62 | process.argv = [process.argv[0], ...process.argv.slice(2)]; |
| 52 | hot.load(file).main?.(); | |
| 63 | hot.load(found).main?.(); | |
| 53 | 64 | } |
| 54 | 65 | |
| 55 | 66 | export { hot }; |