import type { parse } from "fenceparser" ; export type Meta = NonNullable < ReturnType < typeof parse > > ; type Range = { begin : number ; end : number ; text ? : string ; count ? : number ; tooltip ? : string [ ] ; classes ? : string ; lsp ? : string ; } ; /**
 * We're given the text which lives inside the token, and this function will
 * annotate it with twoslash metadata
 */ export function createHighlightedString ( ranges , text , targetedWord = "" ) { const tag = ( x ) => `⇍${ x }⇏` ; const makeTagFromRange = ( r , close ? ) => { switch ( r . classes ) { case "lsp" : const lsp = htmlAttrReplacer ( r . lsp || "" ) ; const underLineTargetedWord = r . lsp === targetedWord ? "style=⇯border-bottom: solid 2px lightgrey;⇯" : "" ; return close ? tag ( "/data-lsp" ) : tag ( `data-lsp lsp=¿${ lsp }¿ ${ underLineTargetedWord }` ) ; case "query" : return tag ( `${ close ? "/" : "" }data-highlight` ) ; case "err" : default : return tag ( `${ close ? "/" : "" }data-err` ) ; } } ; ranges . sort ( ( a , b ) => { const precedenceOf = ( x ? ) => [ "err" , "query" , "lsp" ] . indexOf ( x ?? "" ) ; let cmp = 0 ; /***1*/ ! ( cmp = a . begin - b . begin ) && ! ( cmp = b . end - a . end ) && ! ( cmp = precedenceOf ( a . classes ) - precedenceOf ( b . classes ) ) ; return cmp ; } ) ; let cursor = 0 ; const nest = ( data ) => { let stack = "" ; const top = data . shift ( ) ! ; stack += text . substring ( cursor , top . begin ) ; cursor = top . begin ; stack += makeTagFromRange ( top ) ; if ( data . some ( x => x . begin < top . end ) ) { stack += nest ( data ) ; } else { stack += text . substring ( top . begin , top . end ) ; cursor = top . end ; } stack += makeTagFromRange ( top , true ) ; if ( data . length !== 0 ) { stack += nest ( data ) ; } return stack ; } ; const data = JSON . parse ( JSON . stringify ( ranges ) ) ; const html = nest ( data ) + text . substring ( cursor ) ; return htmlAttrUnReplacer ( replaceTripleArrow ( stripHTML ( html ) ) ) ; } const htmlAttrReplacer = ( str ) => str . replace ( /"/g , "⃟" ) ; const htmlAttrUnReplacer = ( str ) => str . replace ( /⃟/g , '"' ) ; export const subTripleArrow = ( str ) => str . replace ( /</g , "⇍" ) . replace ( />/g , "⇏" ) . replace ( /'/g , "⇯" ) ; export const replaceTripleArrow = ( str ) => str . replace ( /⇍/g , "<" ) . replace ( /⇏/g , ">" ) . replace ( /⇯/g , "'" ) . replace ( /¿/g , "'" ) ; export const replaceTripleArrowEncoded = ( str ) => str . replace ( /⇍/g , "&lt;" ) . replace ( /⇏/g , "&gt;" ) . replace ( /⇯/g , "&apos;" ) ; export function stripHTML ( text ) { var table = { "<" : "lt" , '"' : "quot" , "'" : "apos" , "&" : "amp" , "\r" : "#13" , "\n" : "#10" , } ; return text . toString ( ) . replace ( /[<"'\r\n&]/g , function ( chr ) { return "&" + table [ chr ] + ";" ; } ) ; } export function escapeHtml ( html ) { return html . replace ( /</g , "&lt;" ) . replace ( />/g , "&gt;" ) ; } /** Does anything in the object imply that we should highlight any lines? */ export const shouldBeHighlightable = ( highlight ) => { return ! ! Object . keys ( highlight || { } ) . find ( key => { if ( key . includes ( "-" ) ) return true ; if ( ! isNaN ( parseInt ( key ) ) ) return true ; return false ; } ) ; } ; /** Returns a func for figuring out if this line should be highlighted */ export const shouldHighlightLine = ( highlight ) => { const lines = [ ] ; Object . keys ( highlight || { } ) . find ( key => { if ( ! isNaN ( parseInt ( key ) ) ) lines . push ( parseInt ( key ) ) ; if ( key . includes ( "-" ) ) { const [ first , last ] = key . split ( "-" ) ; const lastIndex = parseInt ( last ) + 1 ; for ( let i = parseInt ( first ) ; i < lastIndex ; i ++ ) { lines . push ( i ) ; } } } ) ; return ( line ) => lines . includes ( line ) ; } ;