UNPKG

@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
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