polymech-astro/packages/imagetools_3/plugin/hooks/transform.js
2025-08-26 12:17:29 +02:00

63 lines
2.0 KiB
JavaScript

// @ts-check
import path from "node:path";
import crypto from "node:crypto";
import MagicString from "magic-string";
import { cwd } from "../../utils/runtimeChecks.js";
const regexTestPattern =
/<img\s+src\s*=(?:"|')([^("|')]*)(?:"|')\s*alt\s*=\s*(?:"|')([^("|')]*)(?:"|')[^>]*>/;
const regexExecPattern = new RegExp(regexTestPattern, "gs");
const regexRenderPattern = /\$\$render`(.*)`/gs;
export default async function transform(code, id) {
if (id.endsWith(".md") && regexTestPattern.test(code)) {
const { default: astroViteConfigs } = await import(
// @ts-ignore
"../../astroViteConfigs.js"
);
const { sourcemap } = astroViteConfigs;
// Extract the "$$render`" part of the markdown string
const [result] = [...code.matchAll(regexRenderPattern)];
const [, renderString] = result;
const renderIndex = result.index + "$$render`".length;
const matches = renderString.matchAll(regexExecPattern);
if (matches !== null) {
const s = new MagicString(code);
const uuid = crypto.randomBytes(4).toString("hex");
const Picture = "Picture" + uuid;
const renderComponent = "renderComponent" + uuid;
s.prepend(
`import { Picture as ${Picture} } from "astro-imagetools/components";\nimport { renderComponent as ${renderComponent} } from "${
cwd + "/node_modules/astro/dist/runtime/server/index.js"
}"\n;`
);
for (const match of matches) {
const [matchedText, rawSrc, alt] = match;
const src = rawSrc.match("(http://|https://|data:image/).*")
? rawSrc
: path.resolve(path.dirname(id), rawSrc).replace(cwd, "");
s.overwrite(
renderIndex + match.index,
renderIndex + match.index + matchedText.length,
`\${${renderComponent}($$result, "${Picture}", ${Picture}, { "src": "${src}", "alt": "${alt}" })}`
);
}
return {
code: s.toString(),
map: sourcemap ? s.generateMap({ hires: true }) : null,
};
}
}
}