import parse5 , { Node , TextNode , ParentNode , ChildNode , Element , DocumentFragment , } from "parse5" ; import { ensureArray } from "./misc" ; export interface Attrs { [ name ] : string ; } export interface VElement { name : string ; attrs : Attrs ; childNodes : ( VNode | string ) [ ] ; } export type VTextNode = string ; export type VNode = VElement | VTextNode | undefined ; const extractTextFromNode = ( node ) : string => node . nodeName === "#text" ? ( < TextNode > node ) . value : ( ( < any > node ) . childNodes || [ ] ) . reduce ( ( memo , node ) => memo + extractTextFromNode ( node ) , "" ) + ( node . nodeName === "p" ? "\n" : "" ) ; export const extractText = ( html ) : string => extractTextFromNode ( < DocumentFragment > parse5 . parseFragment ( html ) ) . replace ( /[\x00-\x09\x0b-\x1f\x7f]/g , "" ) ; export const createElement = ( name , attrs = { } , childNodes = [ ] ) => ( { name , attrs , childNodes , } ) ; const toFragment = ( nodes ) : DocumentFragment => { const result = { nodeName : "#document-fragment" , childNodes : [ ] , } ; for ( const childVNode of ensureArray ( nodes ) ) { const childNode = toFragmentNode ( childVNode , result ) ; if ( childNode ) { result . childNodes . push ( childNode ) ; } } return result ; } ; const toFragmentNode = ( node , parentNode ) : ChildNode | undefined => { if ( node === undefined ) { return undefined ; } else if ( typeof node === "string" ) { const result = { nodeName : "#text" , value : node , parentNode , } ; return result ; } else { const result = { nodeName : node . name , tagName : node . name , namespaceURI : "" , attrs : [ ] , parentNode , childNodes : [ ] , } ; result . attrs = Object . entries ( node . attrs ) . map ( ( [ name , value ] ) => ( { name , value : typeof value === "string" ? value : "" , } ) ) ; for ( const childVNode of ensureArray ( node . childNodes ) ) { const childNode = toFragmentNode ( childVNode , result ) ; if ( childNode ) { result . childNodes . push ( childNode ) ; } } return result ; } } ; export const render = ( nodes ) : string => parse5 . serialize ( toFragment ( nodes ) ) ; const h = createElement ; export const createMention = ( id , name ) : VNode => h ( "span" , { class : "h-card" } , [ h ( "a" , { class : "u-url mention" , href : id } , [ "@" , h ( "span" , { class : "p-nickname" } , [ `${ name || "???" }` ] ) , ] ) , ] ) ;