@ogs-gmbh/ngx-template-engine
Version:
A library providing a flexible and efficient template engine for dynamic content rendering. It enables easy integration of customizable templates within Angular applications.
211 lines (201 loc) • 8.22 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, Pipe, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
var AstKind;
(function (AstKind) {
AstKind["TEMPLATE_PROPERTY"] = "template-property";
AstKind["TEMPLATE_INDEX"] = "template-index";
AstKind["TEXT"] = "text";
})(AstKind || (AstKind = {}));
function createAstTemplatePropertyNode(property) {
return {
kind: AstKind.TEMPLATE_PROPERTY,
property
};
}
function createAstTemplateIndexNode(index) {
return {
kind: AstKind.TEMPLATE_INDEX,
index
};
}
function createAstTextNode(value) {
return {
kind: AstKind.TEXT,
value
};
}
var CharKind;
(function (CharKind) {
CharKind["START"] = "start";
CharKind["END"] = "end";
})(CharKind || (CharKind = {}));
const TEMPLATE_CHARS = {
CURLY_LEFT: {
"char": "{",
kind: CharKind.START
},
CURLY_RIGHT: {
"char": "}",
kind: CharKind.END
}
};
function getCharDescriptor(char) {
const templateCharKeys = Object.keys(TEMPLATE_CHARS);
let charDescriptor = null;
templateCharKeys.forEach((templateCharKey) => {
const templateChar = TEMPLATE_CHARS[templateCharKey];
if (templateChar?.char !== char)
return;
charDescriptor = templateChar;
});
return charDescriptor;
}
function isObject(value) {
return typeof value === "object" && !Array.isArray(value) && value !== null;
}
function transformAst(ast, data) {
if (Array.isArray(data) && ast.mode !== "index" || isObject(data) && ast.mode !== "property")
throw new Error(`Expected an appropiate data type matching to ${ast.mode}-based template variables`);
return ast.nodes.map((node) => {
if (node.kind === AstKind.TEXT)
return node.value;
switch (ast.mode) {
case "property": {
const dataIndex = node.property;
const dataValue = data[dataIndex];
if (dataValue === undefined)
throw new Error(`Expected data for key ${dataIndex}`);
return dataValue.toString();
}
case "index": {
const dataIndex = node.index;
const dataValue = data[dataIndex];
if (dataValue === undefined)
throw new Error(`Expected data for key ${dataIndex}`);
return dataValue.toString();
}
}
}).join("");
}
function parseAst(value) {
const splittedValue = value.split("");
if (splittedValue.length === 0)
throw new Error("Error processing a zero length data sequence");
const astNodes = [];
let sequence = null;
let lastCharKind = null;
let detectedAstMode = null;
splittedValue.forEach((char, index) => {
const charDescriptor = getCharDescriptor(char);
if (charDescriptor === null) {
sequence === null ? sequence = char : sequence += char;
if (index === splittedValue.length - 1) {
astNodes.push(createAstTextNode(sequence));
sequence = null;
}
return;
}
switch (charDescriptor.kind) {
case CharKind.START: {
if (lastCharKind !== null && lastCharKind !== CharKind.END)
throw new Error(`Expected an end char kind, but got a start char kind at index ${index} instead`);
if (sequence !== null) {
astNodes.push(createAstTextNode(sequence));
sequence = null;
}
break;
}
case CharKind.END: {
if (sequence === null)
throw new Error(`Unexpected end at index ${index}. Expected a index or keyword property`);
if (lastCharKind !== CharKind.START)
throw new Error(`Expected start char kind to be ${CharKind.START}, but got ${lastCharKind} instead`);
const indexSequence = Number(sequence);
const nodeAstMode = Number.isNaN(indexSequence) ? "property" : "index";
if (detectedAstMode !== null && detectedAstMode !== nodeAstMode)
throw new Error(`Expected to have only ${detectedAstMode}-based template variables, but got a ${nodeAstMode}-based instead`);
detectedAstMode ??= nodeAstMode;
astNodes.push(detectedAstMode === "index"
? createAstTemplateIndexNode(indexSequence)
: createAstTemplatePropertyNode(sequence));
sequence = null;
break;
}
}
lastCharKind = charDescriptor.kind;
});
if (detectedAstMode === null)
throw new Error(`Expected template to have at least 1 index- or property-based variable`);
return {
mode: detectedAstMode,
nodes: astNodes
};
}
const TEMPLATE_ENGINE_CONFIG_TOKEN = new InjectionToken("template-engine-config");
function provideTemplateEngineConfig(config) {
return {
provide: TEMPLATE_ENGINE_CONFIG_TOKEN,
useValue: config
};
}
class TemplatePipe {
_config = inject(TEMPLATE_ENGINE_CONFIG_TOKEN, { optional: true });
_boostrapValue = null;
_parseAndTransform(value, data) {
const ast = parseAst(value);
return transformAst(ast, data);
}
_updateBoostrapValue(value) {
if (this._boostrapValue !== null)
return;
this._boostrapValue = value;
}
transform(value, data, fallbackOnError) {
const shouldFallbackOnError = fallbackOnError ?? this._config?.fallbackOnError;
if (!shouldFallbackOnError) {
const transformedValue = this._parseAndTransform(value, data);
this._updateBoostrapValue(transformedValue);
return transformedValue;
}
try {
const transformedValue = this._parseAndTransform(value, data);
this._updateBoostrapValue(transformedValue);
return transformedValue;
}
catch {
if (this._boostrapValue === null)
throw new Error("Expected an initial fallback value");
return this._boostrapValue;
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TemplatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TemplatePipe, name: "template" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TemplatePipe, decorators: [{
type: Pipe,
args: [{
name: "template"
}]
}] });
class TemplatePipeModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TemplatePipeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TemplatePipeModule, declarations: [TemplatePipe], imports: [CommonModule], exports: [TemplatePipe] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TemplatePipeModule, imports: [CommonModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TemplatePipeModule, decorators: [{
type: NgModule,
args: [{
imports: [
CommonModule
],
declarations: [
TemplatePipe
],
exports: [
TemplatePipe
]
}]
}] });
export { AstKind, TEMPLATE_ENGINE_CONFIG_TOKEN, TemplatePipe, TemplatePipeModule, createAstTemplateIndexNode, createAstTemplatePropertyNode, createAstTextNode, parseAst, provideTemplateEngineConfig, transformAst };
//# sourceMappingURL=ogs-gmbh-ngx-template-engine.mjs.map