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.

1 lines 16.5 kB
{"version":3,"file":"ogs-gmbh-ngx-template-engine.mjs","sources":["../../../src/ast.ts","../../../src/chars.ts","../../../src/utils.ts","../../../src/transformer.ts","../../../src/parser.ts","../../../src/token.ts","../../../src/pipes/template.ts","../../../src/lib.ts"],"sourcesContent":["type Ast = {\n mode: AstMode;\n nodes: AstNodes;\n};\n\ntype AstNodes = AstNode[];\n\n/**\n * When the first template variable is {0} (index-based), every following\n * template variable must be index-based. Same applies to {property} (property-based).\n * This result in only having one mode for the ast to work with.\n */\ntype AstMode = \"index\" | \"property\";\n\ntype AstNode = {\n kind: AstKind;\n};\n\ntype AstTemplatePropertyNode = AstNode & {\n property: string;\n};\n\ntype AstTemplateIndexNode = AstNode & {\n index: number;\n};\n\ntype AstTextNode = AstNode & {\n value: string;\n};\n\nenum AstKind {\n TEMPLATE_PROPERTY = \"template-property\",\n TEMPLATE_INDEX = \"template-index\",\n TEXT = \"text\"\n}\n\nfunction createAstTemplatePropertyNode (property: string): AstTemplatePropertyNode {\n return {\n kind: AstKind.TEMPLATE_PROPERTY,\n property\n };\n}\n\nfunction createAstTemplateIndexNode (index: number): AstTemplateIndexNode {\n return {\n kind: AstKind.TEMPLATE_INDEX,\n index\n };\n}\n\nfunction createAstTextNode (value: string): AstTextNode {\n return {\n kind: AstKind.TEXT,\n value\n };\n}\n\nexport type {\n Ast,\n AstNodes,\n AstNode,\n AstMode,\n AstTemplatePropertyNode,\n AstTemplateIndexNode,\n AstTextNode\n};\nexport {\n AstKind,\n createAstTemplatePropertyNode,\n createAstTemplateIndexNode,\n createAstTextNode\n};\n","enum CharKind {\n START = \"start\",\n END = \"end\"\n}\n\ntype CharDescriptor = {\n \"char\": string;\n kind: CharKind;\n};\n\nconst TEMPLATE_CHARS: Record<string, CharDescriptor> = {\n CURLY_LEFT: {\n \"char\": \"{\",\n kind: CharKind.START\n },\n CURLY_RIGHT: {\n \"char\": \"}\",\n kind: CharKind.END\n }\n};\n\nexport type {\n CharDescriptor\n};\nexport {\n CharKind,\n TEMPLATE_CHARS\n};\n","import { CharDescriptor, TEMPLATE_CHARS } from \"./chars\";\n\nfunction getCharDescriptor (char: string): CharDescriptor | null {\n const templateCharKeys: string[] = Object.keys(TEMPLATE_CHARS);\n\n let charDescriptor: CharDescriptor | null = null;\n\n templateCharKeys.forEach((templateCharKey: string): void => {\n const templateChar: CharDescriptor | undefined = TEMPLATE_CHARS[ templateCharKey ];\n\n /* eslint-disable-next-line @tseslint/dot-notation */\n if (templateChar?.char !== char)\n return;\n\n charDescriptor = templateChar;\n });\n\n return charDescriptor;\n}\n\nfunction isObject (value: unknown): boolean {\n return typeof value === \"object\" && !Array.isArray(value) && value !== null;\n}\n\nexport {\n getCharDescriptor,\n isObject\n};\n","import { Ast, AstKind, AstNode, AstTemplatePropertyNode, AstTextNode, AstTemplateIndexNode } from \"./ast\";\nimport { isObject } from \"./utils\";\n\ntype DataRecord = Record<string, string | number>;\n\ntype DataArray = Array<string | number>;\n\nfunction transformAst (ast: Ast, data: DataRecord | DataArray): string {\n if (Array.isArray(data) && ast.mode !== \"index\" || isObject(data) && ast.mode !== \"property\")\n throw new Error(`Expected an appropiate data type matching to ${ ast.mode }-based template variables`);\n\n /* eslint-disable-next-line array-callback-return */\n return ast.nodes.map((node: AstNode): string => {\n if (node.kind === AstKind.TEXT)\n return (node as AstTextNode).value;\n\n switch (ast.mode) {\n case \"property\": {\n const dataIndex: string = (node as AstTemplatePropertyNode).property;\n const dataValue: string | number | undefined = (data as DataRecord)[ dataIndex ];\n\n if (dataValue === undefined)\n throw new Error(`Expected data for key ${ dataIndex }`);\n\n return dataValue.toString();\n }\n\n case \"index\": {\n const dataIndex: number = (node as AstTemplateIndexNode).index;\n const dataValue: string | number | undefined = (data as DataArray)[ dataIndex ];\n\n if (dataValue === undefined)\n throw new Error(`Expected data for key ${ dataIndex }`);\n\n return dataValue.toString();\n }\n }\n }).join(\"\");\n}\n\nexport type {\n DataRecord,\n DataArray\n};\nexport {\n transformAst\n};\n","import { CharDescriptor, CharKind } from \"./chars\";\nimport { Ast, AstMode, AstNodes, createAstTemplateIndexNode, createAstTemplatePropertyNode, createAstTextNode } from \"./ast\";\nimport { getCharDescriptor } from \"./utils\";\n\nfunction parseAst (value: string): Ast {\n /* eslint-disable-next-line @unicorn/prefer-spread */\n const splittedValue: string[] = value.split(\"\");\n\n if (splittedValue.length === 0)\n throw new Error(\"Error processing a zero length data sequence\");\n\n const astNodes: AstNodes = [];\n\n let sequence: string | null = null;\n let lastCharKind: CharKind | null = null;\n let detectedAstMode: AstMode | null = null;\n\n splittedValue.forEach((char: string, index: number): void => {\n const charDescriptor: CharDescriptor | null = getCharDescriptor(char);\n\n // Got a char so just append it\n if (charDescriptor === null) {\n sequence === null ? sequence = char : sequence += char;\n\n if (index === splittedValue.length - 1) {\n astNodes.push(\n createAstTextNode(sequence)\n );\n sequence = null;\n }\n\n\n return;\n }\n\n // Got a char descriptor, so handle it\n switch (charDescriptor.kind) {\n case CharKind.START: {\n // When no char kind ended before start char kind then its a syntax error\n if (lastCharKind !== null && lastCharKind !== CharKind.END)\n throw new Error(`Expected an end char kind, but got a start char kind at index ${ index } instead`);\n\n if (sequence !== null) {\n astNodes.push(\n createAstTextNode(sequence)\n );\n sequence = null;\n }\n\n break;\n }\n\n case CharKind.END: {\n // When no property inside text is found, char kinds job is not fullfilled\n if (sequence === null)\n throw new Error(`Unexpected end at index ${ index }. Expected a index or keyword property`);\n\n // End char kind is only possible when start char kind was the previous char kind\n if (lastCharKind !== CharKind.START)\n throw new Error(`Expected start char kind to be ${ CharKind.START }, but got ${ lastCharKind } instead`);\n\n const indexSequence: number = Number(sequence);\n const nodeAstMode: AstMode = Number.isNaN(indexSequence) ? \"property\" : \"index\";\n\n // If current template variable is based differently than detected ast mode its a syntax error\n if (detectedAstMode !== null && detectedAstMode !== nodeAstMode)\n throw new Error(`Expected to have only ${ detectedAstMode }-based template variables, but got a ${ nodeAstMode }-based instead`);\n\n detectedAstMode ??= nodeAstMode;\n astNodes.push(\n detectedAstMode === \"index\"\n ? createAstTemplateIndexNode(indexSequence)\n : createAstTemplatePropertyNode(sequence)\n );\n sequence = null;\n\n break;\n }\n }\n\n lastCharKind = charDescriptor.kind;\n });\n\n // When ast mode could not be detected, then why is someone using this on a value only char sequence?\n /* eslint-disable-next-line @tseslint/no-unnecessary-condition */\n if (detectedAstMode === null)\n throw new Error(`Expected template to have at least 1 index- or property-based variable`);\n\n return {\n mode: detectedAstMode,\n nodes: astNodes\n };\n}\n\nexport {\n parseAst\n};\n","import { InjectionToken, ValueProvider } from \"@angular/core\";\n\nexport type TemplateEngineConfig = {\n fallbackOnError?: boolean;\n};\nexport const TEMPLATE_ENGINE_CONFIG_TOKEN: InjectionToken<TemplateEngineConfig> = new InjectionToken<TemplateEngineConfig>(\"template-engine-config\");\nexport function provideTemplateEngineConfig (config: TemplateEngineConfig): ValueProvider {\n return {\n provide: TEMPLATE_ENGINE_CONFIG_TOKEN,\n useValue: config\n };\n}\n","/* eslint-disable */\n\nimport { inject, Pipe, PipeTransform } from \"@angular/core\";\nimport { DataArray, DataRecord, transformAst } from \"../transformer\";\nimport { Ast } from \"../ast\";\nimport { parseAst } from \"../parser\";\nimport { TEMPLATE_ENGINE_CONFIG_TOKEN, TemplateEngineConfig } from \"../token\";\n\n@Pipe({\n name: \"template\"\n})\nexport class TemplatePipe implements PipeTransform {\n private readonly _config: TemplateEngineConfig | null = inject(TEMPLATE_ENGINE_CONFIG_TOKEN, { optional: true });\n\n private _boostrapValue: string | null = null;\n \n private _parseAndTransform (value: string, data: DataRecord | DataArray): string {\n const ast: Ast = parseAst(value);\n\n return transformAst(ast, data);\n }\n\n private _updateBoostrapValue (value: string): void {\n if (this._boostrapValue !== null)\n return;\n\n this._boostrapValue = value;\n }\n\n public transform(value: string, data: DataRecord | DataArray, fallbackOnError?: boolean): string {\n const shouldFallbackOnError: boolean | undefined = fallbackOnError ?? this._config?.fallbackOnError;\n\n if (!shouldFallbackOnError) {\n const transformedValue = this._parseAndTransform(value, data);\n\n this._updateBoostrapValue(transformedValue);\n\n return transformedValue;\n }\n\n try {\n const transformedValue = this._parseAndTransform(value, data);\n\n this._updateBoostrapValue(transformedValue);\n\n return transformedValue;\n } catch {\n if (this._boostrapValue === null)\n throw new Error(\"Expected an initial fallback value\");\n\n return this._boostrapValue;\n }\n }\n}\n","import { NgModule } from \"@angular/core\";\nimport { CommonModule } from \"@angular/common\";\nimport { TemplatePipe } from \"./pipes/template\";\n\n/* eslint-disable @tseslint/no-extraneous-class */\n@NgModule({\n imports: [\n CommonModule\n ],\n declarations: [\n TemplatePipe\n ],\n exports: [\n TemplatePipe\n ]\n})\nexport class TemplatePipeModule {}\n/* eslint-enable @tseslint/no-extraneous-class */\n"],"names":[],"mappings":"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"}