11cb0ef41Sopenharmony_ciconst stringWidth = require('string-width'); 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_cifunction codeRegex(capture) { 41cb0ef41Sopenharmony_ci return capture ? /\u001b\[((?:\d*;){0,5}\d*)m/g : /\u001b\[(?:\d*;){0,5}\d*m/g; 51cb0ef41Sopenharmony_ci} 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cifunction strlen(str) { 81cb0ef41Sopenharmony_ci let code = codeRegex(); 91cb0ef41Sopenharmony_ci let stripped = ('' + str).replace(code, ''); 101cb0ef41Sopenharmony_ci let split = stripped.split('\n'); 111cb0ef41Sopenharmony_ci return split.reduce(function (memo, s) { 121cb0ef41Sopenharmony_ci return stringWidth(s) > memo ? stringWidth(s) : memo; 131cb0ef41Sopenharmony_ci }, 0); 141cb0ef41Sopenharmony_ci} 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cifunction repeat(str, times) { 171cb0ef41Sopenharmony_ci return Array(times + 1).join(str); 181cb0ef41Sopenharmony_ci} 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cifunction pad(str, len, pad, dir) { 211cb0ef41Sopenharmony_ci let length = strlen(str); 221cb0ef41Sopenharmony_ci if (len + 1 >= length) { 231cb0ef41Sopenharmony_ci let padlen = len - length; 241cb0ef41Sopenharmony_ci switch (dir) { 251cb0ef41Sopenharmony_ci case 'right': { 261cb0ef41Sopenharmony_ci str = repeat(pad, padlen) + str; 271cb0ef41Sopenharmony_ci break; 281cb0ef41Sopenharmony_ci } 291cb0ef41Sopenharmony_ci case 'center': { 301cb0ef41Sopenharmony_ci let right = Math.ceil(padlen / 2); 311cb0ef41Sopenharmony_ci let left = padlen - right; 321cb0ef41Sopenharmony_ci str = repeat(pad, left) + str + repeat(pad, right); 331cb0ef41Sopenharmony_ci break; 341cb0ef41Sopenharmony_ci } 351cb0ef41Sopenharmony_ci default: { 361cb0ef41Sopenharmony_ci str = str + repeat(pad, padlen); 371cb0ef41Sopenharmony_ci break; 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci } 411cb0ef41Sopenharmony_ci return str; 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cilet codeCache = {}; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_cifunction addToCodeCache(name, on, off) { 471cb0ef41Sopenharmony_ci on = '\u001b[' + on + 'm'; 481cb0ef41Sopenharmony_ci off = '\u001b[' + off + 'm'; 491cb0ef41Sopenharmony_ci codeCache[on] = { set: name, to: true }; 501cb0ef41Sopenharmony_ci codeCache[off] = { set: name, to: false }; 511cb0ef41Sopenharmony_ci codeCache[name] = { on: on, off: off }; 521cb0ef41Sopenharmony_ci} 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci//https://github.com/Marak/colors.js/blob/master/lib/styles.js 551cb0ef41Sopenharmony_ciaddToCodeCache('bold', 1, 22); 561cb0ef41Sopenharmony_ciaddToCodeCache('italics', 3, 23); 571cb0ef41Sopenharmony_ciaddToCodeCache('underline', 4, 24); 581cb0ef41Sopenharmony_ciaddToCodeCache('inverse', 7, 27); 591cb0ef41Sopenharmony_ciaddToCodeCache('strikethrough', 9, 29); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_cifunction updateState(state, controlChars) { 621cb0ef41Sopenharmony_ci let controlCode = controlChars[1] ? parseInt(controlChars[1].split(';')[0]) : 0; 631cb0ef41Sopenharmony_ci if ((controlCode >= 30 && controlCode <= 39) || (controlCode >= 90 && controlCode <= 97)) { 641cb0ef41Sopenharmony_ci state.lastForegroundAdded = controlChars[0]; 651cb0ef41Sopenharmony_ci return; 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci if ((controlCode >= 40 && controlCode <= 49) || (controlCode >= 100 && controlCode <= 107)) { 681cb0ef41Sopenharmony_ci state.lastBackgroundAdded = controlChars[0]; 691cb0ef41Sopenharmony_ci return; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci if (controlCode === 0) { 721cb0ef41Sopenharmony_ci for (let i in state) { 731cb0ef41Sopenharmony_ci /* istanbul ignore else */ 741cb0ef41Sopenharmony_ci if (Object.prototype.hasOwnProperty.call(state, i)) { 751cb0ef41Sopenharmony_ci delete state[i]; 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci return; 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci let info = codeCache[controlChars[0]]; 811cb0ef41Sopenharmony_ci if (info) { 821cb0ef41Sopenharmony_ci state[info.set] = info.to; 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci} 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cifunction readState(line) { 871cb0ef41Sopenharmony_ci let code = codeRegex(true); 881cb0ef41Sopenharmony_ci let controlChars = code.exec(line); 891cb0ef41Sopenharmony_ci let state = {}; 901cb0ef41Sopenharmony_ci while (controlChars !== null) { 911cb0ef41Sopenharmony_ci updateState(state, controlChars); 921cb0ef41Sopenharmony_ci controlChars = code.exec(line); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci return state; 951cb0ef41Sopenharmony_ci} 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_cifunction unwindState(state, ret) { 981cb0ef41Sopenharmony_ci let lastBackgroundAdded = state.lastBackgroundAdded; 991cb0ef41Sopenharmony_ci let lastForegroundAdded = state.lastForegroundAdded; 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci delete state.lastBackgroundAdded; 1021cb0ef41Sopenharmony_ci delete state.lastForegroundAdded; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci Object.keys(state).forEach(function (key) { 1051cb0ef41Sopenharmony_ci if (state[key]) { 1061cb0ef41Sopenharmony_ci ret += codeCache[key].off; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci }); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { 1111cb0ef41Sopenharmony_ci ret += '\u001b[49m'; 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { 1141cb0ef41Sopenharmony_ci ret += '\u001b[39m'; 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci return ret; 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_cifunction rewindState(state, ret) { 1211cb0ef41Sopenharmony_ci let lastBackgroundAdded = state.lastBackgroundAdded; 1221cb0ef41Sopenharmony_ci let lastForegroundAdded = state.lastForegroundAdded; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci delete state.lastBackgroundAdded; 1251cb0ef41Sopenharmony_ci delete state.lastForegroundAdded; 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci Object.keys(state).forEach(function (key) { 1281cb0ef41Sopenharmony_ci if (state[key]) { 1291cb0ef41Sopenharmony_ci ret = codeCache[key].on + ret; 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci }); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { 1341cb0ef41Sopenharmony_ci ret = lastBackgroundAdded + ret; 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { 1371cb0ef41Sopenharmony_ci ret = lastForegroundAdded + ret; 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci return ret; 1411cb0ef41Sopenharmony_ci} 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_cifunction truncateWidth(str, desiredLength) { 1441cb0ef41Sopenharmony_ci if (str.length === strlen(str)) { 1451cb0ef41Sopenharmony_ci return str.substr(0, desiredLength); 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci while (strlen(str) > desiredLength) { 1491cb0ef41Sopenharmony_ci str = str.slice(0, -1); 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci return str; 1531cb0ef41Sopenharmony_ci} 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_cifunction truncateWidthWithAnsi(str, desiredLength) { 1561cb0ef41Sopenharmony_ci let code = codeRegex(true); 1571cb0ef41Sopenharmony_ci let split = str.split(codeRegex()); 1581cb0ef41Sopenharmony_ci let splitIndex = 0; 1591cb0ef41Sopenharmony_ci let retLen = 0; 1601cb0ef41Sopenharmony_ci let ret = ''; 1611cb0ef41Sopenharmony_ci let myArray; 1621cb0ef41Sopenharmony_ci let state = {}; 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci while (retLen < desiredLength) { 1651cb0ef41Sopenharmony_ci myArray = code.exec(str); 1661cb0ef41Sopenharmony_ci let toAdd = split[splitIndex]; 1671cb0ef41Sopenharmony_ci splitIndex++; 1681cb0ef41Sopenharmony_ci if (retLen + strlen(toAdd) > desiredLength) { 1691cb0ef41Sopenharmony_ci toAdd = truncateWidth(toAdd, desiredLength - retLen); 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci ret += toAdd; 1721cb0ef41Sopenharmony_ci retLen += strlen(toAdd); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci if (retLen < desiredLength) { 1751cb0ef41Sopenharmony_ci if (!myArray) { 1761cb0ef41Sopenharmony_ci break; 1771cb0ef41Sopenharmony_ci } // full-width chars may cause a whitespace which cannot be filled 1781cb0ef41Sopenharmony_ci ret += myArray[0]; 1791cb0ef41Sopenharmony_ci updateState(state, myArray); 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci return unwindState(state, ret); 1841cb0ef41Sopenharmony_ci} 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_cifunction truncate(str, desiredLength, truncateChar) { 1871cb0ef41Sopenharmony_ci truncateChar = truncateChar || '…'; 1881cb0ef41Sopenharmony_ci let lengthOfStr = strlen(str); 1891cb0ef41Sopenharmony_ci if (lengthOfStr <= desiredLength) { 1901cb0ef41Sopenharmony_ci return str; 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci desiredLength -= strlen(truncateChar); 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci let ret = truncateWidthWithAnsi(str, desiredLength); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci return ret + truncateChar; 1971cb0ef41Sopenharmony_ci} 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_cifunction defaultOptions() { 2001cb0ef41Sopenharmony_ci return { 2011cb0ef41Sopenharmony_ci chars: { 2021cb0ef41Sopenharmony_ci top: '─', 2031cb0ef41Sopenharmony_ci 'top-mid': '┬', 2041cb0ef41Sopenharmony_ci 'top-left': '┌', 2051cb0ef41Sopenharmony_ci 'top-right': '┐', 2061cb0ef41Sopenharmony_ci bottom: '─', 2071cb0ef41Sopenharmony_ci 'bottom-mid': '┴', 2081cb0ef41Sopenharmony_ci 'bottom-left': '└', 2091cb0ef41Sopenharmony_ci 'bottom-right': '┘', 2101cb0ef41Sopenharmony_ci left: '│', 2111cb0ef41Sopenharmony_ci 'left-mid': '├', 2121cb0ef41Sopenharmony_ci mid: '─', 2131cb0ef41Sopenharmony_ci 'mid-mid': '┼', 2141cb0ef41Sopenharmony_ci right: '│', 2151cb0ef41Sopenharmony_ci 'right-mid': '┤', 2161cb0ef41Sopenharmony_ci middle: '│', 2171cb0ef41Sopenharmony_ci }, 2181cb0ef41Sopenharmony_ci truncate: '…', 2191cb0ef41Sopenharmony_ci colWidths: [], 2201cb0ef41Sopenharmony_ci rowHeights: [], 2211cb0ef41Sopenharmony_ci colAligns: [], 2221cb0ef41Sopenharmony_ci rowAligns: [], 2231cb0ef41Sopenharmony_ci style: { 2241cb0ef41Sopenharmony_ci 'padding-left': 1, 2251cb0ef41Sopenharmony_ci 'padding-right': 1, 2261cb0ef41Sopenharmony_ci head: ['red'], 2271cb0ef41Sopenharmony_ci border: ['grey'], 2281cb0ef41Sopenharmony_ci compact: false, 2291cb0ef41Sopenharmony_ci }, 2301cb0ef41Sopenharmony_ci head: [], 2311cb0ef41Sopenharmony_ci }; 2321cb0ef41Sopenharmony_ci} 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_cifunction mergeOptions(options, defaults) { 2351cb0ef41Sopenharmony_ci options = options || {}; 2361cb0ef41Sopenharmony_ci defaults = defaults || defaultOptions(); 2371cb0ef41Sopenharmony_ci let ret = Object.assign({}, defaults, options); 2381cb0ef41Sopenharmony_ci ret.chars = Object.assign({}, defaults.chars, options.chars); 2391cb0ef41Sopenharmony_ci ret.style = Object.assign({}, defaults.style, options.style); 2401cb0ef41Sopenharmony_ci return ret; 2411cb0ef41Sopenharmony_ci} 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci// Wrap on word boundary 2441cb0ef41Sopenharmony_cifunction wordWrap(maxLength, input) { 2451cb0ef41Sopenharmony_ci let lines = []; 2461cb0ef41Sopenharmony_ci let split = input.split(/(\s+)/g); 2471cb0ef41Sopenharmony_ci let line = []; 2481cb0ef41Sopenharmony_ci let lineLength = 0; 2491cb0ef41Sopenharmony_ci let whitespace; 2501cb0ef41Sopenharmony_ci for (let i = 0; i < split.length; i += 2) { 2511cb0ef41Sopenharmony_ci let word = split[i]; 2521cb0ef41Sopenharmony_ci let newLength = lineLength + strlen(word); 2531cb0ef41Sopenharmony_ci if (lineLength > 0 && whitespace) { 2541cb0ef41Sopenharmony_ci newLength += whitespace.length; 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci if (newLength > maxLength) { 2571cb0ef41Sopenharmony_ci if (lineLength !== 0) { 2581cb0ef41Sopenharmony_ci lines.push(line.join('')); 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci line = [word]; 2611cb0ef41Sopenharmony_ci lineLength = strlen(word); 2621cb0ef41Sopenharmony_ci } else { 2631cb0ef41Sopenharmony_ci line.push(whitespace || '', word); 2641cb0ef41Sopenharmony_ci lineLength = newLength; 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci whitespace = split[i + 1]; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci if (lineLength) { 2691cb0ef41Sopenharmony_ci lines.push(line.join('')); 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci return lines; 2721cb0ef41Sopenharmony_ci} 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci// Wrap text (ignoring word boundaries) 2751cb0ef41Sopenharmony_cifunction textWrap(maxLength, input) { 2761cb0ef41Sopenharmony_ci let lines = []; 2771cb0ef41Sopenharmony_ci let line = ''; 2781cb0ef41Sopenharmony_ci function pushLine(str, ws) { 2791cb0ef41Sopenharmony_ci if (line.length && ws) line += ws; 2801cb0ef41Sopenharmony_ci line += str; 2811cb0ef41Sopenharmony_ci while (line.length > maxLength) { 2821cb0ef41Sopenharmony_ci lines.push(line.slice(0, maxLength)); 2831cb0ef41Sopenharmony_ci line = line.slice(maxLength); 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci } 2861cb0ef41Sopenharmony_ci let split = input.split(/(\s+)/g); 2871cb0ef41Sopenharmony_ci for (let i = 0; i < split.length; i += 2) { 2881cb0ef41Sopenharmony_ci pushLine(split[i], i && split[i - 1]); 2891cb0ef41Sopenharmony_ci } 2901cb0ef41Sopenharmony_ci if (line.length) lines.push(line); 2911cb0ef41Sopenharmony_ci return lines; 2921cb0ef41Sopenharmony_ci} 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_cifunction multiLineWordWrap(maxLength, input, wrapOnWordBoundary = true) { 2951cb0ef41Sopenharmony_ci let output = []; 2961cb0ef41Sopenharmony_ci input = input.split('\n'); 2971cb0ef41Sopenharmony_ci const handler = wrapOnWordBoundary ? wordWrap : textWrap; 2981cb0ef41Sopenharmony_ci for (let i = 0; i < input.length; i++) { 2991cb0ef41Sopenharmony_ci output.push.apply(output, handler(maxLength, input[i])); 3001cb0ef41Sopenharmony_ci } 3011cb0ef41Sopenharmony_ci return output; 3021cb0ef41Sopenharmony_ci} 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_cifunction colorizeLines(input) { 3051cb0ef41Sopenharmony_ci let state = {}; 3061cb0ef41Sopenharmony_ci let output = []; 3071cb0ef41Sopenharmony_ci for (let i = 0; i < input.length; i++) { 3081cb0ef41Sopenharmony_ci let line = rewindState(state, input[i]); 3091cb0ef41Sopenharmony_ci state = readState(line); 3101cb0ef41Sopenharmony_ci let temp = Object.assign({}, state); 3111cb0ef41Sopenharmony_ci output.push(unwindState(temp, line)); 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci return output; 3141cb0ef41Sopenharmony_ci} 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci/** 3171cb0ef41Sopenharmony_ci * Credit: Matheus Sampaio https://github.com/matheussampaio 3181cb0ef41Sopenharmony_ci */ 3191cb0ef41Sopenharmony_cifunction hyperlink(url, text) { 3201cb0ef41Sopenharmony_ci const OSC = '\u001B]'; 3211cb0ef41Sopenharmony_ci const BEL = '\u0007'; 3221cb0ef41Sopenharmony_ci const SEP = ';'; 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci return [OSC, '8', SEP, SEP, url || text, BEL, text, OSC, '8', SEP, SEP, BEL].join(''); 3251cb0ef41Sopenharmony_ci} 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_cimodule.exports = { 3281cb0ef41Sopenharmony_ci strlen: strlen, 3291cb0ef41Sopenharmony_ci repeat: repeat, 3301cb0ef41Sopenharmony_ci pad: pad, 3311cb0ef41Sopenharmony_ci truncate: truncate, 3321cb0ef41Sopenharmony_ci mergeOptions: mergeOptions, 3331cb0ef41Sopenharmony_ci wordWrap: multiLineWordWrap, 3341cb0ef41Sopenharmony_ci colorizeLines: colorizeLines, 3351cb0ef41Sopenharmony_ci hyperlink, 3361cb0ef41Sopenharmony_ci}; 337