mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 13:39:01 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			86 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { readFile } from 'fs/promises';
 | 
						|
import { compile, type Options } from 'ejs';
 | 
						|
import { resolve, dirname, basename } from 'path';
 | 
						|
 | 
						|
export default function esbuildPluginEjs(options = {}) {
 | 
						|
    return {
 | 
						|
        name: 'ejs',
 | 
						|
        setup(build) {
 | 
						|
            build.onLoad({ filter: /\.ejs$/ }, async args => {
 | 
						|
                const ejsOptions: Options = {
 | 
						|
                    ...options,
 | 
						|
                    client: true,
 | 
						|
                    strict: true,
 | 
						|
                    compileDebug: false
 | 
						|
                }
 | 
						|
 | 
						|
                const contents: string[] = [];
 | 
						|
                contents.push(`const includeMap = {}`);
 | 
						|
                contents.push(`
 | 
						|
                    function __include(name, ...args) {
 | 
						|
                        return includeMap[name](...args);
 | 
						|
                    }
 | 
						|
                `);
 | 
						|
 | 
						|
                let main;
 | 
						|
 | 
						|
                // Compile the subtemplates.
 | 
						|
                const subtemplates = await collectTemplateTree(args.path);
 | 
						|
                for (const [ path, subtemplate ] of Object.entries(subtemplates)) {
 | 
						|
                    const functionName = basename(path).split(".")[0];
 | 
						|
                    const isMain = (path === args.path);
 | 
						|
 | 
						|
                    const generator = compile(subtemplate, ejsOptions);
 | 
						|
                    const functionOutput = generator.toString().split("\n");
 | 
						|
 | 
						|
                    if (isMain) {
 | 
						|
                        functionOutput[0] = functionOutput[0].replace(/^function anonymous/, `module.exports = function`);
 | 
						|
                    } else {
 | 
						|
                        functionOutput[0] = functionOutput[0].replace(/^function anonymous/, `includeMap["${functionName}"] = function`);
 | 
						|
                    }
 | 
						|
 | 
						|
                    // Inject include function.
 | 
						|
                    functionOutput[2] = `include = __include;\n${functionOutput[2]}`;
 | 
						|
 | 
						|
                    if (isMain) {
 | 
						|
                        main = functionOutput.join("\n");
 | 
						|
                    } else {
 | 
						|
                        contents.push(functionOutput.join("\n"));
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                // Compile the rest.
 | 
						|
                if (!main) {
 | 
						|
                    throw new Error("Missing main entry point");
 | 
						|
                }
 | 
						|
                contents.push(main);
 | 
						|
 | 
						|
                return { contents: contents.join("\n"), loader: 'js' }
 | 
						|
            })
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
const includeRegex = /<%-?\s*include\((['"`])(.+?)\1\s*(?:,[^)]+)?\)\s*-?%>/g;
 | 
						|
 | 
						|
async function collectTemplateTree(filePath, seen: Record<string, string> = {}) {
 | 
						|
    if (seen[filePath]) return;
 | 
						|
 | 
						|
    const source = await readFile(filePath, 'utf8');
 | 
						|
    seen[filePath] = source;
 | 
						|
 | 
						|
    const dir = dirname(filePath);
 | 
						|
 | 
						|
    const matches = [...source.matchAll(includeRegex)];
 | 
						|
    for (const match of matches) {
 | 
						|
        const includePath = match[2];
 | 
						|
 | 
						|
        // Add .ejs extension if needed
 | 
						|
        const resolvedPath = resolve(dir, includePath.endsWith('.ejs') ? includePath : includePath + '.ejs');
 | 
						|
        await collectTemplateTree(resolvedPath, seen);
 | 
						|
    }
 | 
						|
 | 
						|
    return seen;
 | 
						|
}
 |