@@ -13,14 +13,10 @@ type ProviderTextFormat = 'plain' | 'escaped' | 'html' | 'auto'
1313 * followed by a pictograph is kept because it composes a single emoji. The combining grapheme
1414 * joiner is its own alternative because it cannot share a character class with base characters.
1515 */
16- const INVISIBLE_CHARACTERS = new RegExp (
17- [
18- '[\\u00AD\\u061C\\u115F\\u1160\\u17B4\\u17B5\\u180E\\u200B\\u200C\\u200E\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u206F\\u3164\\uFEFF\\uFFA0]' ,
19- '\\u034F' ,
20- '\\u200D(?!\\p{Extended_Pictographic})' ,
21- ] . join ( '|' ) ,
22- 'gu'
23- )
16+ const INVISIBLE_CHARACTER =
17+ '[\\u00AD\\u061C\\u115F\\u1160\\u17B4\\u17B5\\u180E\\u200B\\u200C\\u200E\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u206F\\u3164\\uFEFF\\uFFA0]|\\u034F|\\u200D(?!\\p{Extended_Pictographic})'
18+ /** A run of invisible characters with the spaces between them, as preheader padding is built. */
19+ const INVISIBLE_RUN = new RegExp ( `(?:[^\\S\\n]*(?:${ INVISIBLE_CHARACTER } ))+[^\\S\\n]*` , 'gu' )
2420
2521/** Markup becomes text only: links keep their visible text, and non-text elements are dropped. */
2622const HTML_TO_TEXT : HtmlToTextOptions = {
@@ -48,10 +44,11 @@ export function providerText(value: string, format: ProviderTextFormat = 'plain'
4844 } else if ( format === 'escaped' ) {
4945 text = decodeHtmlEntities ( text )
5046 }
47+ /** Padding collapses to one space, or to nothing inside a word; other spacing is kept. */
48+ text = text . replace ( INVISIBLE_RUN , ( run ) => ( / \s / . test ( run ) ? ' ' : '' ) )
49+ if ( format === 'escaped' ) return text . replace ( / \s + / g, ' ' ) . trim ( )
5150 return text
52- . replace ( INVISIBLE_CHARACTERS , '' )
53- . replace ( / [ ^ \S \n ] + / g, ' ' )
54- . replace ( / * \n * / g, '\n' )
51+ . replace ( / [ ^ \S \n ] + $ / gm, '' )
5552 . replace ( / \n { 3 , } / g, '\n\n' )
56- . trim ( )
53+ . replace ( / ^ \n + | \n + $ / g , '' )
5754}
0 commit comments