Switch to deno
This commit is contained in:
parent
4b4aa3ff79
commit
40723b32cf
|
@ -2,4 +2,3 @@ root = true
|
|||
|
||||
[*]
|
||||
indent_size = 4
|
||||
max_line_length = 100
|
||||
|
|
19
bin/build.ts
19
bin/build.ts
|
@ -1,8 +1,8 @@
|
|||
import { articles } from "../lib/tasks/articles.js";
|
||||
import { css } from "../lib/tasks/css.js";
|
||||
import { fonts } from "../lib/tasks/fonts.js";
|
||||
import { images } from "../lib/tasks/images.js";
|
||||
import { svg } from "../lib/tasks/svg.js";
|
||||
import { articles } from "../lib/tasks/articles.ts";
|
||||
import { css } from "../lib/tasks/css.ts";
|
||||
import { fonts } from "../lib/tasks/fonts.ts";
|
||||
import { images } from "../lib/tasks/images.ts";
|
||||
import { svg } from "../lib/tasks/svg.ts";
|
||||
|
||||
import { argv, exit } from "node:process";
|
||||
|
||||
|
@ -12,7 +12,7 @@ const wrapTask = (name: string, task: () => Promise<void>) => async () => {
|
|||
console.log("[end]", name);
|
||||
};
|
||||
|
||||
const TASKS = {
|
||||
const TASKS: { [task: string]: () => Promise<void> } = {
|
||||
articles: wrapTask("articles", articles),
|
||||
css: wrapTask("css", css),
|
||||
fonts: wrapTask("fonts", fonts),
|
||||
|
@ -23,8 +23,9 @@ const TASKS = {
|
|||
const ALL_TASKS = ["fonts", "images", "svg", "css", "articles"];
|
||||
|
||||
const args = argv.slice(2);
|
||||
await (args.length ? args : ALL_TASKS)
|
||||
.map((task) => {
|
||||
console.log("args", args);
|
||||
(args.length ? args : ALL_TASKS)
|
||||
.map((task: string) => {
|
||||
if (!TASKS.hasOwnProperty(task)) {
|
||||
console.error("Unknown task", task);
|
||||
exit(1);
|
||||
|
@ -32,4 +33,4 @@ await (args.length ? args : ALL_TASKS)
|
|||
|
||||
return TASKS[task];
|
||||
})
|
||||
.reduce((prev, cur) => prev.then(cur), Promise.resolve());
|
||||
.reduce((prev: Promise<void>, cur: () => Promise<void>) => prev.then(cur), Promise.resolve());
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import { Worker } from "node:worker_threads";
|
||||
import chokidar from "chokidar";
|
||||
|
||||
const watch = (glob: string | string[], task: string) =>
|
||||
chokidar.watch(glob).on("change", (path: string) => {
|
||||
console.log("[change]", path, "->", task);
|
||||
return new Promise<void>((resolve) => {
|
||||
const worker = new Worker(new URL(import.meta.resolve("./build.ts")), { argv: [task] });
|
||||
worker.on("exit", () => resolve());
|
||||
const worker = new Worker(import.meta.resolve("../lib/watch-worker.ts"), { type: "module" });
|
||||
worker.addEventListener("message", () => {
|
||||
worker.terminate();
|
||||
resolve();
|
||||
});
|
||||
worker.postMessage({ task });
|
||||
});
|
||||
});
|
||||
|
||||
|
|
37
deno.jsonc
Normal file
37
deno.jsonc
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"imports": {
|
||||
"@std/io": "jsr:@std/io@^0.224.2",
|
||||
"asciidoctor": "https://esm.sh/asciidoctor@^3.0.4",
|
||||
"chokidar": "npm:chokidar@^3.6.0",
|
||||
"cssnano": "npm:cssnano@^7.0.2",
|
||||
"glob": "npm:glob@^10.4.2",
|
||||
"luxon": "npm:luxon@^3.4.4",
|
||||
"postcss": "npm:postcss@^8.4.38",
|
||||
"postcss-import": "npm:postcss-import@^16.1.0",
|
||||
"postcss-nesting": "npm:postcss-nesting@^12.1.5",
|
||||
"preact": "npm:preact@^10.22.0",
|
||||
"preact-render-to-string": "npm:preact-render-to-string@^6.5.5",
|
||||
"rehype": "npm:rehype@^13.0.1",
|
||||
"rehype-external-links": "npm:rehype-external-links@^3.0.0",
|
||||
"rehype-parse": "npm:rehype-parse@^9.0.0",
|
||||
"rehype-preset-minify": "npm:rehype-preset-minify@^7.0.0",
|
||||
"rehype-prism": "npm:@mapbox/rehype-prism@^0.9.0",
|
||||
"rehype-stringify": "npm:rehype-stringify@^10.0.0",
|
||||
"rxjs": "npm:rxjs@^7.8.1",
|
||||
"tmp": "npm:tmp@^0.2.3",
|
||||
"unified": "npm:unified@^11.0.4",
|
||||
"unist-util-visit": "npm:unist-util-visit@^5.0.0",
|
||||
"vinyl": "npm:vinyl@^3.0.0"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "preact"
|
||||
},
|
||||
"fmt": {
|
||||
"lineWidth": 120
|
||||
},
|
||||
"tasks": {
|
||||
"build": "deno run -A bin/build.ts",
|
||||
"watch": "deno run -A bin/watch.ts"
|
||||
}
|
||||
}
|
|
@ -20,11 +20,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1717646450,
|
||||
"narHash": "sha256-KE+UmfSVk5PG8jdKdclPVcMrUB8yVZHbsjo7ZT1Bm3c=",
|
||||
"lastModified": 1719379843,
|
||||
"narHash": "sha256-u+D+IOAMMl70+CJ9NKB+RMrASjInuIWMHzjLWQjPZ6c=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "818dbe2f96df233d2041739d6079bb616d3e5597",
|
||||
"rev": "b3f3c1b13fb08f3828442ee86630362e81136bbc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
pkgs = import nixpkgs { inherit system; };
|
||||
in {
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [ nodejs_20 python312Packages.fonttools python312Packages.brotli libavif pandoc imagemagick ];
|
||||
buildInputs = with pkgs; [ deno python312Packages.fonttools python312Packages.brotli libavif pandoc imagemagick ];
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,18 +10,13 @@ export function reloadAssets() {
|
|||
|
||||
globSync("dist/_assets/*.manifest")
|
||||
.map(
|
||||
(manifest) =>
|
||||
JSON.parse(readFileSync(manifest).toString()) as { [orig: string]: string },
|
||||
(manifest) => JSON.parse(readFileSync(manifest).toString()) as { [orig: string]: string },
|
||||
)
|
||||
.forEach((mapping) =>
|
||||
Object.entries(mapping).forEach(([orig, hashed]) => assetMap.set(orig, hashed)),
|
||||
);
|
||||
.forEach((mapping) => Object.entries(mapping).forEach(([orig, hashed]) => assetMap.set(orig, hashed)));
|
||||
}
|
||||
|
||||
export function asset(path: string): string {
|
||||
const realPath = assetMap.has(path) ? assetMap.get(path) : path;
|
||||
const realPath = assetMap.has(path) ? assetMap.get(path)! : path;
|
||||
|
||||
return env.ASSETS_HOSTS
|
||||
? new URL(realPath, env.ASSETS_HOSTS).toString()
|
||||
: join("/_assets/", realPath);
|
||||
return env.ASSETS_HOSTS ? new URL(realPath, env.ASSETS_HOSTS).toString() : join("/_assets/", realPath);
|
||||
}
|
||||
|
|
27
lib/hash.ts
27
lib/hash.ts
|
@ -1,7 +1,8 @@
|
|||
import { createHash } from "node:crypto";
|
||||
import File from "vinyl";
|
||||
import { PRODUCTION } from "./environment.js";
|
||||
import { PRODUCTION } from "./environment.ts";
|
||||
import { Observable } from "rxjs";
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
function fileHash(buffer: Buffer) {
|
||||
const hash = createHash("sha256");
|
||||
|
@ -9,21 +10,19 @@ function fileHash(buffer: Buffer) {
|
|||
return hash.digest("hex");
|
||||
}
|
||||
|
||||
const hashPath =
|
||||
(mappings: Map<string, string>) =>
|
||||
(file: File): File => {
|
||||
const hash = PRODUCTION ? fileHash(file.contents as Buffer) : "00000000";
|
||||
const newName = [
|
||||
file.basename.substring(0, file.basename.length - file.extname.length),
|
||||
hash.substring(0, 8),
|
||||
file.extname.substring(1),
|
||||
].join(".");
|
||||
const hashPath = (mappings: Map<string, string>) => (file: File): File => {
|
||||
const hash = PRODUCTION ? fileHash(file.contents as Buffer) : "00000000";
|
||||
const newName = [
|
||||
file.basename.substring(0, file.basename.length - file.extname.length),
|
||||
hash.substring(0, 8),
|
||||
file.extname.substring(1),
|
||||
].join(".");
|
||||
|
||||
mappings.set(file.basename, newName);
|
||||
file.basename = newName;
|
||||
mappings.set(file.basename, newName);
|
||||
file.basename = newName;
|
||||
|
||||
return file;
|
||||
};
|
||||
return file;
|
||||
};
|
||||
|
||||
export default function (manifestName: string) {
|
||||
return (observable: Observable<File>): Observable<File> =>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Postcss from "postcss";
|
||||
import { reloadAssets, assetMap } from "../assets.js";
|
||||
import { assetMap, reloadAssets } from "../assets.ts";
|
||||
|
||||
export default (): Postcss.Plugin => {
|
||||
return {
|
||||
|
@ -8,9 +8,9 @@ export default (): Postcss.Plugin => {
|
|||
reloadAssets();
|
||||
},
|
||||
Declaration(decl: Postcss.Declaration) {
|
||||
decl.value = decl.value.replace(/url\("([^"]+)"\)/, (v, url) => {
|
||||
decl.value = decl.value.replace(/url\("([^"]+)"\)/, (v: string, url: string) => {
|
||||
if (assetMap.has(url)) {
|
||||
return v.replace(url, assetMap.get(url));
|
||||
return v.replace(url, assetMap.get(url)!);
|
||||
}
|
||||
|
||||
return v;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Observable, Subscriber, from, mergeMap } from "rxjs";
|
||||
import { from, mergeMap, Observable, Subscriber } from "rxjs";
|
||||
import File from "vinyl";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { join, dirname } from "node:path";
|
||||
import { dirname, join } from "node:path";
|
||||
import { existsSync } from "node:fs";
|
||||
import { writeFile, mkdir } from "node:fs/promises";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { Glob } from "glob";
|
||||
|
||||
export function dest(prefix: string) {
|
||||
|
@ -33,12 +33,11 @@ export function onComplete<T>(f: (sink: Subscriber<T>) => Promise<void>) {
|
|||
f(subscriber);
|
||||
subscriber.complete();
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const loadFile = async (path: string): Promise<File> =>
|
||||
new File({ path, contents: await readFile(path) });
|
||||
const loadFile = async (path: string): Promise<File> => new File({ path, contents: await readFile(path) });
|
||||
|
||||
export const fromGlob = (paths: string | string[]): Observable<File> =>
|
||||
from(new Glob(paths, {})).pipe(mergeMap(loadFile));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { readFileSync } from "node:fs";
|
||||
import { join, basename, dirname } from "node:path";
|
||||
import { basename, dirname, join } from "node:path";
|
||||
import asciidoctor from "asciidoctor";
|
||||
import File from "vinyl";
|
||||
import { DateTime } from "luxon";
|
||||
|
@ -7,21 +7,22 @@ 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 rehypePrism from "rehype-prism";
|
||||
import { DEFAULT_DATE, PRODUCTION } from "../environment.ts";
|
||||
import rehypeExternalLinks from "rehype-external-links";
|
||||
import visit from "unist-util-visit";
|
||||
import renderLayout from "../views/layout.js";
|
||||
import renderArticleLayout, { Article } from "../views/article.js";
|
||||
import renderIndex from "../views/index.js";
|
||||
import { visit } from "unist-util-visit";
|
||||
import renderLayout from "../views/layout.tsx";
|
||||
import renderArticleLayout, { Article } from "../views/article.tsx";
|
||||
import renderIndex from "../views/index.tsx";
|
||||
import { renderToStaticMarkup } from "preact-render-to-string";
|
||||
import { SITE_TITLE, SITE_DESCRIPTION } from "../constants.js";
|
||||
import { SITE_DESCRIPTION, SITE_TITLE } from "../constants.ts";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
import { reloadAssets } from "../assets.js";
|
||||
import { reloadAssets } from "../assets.ts";
|
||||
import { lastValueFrom, mergeMap, Observable, Subscriber } from "rxjs";
|
||||
import { dest, fromGlob, onComplete } from "../rx-utils.js";
|
||||
import { dest, fromGlob, onComplete } from "../rx-utils.ts";
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
const Asciidoctor = (asciidoctor as unknown as () => asciidoctor.Asciidoctor)();
|
||||
const Asciidoctor = asciidoctor();
|
||||
const EXTENSION_REGISTRY = Asciidoctor.Extensions.create();
|
||||
EXTENSION_REGISTRY.inlineMacro("abbr", function () {
|
||||
this.process(function (parent, target, attributes) {
|
||||
|
@ -35,7 +36,7 @@ EXTENSION_REGISTRY.inlineMacro("abbr", function () {
|
|||
|
||||
function extractImages(sink: (image: File) => void, articlePath: string) {
|
||||
return function () {
|
||||
return function (tree) {
|
||||
return function (tree: any) {
|
||||
visit(tree, "element", function (node: any) {
|
||||
if (node.tagName !== "img") {
|
||||
return;
|
||||
|
@ -57,48 +58,47 @@ function renderDocument(root: JSX.Element): Buffer {
|
|||
return Buffer.concat([Buffer.from("<!doctype html>"), Buffer.from(renderToStaticMarkup(root))]);
|
||||
}
|
||||
|
||||
const transformArticle =
|
||||
(sink: (file: File) => void, articles: Article[]) => async (file: File) => {
|
||||
const slug = basename(file.path, ".asciidoc");
|
||||
const document = Asciidoctor.load(file.contents.toString(), {
|
||||
extension_registry: EXTENSION_REGISTRY,
|
||||
});
|
||||
const date = DateTime.fromISO(document.getAttribute("docdate", { zone: "UTC" }));
|
||||
const article = { path: file.path, slug, date, document };
|
||||
const transformArticle = (sink: (file: File) => void, articles: Article[]) => async (file: File) => {
|
||||
const slug = basename(file.path, ".asciidoc");
|
||||
const document = Asciidoctor.load(file.contents!.toString(), {
|
||||
extension_registry: EXTENSION_REGISTRY,
|
||||
});
|
||||
const date = DateTime.fromISO(document.getAttribute("docdate", { zone: "UTC" }));
|
||||
const article = { path: file.path, slug, date, document };
|
||||
|
||||
if (PRODUCTION && date.equals(DEFAULT_DATE)) {
|
||||
return;
|
||||
}
|
||||
if (PRODUCTION && date.equals(DEFAULT_DATE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const vfile = await unified()
|
||||
.use(rehypeParse)
|
||||
.use(rehypeExternalLinks, { rel: "noopener", target: "_blank" })
|
||||
.use(extractImages(sink, file.path))
|
||||
.use(rehypePrism)
|
||||
.use(rehypePresetMinify)
|
||||
.use(rehypeStringify)
|
||||
.process(document.convert());
|
||||
const content = renderLayout({
|
||||
title: document.getDoctitle({}) as string,
|
||||
meta: {
|
||||
description: document.getAttribute("description"),
|
||||
keywords: document.getAttribute("keywords"),
|
||||
"og:title": document.getDoctitle({}) as string,
|
||||
"og:type": "article",
|
||||
"og:article:published_time": document.getAttribute("docdate"),
|
||||
"og:url": `https://adaedra.eu/${slug}/`,
|
||||
"og:description": document.getAttribute("description"),
|
||||
"og:site_name": SITE_TITLE,
|
||||
},
|
||||
Content: () => renderArticleLayout({ article, body: vfile.toString() }),
|
||||
});
|
||||
const vfile = await unified()
|
||||
.use(rehypeParse as any)
|
||||
.use(rehypeExternalLinks, { rel: "noopener", target: "_blank" })
|
||||
.use(extractImages(sink, file.path))
|
||||
.use(rehypePrism)
|
||||
.use(rehypePresetMinify as any)
|
||||
.use(rehypeStringify as any)
|
||||
.process(document.convert());
|
||||
const content = renderLayout({
|
||||
title: document.getDoctitle({}) as string,
|
||||
meta: {
|
||||
description: document.getAttribute("description"),
|
||||
keywords: document.getAttribute("keywords"),
|
||||
"og:title": document.getDoctitle({}) as string,
|
||||
"og:type": "article",
|
||||
"og:article:published_time": document.getAttribute("docdate"),
|
||||
"og:url": `https://adaedra.eu/${slug}/`,
|
||||
"og:description": document.getAttribute("description"),
|
||||
"og:site_name": SITE_TITLE,
|
||||
},
|
||||
Content: () => renderArticleLayout({ article, body: vfile.toString() }),
|
||||
});
|
||||
|
||||
file.path = join(slug, "index.html");
|
||||
file.contents = renderDocument(content);
|
||||
file.path = join(slug, "index.html");
|
||||
file.contents = renderDocument(content);
|
||||
|
||||
articles.push(article);
|
||||
sink(file);
|
||||
};
|
||||
articles.push(article);
|
||||
sink(file);
|
||||
};
|
||||
|
||||
const finalizeArticles = (articles: Article[]) => async (sink: Subscriber<File>) => {
|
||||
articles.sort(({ date: a }, { date: b }) => b.diff(a).toMillis());
|
||||
|
@ -117,7 +117,7 @@ const finalizeArticles = (articles: Article[]) => async (sink: Subscriber<File>)
|
|||
|
||||
export const articles = () => {
|
||||
reloadAssets();
|
||||
const articles = [];
|
||||
const articles: Article[] = [];
|
||||
|
||||
return lastValueFrom(
|
||||
fromGlob("articles/**/*.asciidoc").pipe(
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import postcss, { Result } from "postcss";
|
||||
import config from "../../postcss.config.js";
|
||||
import { dest, fromGlob } from "../rx-utils.js";
|
||||
import config from "../../postcss.config.ts";
|
||||
import { dest, fromGlob } from "../rx-utils.ts";
|
||||
import { lastValueFrom, mergeMap } from "rxjs";
|
||||
import hashPaths from "../hash.js";
|
||||
import hashPaths from "../hash.ts";
|
||||
import File from "vinyl";
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
export const css = () =>
|
||||
lastValueFrom(
|
||||
fromGlob("src/index.css").pipe(
|
||||
mergeMap(
|
||||
(file) =>
|
||||
new Promise((resolve) =>
|
||||
new Promise<File>((resolve) =>
|
||||
postcss(config.plugins)
|
||||
.process(file.contents, { from: file.path })
|
||||
.then((result: Result) => {
|
||||
|
@ -17,7 +19,7 @@ export const css = () =>
|
|||
file.path = "index.css";
|
||||
|
||||
resolve(file);
|
||||
}),
|
||||
})
|
||||
),
|
||||
),
|
||||
hashPaths("css.manifest"),
|
||||
|
|
|
@ -2,17 +2,17 @@ import File from "vinyl";
|
|||
import tmp from "tmp";
|
||||
import { execFile } from "node:child_process";
|
||||
import { readFileSync, unlinkSync } from "node:fs";
|
||||
import hashPaths from "../hash.js";
|
||||
import { dest, fromGlob } from "../rx-utils.js";
|
||||
import hashPaths from "../hash.ts";
|
||||
import { dest, fromGlob } from "../rx-utils.ts";
|
||||
import { mergeMap } from "rxjs";
|
||||
|
||||
const FONT_PRESETS = {
|
||||
const FONT_PRESETS: { [variant: string]: { ranges: string[] } } = {
|
||||
mono: { ranges: ["20-7F", "2205", "2E22-2E25", "2713", "2717"] },
|
||||
text: { ranges: ["20-7F", "A0-FF", "2000-206F", "20AC"] },
|
||||
};
|
||||
|
||||
function compileFont(font: File): Promise<File> {
|
||||
const [, variant, weight] = /([A-Z][a-z]+)-(\w+)\.ttf$/.exec(font.basename);
|
||||
const [, variant, weight] = /([A-Z][a-z]+)-(\w+)\.ttf$/.exec(font.basename) as string[];
|
||||
const tmpOutput = tmp.fileSync({ discardDescriptor: true });
|
||||
const unicodes = FONT_PRESETS[variant.toLowerCase()].ranges;
|
||||
|
||||
|
@ -25,7 +25,7 @@ function compileFont(font: File): Promise<File> {
|
|||
]).once("exit", () => {
|
||||
font.path = `iosevka-adaedra-${variant.toLowerCase()}-${weight.toLowerCase()}.woff2`;
|
||||
font.contents = readFileSync(tmpOutput.name);
|
||||
font.base = null;
|
||||
(font as any).base = null;
|
||||
|
||||
unlinkSync(tmpOutput.name);
|
||||
resolve(font);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import hashPaths from "../hash.js";
|
||||
import { dest, fromGlob } from "../rx-utils.js";
|
||||
import { mergeMap, tap } from "rxjs";
|
||||
import hashPaths from "../hash.ts";
|
||||
import { dest, fromGlob } from "../rx-utils.ts";
|
||||
import { tap } from "rxjs";
|
||||
|
||||
export const images = () =>
|
||||
fromGlob("src/*.avif")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { tap } from "rxjs";
|
||||
import { dest, fromGlob } from "../rx-utils.js";
|
||||
import { dest, fromGlob } from "../rx-utils.ts";
|
||||
|
||||
// SVG `use` has no way of allowing cross-origin, so we need to keep them with the HTML files.
|
||||
export const svg = () =>
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
import { register } from "node:module";
|
||||
|
||||
register("ts-node/esm", import.meta.url);
|
|
@ -1,6 +1,6 @@
|
|||
import { Document } from "asciidoctor";
|
||||
import { DateTime } from "luxon";
|
||||
import { asset } from "../assets.js";
|
||||
import { asset } from "../assets.ts";
|
||||
|
||||
type Props = {
|
||||
article: Article;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { asset } from "../assets.js";
|
||||
import { Article } from "./article.js";
|
||||
import { asset } from "../assets.ts";
|
||||
import { Article } from "./article.tsx";
|
||||
|
||||
const Header = () => (
|
||||
<header class="index-header">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { SITE_DEFAULT_META, SITE_TITLE } from "../constants.js";
|
||||
import { SITE_DEFAULT_META, SITE_TITLE } from "../constants.ts";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
import { asset } from "../assets.js";
|
||||
import { asset } from "../assets.ts";
|
||||
|
||||
type Props = {
|
||||
title?: string;
|
||||
|
|
17
lib/watch-worker.ts
Normal file
17
lib/watch-worker.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { articles } from "./tasks/articles.ts";
|
||||
import { css } from "./tasks/css.ts";
|
||||
import { fonts } from "./tasks/fonts.ts";
|
||||
import { images } from "./tasks/images.ts";
|
||||
import { svg } from "./tasks/svg.ts";
|
||||
|
||||
const TASKS: { [task: string]: () => Promise<void> } = { articles, css, fonts, images, svg };
|
||||
|
||||
self.addEventListener("message", async (message) => {
|
||||
const { task } = message.data;
|
||||
|
||||
console.log("[start]", task);
|
||||
await TASKS[task]();
|
||||
console.log("[done]", task);
|
||||
|
||||
self.postMessage({ done: true });
|
||||
});
|
5797
package-lock.json
generated
5797
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"name": "@adaedra/blog",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@mapbox/rehype-prism": "^0.9.0",
|
||||
"asciidoctor": "^3.0.4",
|
||||
"chokidar": "^3.6.0",
|
||||
"cssnano": "^7.0.2",
|
||||
"glob": "^10.4.2",
|
||||
"luxon": "^3.4.4",
|
||||
"postcss": "^8.4.38",
|
||||
"postcss-import": "^16.1.0",
|
||||
"postcss-nesting": "^12.1.5",
|
||||
"preact": "^10.22.0",
|
||||
"preact-render-to-string": "^6.5.5",
|
||||
"rehype": "^13.0.1",
|
||||
"rehype-external-links": "^3.0.0",
|
||||
"rehype-preset-minify": "^7.0.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"tmp": "^0.2.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"unified": "^11.0.4",
|
||||
"vinyl": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/tmp": "^0.2.6",
|
||||
"@types/vinyl": "^2.0.12",
|
||||
"prettier": "^3.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node --import ./lib/ts-loader.js ./bin/build.ts",
|
||||
"watch": "node --import ./lib/ts-loader.js ./bin/watch.ts",
|
||||
"dev": "python -m http.server -d dist"
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
import importPlugin from "postcss-import";
|
||||
import nestingPlugin from "postcss-nesting";
|
||||
import cssnanoPlugin from "cssnano";
|
||||
import hashesPlugin from "./lib/postcss/hashes.js";
|
||||
import hashesPlugin from "./lib/postcss/hashes.ts";
|
||||
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
export default {
|
||||
plugins: [
|
||||
importPlugin(),
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "preact",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user