'use strict'; import { Injectable, Renderer, ComponentRef, Type, Injector, Inject, ComponentFactoryResolver } from '@angular/core'; export type NodesOrComponents = HTMLElement | ComponentRef; export const COMPONENT_PARSER_ALLOWED = 'COMPONENT_PARSER_ALLOWED'; const COMPONENT_REGEXP = '^\\s*\\s*$'; @Injectable() export class ComponentParser { private renderer: Renderer; private allowedComponents: any; static contains(content: string, componentSelector: string) { let regexp = new RegExp(COMPONENT_REGEXP.replace('{component}', `<${componentSelector}.*>`), 'mi'); return regexp.test(content); } static build(componentSelector) { return ``; } constructor( private resolver: ComponentFactoryResolver, @Inject(COMPONENT_PARSER_ALLOWED) allowedComponents ) { this.allowedComponents = allowedComponents; } setRenderer(_renderer: Renderer) { this.renderer = _renderer; } splitIntoNodesOrComponents(content: string, injector: Injector):NodesOrComponents[] { let componentDefs = []; let match; let anyCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '(.*?)'), 'gmi'); while (match = anyCompRegexp.exec(content)) { componentDefs.push(match[1]); } let splitCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '.*?'), 'mi'); let htmlParts = content.split(splitCompRegexp); let res = []; for (let i = 0; i < htmlParts.length; i++) { let node = this.renderer.createElement(null, 'div'); this.renderer.setElementProperty(node, 'innerHTML', htmlParts[i]); if (htmlParts[i]) res.push(node); if (componentDefs[i]) { let componentRef = this.createComponentByHtml(componentDefs[i], injector); res.push(componentRef); } } return res; } createComponentByHtml(htmlTag: string, injector:Injector):ComponentRef| null { let { componentType } = this._parseHtml(htmlTag); if (!componentType) return null; let factory = this.resolver.resolveComponentFactory(componentType); return factory.create(injector); } private _parseHtml(htmlTag: string):{componentType: Type | null, options: any} { // TODO: for now only primitive parsing by tagname let match = /<([\w_-]+).*?>/.exec(htmlTag); if (match.length <= 1) return { componentType: null, options: null }; let componentName = match[1]; let componentType = this.allowedComponents[componentName]; // TODO parse options let options = {}; return { componentType, options }; } }