'],
                [HtmlAttrAst, '[prop]', 'v1', '[prop]="v1"'],
                [HtmlAttrAst, '(e)', 'do()', '(e)="do()"'],
                [HtmlAttrAst, 'attr', 'v2', 'attr="v2"'],
                [HtmlAttrAst, 'noValue', '', 'noValue'],
                [HtmlTextAst, '\na\n', 1, '\na\n'],
              ]);
        });
      });
      describe('errors', () => {
        it('should report unexpected closing tags', () => {
          let errors = parser.parse('
', 'TestComp').errors;
          expect(errors.length).toEqual(1);
          expect(humanizeErrors(errors)).toEqual([['p', 'Unexpected closing tag "p"', '0:5']]);
        });
        it('should report closing tag for void elements', () => {
          let errors = parser.parse('
', 'TestComp').errors;
          expect(errors.length).toEqual(1);
          expect(humanizeErrors(errors))
              .toEqual([['input', 'Void elements do not have end tags "input"', '0:7']]);
        });
        it('should report self closing html element', () => {
          let errors = parser.parse('
', 'TestComp').errors;
          expect(errors.length).toEqual(1);
          expect(humanizeErrors(errors))
              .toEqual([['p', 'Only void and foreign elements can be self closed "p"', '0:0']]);
        });
        it('should report self closing custom element', () => {
          let errors = parser.parse('
', 'TestComp').errors;
          expect(errors.length).toEqual(1);
          expect(humanizeErrors(errors))
              .toEqual([
                ['my-cmp', 'Only void and foreign elements can be self closed "my-cmp"', '0:0']
              ]);
        });
        it('should also report lexer errors', () => {
          let errors = parser.parse('
', 'TestComp').errors;
          expect(errors.length).toEqual(2);
          expect(humanizeErrors(errors))
              .toEqual([
                [HtmlTokenType.COMMENT_START, 'Unexpected character "e"', '0:3'],
                ['p', 'Unexpected closing tag "p"', '0:14']
              ]);
        });
      });
    });
  });
}
function humanizeDom(parseResult: HtmlParseTreeResult): any[] {
  if (parseResult.errors.length > 0) {
    var errorString = parseResult.errors.join('\n');
    throw new BaseException(`Unexpected parse errors:\n${errorString}`);
  }
  var humanizer = new Humanizer(false);
  htmlVisitAll(humanizer, parseResult.rootNodes);
  return humanizer.result;
}
function humanizeDomSourceSpans(parseResult: HtmlParseTreeResult): any[] {
  if (parseResult.errors.length > 0) {
    var errorString = parseResult.errors.join('\n');
    throw new BaseException(`Unexpected parse errors:\n${errorString}`);
  }
  var humanizer = new Humanizer(true);
  htmlVisitAll(humanizer, parseResult.rootNodes);
  return humanizer.result;
}
function humanizeLineColumn(location: ParseLocation): string {
  return `${location.line}:${location.col}`;
}
function humanizeErrors(errors: ParseError[]): any[] {
  return errors.map(error => {
    if (error instanceof HtmlTreeError) {
      // Parser errors
      return [
error.elementName, error.msg, humanizeLineColumn(error.span.start)];
    }
    // Tokenizer errors
    return [(error).tokenType, error.msg, humanizeLineColumn(error.span.start)];
  });
}
class Humanizer implements HtmlAstVisitor {
  result: any[] = [];
  elDepth: number = 0;
  constructor(private includeSourceSpan: boolean){};
  visitElement(ast: HtmlElementAst, context: any): any {
    var res = this._appendContext(ast, [HtmlElementAst, ast.name, this.elDepth++]);
    this.result.push(res);
    htmlVisitAll(this, ast.attrs);
    htmlVisitAll(this, ast.children);
    this.elDepth--;
    return null;
  }
  visitAttr(ast: HtmlAttrAst, context: any): any {
    var res = this._appendContext(ast, [HtmlAttrAst, ast.name, ast.value]);
    this.result.push(res);
    return null;
  }
  visitText(ast: HtmlTextAst, context: any): any {
    var res = this._appendContext(ast, [HtmlTextAst, ast.value, this.elDepth]);
    this.result.push(res);
    return null;
  }
  private _appendContext(ast: HtmlAst, input: any[]): any[] {
    if (!this.includeSourceSpan) return input;
    input.push(ast.sourceSpan.toString());
    return input;
  }
}