Add support for pipes in templates #53
The goal is to be able to modify values of variables used in templates. It enables future functionality such as escaping, inlining etc. It adds support applying predefined pipes to variables. Pipes can be applied to variable substitution in with and parameter substitution expressions. They work in similar way to piping in Unix where each pipe applied to the compiled result of pipe before. It adds support for using pipes in `with` and parameter substitution expressions. It also refactors how their regex is build to reuse more of the logic by abstracting regex building into a new class. Finally, it separates and extends documentation for templating.
This commit is contained in:
19
tests/unit/stubs/ExpressionEvaluationContextStub.ts
Normal file
19
tests/unit/stubs/ExpressionEvaluationContextStub.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { IExpressionEvaluationContext } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionEvaluationContext';
|
||||
import { IPipelineCompiler } from '@/application/Parser/Script/Compiler/Expressions/Pipes/IPipelineCompiler';
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Script/Compiler/FunctionCall/Argument/IFunctionCallArgumentCollection';
|
||||
import { FunctionCallArgumentCollectionStub } from './FunctionCallArgumentCollectionStub';
|
||||
import { PipelineCompilerStub } from './PipelineCompilerStub';
|
||||
|
||||
export class ExpressionEvaluationContextStub implements IExpressionEvaluationContext {
|
||||
public args: IReadOnlyFunctionCallArgumentCollection = new FunctionCallArgumentCollectionStub()
|
||||
.withArgument('test-arg', 'test-value');
|
||||
public pipelineCompiler: IPipelineCompiler = new PipelineCompilerStub();
|
||||
public withArgs(args: IReadOnlyFunctionCallArgumentCollection) {
|
||||
this.args = args;
|
||||
return this;
|
||||
}
|
||||
public withPipelineCompiler(pipelineCompiler: IPipelineCompiler) {
|
||||
this.pipelineCompiler = pipelineCompiler;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { ExpressionPosition } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionPosition';
|
||||
import { IExpression } from '@/application/Parser/Script/Compiler/Expressions/Expression/IExpression';
|
||||
import { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Script/Compiler/FunctionCall/Argument/IFunctionCallArgumentCollection';
|
||||
import { IReadOnlyFunctionParameterCollection } from '@/application/Parser/Script/Compiler/Function/Parameter/IFunctionParameterCollection';
|
||||
import { FunctionParameterCollectionStub } from './FunctionParameterCollectionStub';
|
||||
import { IExpressionEvaluationContext } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionEvaluationContext';
|
||||
|
||||
export class ExpressionStub implements IExpression {
|
||||
public callHistory = new Array<IReadOnlyFunctionCallArgumentCollection>();
|
||||
public callHistory = new Array<IExpressionEvaluationContext>();
|
||||
public position = new ExpressionPosition(0, 5);
|
||||
public parameters: IReadOnlyFunctionParameterCollection = new FunctionParameterCollectionStub();
|
||||
private result: string;
|
||||
@@ -26,8 +26,9 @@ export class ExpressionStub implements IExpression {
|
||||
this.result = result;
|
||||
return this;
|
||||
}
|
||||
public evaluate(args: IReadOnlyFunctionCallArgumentCollection): string {
|
||||
this.callHistory.push(args);
|
||||
public evaluate(context: IExpressionEvaluationContext): string {
|
||||
const args = context.args;
|
||||
this.callHistory.push(context);
|
||||
const result = this.result || `[expression-stub] args: ${args ? Object.keys(args).map((key) => `${key}: ${args[key]}`).join('", "') : 'none'}`;
|
||||
return result;
|
||||
}
|
||||
|
||||
28
tests/unit/stubs/PipeFactoryStub.ts
Normal file
28
tests/unit/stubs/PipeFactoryStub.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { IPipe } from '@/application/Parser/Script/Compiler/Expressions/Pipes/IPipe';
|
||||
import { IPipeFactory } from '@/application/Parser/Script/Compiler/Expressions/Pipes/PipeFactory';
|
||||
|
||||
export class PipeFactoryStub implements IPipeFactory {
|
||||
private readonly pipes = new Array<IPipe>();
|
||||
|
||||
public get(pipeName: string): IPipe {
|
||||
const result = this.pipes.find((pipe) => pipe.name === pipeName);
|
||||
if (!result) {
|
||||
throw new Error(`pipe not registered: "${pipeName}"`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public withPipe(pipe: IPipe) {
|
||||
if (!pipe) {
|
||||
throw new Error('undefined pipe');
|
||||
}
|
||||
this.pipes.push(pipe);
|
||||
return this;
|
||||
}
|
||||
public withPipes(pipes: IPipe[]) {
|
||||
for (const pipe of pipes) {
|
||||
this.withPipe(pipe);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
16
tests/unit/stubs/PipeStub.ts
Normal file
16
tests/unit/stubs/PipeStub.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { IPipe } from '@/application/Parser/Script/Compiler/Expressions/Pipes/IPipe';
|
||||
|
||||
export class PipeStub implements IPipe {
|
||||
public name: string = 'pipeStub';
|
||||
public apply(raw: string): string {
|
||||
return raw;
|
||||
}
|
||||
public withName(name: string): PipeStub {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
public withApplier(applier: (input: string) => string): PipeStub {
|
||||
this.apply = applier;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
9
tests/unit/stubs/PipelineCompilerStub.ts
Normal file
9
tests/unit/stubs/PipelineCompilerStub.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { IPipelineCompiler } from '@/application/Parser/Script/Compiler/Expressions/Pipes/IPipelineCompiler';
|
||||
|
||||
export class PipelineCompilerStub implements IPipelineCompiler {
|
||||
public compileHistory: Array<{ value: string, pipeline: string }> = [];
|
||||
public compile(value: string, pipeline: string): string {
|
||||
this.compileHistory.push({value, pipeline});
|
||||
return `value: ${value}"\n${pipeline}: ${pipeline}`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user