import process from 'node:process'; import escapeStringRegexp from 'escape-string-regexp'; import isUnicodeSupported from 'is-unicode-supported'; const {platform} = process; const common = { square: '█', squareDarkShade: '▓', squareMediumShade: '▒', squareLightShade: '░', squareTop: '▀', squareBottom: '▄', squareLeft: '▌', squareRight: '▐', squareCenter: '■', bullet: '●', dot: '․', ellipsis: '…', pointerSmall: '›', triangleUp: '▲', triangleUpSmall: '▴', triangleDown: '▼', triangleDownSmall: '▾', triangleLeftSmall: '◂', triangleRightSmall: '▸', home: '⌂', heart: '♥', musicNote: '♪', musicNoteBeamed: '♫', arrowUp: '↑', arrowDown: '↓', arrowLeft: '←', arrowRight: '→', arrowLeftRight: '↔', arrowUpDown: '↕', almostEqual: '≈', notEqual: '≠', lessOrEqual: '≤', greaterOrEqual: '≥', identical: '≡', infinity: '∞', subscriptZero: '₀', subscriptOne: '₁', subscriptTwo: '₂', subscriptThree: '₃', subscriptFour: '₄', subscriptFive: '₅', subscriptSix: '₆', subscriptSeven: '₇', subscriptEight: '₈', subscriptNine: '₉', oneHalf: '½', oneThird: '⅓', oneQuarter: '¼', oneFifth: '⅕', oneSixth: '⅙', oneEighth: '⅛', twoThirds: '⅔', twoFifths: '⅖', threeQuarters: '¾', threeFifths: '⅗', threeEighths: '⅜', fourFifths: '⅘', fiveSixths: '⅚', fiveEighths: '⅝', sevenEighths: '⅞', line: '─', lineBold: '━', lineDouble: '═', lineDashed0: '┄', lineDashed1: '┅', lineDashed2: '┈', lineDashed3: '┉', lineDashed4: '╌', lineDashed5: '╍', lineDashed6: '╴', lineDashed7: '╶', lineDashed8: '╸', lineDashed9: '╺', lineDashed10: '╼', lineDashed11: '╾', lineDashed12: '−', lineDashed13: '–', lineDashed14: '‐', lineDashed15: '⁃', lineVertical: '│', lineVerticalBold: '┃', lineVerticalDouble: '║', lineVerticalDashed0: '┆', lineVerticalDashed1: '┇', lineVerticalDashed2: '┊', lineVerticalDashed3: '┋', lineVerticalDashed4: '╎', lineVerticalDashed5: '╏', lineVerticalDashed6: '╵', lineVerticalDashed7: '╷', lineVerticalDashed8: '╹', lineVerticalDashed9: '╻', lineVerticalDashed10: '╽', lineVerticalDashed11: '╿', lineDownLeft: '┐', lineDownLeftArc: '╮', lineDownBoldLeftBold: '┓', lineDownBoldLeft: '┒', lineDownLeftBold: '┑', lineDownDoubleLeftDouble: '╗', lineDownDoubleLeft: '╖', lineDownLeftDouble: '╕', lineDownRight: '┌', lineDownRightArc: '╭', lineDownBoldRightBold: '┏', lineDownBoldRight: '┎', lineDownRightBold: '┍', lineDownDoubleRightDouble: '╔', lineDownDoubleRight: '╓', lineDownRightDouble: '╒', lineUpLeft: '┘', lineUpLeftArc: '╯', lineUpBoldLeftBold: '┛', lineUpBoldLeft: '┚', lineUpLeftBold: '┙', lineUpDoubleLeftDouble: '╝', lineUpDoubleLeft: '╜', lineUpLeftDouble: '╛', lineUpRight: '└', lineUpRightArc: '╰', lineUpBoldRightBold: '┗', lineUpBoldRight: '┖', lineUpRightBold: '┕', lineUpDoubleRightDouble: '╚', lineUpDoubleRight: '╙', lineUpRightDouble: '╘', lineUpDownLeft: '┤', lineUpBoldDownBoldLeftBold: '┫', lineUpBoldDownBoldLeft: '┨', lineUpDownLeftBold: '┥', lineUpBoldDownLeftBold: '┩', lineUpDownBoldLeftBold: '┪', lineUpDownBoldLeft: '┧', lineUpBoldDownLeft: '┦', lineUpDoubleDownDoubleLeftDouble: '╣', lineUpDoubleDownDoubleLeft: '╢', lineUpDownLeftDouble: '╡', lineUpDownRight: '├', lineUpBoldDownBoldRightBold: '┣', lineUpBoldDownBoldRight: '┠', lineUpDownRightBold: '┝', lineUpBoldDownRightBold: '┡', lineUpDownBoldRightBold: '┢', lineUpDownBoldRight: '┟', lineUpBoldDownRight: '┞', lineUpDoubleDownDoubleRightDouble: '╠', lineUpDoubleDownDoubleRight: '╟', lineUpDownRightDouble: '╞', lineDownLeftRight: '┬', lineDownBoldLeftBoldRightBold: '┳', lineDownLeftBoldRightBold: '┯', lineDownBoldLeftRight: '┰', lineDownBoldLeftBoldRight: '┱', lineDownBoldLeftRightBold: '┲', lineDownLeftRightBold: '┮', lineDownLeftBoldRight: '┭', lineDownDoubleLeftDoubleRightDouble: '╦', lineDownDoubleLeftRight: '╥', lineDownLeftDoubleRightDouble: '╤', lineUpLeftRight: '┴', lineUpBoldLeftBoldRightBold: '┻', lineUpLeftBoldRightBold: '┷', lineUpBoldLeftRight: '┸', lineUpBoldLeftBoldRight: '┹', lineUpBoldLeftRightBold: '┺', lineUpLeftRightBold: '┶', lineUpLeftBoldRight: '┵', lineUpDoubleLeftDoubleRightDouble: '╩', lineUpDoubleLeftRight: '╨', lineUpLeftDoubleRightDouble: '╧', lineUpDownLeftRight: '┼', lineUpBoldDownBoldLeftBoldRightBold: '╋', lineUpDownBoldLeftBoldRightBold: '╈', lineUpBoldDownLeftBoldRightBold: '╇', lineUpBoldDownBoldLeftRightBold: '╊', lineUpBoldDownBoldLeftBoldRight: '╉', lineUpBoldDownLeftRight: '╀', lineUpDownBoldLeftRight: '╁', lineUpDownLeftBoldRight: '┽', lineUpDownLeftRightBold: '┾', lineUpBoldDownBoldLeftRight: '╂', lineUpDownLeftBoldRightBold: '┿', lineUpBoldDownLeftBoldRight: '╃', lineUpBoldDownLeftRightBold: '╄', lineUpDownBoldLeftBoldRight: '╅', lineUpDownBoldLeftRightBold: '╆', lineUpDoubleDownDoubleLeftDoubleRightDouble: '╬', lineUpDoubleDownDoubleLeftRight: '╫', lineUpDownLeftDoubleRightDouble: '╪', lineCross: '╳', lineBackslash: '╲', lineSlash: '╱', }; export const mainSymbols = { ...common, // The main symbols for those do not look that good on Ubuntu. ...( platform === 'linux' ? { circleQuestionMark: '?⃝', questionMarkPrefix: '?⃝', } : { circleQuestionMark: '?', questionMarkPrefix: '?', } ), tick: '✔', info: 'ℹ', warning: '⚠', cross: '✘', squareSmall: '◻', squareSmallFilled: '◼', circle: '◯', circleFilled: '◉', circleDotted: '◌', circleDouble: '◎', circleCircle: 'ⓞ', circleCross: 'ⓧ', circlePipe: 'Ⓘ', radioOn: '◉', radioOff: '◯', checkboxOn: '☒', checkboxOff: '☐', checkboxCircleOn: 'ⓧ', checkboxCircleOff: 'Ⓘ', pointer: '❯', triangleUpOutline: '△', triangleLeft: '◀', triangleRight: '▶', lozenge: '◆', lozengeOutline: '◇', hamburger: '☰', smiley: '㋡', mustache: '෴', star: '★', play: '▶', nodejs: '⬢', oneSeventh: '⅐', oneNinth: '⅑', oneTenth: '⅒', }; export const fallbackSymbols = { ...common, tick: '√', info: 'i', warning: '‼', cross: '×', squareSmall: '□', squareSmallFilled: '■', circle: '( )', circleFilled: '(*)', circleDotted: '( )', circleDouble: '( )', circleCircle: '(○)', circleCross: '(×)', circlePipe: '(│)', circleQuestionMark: '(?)', radioOn: '(*)', radioOff: '( )', checkboxOn: '[×]', checkboxOff: '[ ]', checkboxCircleOn: '(×)', checkboxCircleOff: '( )', questionMarkPrefix: '?', pointer: '>', triangleUpOutline: '∆', triangleLeft: '◄', triangleRight: '►', lozenge: '♦', lozengeOutline: '◊', hamburger: '≡', smiley: '☺', mustache: '┌─┐', star: '✶', play: '►', nodejs: '♦', oneSeventh: '1/7', oneNinth: '1/9', oneTenth: '1/10', }; const shouldUseMain = isUnicodeSupported(); const figures = shouldUseMain ? mainSymbols : fallbackSymbols; export default figures; const isFallbackSymbol = (key, mainSymbol) => fallbackSymbols[key] !== mainSymbol; const getFigureRegExp = (key, mainSymbol) => [new RegExp(escapeStringRegexp(mainSymbol), 'g'), fallbackSymbols[key]]; let replacements = []; const getReplacements = () => { if (replacements.length > 0) { return replacements; } replacements = Object.entries(mainSymbols) .filter(([key, mainSymbol]) => isFallbackSymbol(key, mainSymbol)) .map(([key, mainSymbol]) => getFigureRegExp(key, mainSymbol)); return replacements; }; // On terminals which do not support Unicode symbols, substitute them to other symbols export const replaceSymbols = string => { if (shouldUseMain) { return string; } for (const [figureRegExp, fallbackSymbol] of getReplacements()) { string = string.replace(figureRegExp, fallbackSymbol); } return string; };