[@kbn/handlebars] Minor refactor (#150440)

This commit is contained in:
Thomas Watson 2023-02-09 12:21:32 +01:00 committed by GitHub
parent 381b82052f
commit 5f0b56d3bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 60 deletions

View file

@ -506,12 +506,13 @@ describe('blocks', () => {
it('should call multiple decorators in the same program body in the expected order and get the expected output', () => {
let decoratorCall = 0;
let progCall = 0;
expectTemplate('{{*decorator}}con{{*decorator}}tent')
.beforeRender(() => {
expectTemplate('{{*decorator}}con{{*decorator}}tent', {
beforeRender() {
// ensure the counters are reset between EVAL/AST render calls
decoratorCall = 0;
progCall = 0;
})
},
})
.withInput({
decoratorCall: 0,
progCall: 0,

View file

@ -24,6 +24,7 @@ global.kbnHandlebarsEnv = null;
interface TestOptions {
beforeEach?: Function;
beforeRender?: Function;
}
export function expectTemplate(template: string, options?: TestOptions) {
@ -39,7 +40,6 @@ export function forEachCompileFunctionName(
class HandlebarsTestBench {
private template: string;
private options: TestOptions;
private beforeRenderFn: Function = () => {};
private compileOptions?: ExtendedCompileOptions;
private runtimeOptions?: ExtendedRuntimeOptions;
private helpers: { [name: string]: Handlebars.HelperDelegate | undefined } = {};
@ -52,11 +52,6 @@ class HandlebarsTestBench {
this.options = options;
}
beforeRender(fn: Function) {
this.beforeRenderFn = fn;
return this;
}
withCompileOptions(compileOptions?: ExtendedCompileOptions) {
this.compileOptions = compileOptions;
return this;
@ -159,16 +154,14 @@ class HandlebarsTestBench {
private compileAndExecuteEval() {
const renderEval = this.compileEval();
const runtimeOptions: ExtendedRuntimeOptions = Object.assign(
{
helpers: this.helpers,
partials: this.partials,
decorators: this.decorators,
},
this.runtimeOptions
);
const runtimeOptions: ExtendedRuntimeOptions = {
helpers: this.helpers as Record<string, Function>,
partials: this.partials as Record<string, HandlebarsTemplateDelegate>,
decorators: this.decorators,
...this.runtimeOptions,
};
this.beforeRenderFn();
this.execBeforeRender();
return renderEval(this.input, runtimeOptions);
}
@ -176,16 +169,14 @@ class HandlebarsTestBench {
private compileAndExecuteAST() {
const renderAST = this.compileAST();
const runtimeOptions: ExtendedRuntimeOptions = Object.assign(
{
helpers: this.helpers,
partials: this.partials,
decorators: this.decorators,
},
this.runtimeOptions
);
const runtimeOptions: ExtendedRuntimeOptions = {
helpers: this.helpers as Record<string, Function>,
partials: this.partials as Record<string, HandlebarsTemplateDelegate>,
decorators: this.decorators,
...this.runtimeOptions,
};
this.beforeRenderFn();
this.execBeforeRender();
return renderAST(this.input, runtimeOptions);
}
@ -200,6 +191,10 @@ class HandlebarsTestBench {
return handlebarsEnv.compileAST(this.template, this.compileOptions);
}
private execBeforeRender() {
this.options.beforeRender?.();
}
private execBeforeEach() {
if (this.options.beforeEach) {
this.options.beforeEach();

View file

@ -7,7 +7,7 @@
// https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require
import Handlebars from 'handlebars';
import type { DecoratorsHash, ExtendedCompileOptions, ExtendedRuntimeOptions } from './types';
import type { ExtendedCompileOptions, ExtendedRuntimeOptions } from './types';
import { ElasticHandlebarsVisitor } from './visitor';
const originalCreate = Handlebars.create;
@ -46,11 +46,8 @@ Handlebars.compileAST = function (
}
// If `Handlebars.compileAST` is reassigned, `this` will be undefined.
const helpers = (this ?? Handlebars).helpers;
const partials = (this ?? Handlebars).partials;
const decorators = (this ?? Handlebars).decorators as DecoratorsHash;
const visitor = new ElasticHandlebarsVisitor(this ?? Handlebars, input, options);
const visitor = new ElasticHandlebarsVisitor(this, input, options, helpers, partials, decorators);
return (context: any, runtimeOptions?: ExtendedRuntimeOptions) =>
visitor.render(context, runtimeOptions);
};

View file

@ -27,7 +27,6 @@ import type {
HelpersHash,
NodeType,
NonBlockHelperOptions,
PartialsHash,
ProcessableBlockStatementNode,
ProcessableNode,
ProcessableNodeWithPathParts,
@ -51,9 +50,6 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor {
private template?: string;
private compileOptions: ExtendedCompileOptions;
private runtimeOptions?: ExtendedRuntimeOptions;
private initialHelpers: HelpersHash;
private initialPartials: PartialsHash;
private initialDecorators: DecoratorsHash;
private blockParamNames: any[][] = [];
private blockParamValues: any[][] = [];
private ast?: hbs.AST.Program;
@ -65,10 +61,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor {
constructor(
env: typeof Handlebars,
input: string | hbs.AST.Program,
options: ExtendedCompileOptions = {},
helpers: HelpersHash,
partials: PartialsHash,
decorators: DecoratorsHash
options: ExtendedCompileOptions = {}
) {
super();
@ -80,13 +73,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor {
this.template = input as string;
}
this.compileOptions = Object.assign(
{
data: true,
},
options
);
this.compileOptions = { data: true, ...options };
this.compileOptions.knownHelpers = Object.assign(
Object.create(null),
{
@ -102,10 +89,6 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor {
this.compileOptions.knownHelpers
);
this.initialHelpers = Object.assign({}, helpers);
this.initialPartials = Object.assign({}, partials);
this.initialDecorators = Object.assign({}, decorators);
const protoAccessControl = createProtoAccessControl({});
const container: Container = (this.container = {
@ -156,13 +139,16 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor {
render(context: any, options: ExtendedRuntimeOptions = {}): string {
this.contexts = [context];
this.output = [];
this.runtimeOptions = Object.assign({}, options);
this.container.helpers = Object.assign(this.initialHelpers, options.helpers);
this.container.partials = Object.assign(this.initialPartials, options.partials);
this.container.decorators = Object.assign(
this.initialDecorators,
options.decorators as DecoratorsHash
);
this.runtimeOptions = { ...options };
this.container.helpers = {
...this.env.helpers,
...(options.helpers as HelpersHash),
};
this.container.partials = { ...this.env.partials, ...options.partials };
this.container.decorators = {
...(this.env.decorators as DecoratorsHash),
...(options.decorators as DecoratorsHash),
};
this.container.hooks = {};
this.processedRootDecorators = false;
this.processedDecoratorsForProgram.clear();
@ -540,7 +526,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor {
};
if (fn.partials) {
options.partials = Object.assign({}, options.partials, fn.partials);
options.partials = { ...options.partials, ...fn.partials };
}
}
@ -694,7 +680,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor {
nextContext: any,
runtimeOptions: ExtendedRuntimeOptions = {}
) => {
runtimeOptions = Object.assign({}, runtimeOptions);
runtimeOptions = { ...runtimeOptions };
// inherit data in blockParams from parent program
runtimeOptions.data = runtimeOptions.data || this.runtimeOptions!.data;