license import { Element , LexerRange , Node , ParseError , ParseErrorLevel , ParseSourceSpan , XmlParser , } from '@angular/compiler' ; import { ParseAnalysis } from './translation_parser' ; import { Diagnostics } from '../../common/diagnostics' ; import { TranslationParseError } from './translation_parse_error' ; export function getAttrOrThrow ( element , attrName ) { const attrValue = getAttribute ( element , attrName ) ; if ( attrValue === undefined ) { throw new TranslationParseError ( element . sourceSpan , `Missing required "${ attrName }" attribute:` ) ; } return attrValue ; } export function getAttribute ( element , attrName ) { const attr = element . attrs . find ( ( a ) => a . name === attrName ) ; return attr !== undefined ? attr . value : undefined ; } export function parseInnerRange ( element ) { const xmlParser = new XmlParser ( ) ; const xml = xmlParser . parse ( element . sourceSpan . start . file . content , element . sourceSpan . start . file . url , { tokenizeExpansionForms : true , range : getInnerRange ( element ) } ) ; if ( xml . errors . length ) { throw xml . errors . map ( ( e ) => new TranslationParseError ( e . span , e . msg ) . toString ( ) ) . join ( '\n' ) ; } return xml . rootNodes ; } function getInnerRange ( element ) { const start = element . startSourceSpan ! . end ; const end = element . endSourceSpan ! . start ; return { startPos : start . offset , startLine : start . line , startCol : start . col , endPos : end . offset , } ; } param name export function isNamedElement ( name ) { function predicate ( node ) { return node instanceof Element && node . name === name ; } return predicate ; } /**
 * This "hint" object is used to pass information from `canParse()` to `parse()` for
 * `TranslationParser`s that expect XML contents.
 *
 * This saves the `parse()` method from having to re-parse the XML.
 */ export interface XmlTranslationParserHint { element : Element ; errors : ParseError [ ] ; } param filePath param contents param rootNodeName param attributes returns export function canParseXml ( filePath , contents , rootNodeName , attributes ) { const diagnostics = new Diagnostics ( ) ; const xmlParser = new XmlParser ( ) ; const xml = xmlParser . parse ( contents , filePath ) ; if ( xml . rootNodes . length === 0 || xml . errors . some ( ( error ) => error . level === ParseErrorLevel . ERROR ) ) { xml . errors . forEach ( ( e ) => addParseError ( diagnostics , e ) ) ; return { canParse : false , diagnostics } ; } const rootElements = xml . rootNodes . filter ( isNamedElement ( rootNodeName ) ) ; const rootElement = rootElements [ 0 ] ; if ( rootElement === undefined ) { diagnostics . warn ( `The XML file does not contain a <${ rootNodeName }> root node.` ) ; return { canParse : false , diagnostics } ; } for ( const attrKey of Object . keys ( attributes ) ) { const attr = rootElement . attrs . find ( ( at ) => at . name === attrKey ) ; if ( attr === undefined || attr . value !== attributes [ attrKey ] ) { addParseDiagnostic ( diagnostics , rootElement . sourceSpan , `The <${ rootNodeName }> node does not have the required attribute: ${ attrKey }="${ attributes [ attrKey ] }".` , ParseErrorLevel . WARNING ) ; return { canParse : false , diagnostics } ; } } if ( rootElements . length > 1 ) { xml . errors . push ( new ParseError ( xml . rootNodes [ 1 ] . sourceSpan , 'Unexpected root node. XLIFF 1.2 files should only have a single <xliff> root node.' , ParseErrorLevel . WARNING ) ) ; } return { canParse : true , diagnostics , hint : { element : rootElement , errors : xml . errors } , } ; } /**
 * Add an XML parser related message to the given `diagnostics` object.
 */ export function addParseDiagnostic ( diagnostics , sourceSpan , message , level ) { addParseError ( diagnostics , new ParseError ( sourceSpan , message , level ) ) ; } /**
 * Copy the formatted error message from the given `parseError` object into the given `diagnostics`
 * object.
 */ export function addParseError ( diagnostics , parseError ) { if ( parseError . level === ParseErrorLevel . ERROR ) { diagnostics . error ( parseError . toString ( ) ) ; } else { diagnostics . warn ( parseError . toString ( ) ) ; } }