import markdownit from 'markdown-it' ; import { MailSettings } from '@proton/shared/lib/interfaces' ; import { defaultFontStyle } from '@proton/components/components/editor/squireConfig' ; import { templateBuilder } from './message/messageSignature' ; import { toText } from './parserHtml' ; const SIGNATURE_PLACEHOLDER = '--protonSignature--' ; const OPTIONS = { breaks : true , linkify : true , } ; const md = markdownit ( 'default' , OPTIONS ) ; param text returns { string } const generatePlaceHolder = ( text ) => { let placeholder = '' ; do { placeholder = Math . random ( ) . toString ( 36 ) . substring ( 3 ) + Math . random ( ) . toString ( 36 ) . substring ( 3 ) ; } while ( text . includes ( placeholder ) ) ; return placeholder ; } ; /**
 * Fills a given text with newlines with placeholders that can be removed later.
 * For instance the following input:
 * "
 *
 *
 * "
 * is turned into
 * "
 * placeholder
 * "
 * The input is not turned into
 * "placeholder
 * placeholder
 * placeholder"
 * as we expect the first new line to come from an non empty new line, and the last new line is followed by a non
 * empty new line. This is how addNewLinePlaceholders uses this function.
 */ const newLineIntoPlaceholder = ( match , placeholder ) => match . replace ( /(\r\n|\n)/g , ( match ) => match + placeholder ) . replace ( new RegExp ( `${ placeholder }$` , 'g' ) , '' ) ; /**
 * Turns any empty lines into lines filled with the specified placeholder
 * to trick the markdown converter into keeping
 * those empty lines.
 */ const addNewLinePlaceholders = ( text , placeholder ) => { const startingNewline = text . startsWith ( '\n' ) ? text : `\n${ text }` ; const textWPlaceholder = startingNewline . replace ( /((\r\n|\n)\s*(\r\n|\n))+/g , ( match ) => newLineIntoPlaceholder ( match , placeholder ) ) ; const noEmptyLines = textWPlaceholder . replace ( /^\n/g , '' ) ; return noEmptyLines . replace ( /(>[^\r\n]*(?:\r\n|\n))(\s*[^>])/g , ( match , line1 , line2 ) => `${ line1 }\n${ line2 }` ) ; } ; const removeNewLinePlaceholder = ( html , placeholder ) => html . replace ( new RegExp ( placeholder , 'g' ) , '' ) ; /**
 * Escapes backslashes from the input text with another backslash.
 */ const escapeBackslash = ( text = '' ) => text . replace ( /\\/g , '\\\\' ) ; /**
 * Replace the signature by a temp hash, we replace it only
 * if the content is the same.
 */ const replaceSignature = ( input , signature , mailSettings ) => { const fontStyle = defaultFontStyle ( mailSettings ) ; const signatureTemplate = templateBuilder ( signature , mailSettings , fontStyle , false , true ) ; const signatureText = toText ( signatureTemplate ) . replace ( /\u200B/g , '' ) . trim ( ) ; return input . replace ( signatureText , SIGNATURE_PLACEHOLDER ) ; } ; /**
 * Replace the hash by the signature inside the message formated as HTML
 * We prevent too many lines to be added as we already have a correct message
 */ const attachSignature = ( input , signature , plaintext , mailSettings ) => { const fontStyle = defaultFontStyle ( mailSettings ) ; const signatureTemplate = templateBuilder ( signature , mailSettings , fontStyle , false , ! plaintext . startsWith ( SIGNATURE_PLACEHOLDER ) ) ; return input . replace ( SIGNATURE_PLACEHOLDER , signatureTemplate ) ; } ; export const textToHtml = ( input = '' , signature , mailSettings ) => { const text = replaceSignature ( input , signature , mailSettings ) ; const placeholder = generatePlaceHolder ( text ) ; const withPlaceholder = addNewLinePlaceholders ( escapeBackslash ( text ) , placeholder ) ; const rendered = md . render ( withPlaceholder ) ; const html = removeNewLinePlaceholder ( rendered , placeholder ) ; const withSignature = attachSignature ( html , signature , text , mailSettings ) ; const result = /^<p>([\s\S]*)<\/p>$/gm . exec ( withSignature ) ?. [ 1 ] || withSignature ; return result ; } ;