104 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
/**
 | 
						|
 * @license
 | 
						|
 * Copyright Google Inc. All Rights Reserved.
 | 
						|
 *
 | 
						|
 * Use of this source code is governed by an MIT-style license that can be
 | 
						|
 * found in the LICENSE file at https://angular.io/license
 | 
						|
 */
 | 
						|
 | 
						|
import * as e from '../../../src/expression_parser/ast';
 | 
						|
import {Lexer} from '../../../src/expression_parser/lexer';
 | 
						|
import {Parser} from '../../../src/expression_parser/parser';
 | 
						|
import * as html from '../../../src/ml_parser/ast';
 | 
						|
import {HtmlParser} from '../../../src/ml_parser/html_parser';
 | 
						|
import {WhitespaceVisitor} from '../../../src/ml_parser/html_whitespaces';
 | 
						|
import {DEFAULT_INTERPOLATION_CONFIG} from '../../../src/ml_parser/interpolation_config';
 | 
						|
import * as a from '../../../src/render3/r3_ast';
 | 
						|
import {Render3ParseResult, htmlAstToRender3Ast} from '../../../src/render3/r3_template_transform';
 | 
						|
import {processI18nMeta} from '../../../src/render3/view/i18n/meta';
 | 
						|
import {BindingParser} from '../../../src/template_parser/binding_parser';
 | 
						|
import {MockSchemaRegistry} from '../../../testing';
 | 
						|
 | 
						|
export function findExpression(tmpl: a.Node[], expr: string): e.AST|null {
 | 
						|
  const res = tmpl.reduce((found, node) => {
 | 
						|
    if (found !== null) {
 | 
						|
      return found;
 | 
						|
    } else {
 | 
						|
      return findExpressionInNode(node, expr);
 | 
						|
    }
 | 
						|
  }, null as e.AST | null);
 | 
						|
  if (res instanceof e.ASTWithSource) {
 | 
						|
    return res.ast;
 | 
						|
  }
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
function findExpressionInNode(node: a.Node, expr: string): e.AST|null {
 | 
						|
  if (node instanceof a.Element || node instanceof a.Template) {
 | 
						|
    return findExpression(
 | 
						|
        [
 | 
						|
          ...node.inputs,
 | 
						|
          ...node.outputs,
 | 
						|
          ...node.children,
 | 
						|
        ],
 | 
						|
        expr);
 | 
						|
  } else if (node instanceof a.BoundAttribute || node instanceof a.BoundText) {
 | 
						|
    const ts = toStringExpression(node.value);
 | 
						|
    return toStringExpression(node.value) === expr ? node.value : null;
 | 
						|
  } else if (node instanceof a.BoundEvent) {
 | 
						|
    return toStringExpression(node.handler) === expr ? node.handler : null;
 | 
						|
  } else {
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export function toStringExpression(expr: e.AST): string {
 | 
						|
  while (expr instanceof e.ASTWithSource) {
 | 
						|
    expr = expr.ast;
 | 
						|
  }
 | 
						|
  if (expr instanceof e.PropertyRead) {
 | 
						|
    if (expr.receiver instanceof e.ImplicitReceiver) {
 | 
						|
      return expr.name;
 | 
						|
    } else {
 | 
						|
      return `${toStringExpression(expr.receiver)}.${expr.name}`;
 | 
						|
    }
 | 
						|
  } else if (expr instanceof e.ImplicitReceiver) {
 | 
						|
    return '';
 | 
						|
  } else if (expr instanceof e.Interpolation) {
 | 
						|
    let str = '{{';
 | 
						|
    for (let i = 0; i < expr.expressions.length; i++) {
 | 
						|
      str += expr.strings[i] + toStringExpression(expr.expressions[i]);
 | 
						|
    }
 | 
						|
    str += expr.strings[expr.strings.length - 1] + '}}';
 | 
						|
    return str;
 | 
						|
  } else {
 | 
						|
    throw new Error(`Unsupported type: ${(expr as any).constructor.name}`);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Parse an html string to IVY specific info
 | 
						|
export function parseR3(
 | 
						|
    input: string, options: {preserveWhitespaces?: boolean} = {}): Render3ParseResult {
 | 
						|
  const htmlParser = new HtmlParser();
 | 
						|
 | 
						|
  const parseResult = htmlParser.parse(input, 'path:://to/template', true);
 | 
						|
 | 
						|
  if (parseResult.errors.length > 0) {
 | 
						|
    const msg = parseResult.errors.map(e => e.toString()).join('\n');
 | 
						|
    throw new Error(msg);
 | 
						|
  }
 | 
						|
 | 
						|
  let htmlNodes = processI18nMeta(parseResult).rootNodes;
 | 
						|
 | 
						|
  if (!options.preserveWhitespaces) {
 | 
						|
    htmlNodes = html.visitAll(new WhitespaceVisitor(), htmlNodes);
 | 
						|
  }
 | 
						|
 | 
						|
  const expressionParser = new Parser(new Lexer());
 | 
						|
  const schemaRegistry = new MockSchemaRegistry(
 | 
						|
      {'invalidProp': false}, {'mappedAttr': 'mappedProp'}, {'unknown': false, 'un-known': false},
 | 
						|
      ['onEvent'], ['onEvent']);
 | 
						|
  const bindingParser =
 | 
						|
      new BindingParser(expressionParser, DEFAULT_INTERPOLATION_CONFIG, schemaRegistry, null, []);
 | 
						|
  return htmlAstToRender3Ast(htmlNodes, bindingParser);
 | 
						|
} |