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,
+ }
+}