Skip to content

Commit

Permalink
Merge pull request #42 from boehs/charts
Browse files Browse the repository at this point in the history
Add charts
  • Loading branch information
boehs authored Jan 8, 2025
2 parents 4434823 + b9547b6 commit 18bf742
Show file tree
Hide file tree
Showing 12 changed files with 1,036 additions and 58 deletions.
9 changes: 4 additions & 5 deletions .eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let gardenStr = "./src/pages/garden/node/**/*.{md,csv}";
import slugify from "./utils/slugify.js";

import scss from "./conf/templating/scss.js";
import markdownIt from "./conf/templating/markdown.js";
import { markdownTemplate } from "./conf/templating/markdown.js";
import csv from "./conf/templating/csv.js";
import vento from "./conf/templating/vento.js";

Expand All @@ -27,7 +27,9 @@ Error.stackTraceLimit = 100;

/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
export default function (eleventyConfig) {
const markdown = markdownIt();
eleventyConfig.addPlugin(vento);

const markdown = markdownTemplate(eleventyConfig);

eleventyConfig.addShortcode("getSvg", function (name) {
const data = readFileSync(`./src/pages/garden/node/Assets/${name}.svg`);
Expand All @@ -43,7 +45,6 @@ export default function (eleventyConfig) {
content ? markdown.render(content) : "",
);

eleventyConfig.setLibrary("md", markdown);
eleventyConfig.setFrontMatterParsingOptions({
// @ts-ignore
excerpt: (file, options) =>
Expand Down Expand Up @@ -274,8 +275,6 @@ export default function (eleventyConfig) {

eleventyConfig.setQuietMode(true);

eleventyConfig.addPlugin(vento);

return {
dir: {
input: "src",
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![](https://wakapi.dev/api/badge/evan/interval:any/project:site) ![](https://img.shields.io/w3c-validation/html?targetUrl=https%3A%2F%2Fboehs.org) ![](https://img.shields.io/website?url=https%3A%2F%2Fboehs.org)

This is the site wherein I push 11ty to it's absolute limits and then some. It works on some 11ty versions but not all of them.
This is the site wherein I push 11ty to it's absolute limits and then some. It works on some 11ty versions but not all of them. I'm pretty sure it is the most complex 11ty site in existence, at least in terms of the amount of crimes against humanity committed in the name of web development.

This website is my `indieweb`-enabled `digital garden` with `dynamic taxonomies`, `aliases`, ~~`gemini`~~, `scss`, `ts`, and lots of love.

Expand Down
4 changes: 0 additions & 4 deletions conf/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ export default function filters(eleventyConfig) {
return str;
});

eleventyConfig.addFilter("dropContentFolder", (path, folder) =>
path.replace(new RegExp(folder + "/"), ""),
);

// I frankly don't recall why I don't use the built-in slug filter
// but I'm sure I had a good reason
eleventyConfig.addFilter("slugshive", (path) => slugify(path));
Expand Down
58 changes: 57 additions & 1 deletion conf/templating/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ import iterator from "markdown-it-for-inline";
import Shiki from "@shikijs/markdown-it";
import { transformerNotationDiff } from "@shikijs/transformers";
import { gruvBoxDarkHard } from "./highlight.js";
import { injectPintora } from "./pintora/index.js";

const proxy = (tokens, idx, options, env, self) =>
self.renderToken(tokens, idx, options);

const shiki = await Shiki({
langs: [
Expand Down Expand Up @@ -132,6 +136,7 @@ markdownIt
}
},
})
// ::: figure <Figcaption goes here>
.use(mdItC, "figure", {
validate: function (params) {
return params.trim().match(/^figure\s+(.*)$/);
Expand Down Expand Up @@ -182,12 +187,63 @@ markdownIt.renderer.rules.footnote_block_open = () =>
'<section class="footnotes">\n' +
'<ol class="footnotes-list">\n';

// why did i write this
markdownIt.renderer.rules.footnote_caption = function (tokens, idx) {
let n = Number(tokens[idx].meta.id + 1).toString();
if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}`;
return `${n}`;
};

export default function markdown() {
/**
* Pintora codeblocks are replaced with a placeholder that is found and replaced
* by 11ty, as markdown-it does not support async rendering.
*
* If it is a codeblock that's *not* a Pintora codeblock, it should fall through
* to shiki for syntax highlighting.
*/
const defaultFence = markdownIt.renderer.rules.fence || proxy;
markdownIt.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx];

if (token.info.trim() === "pintora") {
let id = Math.random().toString(36).substring(7);
return `___PINTORA_${id}_${token.content.trim()}_`;
}

return defaultFence(tokens, idx, options, env, self);
};

let ventoCompileFunction;

export function markdownTemplate(eleventyConfig) {
eleventyConfig.addExtension("md", {
outputFileExtension: "html",
compile: async (str, path) => {
// it would be most optimal to use the `key` property to pipe to vento
// but we can't have nice things: https://github.com/11ty/eleventy/issues/2827
// ... or the this.getEngine method, but we don't have `this`.
// augmentFunctionContext might be helpful: https://github.com/noelforte/eleventy-plugin-vento/issues/9
// ... maybe look into how the `render` plugin works?
// ... or if https://github.com/11ty/eleventy/blob/4e97e017714f97025409af437fe0d17694dc6bb6/src/Engines/Markdown.js#L75 was `await`
// we could use the `setLibrary` method and we wouldn't need to worry about this
// ... but this code works fine.
if (!ventoCompileFunction) {
ventoCompileFunction = [
...eleventyConfig.extensionMap.values(),
].find((r) => r.key === "vto").compile;
}
return async (data) => {
let result = str;
if (str.includes("{{")) {
result = await (
await ventoCompileFunction(str, path)
)(data);
}
result = markdownIt.render(result, data);
result = await injectPintora(result);
return result;
};
},
});
return markdownIt;
}
99 changes: 99 additions & 0 deletions conf/templating/pintora/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import pintora from "@pintora/standalone";
import { JSDOM } from "jsdom";

if (process.env.ELEVENTY_ENV == "production") {
await import("./wintercg.js");
}

class GlobalPatcher {
records = {};
set(k, v) {
const prevValue = globalThis[k];
this.records[k] = {
prevValue,
value: v,
};

globalThis[k] = v;
}

restore() {
for (const k in this.records) {
if (globalThis[k] === this.records[k].value) {
globalThis[k] = this.records[k].prevValue;
}
}
}
}

const patcher = new GlobalPatcher();

function createContainer() {
const dom = new JSDOM("<!DOCTYPE html><body></body>");
const document = dom.window.document;
const container = document.createElement("div");
container.id = "pintora-container";
patcher.set("window", dom.window);
patcher.set("document", document);
return container;
}

export default function renderPintora(code) {
return new Promise((resolve, reject) => {
const container = createContainer();
pintora.renderTo(code, {
container,
renderer: "svg",
containerSize: {
width: 600,
},
onRender: (renderer) => {
const rootElement = renderer.getRootElement();
rootElement.setAttribute("xmlns", "http://www.w3.org/2000/svg");
rootElement.classList.add("pintora");
const html = rootElement.outerHTML;
patcher.restore();
resolve(html);
},
config: {
core: {
defaultFontFamily: "'Input Mono Compressed', monospace",
},
themeConfig: {
themeVariables: {
primaryColor: "var(--light)",
canvasBackground: "transparent",
textColor: "var(--fg2)",
},
},
sequence: {
diagramPadding: 0,
messageFontSize: 13,
actorLineColor: "var(--fg2)",
},
},
});
});
}

/**
* Replaces Pintora placeholders with rendered SVGs.
*/
export async function injectPintora(result) {
if (result.includes("___PINTORA_")) {
const pintoraBlocks = [];
const regex = /___PINTORA_(\w+)_(.*?)_/gs;
let match;
while ((match = regex.exec(result)) !== null) {
pintoraBlocks.push({ id: match[1], content: match[2] });
}
for (const block of pintoraBlocks) {
const rendered = await renderPintora(block.content);
result = result.replace(
`___PINTORA_${block.id}_${block.content}_`,
rendered,
);
}
}
return result;
}
71 changes: 71 additions & 0 deletions conf/templating/pintora/wintercg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* In wintercg runtimes (assuming build on ci) we import our own ttf because it probably doesn't exist
*/

import { textMetrics } from "@pintora/standalone";
import { create } from "fontkit";
import { readFileSync } from "fs";
import { join } from "path";

const b = readFileSync(
join(import.meta.dirname, "../../../src/_public/office.ttf"),
);
const defaultFont = create(b);
const fonts = {
"sans-serif": defaultFont,
"Source Code Pro": defaultFont,
};

class FontkitCalculator {
name = "fontkit";
getLineMetric(text, fontConfig) {
const fontSize = fontConfig?.fontSize || 14;
const fontName = fontConfig?.fontFamily || "sans-serif";
const font = fonts[fontName] || defaultFont;
const glyph = font.layout(text);
const sizeUnit = fontSize / font.unitsPerEm;
// const width = glyph.glyphs.reduce((last, curr) => last + curr.cbox.width, 0) * sizeUnit
const width = glyph.bbox.width * sizeUnit; // fine

const glyphActualMaxHeight =
glyph.glyphs.reduce(
(last, curr) => Math.max(last, curr.cbox.height),
0,
) * sizeUnit;
const height = glyphActualMaxHeight;

const actualBoundingBoxAscent = height;
// console.log('line:', text, 'width', width, 'actualBoundingBoxAscent', actualBoundingBoxAscent)
const actualBoundingBoxDescent = 0;
return {
actualBoundingBoxAscent,
actualBoundingBoxDescent,
width,
};
}

calculateTextDimensions(text, font) {
const lines = text.split("\n");
let width = 0;
let height = 0;
const fontSize = font?.fontSize || 14;
lines.forEach((line, i) => {
const lineMetric = this.getLineMetric(line, font);
const w = lineMetric.width;
width = Math.max(w, width);
let lineHeight = fontSize;
if ("actualBoundingBoxDescent" in lineMetric) {
lineHeight =
lineMetric.actualBoundingBoxAscent +
lineMetric.actualBoundingBoxDescent;
}
height += lineHeight;
});
return {
width,
height,
};
}
}

textMetrics.setImpl(new FontkitCalculator());
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
"format": "prettier --write ."
},
"dependencies": {
"@11ty/eleventy": "3.0.0",
"@11ty/eleventy": "3.0.1-alpha.1",
"@11ty/eleventy-fetch": "^5.0.1",
"@gardeners/markdown-it-wikilinks": "^1.5.1",
"@pintora/standalone": "^0.7.5",
"@resvg/resvg-js": "^2.6.2",
"@shikijs/markdown-it": "^1.26.1",
"@shikijs/transformers": "^1.26.1",
"eleventy-plugin-vento": "^4.0.1",
"esbuild": "^0.24.0",
"fontkit": "^2.0.4",
"html-minifier": "^4.0.0",
"jsdom": "^25.0.1",
"markdown-it": "^14.1.0",
"markdown-it-anchor": "^9.2.0",
"markdown-it-attribution": "^0.1.4",
Expand Down
Loading

0 comments on commit 18bf742

Please sign in to comment.