From 4dcdcf8ae871478e19ad1ee81a26d0ea9e403280 Mon Sep 17 00:00:00 2001 From: Jade Ellis Date: Tue, 16 Jul 2024 20:24:04 +0100 Subject: [PATCH] Add image support Works around Vite imports vite-imagetools is borked for this --- packages/website/mdsvex.config.js | 95 ++++++++++++++++++- packages/website/package.json | 1 + .../website/src/lib/htmlComponents/img.svelte | 8 ++ .../website/src/lib/mdlayouts/default.svelte | 6 ++ packages/website/vite.config.ts | 32 +++++++ pnpm-lock.yaml | 10 +- 6 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 packages/website/src/lib/htmlComponents/img.svelte create mode 100644 packages/website/src/lib/mdlayouts/default.svelte diff --git a/packages/website/mdsvex.config.js b/packages/website/mdsvex.config.js index 0e0c469e..c48b6e08 100644 --- a/packages/website/mdsvex.config.js +++ b/packages/website/mdsvex.config.js @@ -185,7 +185,7 @@ function add_toc_rehype(self, opts) { vFile.data.headings = []; visit(tree, isHeadingNode, (node) => { - console.log(node) + // console.log(node) vFile.data.headings.push({ level: node.depth, title: hast_tree_to_string(node), @@ -196,6 +196,96 @@ function add_toc_rehype(self, opts) { vFile.data.fm.headings = vFile.data.headings; }; } + + +import toCamel from "just-camel-case"; +const RE_SCRIPT_START = + //; +function vite_images_rehype(opts) { + return async function transformer(tree, vFile) { + const urls = new Map(); + const url_count = new Map(); + + /** + * @param {string} url + */ + function transformUrl(url) { + // url = decodeURIComponent(url) + // console.log("decoded", url) + + // filenames can start with digits, + // prepend underscore to guarantee valid module name + let camel = `_${toCamel(url)}`; + const count = url_count.get(camel); + const dupe = urls.get(url); + + if (count && !dupe) { + url_count.set(camel, count + 1); + camel = `${camel}_${count}`; + } else if (!dupe) { + url_count.set(camel, 1); + } + + urls.set(url, { + path: url, + id: camel + }); + + return camel; + + + } + // console.log(tree) + // vFile.data.headings = []; + + // console.log(tree) + visit(tree, { tagName: "img" }, (node) => { + node.properties.src = `{${transformUrl(node.properties.src)}}` + // new URL('./img.png', import.meta.url).href + // vFile.data.headings.push({ + // level: node.depth, + // title: hast_tree_to_string(node), + // }); + }); + visit(tree, { tagName: "Components.img" }, (node) => { + // let url = node.properties.src; + // url.includes("?") ? url = url + "&svex-enhanced" : url + "?svex-enhanced"; + + node.properties.src = `{${transformUrl(node.properties.src)}}` + // node.properties.src = `{new URL('${url}', import.meta.url)}` + // new URL('./img.png', import.meta.url).href + // vFile.data.headings.push({ + // level: node.depth, + // title: hast_tree_to_string(node), + // }); + }); + + let scripts = ""; + // urls.forEach((x) => (scripts += `import ${x.id} from "${(x.path.includes("?") ? x.path + "&" : x.path + "?") + "url"}";\n`)); + urls.forEach((x) => (scripts += `const ${x.id} = new URL("${x.path}", import.meta.url);\n`)); + // console.log(scripts) + // urls.forEach((x) => { + // if (x.meta) { + // let a = ["src", "width", "height"] + // scripts += `import {${a.map((a) => a + " as " + x.id + "_" + a).join(",")}} from "${x.path.includes("?") ? x.path + "&as=metadata" : x.path + "?as=metadata:src;width;height"}";\n` + // } + // }); + + let is_script = false; + + visit(tree, { type: "raw" }, (node) => { + // console.log(node) + if (RE_SCRIPT_START.test(node.value)) { + // console.log("inserting") + is_script = true; + node.value = node.value.replace(RE_SCRIPT_START, (script) => { + return `${script}\n${scripts}`; + }); + } + }); + + }; +} /** * @type {import("mdsvex").MdsvexOptions} */ @@ -209,7 +299,7 @@ const config = { }, // layout: { - // _: "./src/layout.svelte" + // _: "./src/lib/mdlayouts/default.svelte" // }, highlight: { @@ -264,6 +354,7 @@ const config = { rehypeKatexSvelte, // @ts-ignore [rehypeSlug, { prefix: "h-" }], + vite_images_rehype ], }; diff --git a/packages/website/package.json b/packages/website/package.json index a074bd28..d6ed61bc 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -24,6 +24,7 @@ "github-slugger": "^2.0.0", "glob": "^10.4.1", "hast-util-to-string": "^3.0.0", + "just-camel-case": "^6.2.0", "mdast-util-to-string": "^4.0.0", "mdsvex": "^0.11.2", "rehype-katex-svelte": "1.2", diff --git a/packages/website/src/lib/htmlComponents/img.svelte b/packages/website/src/lib/htmlComponents/img.svelte new file mode 100644 index 00000000..e49d28d7 --- /dev/null +++ b/packages/website/src/lib/htmlComponents/img.svelte @@ -0,0 +1,8 @@ + + {alt}/ \ No newline at end of file diff --git a/packages/website/src/lib/mdlayouts/default.svelte b/packages/website/src/lib/mdlayouts/default.svelte new file mode 100644 index 00000000..5e3b1ffd --- /dev/null +++ b/packages/website/src/lib/mdlayouts/default.svelte @@ -0,0 +1,6 @@ + + + diff --git a/packages/website/vite.config.ts b/packages/website/vite.config.ts index 951616b3..d4753980 100644 --- a/packages/website/vite.config.ts +++ b/packages/website/vite.config.ts @@ -9,6 +9,8 @@ import { mdsvex } from 'mdsvex'; import mdsvexConfig from "./mdsvex.config.js"; import { extname } from 'node:path'; +// import { imagetools } from 'vite-imagetools' + function mdsvex_transform() { return { name: "Mdsvex transformer", @@ -23,6 +25,17 @@ function mdsvex_transform() { } }; } +const fallback: {[key: string]: string} = { + '.avif': 'png', + '.gif': 'gif', + '.heif': 'jpg', + '.jpeg': 'jpg', + '.jpg': 'jpg', + '.png': 'png', + '.tiff': 'jpg', + '.webp': 'png' +}; + export default defineConfig({ resolve: { alias: { @@ -34,6 +47,25 @@ export default defineConfig({ ViteImageOptimizer({ /* pass your config */ }), + // imagetools({ + // namedExports: false, + // defaultDirectives: async (url, metadata) => { + // console.log("vite", url) + // // if (!url.searchParams.has('svex-enhanced')) return new URLSearchParams(); + + // // const img_width = url.searchParams.get('imgWidth'); + // // const width = img_width ? parseInt(img_width) : (await metadata()).width; + // // if (!width) { + // // console.warn(`Could not determine width of image ${url.href}`); + // return new URLSearchParams(); + // // } + + // // return new URLSearchParams({ + // // 'metadata': '', + // // // format: `avif;webp;${fallback[path.extname(url.href)] ?? 'png'}` + // // }); + // }, + // }), // mdsvex_transform(), sveltekit(), dynamicImport({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c84a847b..ceb74728 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -122,6 +122,9 @@ importers: hast-util-to-string: specifier: ^3.0.0 version: 3.0.0 + just-camel-case: + specifier: ^6.2.0 + version: 6.2.0 mdast-util-to-string: specifier: ^4.0.0 version: 4.0.0 @@ -946,7 +949,7 @@ packages: '@codemirror/view': '>=6.0.0' Notes@file:packages/website/Notes-1.0.0.tgz: - resolution: {integrity: sha512-5ly2YBmx1v2j7S5QtOTzZbTY5WJv1/1JNKGXOle8VtgRwg1WvOohRqDSaySiypHDWOGebqLq9KbxIr/Y6VCUnw==, tarball: file:packages/website/Notes-1.0.0.tgz} + resolution: {integrity: sha512-/+M3hG2iGHPS6t1mSgVniEdhrVG0jZ41BikQqqvGt3AgOXCY7FnyqziKALc/g3oVaulnwduqg0ZjaxwhQlh3GA==, tarball: file:packages/website/Notes-1.0.0.tgz} version: 1.0.0 acorn@8.12.0: @@ -1521,6 +1524,9 @@ packages: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} + just-camel-case@6.2.0: + resolution: {integrity: sha512-ICenRLXwkQYLk3UyvLQZ+uKuwFVJ3JHFYFn7F2782G2Mv2hW8WPePqgdhpnjGaqkYtSVWnyCESZhGXUmY3/bEg==} + jwa@1.4.1: resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} @@ -3661,6 +3667,8 @@ snapshots: ms: 2.1.3 semver: 7.6.2 + just-camel-case@6.2.0: {} + jwa@1.4.1: dependencies: buffer-equal-constant-time: 1.0.1