diff --git a/framework/generate.ts b/framework/generate.ts index ccd29f9707cd7cdc859e27c2ff05fcce0f0ae291..84a9993a4da56a6b4157d2acd026b7d33a2d376f 100644 --- a/framework/generate.ts +++ b/framework/generate.ts @@ -124,6 +124,7 @@ export async function readManifest(io: Io) { return { siteSections: cfg.siteSections.map((section) => ({ root: toRel(section.root), + base: section.base ?? "/", })), backends: cfg.backends.map(toRel), fonts: cfg.fonts, @@ -141,8 +142,11 @@ export async function discoverAllFiles( using node = p.start("discover files"); return ( await Promise.all( - siteConfig.siteSections.map(({ root: sectionRoot }) => - incr.work(node, scanSiteSection, toAbs(sectionRoot)) + siteConfig.siteSections.map(({ root: root, base }) => + incr.work(node, scanSiteSection, { + root: toAbs(root), + base: base.endsWith("/") ? base : base + "/", + }) ), ) ).reduce((acc, next) => ({ @@ -153,8 +157,8 @@ export async function discoverAllFiles( })); } -export async function scanSiteSection(io: Io, sectionRoot: string) { - using _ = io.start(toRel(sectionRoot)); +export async function scanSiteSection(io: Io, section: sg.Section) { + using _ = io.start(toRel(section.root)); // Static files are compressed and served as-is. // - "{section}/static/*.png" let staticFiles: FileItem[] = []; @@ -170,29 +174,32 @@ export async function scanSiteSection(io: Io, sectionRoot: string) { // - "{section}/scripts/*.client.ts" let scripts: FileItem[] = []; - const sectionPath = (...sub: string[]) => path.join(sectionRoot, ...sub); - const rootPrefix = hot.projectSrc === sectionRoot + const sectionPath = (...sub: string[]) => path.join(section.root, ...sub); + const rootPrefix = hot.projectSrc === section.root ? "" - : path.relative(hot.projectSrc, sectionRoot) + "/"; + : path.relative(hot.projectSrc, section.root) + "/"; const kinds = [ { dir: sectionPath("pages"), list: pages, - prefix: "/", + prefix: section.base, include: [".tsx", ".mdx", ".marko"], exclude: [".client.ts", ".client.tsx"], + page: true, }, { dir: sectionPath("static"), list: staticFiles, - prefix: "/", + prefix: section.base, ext: true, + page: true, }, { dir: sectionPath("scripts"), list: scripts, prefix: rootPrefix, include: [".client.ts", ".client.tsx"], + page: false, }, { dir: sectionPath("views"), @@ -200,6 +207,7 @@ export async function scanSiteSection(io: Io, sectionRoot: string) { prefix: rootPrefix, include: [".tsx", ".mdx", ".marko"], exclude: [".client.ts", ".client.tsx"], + page: false, }, ]; for (const kind of kinds) { @@ -229,7 +237,7 @@ export async function scanSiteSection(io: Io, sectionRoot: string) { ? subPath : subPath.slice(0, -path.extname(subPath).length).replaceAll(".", "/"); let id = prefix + trim.replaceAll("\\", "/"); - if (prefix === "/" && id.endsWith("/index")) { + if (kind.page && id.endsWith("/index")) { id = id.slice(0, -"/index".length) || "/"; } list.push({ id, file: path.relative(hot.projectRoot, file) }); diff --git a/framework/hot.ts b/framework/hot.ts index 324b86ff3d226041a25697f36e3a02cd9b5e3743..3695084aa3edbff84c537ad35fa75e8265e48355 100644 --- a/framework/hot.ts +++ b/framework/hot.ts @@ -174,7 +174,11 @@ function loadMarko(module: NodeJS.Module, filepath: string) { function loadMdx(module: NodeJS.Module, filepath: string) { const input = fs.readFileSync(filepath); - const out = mdx.compileSync(input, { jsxImportSource: "#jsx" }).value; + const out = mdx.compileSync(input, { + jsxImportSource: "#jsx", + providerImportSource: "#mdx", + rehypePlugins: [rehypeMdxCodeProps], + }).value; const src = typeof out === "string" ? out : Buffer.from(out).toString("utf8"); return loadEsbuildCode(module, filepath, src); } @@ -323,6 +327,7 @@ import { pathToFileURL } from "node:url"; import * as esbuild from "esbuild"; import { createRequire } from "node:module"; import * as mdx from "@mdx-js/mdx"; +import rehypeMdxCodeProps from "rehype-mdx-code-props"; import * as self from "./hot.ts"; import { Buffer } from "node:buffer"; import { UNWRAP } from "lib/assert.ts"; diff --git a/framework/lib/sitegen.ts b/framework/lib/sitegen.ts index f2413829534ccc8c9e60b1a3afc6e210800fa8b3..1e72bc84fd68700b90023d706e31f3232749722f 100644 --- a/framework/lib/sitegen.ts +++ b/framework/lib/sitegen.ts @@ -30,6 +30,7 @@ export interface FileItem { } export interface Section { root: string; + base?: string; } export interface Font { name: string; @@ -59,6 +60,17 @@ export function addScript(id: ScriptId | { value: ScriptId }) { context.get().scripts.add(typeof id === "string" ? id : id.value); } +// TODO: self-host plausible for extra privacy. i am in a rush as i write this +// TODO: properly locate this constant in `site.ts` +// +// I have this so I can see if the blog is actually seen by people. And for +// understanding where paperclover.net gets its load for. When I need to scale +// large enough, analytics will determine the location of the second web +// hosting node. +export const analytics = + ` + `; + export function wrapDocument({ body, head, @@ -72,7 +84,7 @@ export function wrapDocument({ }) { return `${head}${ inlineCss ? `` : "" - }${body}${ + }${analytics}${body}${ scripts ? `` : "" }`; } diff --git a/framework/mdx-hack.tsx b/framework/mdx-hack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..61e2cc424968a8514b703934bdc34a70b2de921d --- /dev/null +++ b/framework/mdx-hack.tsx @@ -0,0 +1,32 @@ +export function useMDXComponents() { + return { + pre: async ( + { filename, whitespace, tint, children: [, , { className, children }] }, + ) => { + const lang = className.split("-")?.[1] ?? null; + const code = ["tsx", "jsx", "json", "html", "ts", "js"].includes(lang) + ? await highlight.highlightCode( + children.trim(), + lang, + ) + : children.trim(); + return ( +
+ {filename &&
{filename}
} +
{render.raw(code)}
+
+ ); + }, + code: ({ children }) => { + return ( + + {children} + + ); + }, + }; +} +import * as highlight from "../src/file-viewer/highlight.ts"; +import * as render from "lib/render.ts"; diff --git a/lib/progress.ts b/lib/progress.ts index 3f7b824c9db23367c7c93c819e1a2ef66639d911..dbff7153c437ea6114f1e42192b39f7cd53ac52a 100644 --- a/lib/progress.ts +++ b/lib/progress.ts @@ -1,3 +1,9 @@ +// For those coming from my blog, check out this video +// -> https://paperclover.net/file/2025/file%20scanner.mp4?view=embed +// +// There is some massive rework pending on this file, check out the PR +// -> https://git.paperclover.net/clo/sitegen/pulls/48 +// // This file is under heavy construction. // - I am happy with the overall design // - Will rename things diff --git a/lib/render.ts b/lib/render.ts index e26b182987ef60159fee6875230cfbb457687572..bf70fc98de65366114786764832d6a351f5b55c2 100644 --- a/lib/render.ts +++ b/lib/render.ts @@ -370,6 +370,7 @@ function stringifyStyleAttribute(style: Record): string { ) }`; } + if (!out) return ""; return "style=" + quoteIfNeeded(out); } diff --git a/package-lock.json b/package-lock.json index 46a8b52426e5cf656e75e0f60dfc6fff774cbffa..cde3bb0b5af643e58f9eea9c94892b502e69f25d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,9 +17,8 @@ "marko": "6.0.82", "msgpackr": "1.11.5", "puppeteer": "24.23.0", - "sharp": "0.34.2", + "rehype-mdx-code-props": "^3.0.1", "source-map-support": "0.5.21", - "ts-to-jsdoc": "2.4.0", "unique-names-generator": "4.7.1", "vscode-oniguruma": "2.0.1", "vscode-textmate": "9.2.0" @@ -491,16 +490,6 @@ "w3c-keyname": "^2.2.4" } }, - "node_modules/@emnapi/runtime": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.4.tgz", - "integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", @@ -913,402 +902,6 @@ "hono": "^4" } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", - "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.1.0" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", - "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.1.0" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", - "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", - "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", - "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", - "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", - "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", - "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", - "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", - "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", - "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", - "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.1.0" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", - "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.1.0" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", - "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.1.0" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", - "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.1.0" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", - "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", - "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.1.0" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", - "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.4.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", - "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", - "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", - "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1541,41 +1134,6 @@ "win32" ] }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@puppeteer/browsers": { "version": "2.10.10", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.10.tgz", @@ -1621,18 +1179,6 @@ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", "license": "MIT" }, - "node_modules/@ts-morph/common": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.24.0.tgz", - "integrity": "sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==", - "license": "MIT", - "dependencies": { - "fast-glob": "^3.3.2", - "minimatch": "^9.0.4", - "mkdirp": "^3.0.1", - "path-browserify": "^1.0.1" - } - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -1773,12 +1319,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "license": "MIT" - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1830,12 +1370,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, "node_modules/bare-events": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.7.0.tgz", @@ -1976,27 +1510,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/browserslist": { "version": "4.26.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", @@ -2151,12 +1664,6 @@ "node": ">=12" } }, - "node_modules/code-block-writer": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", - "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", - "license": "MIT" - }, "node_modules/codem-isoboxer": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.10.tgz", @@ -2188,19 +1695,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2219,16 +1713,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -2377,6 +1861,7 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", "license": "Apache-2.0", + "optional": true, "engines": { "node": ">=8" } @@ -2656,6 +2141,18 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/estree-util-value-to-estree": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.4.1.tgz", + "integrity": "sha512-E4fEc8KLhDXnbyDa5XrbdT9PbgSMt0AGZPFUsGFok8N2Q7DTO+F6xAFJjIdw71EkidRg186I1mQCKzZ1ZbEsCw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, "node_modules/estree-util-visit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", @@ -2735,31 +2232,6 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -2769,18 +2241,6 @@ "pend": "~1.2.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2828,16 +2288,23 @@ "node": ">= 14" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", + "node_modules/hast-util-properties-to-mdx-jsx-attributes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-properties-to-mdx-jsx-attributes/-/hast-util-properties-to-mdx-jsx-attributes-1.0.1.tgz", + "integrity": "sha512-ZzxhjHZ+gyxaPIFp/nuRpVL4GIFoqzfH6vNgjaA3CuUAV6XCxYwAQfRczrZRkgL6msi6DdOl+/QEduOdzszvbg==", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "estree-util-value-to-estree": "^3.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://github.com/sponsors/remcohaszing" } }, "node_modules/hast-util-to-estree": { @@ -3075,15 +2542,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -3093,18 +2551,6 @@ "node": ">=8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-hexadecimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", @@ -3115,15 +2561,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -3463,15 +2900,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -4068,55 +3496,12 @@ ], "license": "MIT" }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4298,18 +3683,6 @@ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -4412,26 +3785,6 @@ "node": ">=18" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/raptor-async": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/raptor-async/-/raptor-async-1.1.3.tgz", @@ -4514,6 +3867,24 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-mdx-code-props": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rehype-mdx-code-props/-/rehype-mdx-code-props-3.0.1.tgz", + "integrity": "sha512-BWWKn0N6r7/qd7lbLgv5J8of7imz1l1PyCNoY7BH0AOR9JdJlQIfA9cKqTZVEb2h2GPKh473qrBajF0i01fq3A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-properties-to-mdx-jsx-attributes": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0", + "unified": "^11.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, "node_modules/rehype-recma": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", @@ -4600,39 +3971,6 @@ "node": ">=8" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/sax": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", @@ -4657,74 +3995,6 @@ "semver": "bin/semver.js" } }, - "node_modules/sharp": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", - "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.4", - "semver": "^7.7.2" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.2", - "@img/sharp-darwin-x64": "0.34.2", - "@img/sharp-libvips-darwin-arm64": "1.1.0", - "@img/sharp-libvips-darwin-x64": "1.1.0", - "@img/sharp-libvips-linux-arm": "1.1.0", - "@img/sharp-libvips-linux-arm64": "1.1.0", - "@img/sharp-libvips-linux-ppc64": "1.1.0", - "@img/sharp-libvips-linux-s390x": "1.1.0", - "@img/sharp-libvips-linux-x64": "1.1.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", - "@img/sharp-libvips-linuxmusl-x64": "1.1.0", - "@img/sharp-linux-arm": "0.34.2", - "@img/sharp-linux-arm64": "0.34.2", - "@img/sharp-linux-s390x": "0.34.2", - "@img/sharp-linux-x64": "0.34.2", - "@img/sharp-linuxmusl-arm64": "0.34.2", - "@img/sharp-linuxmusl-x64": "0.34.2", - "@img/sharp-wasm32": "0.34.2", - "@img/sharp-win32-arm64": "0.34.2", - "@img/sharp-win32-ia32": "0.34.2", - "@img/sharp-win32-x64": "0.34.2" - } - }, - "node_modules/sharp/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT" - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -4916,18 +4186,6 @@ "b4a": "^1.6.4" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -4948,32 +4206,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/ts-morph": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-23.0.0.tgz", - "integrity": "sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==", - "license": "MIT", - "dependencies": { - "@ts-morph/common": "~0.24.0", - "code-block-writer": "^13.0.1" - } - }, - "node_modules/ts-to-jsdoc": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-to-jsdoc/-/ts-to-jsdoc-2.4.0.tgz", - "integrity": "sha512-RiI9ipxkLjXESp5+YjXIQJ5GgtjwWTZU4uDahxsIdr1HKLFaC/nQOtgkGRJ+AFxqHrrhwrXtPh093r0nXQwKmw==", - "license": "MIT", - "dependencies": { - "arg": "^5.0.1", - "ts-morph": "^23.0.0" - }, - "bin": { - "ts-to-jsdoc": "bin/ts-to-jsdoc" - }, - "optionalDependencies": { - "typescript": "*" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", diff --git a/package.json b/package.json index 4547a07f4d1c1e63c16180dbd49bb507fcf9e259..78c5874b5a08193304828bdf80db436f37d80cca 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "marko": "6.0.82", "msgpackr": "1.11.5", "puppeteer": "24.23.0", + "rehype-mdx-code-props": "^3.0.1", "source-map-support": "0.5.21", "unique-names-generator": "4.7.1", "vscode-oniguruma": "2.0.1", @@ -39,6 +40,7 @@ "deno": "hono/deno", "node": "@hono/node-server/conninfo", "worker": "hono/cloudflare-workers" - } + }, + "#mdx": "./framework/mdx-hack.tsx" } } diff --git a/src/bin/deploy.ts b/src/bin/deploy.ts new file mode 100644 index 0000000000000000000000000000000000000000..c17ca3edae9022f4dab8398ccb991784e5b6a67a --- /dev/null +++ b/src/bin/deploy.ts @@ -0,0 +1,61 @@ +export async function main() { + await rsync.spawn({ + cwd: Path.resolve(import.meta.dirname).parent!.toString(), + args: [ + "-a", + "--progress", + "clo@zenith:/mnt/storage1/clover/Documents/Config/paperclover/cache.sqlite", + ".clover/", + ], + progress: progress.start("download file cache"), + }); + await rsync.spawn({ + cwd: Path.resolve(import.meta.dirname).parent!.toString(), + args: [ + "-a", + "--progress", + "clo@paperclover.net:~/paperclover.net/.clover/questions.sqlite", + ".clover/", + ], + progress: progress.start("download questions state"), + }); + + // cannot call incr.restore until database calls are + // considered in the watch graph. + // await incr.restore() + await incr.compile(generate); + + await rsync.spawn({ + cwd: Path.resolve(import.meta.dirname).parent!.parent!.toString(), + args: [ + "-a", + "-r", + "--progress", + "--delete", + "--exclude=node_modules", + "--exclude=.clover", + "package.json", + "package-lock.json", + ".clover/o/", + "paperclover.net:~/paperclover.net/", + ], + progress: progress.start("copy site files"), + }); + await subprocess.spawnAndWait({ + stdio: "inherit", + cmd: [ + "ssh", + "paperclover.net", + "cd paperclover.net && " + + "npm i &&" + + "pm2 restart site", + ], + }); +} + +import * as incr from "../../framework/incremental.ts"; +import { generate } from "../../framework/generate.ts"; +import * as progress from "lib/progress.ts"; +import * as subprocess from "lib/subprocess.ts"; +import * as rsync from "../file-viewer/rsync.ts"; +import { Path } from "#sitegen/path"; diff --git a/src/bin/package-lib.ts b/src/bin/package-lib.ts new file mode 100644 index 0000000000000000000000000000000000000000..b26cde479d91bcbcb1e0ebf7d9009b7a1b0dc313 --- /dev/null +++ b/src/bin/package-lib.ts @@ -0,0 +1,226 @@ +export async function updateJsrPackageExportsToAll( + absPath: string, + p: progress.Ref, +) { + using _ = p.start("update deno.json"); + const manifestPath = path.join(absPath, "deno.json"); + const deno = JSON.parse( + await fs.readFile(manifestPath, "utf-8"), + ); + const newExports: Record = {}; + for (const subPath of await fs.readdir(absPath, { recursive: true })) { + if (!subPath.match(/\.tsx?$/)) continue; + if (subPath.match(/\.(test|sample)\.tsx?$/)) continue; + if (subPath.startsWith("dist")) continue; + newExports["./" + subPath] = "./" + subPath; + } + deno.exports = Object.fromEntries( + Object.entries(newExports).sort(([a], [b]) => a.localeCompare(b)), + ) as typeof deno.exports; + await fs.writeFile(manifestPath, JSON.stringify(deno, null, 2)); +} + +export async function transpileForNpm( + absPath: string, + p: progress.Ref, + packageJson: Record, +) { + using node = p.start("transpile into js for npm"); + const manifestPath = path.join(absPath, "deno.json"); + const deno = JSON.parse( + await fs.readFile(manifestPath, "utf-8"), + ); + const distPath = path.join(absPath, "dist-npm"); + await fs.rm(distPath, { recursive: true, force: true }); + await fs.mkdir(distPath, { recursive: true }); + + const files: string[] = []; + const exports: Record = {}; + for (const subPath of await fs.readdir(absPath, { recursive: true })) { + if (!subPath.match(/\.tsx?$/)) continue; + if (subPath.startsWith("dist")) continue; + files.push(subPath); + } + const tsFiles: string[] = []; + for (const subPath of files) { + using _ = node.start(subPath); + const targetSubPath = subPath.replace(/\.tsx?$/, ".js"); + if (!subPath.match(/\.(test|sample)\.tsx?$/)) { + exports["./" + subPath] = "./" + targetSubPath; + } + const out = path.join(distPath, subPath); + await fs.mkdir(path.dirname(out), { recursive: true }); + tsFiles.push(out); + + let code = await fs.readFile(path.join(absPath, subPath), "utf-8"); + code = code.replace( + / from "lib\/([^"]+)"/g, + (_, src) => { + return ' from "./' + path.relative( + path.dirname(subPath), + src.replace(/\.tsx?$/, ".js"), + ) + '"'; + }, + ); + await fs.writeFile(out, code); + } + await subprocess.spawnAndWait({ + cmd: [ + "npx", + "tsc", + "--outdir", + distPath, + "--sourceMap", + "--declarationMap", + "--declaration", + "--module", + "nodenext", + "--lib", + "esnext", + "--skipLibCheck", + "--jsx", + "react-jsx", + "--jsxImportSource", + "./lib/dist-npm/render", + "--target", + "esnext", + "--isolatedModules", + "--verbatimModuleSyntax", + "--allowSyntheticDefaultImports", + "--moduleResolution", + "nodenext", + ...tsFiles, + ], + }); + await fs.writeFile( + path.join(distPath, "readme.md"), + (await fs.readFile(path.join(absPath, "readme.md"), "utf-8")).replace( + "\n", + await fs.readFile(path.join(absPath, "readme.npm.md"), "utf-8"), + ), + ).catch((e) => { + if (e.code !== "ENOENT") throw e; + }); + await fs.cp( + path.join(absPath, "readme.changes.md"), + path.join(distPath, "readme.changes.md"), + ).catch((e) => { + if (e.code !== "ENOENT") throw e; + }); + const { name, description, ...rest } = packageJson; + await fs.writeFile( + path.join(distPath, "package.json"), + JSON.stringify( + { + name, + description, + version: deno.version, + type: "module", + exports, + ...rest, + }, + null, + 2, + ), + ); +} + +// TODO: failed experiment +// +// export async function transpileForNpm( +// absPath: string, +// p: progress.Ref, +// packageJson: Record, +// ) { +// const { transpileFile } = await import("ts-to-jsdoc") as TsToJsdoc; +// +// using node = p.start("transpile into jsdoc for npm"); +// const manifestPath = path.join(absPath, "deno.json"); +// const deno = JSON.parse( +// await fs.readFile(manifestPath, "utf-8"), +// ); +// const distPath = path.join(absPath, "dist-npm"); +// await fs.rm(distPath, { recursive: true, force: true }); +// await fs.mkdir(distPath, { recursive: true }); +// +// const files: string[] = []; +// const exports: Record = {}; +// for (const subPath of await fs.readdir(absPath, { recursive: true })) { +// if (!subPath.match(/\.tsx?$/)) continue; +// if (subPath.startsWith("dist")) continue; +// files.push(subPath); +// } +// node.estimate = Object.keys(exports).length; +// for (const subPath of files) { +// using _ = node.start(subPath); +// const targetSubPath = subPath.replace(/\.tsx?$/, ".js"); +// if (!subPath.match(/\.(test|sample)\.tsx?$/)) { +// exports["./" + subPath] = "./" + targetSubPath; +// } +// +// let code = transpileFile({ +// code: await fs.readFile(path.join(absPath, subPath), "utf-8"), +// }); +// code = code.replace( +// / from "lib\/([^"]+)"/g, +// (_, src) => { +// return ' from "./' + path.relative( +// path.dirname(subPath), +// src.replace(/\.tsx?$/, ".js"), +// ) + '"'; +// }, +// ); +// if (packageJson.homepage) { +// code = +// "// This file is transpiled from TypeScript from paper clover's sitegen\n" + +// "// " + packageJson.homepage + "/" + subPath + "\n" + +// code; +// } +// const out = path.join(distPath, targetSubPath); +// await fs.mkdir(path.dirname(out), { recursive: true }); +// await fs.writeFile(out, code); +// node.value += 1; +// } +// await fs.cp( +// path.join(absPath, "readme.npm.md"), +// path.join(distPath, "readme.md"), +// ).catch((e) => { +// if (e.code !== "ENOENT") throw e; +// }); +// await fs.cp( +// path.join(absPath, "readme.changes.md"), +// path.join(distPath, "readme.changes.md"), +// ).catch((e) => { +// if (e.code !== "ENOENT") throw e; +// }); +// const { name, description, ...rest } = packageJson; +// await fs.writeFile( +// path.join(distPath, "package.json"), +// JSON.stringify({ +// name, +// description, +// version: deno.version, +// type: "module", +// ...rest, +// }), +// ); +// } +// +export function main() { + const main = path.resolve("lib"); + updateJsrPackageExportsToAll(main, progress) + .then(() => + transpileForNpm(main, progress, { + name: "@paperclover/lib", + description: "high quality typescript libraries", + homepage: + "https://git.paperclover.net/clo/sitegen/src/branch/master/lib", + }) + ); +} + +import * as progress from "lib/progress.ts"; +import * as path from "node:path"; +import * as fs from "node:fs/promises"; +import * as subprocess from "lib/subprocess.ts"; +import { UNWRAP } from "lib/assert.ts"; diff --git a/src/blog/blog.css b/src/blog/blog.css new file mode 100644 index 0000000000000000000000000000000000000000..2c845a45d9283687548596773d6a411b5e699f9b --- /dev/null +++ b/src/blog/blog.css @@ -0,0 +1,204 @@ +:root { + --secondary: #a291ff; +} +main { + font-weight: 350; + color: #e9eaff; +} +h1, .description { + color: var(--primary); +} +h1 { + margin-bottom: 0.5rem; +} +p { + line-height: 1.6; +} +.description { + margin-top: 0.5rem; + margin-bottom: 0.5rem; + font-style: italic; +} +.tag-list { + display: flex; + gap: 0.5rem; + font-size: 80%; +} +.tag { + background-color: #0005; + border-radius: 8px; + padding: 0.35rem; + color: #fffc; + &.date { + color: var(--secondary); + } +} +hr { + margin: 1rem 0; + border: 2px solid var(--primary); +} +img { + width: 100%; + border-radius: 8px; +} + +#toc { + background-color: #0003; + border-radius: 8px; + padding: 1rem; + + h2 { + text-decoration: none; + margin: 0; + text-transform: uppercase; + font-weight: bold; + letter-spacing: 1px; + font-size: 0.8rem; + color: #fff8; + } + ul { + margin: 0; + } + li { + list-style-type: square; + &::marker { + color: var(--primary); + } + li { + --primary: var(--secondary); + } + } +} + +h3 { + --primary: var(--secondary); +} +h2, h3 { + color: var(--primary); + text-decoration: underline; + text-decoration-color: var(--primary); + text-decoration-thickness: 2px; + text-underline-offset: 2px; + a.return { + display: inline-block; + font-size: 1rem; + margin-right: 0.1rem; + transform: translateY(-4px); + } +} + +b { + color: var(--secondary); + &.server { + color: #ff7770; + } + &.client { + color: #ffcd70; + } +} + +blockquote { + & > :first-child { + margin-top: 0; + } + & > :last-child { + margin-bottom: 0; + } + figure.code { + border: none; + pre { + padding: 0; + } + } + background-color: #0008; + border-radius: 8px; + padding: 1rem; + border-left: 4px solid var(--secondary); + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +code, kbd { + /* box-decoration-break: clone; */ + border: 1px solid rgb(from var(--secondary) r g b / 0.8); + border-radius: 4px; + padding: 1px 5px; + background-color: #0008; +} +kbd { + /* box-decoration-break: clone; */ + border-color: white; +} +a > code { + --secondary: var(--primary); +} +figure.code { + border: 4px solid var(--secondary); + background-color: lch(from var(--secondary) 4 2 h); + + &:has(figcaption) { + border-top: none; + } + + &.server { + --secondary: #ff7770; + + .variable { + color: lch(from var(--secondary) 70 c calc(h + 50)); + } + } + &.client { + --secondary: #ffcd70; + + .variable { + color: lch(from var(--secondary) 70 c calc(h + 50)); + } + } + figcaption { + padding: 0.5rem; + font-family: "rmo", monospace; + font-weight: bold; + color: black; + background-color: rgb(from var(--secondary) r g b / 100%); + } + pre { + padding: 0.5rem; + overflow-x: auto; + font-size: 95%; + } + pre > code { + border: unset; + border-radius: unset; + padding: unset; + background-color: unset; + + color: lch(from var(--secondary) 90 10 h); + + .keyword { + color: var(--secondary); + color: lch(from var(--secondary) l c h / 90%); + font-weight: bold; + } + .string { + color: lch(from var(--secondary) 90 90 calc(h + 20)); + } + .constant { + color: lch(from var(--secondary) 90 90 calc(h - 10)); + } + .method { + color: lch(from var(--secondary) 70 c calc(h + 20)); + } + .builtin { + color: lch(from var(--secondary) 90 90 calc(h - 25)); + } + .variable { + color: lch(from var(--secondary) 50 c calc(h + 50)); + } + .comment { + color: lch(from var(--secondary) 90 40 h / 50%); + } + .property, .parameter { + color: lch(from var(--secondary) 90 calc(c - 20) h); + } + } +} diff --git a/src/blog/drafts/webdev/deranged-typescript.md b/src/blog/drafts/webdev/deranged-typescript.md new file mode 100644 index 0000000000000000000000000000000000000000..a6f4a450915a4612b7c3cc7aabdfdef0cd034061 --- /dev/null +++ b/src/blog/drafts/webdev/deranged-typescript.md @@ -0,0 +1,87 @@ +- imports at the bottom + - order your file by importance. + - 'G' to jump to imports, etc + - prefer namespace imports + - easier to type and refactor. easier to read. +- large files are okay + - all files are their own library + - split files up by making components modular, not by "oh it's too big" + - engine/render.ts is a standalone library, in order to split JSX, Suspense, + and Marko out, the main file was made modular. +- lowercase +- name objects ultra-concisely + - filenames are often one word describing what they contain + - avoid useless descriptors like "utils", "helpers", and "data" + - examples + - async.ts contains all the async library functions. + - watch.ts contains the file watcher and watch-reload mode. + - render.*, Io +- be ultra-concise in comments +- no "discarded" variables, embrace `void x` + - makes code more readable + - note how i want to write a lint for this + - note the one proposal i want about void +- push the ts inference engine (as const, ReturnType, etc) + - reduces how much you repeat yourself making it easier to refactor things + - use the code as the source of truth +- push the ts inference engine (generics) + - do not implement crazy things with the TS engine, instead use generic input + types, and then use regular control to narrow and transform the return type. + source of truth is your code. +- UNWRAP, ASSERT utility globals are amazing + - ban postfix '!' + - stripped for production frontend builds +- destructure often + - use the one example from work lol +- package.json "imports" are amazing + - remapping + - implementation switching + - testing +- embrace the web and node.js APIs + - sitegen relies on so many node features that bun and deno fail to run it. + - overlay modules are great +- avoid dependencies + - once you build your own mini standard library you win + - talk about regrets with mdx + +## imports at the bottom + +Here is an abridged version of my website's `backend.ts`. When reading it from +top to bottom it is immediately obvious that it is a Hono web server. + +```ts +// This is the main file for paperclover.net's server. +const app = new Hono(); +const logHttp = console.scoped("http", { color: "magenta" }); + +// Middleware +app.use(...); +... + +// Backends +app.route("", require("./q+a/backend.ts").app); +... + +export default app; + +... + +import { type Context, Hono, type Next } from "#hono"; +import { logger } from "hono/logger"; +import { trimTrailingSlash } from "hono/trailing-slash"; +import * as assets from "#sitegen/assets"; +import * as admin from "./admin.ts"; +import * as console from "@paperclover/console"; +``` + +Since `import`/`export` statements are hoisted like `var` and `function`, the +position of these statements within the file does not matter. The imported +modules have to be loaded first before this file can start. With this, I've +found it nicer to sort the file by _importance_ rather than by arbitrary rules +dictated by how C-style `#include`s worked. + +Start with a documentation comment, then the most important +functions/variables/types, sort the file by importance. Imports are not really +important since you very quickly get to know where common namespaces come from. +And since they're at the bottom, you can just press `G` in Vim or `CMD+Down` on +the Mac to scroll to the end of the file. diff --git a/src/blog/drafts/webdev/marko-intro.markodown b/src/blog/drafts/webdev/marko-intro.markodown new file mode 100644 index 0000000000000000000000000000000000000000..8a7df80aeb80d2c561975c3a6ba5ed5c42f22672 --- /dev/null +++ b/src/blog/drafts/webdev/marko-intro.markodown @@ -0,0 +1,339 @@ +export const blog: BlogMeta = { + title: "Marko is the coziest HTML templating language", + desc: "...todo...", + created: "2025-06-13", + draft: true, +}; +export const meta = formatBlogMeta(blob); +export * as layout from "@/blog/layout.tsx"; + +I've been recently playing around [Marko], and after adding limited support +for it in my website generator, [sitegen], I instantly fell in love with how +minimalistic it is in comparison to JSX, Astro components, and Svelte. + +[Marko]: https://next.markojs.com +[sitegen]: https://paperclover.dev/clo/sitegen + +## Introduction to Marko + +If JSX was taking HTML and shoving its syntax into JavaScript, Marko is shoving +JavaScript into HTML. Attributes are JavaScript expressions. + +```marko +
+ // `input` is like props, but given in the top-level scope + + + + // Capital letter variables for imported components + + + // Components also can be auto-imported by lowercase. + // This will look upwards for a `tags/` folder containing + // "custom-footer.marko", similar to how Node.js finds + // package names in all upwards `node_modules` folders. + +
+ +// ESM `import` / `export` just work as expected. +// I prefer my imports at the end, to highlight the markup. +import MarkdownContent from "./MarkdownContent.marko"; +import { formatTimeNicely } from "../date-helpers.ts"; +``` + +Tags with the `value` attribute have a shorthand, which is used by the built-in +`` for conditional rendering. + +```marko +// Sugar for + + +// and it composes amazingly to the 'if' built-in + + + +``` + +Tags can also return values into the scope for use in the template using `/`, such as `` for unique ID generation. This is available to components that ``. + +``` + + + +