diff --git a/gulpfile.js b/gulpfile.js index 8df74eb..3f74fec 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,223 +1,2 @@ -import { src, dest, parallel, watch as _watch } from "gulp"; -import postcss from "gulp-postcss"; -import { Transform } from "node:stream"; -import pug from "pug"; -import asciidoctor from "asciidoctor"; -import { basename, dirname, join } from "node:path"; -import Vinyl from "vinyl"; -import { unified } from "unified"; -import rehypeParse from "rehype-parse"; -import rehypeStringify from "rehype-stringify"; -import rehypePresetMinify from "rehype-preset-minify"; -import rehypeExternalLinks from "rehype-external-links"; -import rehypePrism from "@mapbox/rehype-prism"; -import { DateTime } from "luxon"; -import visit from "unist-util-visit"; -import { readFileSync, unlinkSync } from "node:fs"; -import { env } from "node:process"; -import tmp from "tmp"; -import { execFile } from "node:child_process"; - -const PRODUCTION = env.NODE_ENV === "production"; -const DEFAULT_DATE = DateTime.fromSeconds(Number(env.SOURCE_DATE_EPOCH)).toUTC(); -const FONT_PRESETS = { - mono: { ranges: ["20-7F", "2E22-2E25", "2713", "2717"] }, - text: { ranges: ["20-7F", "A0-FF", "2000-206F", "20AC"] }, -}; -const SITE_TITLE = "Ad\xE6dra's blog"; -const SITE_DESCRIPTION = [ - "Ad\xE6dra", - "Software Developper in Paris, France", - "Rust, Ruby, Typescript, Linux", -].join(" \u2022 "); - -const Asciidoctor = asciidoctor(); - -const EXTENSION_REGISTRY = Asciidoctor.Extensions.create(); -EXTENSION_REGISTRY.inlineMacro("abbr", function () { - this.process((parent, target, attributes) => { - return this.createInline( - parent, - "quoted", - `${target}`, - ); - }); -}); - -const extractImages = (gulp, file) => () => (tree) => { - visit(tree, "element", (node) => { - if (node.tagName !== "img") { - return; - } - - const path = join(dirname(file.path), node.properties.src); - const image = new Vinyl({ - path: join(basename(file.path, ".asciidoc"), node.properties.src), - contents: readFileSync(path), - }); - - gulp.push(image); - }); -}; - -const asset = env.ASSETS_HOSTS - ? (path) => new URL(path, env.ASSETS_HOSTS).toString() - : (path) => join("/_assets/", path); - -const renderArticle = () => { - const allArticles = []; - const renderLayout = pug.compileFile("src/layout.pug"); - const renderArticleLayout = pug.compileFile("src/article.pug"); - - return new Transform({ - readableObjectMode: true, - writableObjectMode: true, - async transform(file, _, callback) { - try { - const slug = basename(file.path, ".asciidoc"); - const article = Asciidoctor.load(file.contents, { - extension_registry: EXTENSION_REGISTRY, - }); - - const date = DateTime.fromISO(article.getAttribute("docdate"), { - zone: "UTC", - }); - if (PRODUCTION && date.equals(DEFAULT_DATE)) { - callback(null); - return; - } - allArticles.push([slug, date, article]); - - const vfile = await unified() - .use(rehypeParse) - .use(rehypeExternalLinks, { rel: "noopener", target: "_blank" }) - .use(extractImages(this, file)) - .use(rehypePrism) - .use(rehypePresetMinify) - .use(rehypeStringify) - .process(article.convert()); - const content = renderLayout({ - SITE_TITLE, - asset, - title: article.getDoctitle(), - meta: { - description: article.getAttribute("description"), - keywords: article.getAttribute("keywords"), - "og:title": article.getDoctitle(), - "og:type": "article", - "og:article:published_time": article.getAttribute("docdate"), - "og:url": `https://adaedra.eu/${slug}/`, - "og:image": - "https://adaedra.blob.core.windows.net/blog-assets/cariboudev.avif", - "og:image:alt": "Ad\xE6dra's mascot", - "og:description": article.getAttribute("description"), - "og:locale": "en_GB", - "og:site_name": SITE_TITLE, - }, - render() { - return renderArticleLayout({ - asset, - article, - date, - DateTime, - body: vfile.toString(), - }); - }, - }); - file.contents = Buffer.from(content); - file.path = join(slug, "index.html"); - file.base = null; - - callback(null, file); - } catch (e) { - console.error(e); - callback(e); - } - }, - final(callback) { - try { - allArticles.sort(([, a], [, b]) => b.diff(a).toMillis()); - const renderIndex = pug.compileFile("src/index.pug"); - const contents = renderLayout({ - SITE_TITLE, - asset, - meta: { - description: SITE_DESCRIPTION, - "og:title": SITE_TITLE, - "og:type": "website", - "og:url": `https://adaedra.eu/`, - "og:image": - "https://adaedra.blob.core.windows.net/blog-assets/cariboudev.avif", - "og:image:alt": "Ad\xE6dra's mascot", - "og:description": SITE_DESCRIPTION, - "og:locale": "en_GB", - }, - render() { - return renderIndex({ articles: allArticles, asset }); - }, - }); - - this.push( - new Vinyl({ - path: "index.html", - contents: Buffer.from(contents), - }), - ); - - callback(null); - } catch (e) { - console.error(e); - callback(e); - } - }, - }); -}; - -export const articles = () => - src("articles/**/*.asciidoc").pipe(renderArticle()).pipe(dest("dist/")); - -export const images = () => src("src/*.avif", { encoding: false }).pipe(dest("dist/_assets/")); - -// SVG use has no way of allowing cross-origin, so we need to keep them with the HTML files. -export const svg = () => src("src/*.svg").pipe(dest("dist/")); - -export const css = () => src("src/index.css").pipe(postcss()).pipe(dest("dist/_assets/")); - -const compileFont = () => - new Transform({ - readableObjectMode: true, - writableObjectMode: true, - transform(chunk, _, callback) { - const [, variant, weight] = /([A-Z][a-z]+)-(\w+)\.ttf$/.exec(chunk.basename); - const tmpOutput = tmp.fileSync({ discardDescriptor: true }); - const unicodes = FONT_PRESETS[variant.toLowerCase()].ranges; - - execFile("pyftsubset", [ - chunk.path, - `--unicodes=${unicodes.join(",")}`, - `--output-file=${tmpOutput.name}`, - "--layout-features=*", - "--flavor=woff2", - ]).once("exit", () => { - const file = new Vinyl({ - path: `iosevka-adaedra-${variant.toLowerCase()}-${weight.toLowerCase()}.woff2`, - contents: readFileSync(tmpOutput.name), - }); - unlinkSync(tmpOutput.name); - - callback(null, file); - }); - }, - }); - -export const fonts = () => src("vendor/*.ttf").pipe(compileFont()).pipe(dest("dist/_assets/")); - -export default parallel(fonts, articles, images, svg, css); - -export const watch = () => { - _watch(["src/*.pug", "articles/**/*.asciidoc"], articles); - - _watch("src/*.css", css); - _watch("src/*.avif", images); - _watch("src/*.svg", svg); -}; +export * from "./lib/tasks.ts"; +export { default } from "./lib/tasks.ts"; diff --git a/lib/environment.ts b/lib/environment.ts new file mode 100644 index 0000000..14d0bb1 --- /dev/null +++ b/lib/environment.ts @@ -0,0 +1,5 @@ +import { env } from "node:process"; +import { DateTime } from "luxon"; + +export const PRODUCTION = env.NODE_ENV === "production"; +export const DEFAULT_DATE = DateTime.fromSeconds(Number(env.SOURCE_DATE_EPOCH)).toUTC(); diff --git a/lib/hash.ts b/lib/hash.ts new file mode 100644 index 0000000..e84c63b --- /dev/null +++ b/lib/hash.ts @@ -0,0 +1,36 @@ +import { Transform } from "node:stream"; +import { createHash } from "node:crypto"; +import File from "vinyl"; + +function fileHash(buffer: Buffer) { + const hash = createHash("sha256"); + hash.update(buffer.toString()); + return hash.digest("hex"); +} + +export default function (manifestName: string) { + const mappings: { [path: string]: string } = {}; + + return new Transform({ + readableObjectMode: true, + writableObjectMode: true, + transform(chunk: File, _, callback) { + const hash = fileHash(chunk.contents as Buffer); + const newName = `${chunk.basename.substring(0, chunk.basename.length - chunk.extname.length)}.${hash.substring(0, 8)}${chunk.extname}`; + + mappings[chunk.basename] = newName; + chunk.basename = newName; + + callback(null, chunk); + }, + final(callback) { + const mappingFile = new File({ + path: manifestName, + contents: Buffer.from(JSON.stringify(mappings)), + }); + this.push(mappingFile); + + callback(null); + }, + }); +} diff --git a/lib/tasks.ts b/lib/tasks.ts new file mode 100644 index 0000000..ebd4a8c --- /dev/null +++ b/lib/tasks.ts @@ -0,0 +1,10 @@ +import { series } from "gulp"; +import { articles } from "./tasks/articles.js"; +import { css } from "./tasks/css.js"; +import { fonts } from "./tasks/fonts.js"; +import { images } from "./tasks/images.js"; +import { svg } from "./tasks/svg.js"; +import { watch } from "./tasks/watch.js"; + +export { articles, css, fonts, images, svg, watch }; +export default series(fonts, css, images, svg, articles); diff --git a/lib/tasks/articles.ts b/lib/tasks/articles.ts new file mode 100644 index 0000000..c26bb37 --- /dev/null +++ b/lib/tasks/articles.ts @@ -0,0 +1,178 @@ +import { compileFile } from "pug"; +import { readFileSync } from "node:fs"; +import { env } from "node:process"; +import { join, basename, dirname } from "node:path"; +import { Transform } from "node:stream"; +import asciidoctor, { Document } from "asciidoctor"; +import File from "vinyl"; +import { DateTime } from "luxon"; +import { unified } from "unified"; +import rehypeParse from "rehype-parse"; +import rehypeStringify from "rehype-stringify"; +import rehypePresetMinify from "rehype-preset-minify"; +import rehypePrism from "@mapbox/rehype-prism"; +import { PRODUCTION, DEFAULT_DATE } from "../environment.js"; +import rehypeExternalLinks from "rehype-external-links"; +import visit from "unist-util-visit"; +import { src, dest } from "gulp"; +import { globSync } from "glob"; + +const Asciidoctor = asciidoctor(); +const EXTENSION_REGISTRY = Asciidoctor.Extensions.create(); +EXTENSION_REGISTRY.inlineMacro("abbr", function () { + this.process(function (parent, target, attributes) { + return this.createInline( + parent, + "quoted", + `${target}`, + ); + }); +}); + +const SITE_TITLE = "Ad\xE6dra's blog"; +const SITE_DESCRIPTION = [ + "Ad\xE6dra", + "Software Developper in Paris, France", + "Rust, Ruby, Typescript, Linux", +].join(" \u2022 "); +const SITE_DEFAULT_META = { + "og:image": "https://adaedra.blob.core.windows.net/blog-assets/cariboudev.avif", + "og:image:alt": SITE_DESCRIPTION, + "og:locale": "en_GB", +}; + +function readAssetManifest(): { [entry: string]: string } { + return Object.assign( + {}, + ...globSync("dist/_assets/*.manifest").map((path) => + JSON.parse(readFileSync(path).toString()), + ), + ); +} + +function extractImages(gulp: Transform, file: File) { + return function () { + return function (tree) { + visit(tree, "element", function (node: any) { + if (node.tagName !== "img") { + return; + } + + const path = join(dirname(file.path)); + const image = new File({ + path: join(basename(file.path, ".asciidoc"), node.properties.src), + contents: readFileSync(path), + }); + + gulp.push(image); + }); + }; + }; +} + +function renderArticle() { + const allArticles: [string, DateTime, Document][] = []; + const renderLayout = compileFile("src/layout.pug"); + const renderArticleLayout = compileFile("src/article.pug"); + const assetManifest = readAssetManifest(); + + const asset = (path: string) => { + if (assetManifest.hasOwnProperty(path)) { + path = assetManifest[path]; + } + + return env.ASSETS_HOSTS + ? new URL(path, env.ASSETS_HOSTS).toString() + : join("/_assets/", path); + }; + + return new Transform({ + readableObjectMode: true, + writableObjectMode: true, + async transform(file: File, _, callback) { + try { + const slug = basename(file.path, ".asciidoc"); + const article = Asciidoctor.load(file.contents.toString(), { + extension_registry: EXTENSION_REGISTRY, + }); + + const date = DateTime.fromISO(article.getAttribute("docdate"), { zone: "UTC" }); + if (PRODUCTION && date.equals(DEFAULT_DATE)) { + callback(null); + return; + } + allArticles.push([slug, date, article]); + + const vfile = await unified() + .use(rehypeParse) + .use(rehypeExternalLinks, { rel: "noopener", target: "_blank" }) + .use(extractImages(this, file)) + .use(rehypePrism) + .use(rehypePresetMinify) + .use(rehypeStringify) + .process(article.convert()); + const content = renderLayout({ + SITE_TITLE, + asset, + title: article.getDoctitle({}), + meta: Object.assign({}, SITE_DEFAULT_META, { + description: article.getAttribute("description"), + keywords: article.getAttribute("keywords"), + "og:title": article.getDoctitle({}), + "og:type": "article", + "og:article:published_time": article.getAttribute("docdate"), + "og:url": `https://adaedra.eu/${slug}/`, + "og:description": article.getAttribute("description"), + "og:site_name": SITE_TITLE, + }), + render() { + return renderArticleLayout({ + asset, + article, + date, + DateTime, + body: vfile.toString(), + }); + }, + }); + + file.contents = Buffer.from(content); + file.path = join(slug, "index.html"); + file.base = null; + + callback(null, file); + } catch (e) { + console.error(e); + callback(e); + } + }, + final(callback) { + try { + allArticles.sort(([, a], [, b]) => b.diff(a).toMillis()); + const renderIndex = compileFile("src/index.pug"); + const contents = renderLayout({ + SITE_TITLE, + asset, + meta: Object.assign({}, SITE_DEFAULT_META, { + description: SITE_DESCRIPTION, + "og:title": SITE_TITLE, + "og:type": "website", + "og:url": `https://adaedra.eu`, + }), + render() { + return renderIndex({ articles: allArticles, asset }); + }, + }); + + this.push(new File({ path: "index.html", contents: Buffer.from(contents) })); + callback(null); + } catch (e) { + console.error(e); + callback(e); + } + }, + }); +} + +export const articles = () => + src("articles/**/*.asciidoc").pipe(renderArticle()).pipe(dest("dist/")); diff --git a/lib/tasks/css.ts b/lib/tasks/css.ts new file mode 100644 index 0000000..134ec72 --- /dev/null +++ b/lib/tasks/css.ts @@ -0,0 +1,6 @@ +import { src, dest } from "gulp"; +import postcss from "gulp-postcss"; +import hashPath from "../hash.js"; + +export const css = () => + src("src/index.css").pipe(postcss()).pipe(hashPath("css.manifest")).pipe(dest("dist/_assets/")); diff --git a/lib/tasks/fonts.ts b/lib/tasks/fonts.ts new file mode 100644 index 0000000..814f8a5 --- /dev/null +++ b/lib/tasks/fonts.ts @@ -0,0 +1,44 @@ +import { Transform } from "node:stream"; +import File from "vinyl"; +import tmp from "tmp"; +import { execFile } from "node:child_process"; +import { readFileSync, unlinkSync } from "node:fs"; +import { src, dest } from "gulp"; +import hashPaths from "../hash.js"; + +const FONT_PRESETS = { + mono: { ranges: ["20-7F", "2205", "2E22-2E25", "2713", "2717"] }, + text: { ranges: ["20-7F", "A0-FF", "2000-206F", "20AC"] }, +}; + +function compileFont() { + return new Transform({ + readableObjectMode: true, + writableObjectMode: true, + async transform(chunk: File, _, callback) { + const [, variant, weight] = /([A-Z][a-z]+)-(\w+)\.ttf$/.exec(chunk.basename); + const tmpOutput = tmp.fileSync({ discardDescriptor: true }); + const unicodes = FONT_PRESETS[variant.toLowerCase()].ranges; + + execFile("pyftsubset", [ + chunk.path, + `--unicodes=${unicodes.join(",")}`, + `--output-file=${tmpOutput.name}`, + "--flavor=woff2", + ]).once("exit", () => { + chunk.path = `iosevka-adaedra-${variant.toLowerCase()}-${weight.toLowerCase()}.woff2`; + chunk.contents = readFileSync(tmpOutput.name); + chunk.base = null; + + unlinkSync(tmpOutput.name); + callback(null, chunk); + }); + }, + }); +} + +export const fonts = () => + src("vendor/*.ttf") + .pipe(compileFont()) + .pipe(hashPaths("fonts.manifest")) + .pipe(dest("dist/_assets")); diff --git a/lib/tasks/images.ts b/lib/tasks/images.ts new file mode 100644 index 0000000..f2880ac --- /dev/null +++ b/lib/tasks/images.ts @@ -0,0 +1,3 @@ +import { src, dest } from "gulp"; + +export const images = () => src("src/*.avif", { encoding: false }).pipe(dest("dist/_assets/")); diff --git a/lib/tasks/svg.ts b/lib/tasks/svg.ts new file mode 100644 index 0000000..bacb021 --- /dev/null +++ b/lib/tasks/svg.ts @@ -0,0 +1,4 @@ +import { src, dest } from "gulp"; + +// SVG `use` has no way of allowing cross-origin, so we need to keep them with the HTML files. +export const svg = () => src("src/*.svg").pipe(dest("dist/")); diff --git a/lib/tasks/watch.ts b/lib/tasks/watch.ts new file mode 100644 index 0000000..0923acf --- /dev/null +++ b/lib/tasks/watch.ts @@ -0,0 +1,16 @@ +import gulp from "gulp"; +import { articles } from "./articles.js"; +import { css } from "./css.js"; +import { images } from "./images.js"; +import { svg } from "./svg.js"; + +export const watch = () => { + gulp.watch(["src/*.pug", "articles/**/*.asciidoc"], articles); + + gulp.watch("src/*.css", css); + gulp.watch("src/*.avif", images); + gulp.watch("src/*.svg", svg); + + gulp.watch("dist/_assets/fonts.manifest", css); + gulp.watch("dist/_assets/css.manifest", articles); +}; diff --git a/lib/ts-loader.js b/lib/ts-loader.js new file mode 100644 index 0000000..32e2ca7 --- /dev/null +++ b/lib/ts-loader.js @@ -0,0 +1,3 @@ +import { register } from "node:module"; + +register("ts-node/esm", import.meta.url); diff --git a/package-lock.json b/package-lock.json index 907159a..ba632bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@mapbox/rehype-prism": "^0.9.0", "asciidoctor": "^3.0.4", "cssnano": "^7.0.2", + "glob": "^10.4.2", "gulp": "^5.0.0", "gulp-cli": "^3.0.0", "gulp-postcss": "^10.0.0", @@ -23,11 +24,14 @@ "rehype-external-links": "^3.0.0", "rehype-preset-minify": "^7.0.0", "tmp": "^0.2.3", + "ts-node": "^10.9.2", "unified": "^11.0.4" }, "devDependencies": { "@types/express": "^4.17.21", + "@types/glob": "^8.1.0", "@types/gulp": "^4.0.17", + "@types/gulp-postcss": "^8.0.6", "@types/luxon": "^3.4.2", "@types/pug": "^2.0.10", "@types/tmp": "^0.2.6", @@ -78,6 +82,25 @@ "node": ">=16" } }, + "node_modules/@asciidoctor/opal-runtime/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", @@ -118,6 +141,17 @@ "node": ">=6.9.0" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@csstools/selector-resolve-nested": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-1.1.0.tgz", @@ -179,6 +213,117 @@ "node": ">=10.13.0" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@mapbox/rehype-prism": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@mapbox/rehype-prism/-/rehype-prism-0.9.0.tgz", @@ -192,6 +337,15 @@ "node": ">=10" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -200,6 +354,26 @@ "node": ">=10.13.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -249,6 +423,16 @@ "@types/send": "*" } }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "node_modules/@types/glob-stream": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-8.0.2.tgz", @@ -272,6 +456,16 @@ "chokidar": "^3.3.1" } }, + "node_modules/@types/gulp-postcss": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@types/gulp-postcss/-/gulp-postcss-8.0.6.tgz", + "integrity": "sha512-mjGEmTvurqRHFeJQnrgtMC9GtKNkI2+56n92zIzff5UFr2jUfilw1elKRxS7bK0FYRvuEcnMX9JH0AUpCxBrpg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/vinyl": "*" + } + }, "node_modules/@types/hast": { "version": "2.3.10", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", @@ -306,11 +500,16 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "node_modules/@types/node": { "version": "20.14.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -439,6 +638,28 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk/node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -492,6 +713,11 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "node_modules/array-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", @@ -1089,6 +1315,38 @@ "node": ">= 10.13.0" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css-declaration-sorter": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", @@ -1311,6 +1569,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/direction": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", @@ -1391,6 +1657,11 @@ "node": ">= 10.13.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -1592,6 +1863,21 @@ "node": ">=0.10.0" } }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fs-mkdirp-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", @@ -1657,19 +1943,22 @@ } }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -1740,6 +2029,20 @@ "node": ">= 10.13.0" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -2924,6 +3227,23 @@ "node": ">=0.10.0" } }, + "node_modules/jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jake": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", @@ -3029,6 +3349,14 @@ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" }, + "node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/luxon": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", @@ -3037,6 +3365,11 @@ "node": ">=12" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -3225,6 +3558,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mute-stdout": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz", @@ -3360,6 +3701,11 @@ "wrappy": "1" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + }, "node_modules/parse-entities": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", @@ -3409,6 +3755,14 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -3433,6 +3787,21 @@ "node": ">=0.10.0" } }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", @@ -5800,6 +6169,36 @@ "node": ">= 0.4" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5880,6 +6279,20 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -5913,6 +6326,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/stylehacks": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.1.tgz", @@ -6067,6 +6492,72 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/typescript": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/uglify-js": { "version": "3.18.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", @@ -6111,8 +6602,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unified": { "version": "11.0.4", @@ -6275,6 +6765,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "node_modules/v8flags": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", @@ -6492,6 +6987,23 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -6549,6 +7061,14 @@ "node": ">=12" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index a767190..ea3d124 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@mapbox/rehype-prism": "^0.9.0", "asciidoctor": "^3.0.4", "cssnano": "^7.0.2", + "glob": "^10.4.2", "gulp": "^5.0.0", "gulp-cli": "^3.0.0", "gulp-postcss": "^10.0.0", @@ -19,18 +20,21 @@ "rehype-external-links": "^3.0.0", "rehype-preset-minify": "^7.0.0", "tmp": "^0.2.3", + "ts-node": "^10.9.2", "unified": "^11.0.4" }, "devDependencies": { "@types/express": "^4.17.21", + "@types/glob": "^8.1.0", "@types/gulp": "^4.0.17", + "@types/gulp-postcss": "^8.0.6", "@types/luxon": "^3.4.2", "@types/pug": "^2.0.10", "@types/tmp": "^0.2.6", "prettier": "^3.3.1" }, "scripts": { - "build": "gulp", + "build": "env NODE_OPTIONS='--import ./lib/ts-loader.js' gulp", "watch": "gulp watch", "dev": "python -m http.server -d dist" } diff --git a/src/layout.pug b/src/layout.pug index 0ef9c0f..464ded4 100644 --- a/src/layout.pug +++ b/src/layout.pug @@ -10,6 +10,6 @@ html(lang="en") meta(name="theme-color" content="#DDCBA3")/ - for([name, content] of Object.entries(meta)) meta(name=name content=content)/ - link(rel="stylesheet" type="text/css" href=`${asset('index.css')}?v2`)/ + link(rel="stylesheet" type="text/css" href=asset("index.css"))/ body: .main != render() diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..97ecc7f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "ts-node": { + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "NodeNext" + } + }, + "compilerOptions": { + "esModuleInterop": true, + } +}