@cloudpss/template
Version:
String and object template engine for Node.js and the browser.
72 lines (66 loc) • 2.3 kB
text/typescript
import type { TemplateType } from '../parser.js';
import { TemplateCompiler } from './compiler.js';
/** 模板编译求值 */
export type TemplateEvaluator = {
/** 注入为 `evaluator` 变量,可在生成的求值代码中使用 */
inject?: unknown;
/** 求值代码是否为异步 @default false */
async?: boolean;
/** 生成求值 JS 代码,可用变量:`evaluator` `context` */
compile: (expression: string, type: TemplateType) => string;
};
/** 模板选项 */
export interface TemplateOptions {
/**
* 模板求值器
* @default context?.[expression] ?? (type === 'formula' ? undefined : '')
*/
evaluator?: TemplateEvaluator;
/**
* 对 object key 的处理方式
* - `template` 使用模板进行插值
* - `ignore` 原样输出
* @default 'template'
*/
objectKeyMode?: 'template' | 'ignore';
}
export const defaultEvaluator: TemplateEvaluator = {
compile: (expression, type) => {
const key = JSON.stringify(expression.trim());
switch (type) {
case 'formula':
return `context[${key}]`;
case 'interpolation':
return `(context[${key}] ?? '')`;
/* c8 ignore next 2 */
default:
throw new Error(`Unsupported type: ${type satisfies never as string}`);
}
},
};
/** 已编译的模板函数 */
export type TemplateFunction<T = unknown, C = Record<string, unknown>> = ((context?: C) => T) & {
source: string;
};
/** 创建模板 */
export function template<T = unknown, C = Record<string, unknown>>(
template: T,
options: TemplateOptions & { evaluator: { async: true } },
): TemplateFunction<Promise<T>, C>;
/** 创建模板 */
export function template<T = unknown, C = Record<string, unknown>>(
template: T,
options?: TemplateOptions,
): TemplateFunction<T, C>;
/** 创建模板 */
export function template<T = unknown, C = Record<string, unknown>>(
template: T,
options: TemplateOptions = {},
): TemplateFunction<T, C> {
const opt = {
objectKeyMode: 'template',
evaluator: defaultEvaluator,
...options,
};
return new TemplateCompiler(template, opt as Required<TemplateOptions>).build() as TemplateFunction<T, C>;
}