import { IParsedObjects , IImageObject , ILinkedItemContentObject , ILinkObject , ParsedItemIndexReferenceWrapper , IParser , IParseResolvers , IParserResult } from '../parse-models' ; import { parserConfiguration } from '../parser-configuration' ; import { ContentItemType , IContentItem } from '../../models' ; import { parserHelper } from '../parser.helper' ; import { Elements } from '../../elements' ; export class BrowserParser implements IParser < string > { parse ( html , mainRichTextElement , resolvers , linkedItems ) { return this . parseInternal ( mainRichTextElement , resolvers , html , linkedItems , new ParsedItemIndexReferenceWrapper ( 0 ) , null ) ; } private parseInternal ( mainRichTextElement , resolvers , html , linkedItems , linkedItemIndex , parentElement ) { const rootElement = this . createWrapperElement ( html ) ; const result = this . processRichTextElement ( mainRichTextElement , resolvers , rootElement . children , { links : [ ] , linkedItems : [ ] , images : [ ] } , linkedItems , linkedItemIndex , parentElement ) ; return { componentCodenames : result . linkedItems . filter ( ( m ) => m . itemType === 'component' ) . map ( ( m ) => m . dataCodename ) , linkedItemCodenames : result . linkedItems . filter ( ( m ) => m . itemType === 'linkedItem' ) . map ( ( m ) => m . dataCodename ) , result : rootElement . innerHTML } ; } private processRichTextElement ( mainRichTextElement , resolvers , htmlCollection , result , linkedItems , linkedItemIndex , parentElement ) { if ( ! htmlCollection || htmlCollection . length === 0 ) { } else { for ( let i = 0 ; i < htmlCollection . length ; i ++ ) { const element = htmlCollection [ i ] ; resolvers . elementResolver ( parserHelper . convertToParserElement ( element ) ) ; const typeAttribute = element . attributes ? element . attributes . getNamedItem ( 'type' ) : undefined ; if ( element . attributes && typeAttribute && typeAttribute . value && typeAttribute . value . toLowerCase ( ) === parserConfiguration . modularContentElementData . type . toLowerCase ( ) ) { const dataCodenameAttribute = element . attributes . getNamedItem ( parserConfiguration . modularContentElementData . dataCodename ) ; const dataTypeAttribute = element . attributes . getNamedItem ( parserConfiguration . modularContentElementData . dataType ) ; if ( ! dataTypeAttribute ) { throw Error ( 'Missing data type attribute. This is likely an error caused by invalid response.' ) ; } const relAttribute = element . attributes . getNamedItem ( parserConfiguration . modularContentElementData . relAttribute ) ; let itemType = 'linkedItem' ; if ( relAttribute && relAttribute . value === parserConfiguration . modularContentElementData . componentRel ) { itemType = 'component' ; } const linkItemContentObject = { dataCodename : dataCodenameAttribute ? dataCodenameAttribute . value : '' , dataType : dataTypeAttribute ? dataTypeAttribute . value : '' , itemType : itemType } ; const elementParent = element . parentElement ; if ( ! elementParent ) { console . warn ( `Could not replace linked item '${ linkItemContentObject . dataCodename }' of '${ linkItemContentObject . dataType }' because parent node is undefined. Please report this error if you are seeing this.` ) ; } else { if ( dataTypeAttribute . value === 'item' ) { result . linkedItems . push ( linkItemContentObject ) ; resolvers . contentItemResolver ( parserHelper . convertToParserElement ( element ) , linkItemContentObject . dataCodename , linkedItemIndex . index , parserHelper . getLinkedItem ( linkedItems , linkItemContentObject . dataCodename ) ) ; linkedItemIndex . increment ( ) ; } else { console . warn ( `Rich text element contains object with unsupported data type '${ dataTypeAttribute . value }'` ) ; } } } else if ( element . nodeName . toLowerCase ( ) === parserConfiguration . linkElementData . nodeName . toLowerCase ( ) ) { const dataItemIdAttribute = element . attributes . getNamedItem ( parserConfiguration . linkElementData . dataItemId ) ; if ( dataItemIdAttribute ) { const linkObject = { dataItemId : dataItemIdAttribute ? dataItemIdAttribute . value : '' } ; result . links . push ( linkObject ) ; const linkText = element . innerHTML ; resolvers . urlResolver ( parserHelper . convertToParserElement ( element ) , linkObject . dataItemId , linkText , parserHelper . tryGetLink ( mainRichTextElement , linkedItems , linkObject . dataItemId ) ) ; } } else if ( element . nodeName . toLowerCase ( ) === parserConfiguration . imageElementData . nodeName . toLowerCase ( ) ) { const dataImageIdAttribute = element . attributes . getNamedItem ( parserConfiguration . imageElementData . dataImageId ) ; if ( dataImageIdAttribute ) { const imageObj = { imageId : dataImageIdAttribute . value } ; result . images . push ( imageObj ) ; resolvers . imageResolver ( parserHelper . convertToParserElement ( element ) , imageObj . imageId , parserHelper . tryGetImage ( mainRichTextElement , linkedItems , imageObj . imageId ) ) ; } } else { resolvers . genericElementResolver ( parserHelper . convertToParserElement ( element ) ) ; } if ( element . children && element . children . length > 0 ) { this . processRichTextElement ( mainRichTextElement , resolvers , element . children , result , linkedItems , linkedItemIndex , parentElement ) ; } } } return result ; } private createWrapperElement ( html ) { const element = document . createElement ( parserConfiguration . linkedItemWrapperElem ) ; element . innerHTML = html ; return element ; } } export const browserParser = new BrowserParser ( ) ;