44 lines
1.1 KiB
JavaScript
44 lines
1.1 KiB
JavaScript
// ESM loader to transpile .jsx files on the fly using esbuild
|
|
// Usage: node --loader ./scripts/jsx-loader.mjs cli-ink.js
|
|
|
|
import { readFile } from 'node:fs/promises';
|
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
import { transform } from 'esbuild';
|
|
|
|
/** @typedef {import('node:module').LoadHook} LoadHook */
|
|
/** @typedef {import('node:module').ResolveHook} ResolveHook */
|
|
|
|
/** @type {ResolveHook} */
|
|
export async function resolve(specifier, context, nextResolve) {
|
|
// Defer to Node's default resolver for most cases
|
|
return nextResolve(specifier, context, nextResolve);
|
|
}
|
|
|
|
/** @type {LoadHook} */
|
|
export async function load(url, context, nextLoad) {
|
|
// Handle .jsx sources
|
|
if (url.endsWith('.jsx')) {
|
|
const filename = fileURLToPath(url);
|
|
const source = await readFile(filename, 'utf8');
|
|
|
|
const result = await transform(source, {
|
|
loader: 'jsx',
|
|
format: 'esm',
|
|
jsx: 'automatic',
|
|
sourcefile: filename,
|
|
});
|
|
|
|
return {
|
|
format: 'module',
|
|
source: result.code,
|
|
shortCircuit: true,
|
|
};
|
|
}
|
|
|
|
// Fallback to default loader for everything else
|
|
return nextLoad(url, context, nextLoad);
|
|
}
|
|
|
|
|
|
|