sitegen/framework/marko.ts
clover caruso 8c0bd4c6c6 rewrite incremental.ts (#21)
the problems with the original implementation was mostly around error
handling. sources had to be tracked manually and provided to each
incremental output. the `hasArtifact` check was frequently forgotten.
this has been re-abstracted through `incr.work()`, which is given an
`io` object. all fs reads and module loads go through this interface,
which allows the sources to be properly tracked, even if it throws.

closes #12
2025-08-02 20:56:36 -04:00

46 lines
1.6 KiB
TypeScript

console.log("MARKO");
export interface MarkoCacheEntry {
src: string;
scannedClientRefs: string[];
}
export const markoCache = new Map<string, MarkoCacheEntry>();
export function loadMarko(module: NodeJS.Module, filepath: string) {
let cache = markoCache.get(filepath);
console.log({ filepath, has: !!cache })
if (!cache) {
let src = fs.readFileSync(filepath, "utf8");
// A non-standard thing here is Clover Sitegen implements
// its own client side scripting stuff, so it overrides
// bare client import statements to it's own usage.
const scannedClientRefs = new Set<string>();
if (src.match(/^\s*client\s+import\s+["']/m)) {
src = src.replace(
/^\s*client\s+import\s+("[^"]+"|'[^']+')[^\n]+/m,
(_, src) => {
const ref = JSON.parse(`"${src.slice(1, -1)}"`);
const resolved = hot.resolveClientRef(filepath, ref);
scannedClientRefs.add(resolved);
return `<CloverScriptInclude=${
JSON.stringify(hot.getScriptId(resolved))
} />`;
},
) + '\nimport { addScript as CloverScriptInclude } from "#sitegen";\n';
}
src = marko.compileSync(src, filepath).code;
src = src.replace("marko/debug/html", "#ssr/marko");
cache = { src, scannedClientRefs: Array.from(scannedClientRefs) };
markoCache.set(filepath, cache);
}
const { src, scannedClientRefs } = cache;
return hot.loadEsbuildCode(module, filepath, src, {
scannedClientRefs,
});
}
import * as marko from "@marko/compiler";
import * as hot from "./hot.ts";
import * as fs from "#sitegen/fs";