feat: Typst preprocessing

This commit is contained in:
Leni Aniva 2025-03-04 22:39:24 -08:00
parent c04e04667c
commit 332082102d
Signed by: aniva
GPG Key ID: 4D9B1C8D10EA4C50
8 changed files with 119 additions and 13 deletions

View File

@ -0,0 +1,61 @@
#import "@preview/cetz:0.3.2"
#metadata((
title: "Title",
date: "2025-01-01",
))<post>
//#set page(width: auto, height: auto, margin: .5cm)
#show math.equation: block.with(fill: white, inset: 1pt)
This is a diagram.
#html.frame(cetz.canvas(length: 3cm, {
import cetz.draw: *
set-style(
mark: (fill: black, scale: 2),
stroke: (thickness: 0.4pt, cap: "round"),
angle: (
radius: 0.3,
label-radius: .22,
fill: green.lighten(80%),
stroke: (paint: green.darken(50%))
),
content: (padding: 1pt)
)
grid((-1.5, -1.5), (1.4, 1.4), step: 0.5, stroke: gray + 0.2pt)
circle((0,0), radius: 1)
line((-1.5, 0), (1.5, 0), mark: (end: "stealth"))
content((), $ x $, anchor: "west")
line((0, -1.5), (0, 1.5), mark: (end: "stealth"))
content((), $ y $, anchor: "south")
for (x, ct) in ((-1, $ -1 $), (-0.5, $ -1/2 $), (1, $ 1 $)) {
line((x, 3pt), (x, -3pt))
content((), anchor: "north", ct)
}
for (y, ct) in ((-1, $ -1 $), (-0.5, $ -1/2 $), (0.5, $ 1/2 $), (1, $ 1 $)) {
line((3pt, y), (-3pt, y))
content((), anchor: "east", ct)
}
// Draw the green angle
cetz.angle.angle((0,0), (1,0), (1, calc.tan(30deg)),
label: text(green, [#sym.alpha]))
line((0,0), (1, calc.tan(30deg)))
set-style(stroke: (thickness: 1.2pt))
line((30deg, 1), ((), "|-", (0,0)), stroke: (paint: red), name: "sin")
content(("sin.start", 50%, "sin.end"), text(red)[$ sin alpha $])
line("sin.end", (0,0), stroke: (paint: blue), name: "cos")
content(("cos.start", 50%, "cos.end"), text(blue)[$ cos alpha $], anchor: "north")
line((1, 0), (1, calc.tan(30deg)), name: "tan", stroke: (paint: orange))
content("tan.end", $ text(#orange, tan alpha) = text(#red, sin alpha) / text(#blue, cos alpha) $, anchor: "west")
}))

View File

@ -1,5 +1,6 @@
<script lang="ts">
import { Moon, Sun } from 'lucide-svelte';
import Moon from 'lucide-svelte/icons/moon';
import Sun from 'lucide-svelte/icons/sun';
import { theme, setTheme } from '$lib/theme'
function toggleTheme() {

View File

@ -17,12 +17,13 @@ export function transformPostMeta(metadata: PostMetadata, slug: string) : Post {
// Generates a list of all posts filtering by tags and series, reverse chronologically ordered.
export async function getPosts(filter: { tag?: string, series?: string }) : Promise<Post[]> {
const allPostFiles = import.meta.glob('$content/post/*.md');
const allPostFiles = import.meta.glob(['$content/post/*.md', '$content/post/*.typ']);
const iterablePostFiles = Object.entries(allPostFiles);
let posts: Post[] = await Promise.all(
iterablePostFiles.map(async ([pathMarkdown, resolver]) => {
const { metadata } = await resolver();
console.log(await resolver());
const slug = pathMarkdown.slice(pathMarkdown.lastIndexOf("/") + 1, -".md".length);
return transformPostMeta(metadata, slug);
@ -42,7 +43,7 @@ export async function getPosts(filter: { tag?: string, series?: string }) : Prom
}
export async function getTags() : Promise<Map<string, number>> {
const allPostFiles = import.meta.glob('$content/post/*.md');
const allPostFiles = import.meta.glob(['$content/post/*.md', '$content/post/*.typ']);
const iterablePostFiles = Object.entries(allPostFiles);
const allPosts: string[][] = await Promise.all(

38
src/lib/typst.js Normal file
View File

@ -0,0 +1,38 @@
import { promisify } from 'util';
import { exec } from 'child_process';
const exec_async = promisify(exec);
export const typstPreprocess = (config) => {
const {
extensions,
} = config;
return {
name: "typst",
markup: async ({content: _, filename}) => {
const extensionsParts = extensions.map((ext) =>
ext.startsWith('.') ? ext : '.' + ext
);
if (!extensionsParts.some((ext) => filename.endsWith(ext))) return;
console.log("Processing typst file: ", filename);
const result_metadata = await exec_async(`typst query --features html ${filename} "<post>" --field value --one`);
const payload = String(result_metadata.stdout);
const data = JSON.parse(payload);
console.log("data", data);
const result_post = await exec_async(`typst compile --features html ${filename} -`);
const code = String(result_post.stdout)
return {
code,
metadata: data,
data,
map: '',
}
}
};
}

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { routes } from "$lib/sitemap.ts"
import { routes } from "$lib/sitemap"
import { Separator } from "$lib/components/ui/separator/index.js";
import { Rss } from "lucide-svelte";
import Rss from "lucide-svelte/icons/rss";
import ThemeSwitch from "$lib/components/ThemeSwitch.svelte"
let scrollPosition: number = .5;
let scrollHeight: number = 1;

View File

@ -2,7 +2,8 @@
import { page } from '$app/stores';
import { routes } from "$lib/sitemap.ts"
import ThemeSwitch from "$lib/components/ThemeSwitch.svelte"
import { Rss, Menu } from "lucide-svelte";
import Rss from "lucide-svelte/icons/rss";
import Menu from "lucide-svelte/icons/menu";
function isCurrentLink(pathname, route) {
return route != "/" && pathname.startsWith(route)

View File

@ -6,7 +6,7 @@ import { getPosts, transformPostMeta } from '$lib/posts';
export const load: PageLoad = async ({ params }) => {
try {
const post = await import(`$content/post/${params.slug}.md`);
if (!post) throw error(404);
if (!post) throw error(404);
const metadata: Post = transformPostMeta(post.metadata, params.slug);
const Content = post.default;

View File

@ -1,14 +1,15 @@
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import adapter from '@sveltejs/adapter-static';
import fs from 'fs';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
import adapter from '@sveltejs/adapter-static'
import fs from 'fs'
import { mdsvex, escapeSvelte } from 'mdsvex';
import { typstPreprocess } from './src/lib/typst.js'
import { mdsvex, escapeSvelte } from 'mdsvex'
import remarkAlert from './src/lib/markdown.js'
import relativeImages from 'mdsvex-relative-images'
import remarkToc from 'remark-toc'
import rehypeSlug from 'rehype-slug'
import { getHighlighter } from 'shiki'
import rehypeKatexSvelte from "rehype-katex-svelte";
import rehypeKatexSvelte from "rehype-katex-svelte"
import remarkMath from 'remark-math'
const contentDir = process.env?.CHRYSOBLOG_CONTENT ?? "src/content";
@ -77,9 +78,12 @@ const config = {
}
},
}),
typstPreprocess({
extensions: ['.typ'],
}),
vitePreprocess(),
],
extensions: [".svelte", ".md"],
extensions: [".svelte", ".typ", ".md"],
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.