diff --git a/src/index.ts b/src/index.ts index 235fe88..6d5ecae 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import type {TruncationOptions, WidthOptions, Result} from './types'; /* HELPERS */ const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/y; +const ANSI_URL_RE = /\u001b\]8;[^;]*;.+(?:\u0007|\u001b\u005c)(.+)\u001b\]8;;(?:\u0007|\u001b\u005c)/y; const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y; const CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu; const TAB_RE = /\t{1,1000}/y; @@ -36,6 +37,7 @@ const getStringTruncatedWidth = ( input: string, truncationOptions: TruncationOp const PARSE_BLOCKS: [RegExp, number][] = [ [LATIN_RE, REGULAR_WIDTH], + [ANSI_URL_RE, REGULAR_WIDTH], [ANSI_RE, ANSI_WIDTH], [CONTROL_RE, CONTROL_WIDTH], [TAB_RE, TAB_WIDTH], @@ -114,9 +116,18 @@ const getStringTruncatedWidth = ( input: string, truncationOptions: TruncationOp BLOCK_RE.lastIndex = index; - if ( BLOCK_RE.test ( input ) ) { + const reResult = BLOCK_RE.exec ( input ); + + if ( reResult !== null ) { + + if ( BLOCK_RE === EMOJI_RE ) { + lengthExtra = 1; + } else if ( BLOCK_RE === ANSI_URL_RE ) { + lengthExtra = reResult[1].length; + } else { + lengthExtra = BLOCK_RE.lastIndex - index; + } - lengthExtra = BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index; widthExtra = lengthExtra * BLOCK_WIDTH; if ( ( width + widthExtra ) > truncationLimit ) { diff --git a/test/index.js b/test/index.js index db473c7..0303f4e 100644 --- a/test/index.js +++ b/test/index.js @@ -185,6 +185,14 @@ describe ( 'Fast String Width', () => { }); + it ( 'supports hyperlink sequences', t => { + + t.is ( getWidth ( '\x1b]8;;https://github.com\u0007Click\x1b]8;;\u0007' ), 5 ); + t.is ( getWidth ( 'twelve chars\x1b]8;;https://github.com\u0007Click\x1b]8;;\u0007twelve chars' ), 24 + 5 ); + t.is ( getWidth ( '\x1b]8;;https://github.com\x1b\x5cClick\x1b]8;;\x1b\x5c' ), 5 ); + + }); + }); describe ( 'truncating a string', it => {