2016-07-01 20:29:54 -04:00
/ * *
* @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 { beforeEach , ddescribe , describe , expect , iit , inject , it , xdescribe , xit } from '@angular/core/testing/testing_internal' ;
2016-08-04 20:46:31 -04:00
import { extractMessages , mergeTranslations } from '../../src/i18n/extractor_merger' ;
import * as i18n from '../../src/i18n/i18n_ast' ;
import { digestMessage , serializeNodes as serializeI18nNodes } from '../../src/i18n/message_bundle' ;
2016-08-01 21:10:34 -04:00
import { TranslationBundle } from '../../src/i18n/translation_bundle' ;
import * as html from '../../src/ml_parser/ast' ;
2016-08-01 15:19:09 -04:00
import { HtmlParser } from '../../src/ml_parser/html_parser' ;
2016-08-01 21:10:34 -04:00
import { DEFAULT_INTERPOLATION_CONFIG } from '../../src/ml_parser/interpolation_config' ;
2016-08-04 20:46:31 -04:00
import { serializeNodes as serializeHtmlNodes } from '../ml_parser/ast_serializer_spec' ;
2016-07-01 20:29:54 -04:00
export function main() {
2016-08-01 21:10:34 -04:00
describe ( 'Extractor' , ( ) = > {
2016-07-21 16:56:58 -04:00
describe ( 'elements' , ( ) = > {
it ( 'should extract from elements' , ( ) = > {
2016-08-01 14:33:35 -04:00
expect ( extract ( '<div i18n="m|d|e">text<span>nested</span></div>' ) ) . toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ 'text' , '<ph tag name="START_TAG_SPAN">nested</ph name="CLOSE_TAG_SPAN">' ] , 'm' , 'd|e' ] ,
2016-07-21 16:56:58 -04:00
] ) ;
2016-08-01 16:11:48 -04:00
} ) ;
2016-08-04 20:46:31 -04:00
it ( 'should extract from attributes' , ( ) = > {
2016-08-01 17:43:20 -04:00
expect (
extract (
2016-08-04 20:46:31 -04:00
'<div i18n="m1|d1"><span i18n-title="m2|d2" title="single child">nested</span></div>' ) )
2016-08-01 17:43:20 -04:00
. toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ '<ph tag name="START_TAG_SPAN">nested</ph name="CLOSE_TAG_SPAN">' ] , 'm1' , 'd1' ] ,
[ [ 'single child' ] , 'm2' , 'd2' ] ,
2016-08-01 17:43:20 -04:00
] ) ;
} ) ;
2016-08-04 20:46:31 -04:00
it ( 'should extract from ICU messages' , ( ) = > {
2016-08-01 16:11:48 -04:00
expect (
extract (
'<div i18n="m|d">{count, plural, =0 { <p i18n-title i18n-desc title="title" desc="desc"></p>}}</div>' ) )
. toEqual ( [
[
[
2016-08-04 20:46:31 -04:00
'{count, plural, =0 {[<ph tag name="START_PARAGRAPH"></ph name="CLOSE_PARAGRAPH">]}}'
2016-08-01 16:11:48 -04:00
] ,
'm' , 'd'
] ,
2016-08-04 20:46:31 -04:00
[ [ 'title' ] , '' , '' ] ,
[ [ 'desc' ] , '' , '' ] ,
2016-08-01 16:11:48 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
} ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
it ( 'should not create a message for empty elements' ,
( ) = > { expect ( extract ( '<div i18n="m|d"></div>' ) ) . toEqual ( [ ] ) ; } ) ;
} ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
describe ( 'blocks' , ( ) = > {
it ( 'should extract from blocks' , ( ) = > {
expect ( extract ( ` <!-- i18n: meaning1|desc1 -->message1<!-- /i18n -->
2016-08-01 14:33:35 -04:00
<!-- i18n : desc2 -- > message2 <!-- / i18n -- >
2016-07-01 20:29:54 -04:00
<!-- i18n -- > message3 <!-- / i18n -- > ` ))
2016-07-21 16:56:58 -04:00
. toEqual ( [
[ [ 'message1' ] , 'meaning1' , 'desc1' ] ,
2016-08-01 14:33:35 -04:00
[ [ 'message2' ] , '' , 'desc2' ] ,
2016-07-21 16:56:58 -04:00
[ [ 'message3' ] , '' , '' ] ,
] ) ;
} ) ;
it ( 'should extract siblings' , ( ) = > {
expect (
extract (
` <!-- i18n -->text<p>html<b>nested</b></p>{count, plural, =0 {<span>html</span>}}{{interp}}<!-- /i18n --> ` ) )
. toEqual ( [
[
[
2016-08-04 20:46:31 -04:00
'{count, plural, =0 {[<ph tag name="START_TAG_SPAN">html</ph name="CLOSE_TAG_SPAN">]}}'
] ,
'' , ''
] ,
[
[
'text' ,
'<ph tag name="START_PARAGRAPH">html, <ph tag name="START_BOLD_TEXT">nested</ph name="CLOSE_BOLD_TEXT"></ph name="CLOSE_PARAGRAPH">' ,
'<ph icu name="ICU">{count, plural, =0 {[<ph tag name="START_TAG_SPAN">html</ph name="CLOSE_TAG_SPAN">]}}</ph>' ,
'[<ph name="INTERPOLATION">interp</ph>]'
2016-07-21 16:56:58 -04:00
] ,
'' , ''
] ,
] ) ;
} ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
it ( 'should ignore other comments' , ( ) = > {
expect ( extract ( ` <!-- i18n: meaning1|desc1 --><!-- other -->message1<!-- /i18n --> ` ) )
. toEqual ( [
[ [ 'message1' ] , 'meaning1' , 'desc1' ] ,
2016-07-01 20:29:54 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
} ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
it ( 'should not create a message for empty blocks' ,
( ) = > { expect ( extract ( ` <!-- i18n: meaning1|desc1 --><!-- /i18n --> ` ) ) . toEqual ( [ ] ) ; } ) ;
} ) ;
describe ( 'ICU messages' , ( ) = > {
it ( 'should extract ICU messages from translatable elements' , ( ) = > {
// single message when ICU is the only children
expect ( extract ( '<div i18n="m|d">{count, plural, =0 {text}}</div>' ) ) . toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ '{count, plural, =0 {[text]}}' ] , 'm' , 'd' ] ,
2016-07-21 16:56:58 -04:00
] ) ;
2016-08-01 17:43:20 -04:00
// single message when ICU is the only (implicit) children
expect ( extract ( '<div>{count, plural, =0 {text}}</div>' , [ 'div' ] ) ) . toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ '{count, plural, =0 {[text]}}' ] , '' , '' ] ,
2016-08-01 17:43:20 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
// one message for the element content and one message for the ICU
expect ( extract ( '<div i18n="m|d">before{count, plural, =0 {text}}after</div>' ) ) . toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ 'before' , '<ph icu name="ICU">{count, plural, =0 {[text]}}</ph>' , 'after' ] , 'm' , 'd' ] ,
[ [ '{count, plural, =0 {[text]}}' ] , '' , '' ] ,
2016-07-21 16:56:58 -04:00
] ) ;
} ) ;
it ( 'should extract ICU messages from translatable block' , ( ) = > {
// single message when ICU is the only children
expect ( extract ( '<!-- i18n:m|d -->{count, plural, =0 {text}}<!-- /i18n -->' ) ) . toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ '{count, plural, =0 {[text]}}' ] , 'm' , 'd' ] ,
2016-07-21 16:56:58 -04:00
] ) ;
// one message for the block content and one message for the ICU
expect ( extract ( '<!-- i18n:m|d -->before{count, plural, =0 {text}}after<!-- /i18n -->' ) )
. toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ '{count, plural, =0 {[text]}}' ] , '' , '' ] ,
[
[ 'before' , '<ph icu name="ICU">{count, plural, =0 {[text]}}</ph>' , 'after' ] , 'm' ,
'd'
] ,
2016-07-01 20:29:54 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
} ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
it ( 'should not extract ICU messages outside of i18n sections' ,
( ) = > { expect ( extract ( '{count, plural, =0 {text}}' ) ) . toEqual ( [ ] ) ; } ) ;
it ( 'should not extract nested ICU messages' , ( ) = > {
expect ( extract ( '<div i18n="m|d">{count, plural, =0 { {sex, gender, =m {m}} }}</div>' ) )
. toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ '{count, plural, =0 {[{sex, gender, =m {[m]}}, ]}}' ] , 'm' , 'd' ] ,
2016-07-01 20:29:54 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
} ) ;
} ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
describe ( 'attributes' , ( ) = > {
2016-08-01 21:10:34 -04:00
it ( 'should extract from attributes outside of translatable sections' , ( ) = > {
2016-07-21 16:56:58 -04:00
expect ( extract ( '<div i18n-title="m|d" title="msg"></div>' ) ) . toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ 'msg' ] , 'm' , 'd' ] ,
2016-07-21 16:56:58 -04:00
] ) ;
} ) ;
2016-08-01 21:10:34 -04:00
it ( 'should extract from attributes in translatable elements' , ( ) = > {
2016-07-21 16:56:58 -04:00
expect ( extract ( '<div i18n><p><b i18n-title="m|d" title="msg"></b></p></div>' ) ) . toEqual ( [
2016-08-04 20:46:31 -04:00
[
[
'<ph tag name="START_PARAGRAPH"><ph tag name="START_BOLD_TEXT"></ph name="CLOSE_BOLD_TEXT"></ph name="CLOSE_PARAGRAPH">'
] ,
'' , ''
] ,
[ [ 'msg' ] , 'm' , 'd' ] ,
2016-07-21 16:56:58 -04:00
] ) ;
} ) ;
2016-07-01 20:29:54 -04:00
2016-08-01 21:10:34 -04:00
it ( 'should extract from attributes in translatable blocks' , ( ) = > {
2016-07-21 16:56:58 -04:00
expect ( extract ( '<!-- i18n --><p><b i18n-title="m|d" title="msg"></b></p><!-- /i18n -->' ) )
. toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ 'msg' ] , 'm' , 'd' ] ,
[
[
'<ph tag name="START_PARAGRAPH"><ph tag name="START_BOLD_TEXT"></ph name="CLOSE_BOLD_TEXT"></ph name="CLOSE_PARAGRAPH">'
] ,
'' , ''
] ,
2016-07-01 20:29:54 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
} ) ;
2016-07-01 20:29:54 -04:00
2016-08-01 21:10:34 -04:00
it ( 'should extract from attributes in translatable ICUs' , ( ) = > {
2016-07-21 16:56:58 -04:00
expect (
extract (
'<!-- i18n -->{count, plural, =0 {<p><b i18n-title="m|d" title="msg"></b></p>}}<!-- /i18n -->' ) )
. toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ 'msg' ] , 'm' , 'd' ] ,
[
[
'{count, plural, =0 {[<ph tag name="START_PARAGRAPH"><ph tag name="START_BOLD_TEXT"></ph name="CLOSE_BOLD_TEXT"></ph name="CLOSE_PARAGRAPH">]}}'
] ,
'' , ''
] ,
2016-07-01 20:29:54 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
} ) ;
2016-07-01 20:29:54 -04:00
2016-08-01 21:10:34 -04:00
it ( 'should extract from attributes in non translatable ICUs' , ( ) = > {
2016-07-21 16:56:58 -04:00
expect ( extract ( '{count, plural, =0 {<p><b i18n-title="m|d" title="msg"></b></p>}}' ) )
. toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ 'msg' ] , 'm' , 'd' ] ,
2016-07-01 20:29:54 -04:00
] ) ;
2016-07-21 16:56:58 -04:00
} ) ;
it ( 'should not create a message for empty attributes' ,
( ) = > { expect ( extract ( '<div i18n-title="m|d" title></div>' ) ) . toEqual ( [ ] ) ; } ) ;
} ) ;
describe ( 'implicit elements' , ( ) = > {
it ( 'should extract from implicit elements' , ( ) = > {
expect ( extract ( '<b>bold</b><i>italic</i>' , [ 'b' ] ) ) . toEqual ( [
[ [ 'bold' ] , '' , '' ] ,
] ) ;
} ) ;
} ) ;
describe ( 'implicit attributes' , ( ) = > {
it ( 'should extract implicit attributes' , ( ) = > {
expect ( extract ( '<b title="bb">bold</b><i title="ii">italic</i>' , [ ] , { 'b' : [ 'title' ] } ) )
. toEqual ( [
2016-08-04 20:46:31 -04:00
[ [ 'bb' ] , '' , '' ] ,
2016-07-21 16:56:58 -04:00
] ) ;
} ) ;
} ) ;
describe ( 'errors' , ( ) = > {
describe ( 'elements' , ( ) = > {
it ( 'should report nested translatable elements' , ( ) = > {
expect ( extractErrors ( ` <p i18n><b i18n></b></p> ` ) ) . toEqual ( [
[ 'Could not mark an element as translatable inside a translatable section' , '<b i18n>' ] ,
] ) ;
2016-07-01 20:29:54 -04:00
} ) ;
2016-07-21 16:56:58 -04:00
it ( 'should report translatable elements in implicit elements' , ( ) = > {
expect ( extractErrors ( ` <p><b i18n></b></p> ` , [ 'p' ] ) ) . toEqual ( [
[ 'Could not mark an element as translatable inside a translatable section' , '<b i18n>' ] ,
] ) ;
2016-07-01 20:29:54 -04:00
} ) ;
2016-07-21 16:56:58 -04:00
it ( 'should report translatable elements in translatable blocks' , ( ) = > {
expect ( extractErrors ( ` <!-- i18n --><b i18n></b><!-- /i18n --> ` ) ) . toEqual ( [
[ 'Could not mark an element as translatable inside a translatable section' , '<b i18n>' ] ,
] ) ;
} ) ;
} ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
describe ( 'blocks' , ( ) = > {
it ( 'should report nested blocks' , ( ) = > {
expect ( extractErrors ( ` <!-- i18n --><!-- i18n --><!-- /i18n --><!-- /i18n --> ` ) ) . toEqual ( [
[ 'Could not start a block inside a translatable section' , '<!--' ] ,
[ 'Trying to close an unopened block' , '<!--' ] ,
] ) ;
2016-07-01 20:29:54 -04:00
2016-07-21 16:56:58 -04:00
} ) ;
it ( 'should report unclosed blocks' , ( ) = > {
expect ( extractErrors ( ` <!-- i18n --> ` ) ) . toEqual ( [
[ 'Unclosed block' , '<!--' ] ,
] ) ;
} ) ;
it ( 'should report translatable blocks in translatable elements' , ( ) = > {
expect ( extractErrors ( ` <p i18n><!-- i18n --><!-- /i18n --></p> ` ) ) . toEqual ( [
[ 'Could not start a block inside a translatable section' , '<!--' ] ,
[ 'Trying to close an unopened block' , '<!--' ] ,
] ) ;
} ) ;
it ( 'should report translatable blocks in implicit elements' , ( ) = > {
expect ( extractErrors ( ` <p><!-- i18n --><!-- /i18n --></p> ` , [ 'p' ] ) ) . toEqual ( [
[ 'Could not start a block inside a translatable section' , '<!--' ] ,
[ 'Trying to close an unopened block' , '<!--' ] ,
] ) ;
} ) ;
it ( 'should report when start and end of a block are not at the same level' , ( ) = > {
expect ( extractErrors ( ` <!-- i18n --><p><!-- /i18n --></p> ` ) ) . toEqual ( [
[ 'I18N blocks should not cross element boundaries' , '<!--' ] ,
[ 'Unclosed block' , '<p>' ] ,
] ) ;
expect ( extractErrors ( ` <p><!-- i18n --></p><!-- /i18n --> ` ) ) . toEqual ( [
[ 'I18N blocks should not cross element boundaries' , '<!--' ] ,
[ 'Unclosed block' , '<!--' ] ,
] ) ;
} ) ;
} ) ;
describe ( 'implicit elements' , ( ) = > {
it ( 'should report nested implicit elements' , ( ) = > {
expect ( extractErrors ( ` <p><b></b></p> ` , [ 'p' , 'b' ] ) ) . toEqual ( [
[ 'Could not mark an element as translatable inside a translatable section' , '<b>' ] ,
] ) ;
} ) ;
it ( 'should report implicit element in translatable element' , ( ) = > {
expect ( extractErrors ( ` <p i18n><b></b></p> ` , [ 'b' ] ) ) . toEqual ( [
[ 'Could not mark an element as translatable inside a translatable section' , '<b>' ] ,
] ) ;
} ) ;
it ( 'should report implicit element in translatable blocks' , ( ) = > {
expect ( extractErrors ( ` <!-- i18n --><b></b><!-- /i18n --> ` , [ 'b' ] ) ) . toEqual ( [
[ 'Could not mark an element as translatable inside a translatable section' , '<b>' ] ,
] ) ;
2016-07-01 20:29:54 -04:00
} ) ;
} ) ;
2016-07-21 16:56:58 -04:00
} ) ;
} ) ;
2016-08-01 21:10:34 -04:00
describe ( 'Merger' , ( ) = > {
describe ( 'elements' , ( ) = > {
it ( 'should merge elements' , ( ) = > {
const HTML = ` <p i18n="m|d">foo</p> ` ;
2016-08-04 20:46:31 -04:00
expect ( fakeTranslate ( HTML ) ) . toEqual ( '<p>**foo**</p>' ) ;
2016-08-01 21:10:34 -04:00
} ) ;
it ( 'should merge nested elements' , ( ) = > {
const HTML = ` <div>before<p i18n="m|d">foo</p><!-- comment --></div> ` ;
2016-08-04 20:46:31 -04:00
expect ( fakeTranslate ( HTML ) ) . toEqual ( '<div>before<p>**foo**</p></div>' ) ;
2016-08-01 21:10:34 -04:00
} ) ;
} ) ;
describe ( 'blocks' , ( ) = > {
it ( 'should merge blocks' , ( ) = > {
const HTML = ` before<!-- i18n --><p>foo</p><span><i>bar</i></span><!-- /i18n -->after ` ;
2016-08-04 20:46:31 -04:00
expect ( fakeTranslate ( HTML ) )
. toEqual (
'before**<ph tag name="START_PARAGRAPH">foo</ph name="CLOSE_PARAGRAPH"><ph tag name="START_TAG_SPAN"><ph tag name="START_ITALIC_TEXT">bar</ph name="CLOSE_ITALIC_TEXT"></ph name="CLOSE_TAG_SPAN">**after' ) ;
2016-08-01 21:10:34 -04:00
} ) ;
it ( 'should merge nested blocks' , ( ) = > {
const HTML =
` <div>before<!-- i18n --><p>foo</p><span><i>bar</i></span><!-- /i18n -->after</div> ` ;
expect ( fakeTranslate ( HTML ) )
2016-08-04 20:46:31 -04:00
. toEqual (
'<div>before**<ph tag name="START_PARAGRAPH">foo</ph name="CLOSE_PARAGRAPH"><ph tag name="START_TAG_SPAN"><ph tag name="START_ITALIC_TEXT">bar</ph name="CLOSE_ITALIC_TEXT"></ph name="CLOSE_TAG_SPAN">**after</div>' ) ;
2016-08-01 21:10:34 -04:00
} ) ;
} ) ;
describe ( 'attributes' , ( ) = > {
it ( 'should merge attributes' , ( ) = > {
const HTML = ` <p i18n-title="m|d" title="foo"></p> ` ;
2016-08-04 20:46:31 -04:00
expect ( fakeTranslate ( HTML ) ) . toEqual ( '<p title="**foo**"></p>' ) ;
2016-08-01 21:10:34 -04:00
} ) ;
it ( 'should merge attributes' , ( ) = > {
const HTML = ` <div>{count, plural, =0 {<p i18n-title title="foo"></p>}}</div> ` ;
2016-08-04 20:46:31 -04:00
expect ( fakeTranslate ( HTML ) )
. toEqual ( '<div>{count, plural, =0 {<p title="**foo**"></p>}}</div>' ) ;
2016-08-01 21:10:34 -04:00
} ) ;
} ) ;
} ) ;
2016-07-01 20:29:54 -04:00
}
2016-07-08 19:46:49 -04:00
2016-08-01 21:10:34 -04:00
function parseHtml ( html : string ) : html . Node [ ] {
2016-07-08 19:46:49 -04:00
const htmlParser = new HtmlParser ( ) ;
const parseResult = htmlParser . parse ( html , 'extractor spec' , true ) ;
if ( parseResult . errors . length > 1 ) {
throw Error ( ` unexpected parse errors: ${ parseResult . errors . join ( '\n' ) } ` ) ;
}
2016-08-01 21:10:34 -04:00
return parseResult . rootNodes ;
}
function fakeTranslate (
content : string , implicitTags : string [ ] = [ ] ,
implicitAttrs : { [ k : string ] : string [ ] } = { } ) : string {
const htmlNodes : html.Node [ ] = parseHtml ( content ) ;
2016-08-04 20:46:31 -04:00
const messages : i18n.Message [ ] =
extractMessages ( htmlNodes , DEFAULT_INTERPOLATION_CONFIG , implicitTags , implicitAttrs )
. messages ;
2016-08-01 21:10:34 -04:00
const i18nMsgMap : { [ id : string ] : html . Node [ ] } = { } ;
2016-08-04 20:46:31 -04:00
messages . forEach ( msg = > {
const id = digestMessage ( msg . nodes , msg . meaning ) ;
const text = serializeI18nNodes ( msg . nodes ) . join ( '' ) ;
i18nMsgMap [ id ] = [ new html . Text ( ` ** ${ text } ** ` , null ) ] ;
2016-08-01 21:10:34 -04:00
} ) ;
const translations = new TranslationBundle ( i18nMsgMap ) ;
const translateNodes = mergeTranslations (
htmlNodes , translations , DEFAULT_INTERPOLATION_CONFIG , implicitTags , implicitAttrs ) ;
2016-07-08 19:46:49 -04:00
2016-08-04 20:46:31 -04:00
return serializeHtmlNodes ( translateNodes ) . join ( '' ) ;
2016-07-08 19:46:49 -04:00
}
function extract (
2016-07-21 16:56:58 -04:00
html : string , implicitTags : string [ ] = [ ] ,
implicitAttrs : { [ k : string ] : string [ ] } = { } ) : [ string [ ] , string , string ] [ ] {
2016-08-04 20:46:31 -04:00
const messages =
extractMessages ( parseHtml ( html ) , DEFAULT_INTERPOLATION_CONFIG , implicitTags , implicitAttrs )
. messages ;
2016-07-08 19:46:49 -04:00
// clang-format off
// https://github.com/angular/clang-format/issues/35
return messages . map (
2016-08-04 20:46:31 -04:00
message = > [ serializeI18nNodes ( message . nodes ) , message . meaning , message . description , ] ) as [ string [ ] , string , string ] [ ] ;
2016-07-08 19:46:49 -04:00
// clang-format on
}
function extractErrors (
2016-07-21 16:56:58 -04:00
html : string , implicitTags : string [ ] = [ ] , implicitAttrs : { [ k : string ] : string [ ] } = { } ) : any [ ] {
2016-08-04 20:46:31 -04:00
const errors =
extractMessages ( parseHtml ( html ) , DEFAULT_INTERPOLATION_CONFIG , implicitTags , implicitAttrs )
. errors ;
2016-07-08 19:46:49 -04:00
return errors . map ( ( e ) : [ string , string ] = > [ e . msg , e . span . toString ( ) ] ) ;
}