-
Dominik Wilkowski committed with GitHub 2 years ago
Showing first 64 files as there are too many
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
img/color-consistency.png
-
.babelrc nodejs/.babelrcContent is identical
-
-
-
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 7 lines 18 18 const { Debugging } = require('./Debugging.js'); 19 19 const { Colorize } = require('./Colorize.js'); 20 20 21 - 22 21 /** 23 22 * Add a new character to the output array 24 23 * skipped 6 lines 31 30 * 32 31 * @return {array} - The output array with new line 33 32 */ 34 - const AddChar = ( CHAR, output, fontLines, fontChars, fontColors, colors ) => { 35 - Debugging.report( `Running AddChar with "${ CHAR }"`, 1 ); 33 + const AddChar = (CHAR, output, fontLines, fontChars, fontColors, colors) => { 34 + Debugging.report(`Running AddChar with "${CHAR}"`, 1); 36 35 37 36 let lines = output.length - fontLines; // last line is fontLines tall and is located at the bottom of the output array 38 37 39 - for( let i = lines; i < output.length; i++ ) { // iterate over last line 38 + for (let i = lines; i < output.length; i++) { 39 + // iterate over last line 40 40 let index = i - lines; 41 41 42 - output[ i ] += Colorize( fontChars[ CHAR ][ index ], fontColors, colors ); 42 + output[i] += Colorize(fontChars[CHAR][index], fontColors, colors); 43 43 } 44 44 45 45 return output; 46 46 }; 47 - 48 47 49 48 module.exports = exports = { 50 49 AddChar, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 7 lines 18 18 const { Debugging } = require('./Debugging.js'); 19 19 const { Colorize } = require('./Colorize.js'); 20 20 21 - 22 - 23 21 /** 24 22 * Add letter spacing for the next character 25 23 * skipped 6 lines 32 30 * 33 31 * @return {array} - The output array with space 34 32 */ 35 - const AddLetterSpacing = ( output, fontLines, fontLetterspace, fontColors, colors, letterSpacing ) => { 36 - Debugging.report( `Running AddLetterSpacing`, 1 ); 33 + const AddLetterSpacing = (output, fontLines, fontLetterspace, fontColors, colors, letterSpacing) => { 34 + Debugging.report(`Running AddLetterSpacing`, 1); 37 35 38 36 let lines = output.length - fontLines; // last line is fontLines tall and is located at the bottom of the output array 39 37 40 - for( let i = lines; i < output.length; i++ ) { // iterate over last line 38 + for (let i = lines; i < output.length; i++) { 39 + // iterate over last line 41 40 let index = i - lines; 42 - let space = Colorize( fontLetterspace[ index ], fontColors, colors ); 41 + let space = Colorize(fontLetterspace[index], fontColors, colors); 43 42 44 - if( space.length === 0 && letterSpacing > 0 ) { 45 - Debugging.report( `AddLetterSpacing: Adding space to letter spacing`, 1 ); 43 + if (space.length === 0 && letterSpacing > 0) { 44 + Debugging.report(`AddLetterSpacing: Adding space to letter spacing`, 1); 46 45 47 46 space = ' '; 48 47 } 49 48 50 - output[ i ] += space.repeat( letterSpacing ); 49 + output[i] += space.repeat(letterSpacing); 51 50 } 52 51 53 52 return output; 54 53 }; 55 - 56 54 57 55 module.exports = exports = { 58 56 AddLetterSpacing, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 5 lines 16 16 'use strict'; 17 17 18 18 const { Debugging } = require('./Debugging.js'); 19 - 20 19 21 20 /** 22 21 * Add a new line to the output array skipped 5 lines 28 27 * 29 28 * @return {array} - The output array with new line 30 29 */ 31 - const AddLine = ( output, fontLines, FontBuffer, lineHeight ) => { 32 - Debugging.report( `Running AddLine`, 1 ); 30 + const AddLine = (output, fontLines, FontBuffer, lineHeight) => { 31 + Debugging.report(`Running AddLine`, 1); 33 32 34 - if( output.length === 0 ) { 33 + if (output.length === 0) { 35 34 lineHeight = 0; 36 35 } 37 36 38 37 let lines = fontLines + output.length + lineHeight; 39 38 let length = output.length; 40 39 41 - for( let i = length; i < lines; i++ ) { 40 + for (let i = length; i < lines; i++) { 42 41 let index = i - length; 43 42 44 - if( index > lineHeight ) { 45 - output[ i ] = FontBuffer[ ( index - lineHeight ) ]; 46 - } 47 - else { 48 - output[ i ] = ''; 43 + if (index > lineHeight) { 44 + output[i] = FontBuffer[index - lineHeight]; 45 + } else { 46 + output[i] = ''; 49 47 } 50 48 } 51 49 52 50 return output; 53 51 }; 54 - 55 52 56 53 module.exports = exports = { 57 54 AddLine, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 - 19 18 /** 20 19 * Flatten the shortcuts in our cli options object 21 20 * skipped 1 lines 23 22 * 24 23 * @return {object} - All short keys flattened into first level 25 24 */ 26 - const AddShortcuts = ( options ) => { 27 - const flatOptions = Object.assign( {}, options ); 25 + const AddShortcuts = (options) => { 26 + const flatOptions = Object.assign({}, options); 28 27 29 - Object.keys( flatOptions ).forEach( option => { 30 - flatOptions[ option ]._name = option; 31 - flatOptions[ flatOptions[ option ].short ] = flatOptions[ option ]; 28 + Object.keys(flatOptions).forEach((option) => { 29 + flatOptions[option]._name = option; 30 + flatOptions[flatOptions[option].short] = flatOptions[option]; 32 31 }); 33 32 34 33 return flatOptions; 35 34 }; 36 - 37 35 38 36 module.exports = exports = { 39 37 AddShortcuts, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 7 lines 18 18 const { Debugging } = require('./Debugging.js'); 19 19 const { Size } = require('./Size.js'); 20 20 21 - 22 21 /** 23 22 * Calculate the spaces to be added to the left of each line to align them either center or right 24 23 * skipped 7 lines 32 31 * 33 32 * @return {array} - The output array with space added on the left for alignment 34 33 */ 35 - const AlignText = ( output, lineLength, characterLines, align, size = Size ) => { 36 - Debugging.report( `Running AlignText`, 1 ); 34 + const AlignText = (output, lineLength, characterLines, align, size = Size) => { 35 + Debugging.report(`Running AlignText`, 1); 37 36 38 37 let space = 0; 39 38 40 - if( align === 'center' ) { // calculate the size for center alignment 41 - space = Math.floor( ( size.width - lineLength ) / 2 ); 39 + if (align === 'center') { 40 + // calculate the size for center alignment 41 + space = Math.ceil((size.width - lineLength) / 2); 42 42 43 - Debugging.report( `AlignText: Center lineLength: ${ lineLength }, size.width: ${ size.width }, space: ${ space }`, 2 ); 43 + Debugging.report(`AlignText: Center lineLength: ${lineLength}, size.width: ${size.width}, space: ${space}`, 2); 44 44 } 45 45 46 - if( align === 'right' ) { // calculate the size for right alignment 46 + if (align === 'right') { 47 + // calculate the size for right alignment 47 48 space = size.width - lineLength; 48 49 49 - Debugging.report( `AlignText: Right lineLength: ${ lineLength }, size.width: ${ size.width }, space: ${ space }`, 2 ); 50 + Debugging.report(`AlignText: Right lineLength: ${lineLength}, size.width: ${size.width}, space: ${space}`, 2); 50 51 } 51 52 52 - 53 - if( space > 0 ) { // only add if there is something to add 53 + if (space > 0) { 54 + // only add if there is something to add 54 55 let lines = output.length - characterLines; // last line is characterLines tall and is located at the bottom of the output array 55 - const spaces = ' '.repeat( space ); 56 + const spaces = ' '.repeat(space); 56 57 57 - for( let i = lines; i < output.length; i++ ) { // iterate over last line (which can be several line breaks long) 58 - output[ i ] = spaces + output[ i ]; 58 + for (let i = lines; i < output.length; i++) { 59 + // iterate over last line (which can be several line breaks long) 60 + output[i] = spaces + output[i]; 59 61 } 60 62 } 61 63 62 64 return output; 63 65 }; 64 - 65 66 66 67 module.exports = exports = { 67 68 AlignText, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 6 lines 17 17 18 18 const { Debugging } = require('./Debugging.js'); 19 19 20 - 21 20 /** 22 21 * Return the max width of a character by looking at its longest line 23 22 * skipped 3 lines 27 26 * 28 27 * @return {number} - The length of a longest line in a character 29 28 */ 30 - const CharLength = ( character, fontLines, letterSpacing ) => { 31 - Debugging.report( `Running CharLength`, 1 ); 29 + const CharLength = (character, fontLines, letterSpacing) => { 30 + Debugging.report(`Running CharLength`, 1); 32 31 33 32 let charWidth = 0; 34 33 35 - for( let i = 0; i < fontLines; i++ ) { 36 - let char = character[ i ].replace( /(<([^>]+)>)/ig, '' ); // get character and strip color infos 34 + for (let i = 0; i < fontLines; i++) { 35 + let char = character[i].replace(/(<([^>]+)>)/gi, ''); // get character and strip color infos 37 36 38 - if( char.length > charWidth ) { 37 + if (char.length > charWidth) { 39 38 charWidth = char.length; // assign only largest 40 39 } 41 40 } 42 41 43 - if( charWidth === 0 && letterSpacing > 0 ) { 44 - Debugging.report( `CharLength: Adding space to letter spacing`, 1 ); 42 + if (charWidth === 0 && letterSpacing > 0) { 43 + Debugging.report(`CharLength: Adding space to letter spacing`, 1); 45 44 46 45 charWidth = 1; 47 46 } 48 47 49 48 return charWidth; 50 49 }; 51 - 52 50 53 51 module.exports = exports = { 54 52 CharLength, skipped 2 lines -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * CheckInput 12 + * Check input for human errors 13 + * 14 + **************************************************************************************************************************************************************/ 15 + 16 + 'use strict'; 17 + 18 + const { HEXTEST, Color } = require('./Color.js'); 19 + const { COLORS, BGCOLORS, GRADIENTCOLORS, GRADIENTS, ALIGNMENT, FONTFACES } = require('./constants.js'); 20 + 21 + /** 22 + * Check input for human errors 23 + * 24 + * @param {string} INPUT - The string you want to write out 25 + * @param {string} userFont - The user specified font 26 + * @param {array} userColors - The user specified colors 27 + * @param {string} userBackground - The user specified background color 28 + * @param {string} userAlign - The user specified alignment option 29 + * @param {array} userGradient - The user specified gradient option 30 + * @param {boolean} userTransitionGradient - The user specified gradient transition option 31 + * @param {string} userEnv - The user specified environment 32 + * @param {object} fontfaces - All allowed fontfaces 33 + * @param {object} colors - All allowed font colors 34 + * @param {object} bgcolors - All allowed background colors 35 + * @param {object} gradientcolors - All allowed gradient colors 36 + * @param {object} gradients - All allowed gradients 37 + * @param {array} alignment - All allowed alignments 38 + * 39 + * @typedef {object} ReturnObject 40 + * @property {boolean} pass - Whether the input is valid 41 + * @property {string} message - Possible error messages 42 + * 43 + * @return {ReturnObject} - An object with error messages and a pass key 44 + */ 45 + const CheckInput = ( 46 + INPUT, 47 + userFont, 48 + userColors, 49 + userBackground, 50 + userAlign, 51 + userGradient, 52 + userTransitionGradient, 53 + userEnv, 54 + fontfaces = FONTFACES, 55 + colors = COLORS, 56 + bgcolors = BGCOLORS, 57 + gradientcolors = GRADIENTCOLORS, 58 + gradients = GRADIENTS, 59 + alignment = ALIGNMENT 60 + ) => { 61 + let result = { 62 + message: '', 63 + pass: true, 64 + }; 65 + 66 + const { open: red_open, close: red_close } = Color('red'); 67 + const { open: green_open, close: green_close } = Color('green'); 68 + 69 + // checking input 70 + if (INPUT === undefined || INPUT === '') { 71 + return { 72 + message: 'Please provide text to convert', 73 + pass: false, 74 + }; 75 + } 76 + 77 + // checking font 78 + if (Object.keys(fontfaces).indexOf(userFont.toLowerCase()) === -1) { 79 + return { 80 + message: 81 + `"${red_open}${userFont}${red_close}" is not a valid font option.\n` + 82 + `Please use a font from the supported stack:\n${green_open}${Object.keys(fontfaces) 83 + .map((font) => fontfaces[font]) 84 + .join(', ')}${green_close}`, 85 + pass: false, 86 + }; 87 + } 88 + 89 + // checking colors 90 + userColors.forEach((color) => { 91 + // check color usage 92 + if (Object.keys(colors).indexOf(color.toLowerCase()) === -1 && color !== 'candy' && !HEXTEST.test(color)) { 93 + result = { 94 + message: 95 + `"${red_open}${color}${red_close}" is not a valid font color option.\n` + 96 + `Please use a color from the supported stack or any valid hex color:\n` + 97 + `${green_open}${Object.keys(colors) 98 + .map((color) => colors[color]) 99 + .join(', ')}, candy, "#3456ff", "#f80", etc...${green_close}`, 100 + pass: false, 101 + }; 102 + } 103 + }); 104 + 105 + // checking background colors 106 + if (Object.keys(bgcolors).indexOf(userBackground.toLowerCase()) === -1 && !HEXTEST.test(userBackground)) { 107 + return { 108 + message: 109 + `"${red_open}${userBackground}${red_close}" is not a valid background option.\n` + 110 + `Please use a color from the supported stack:\n` + 111 + `${green_open}${Object.keys(bgcolors) 112 + .map((bgcolor) => bgcolors[bgcolor]) 113 + .join(', ')}, "#3456ff", "#f80", etc...${green_close}`, 114 + pass: false, 115 + }; 116 + } 117 + 118 + // CHECKING ALIGNMENT 119 + if (alignment.indexOf(userAlign.toLowerCase()) === -1) { 120 + return { 121 + message: 122 + `"${red_open}${userAlign}${red_close}" is not a valid alignment option.\n` + 123 + `Please use an alignment option from the supported stack:\n${green_open}${alignment.join(' | ')}${green_close}`, 124 + pass: false, 125 + }; 126 + } 127 + 128 + // CHECKING GRADIENT 129 + if (userGradient) { 130 + if ( 131 + userGradient.length === 1 && 132 + Object.keys(gradients).indexOf(userGradient[0].toLowerCase()) !== -1 && 133 + userTransitionGradient 134 + ) { 135 + return result; 136 + } else { 137 + if (userGradient.length < 2) { 138 + return { 139 + message: 140 + `"${red_open}${userGradient}${red_close}" is not a valid gradient option.\n` + 141 + `Please pass in${userTransitionGradient ? ' at least' : ''} two colors.`, 142 + pass: false, 143 + }; 144 + } 145 + 146 + if (userGradient.length !== 2 && !userTransitionGradient) { 147 + return { 148 + message: 149 + `"${red_open}${userGradient}${red_close}" is not a valid gradient option.\n` + `Please pass in two colors.`, 150 + pass: false, 151 + }; 152 + } 153 + 154 + // check validity of colors 155 + userGradient.forEach((color) => { 156 + if (Object.keys(gradientcolors).indexOf(color.toLowerCase()) === -1 && !HEXTEST.test(color)) { 157 + result = { 158 + message: 159 + `"${red_open}${color}${red_close}" is not a valid gradient color option.\n` + 160 + `Please use a color from the supported stack or any valid hex color:\n${green_open}${Object.keys( 161 + gradientcolors 162 + ) 163 + .map((color) => colors[color]) 164 + .join(', ')}, "#3456ff", "#f80", etc...${green_close}`, 165 + pass: false, 166 + }; 167 + } 168 + }); 169 + } 170 + } 171 + 172 + // CHECKING ENVIRONMENT 173 + if (userEnv !== 'node' && userEnv !== 'browser') { 174 + return { 175 + message: 176 + `"${red_open}${userEnv}${red_close}" is not a valid environment option.\n` + 177 + `Please use only the supported options:\n${green_open}node | browser${green_close}`, 178 + pass: false, 179 + }; 180 + } 181 + 182 + return result; 183 + }; 184 + 185 + module.exports = exports = { 186 + CheckInput, 187 + }; 188 + -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 6 lines 17 17 18 18 const { CHARS } = require('./constants.js'); 19 19 20 - 21 20 /** 22 21 * Filter only allowed character 23 22 * skipped 2 lines 26 25 * 27 26 * @return {string} - The filtered input text 28 27 */ 29 - const CleanInput = ( INPUT, chars = CHARS ) => { 30 - if( typeof INPUT === 'string' ) { 31 - const clean = INPUT 32 - .replace(/(?:\r\n|\r|\n)/g, '|') 28 + const CleanInput = (INPUT, chars = CHARS) => { 29 + if (typeof INPUT === 'string') { 30 + const clean = INPUT.replace(/(?:\r\n|\r|\n)/g, '|') 33 31 .split('') 34 - .filter( char => chars.includes( char.toUpperCase() ) ) 32 + .filter((char) => chars.includes(char.toUpperCase())) 35 33 .join(''); 36 34 37 35 return clean; 38 - } 39 - else { 36 + } else { 40 37 return ''; 41 38 } 42 39 }; 43 - 44 40 45 41 module.exports = exports = { 46 42 CleanInput, skipped 2 lines -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * HEXTEST - Regex to see if a string is a hex color 12 + * Rgb2hsv - Converts an RGB color value to HSV 13 + * Hsv2rgb - Converts an HSV color value to RGB 14 + * Rgb2hex - Converts RGB to HEX 15 + * Hex2rgb - Convert HEX to RGB 16 + * Hsv2hsvRad - Convert HSV coordinate to HSVrad (degree to radian) 17 + * HsvRad2hsv - Convert HSVrad color to HSV (radian to degree) 18 + * Hex2hsvRad - Convert HEX to HSVrad 19 + * HsvRad2hex - Convert HSVrad to HEX 20 + * rgb2ansi_16m - - Convert RGB values to ANSI16 million colors - truecolor 21 + * rgb2ansi256Code - Convert RGB values to ANSI256 escape code 22 + * rgb2ansi_256 - Convert RGB values to ANSI256 23 + * ansi_2562ansi_16 - Convert ANSI256 code values to ANSI16 24 + * get_term_color_support - Detect the ANSI support for the current terminal taking into account env vars NO_COLOR and FORCE_COLOR 25 + * Color - Abstraction for coloring hex-, keyword- and background-colors 26 + * 27 + **************************************************************************************************************************************************************/ 28 + 29 + 'use strict'; 30 + 31 + const { supportsColor } = require('supports-color'); 32 + 33 + const { Options } = require('./Options.js'); 34 + 35 + /** 36 + * Regex to see if a string is a hex color 37 + * 38 + * @type {RegExp} 39 + */ 40 + const HEXTEST = RegExp('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'); 41 + 42 + /** 43 + * Converts an RGB color value to HSV 44 + * 45 + * @author https://github.com/Gavin-YYC/colorconvert 46 + * 47 + * @param {object} options - Arguments 48 + * @param {number} options.r - The red color value 49 + * @param {number} options.g - The green color value 50 + * @param {number} options.b - The blue color value 51 + * 52 + * @return {array} - The HSV representation 53 + */ 54 + function Rgb2hsv({ r, g, b }) { 55 + r /= 255; 56 + g /= 255; 57 + b /= 255; 58 + 59 + const max = Math.max(r, g, b); 60 + const min = Math.min(r, g, b); 61 + const diff = max - min; 62 + 63 + let h = 0; 64 + let v = max; 65 + let s = max === 0 ? 0 : diff / max; 66 + 67 + // h 68 + if (max === min) { 69 + h = 0; 70 + } else if (max === r && g >= b) { 71 + h = 60 * ((g - b) / diff); 72 + } else if (max === r && g < b) { 73 + h = 60 * ((g - b) / diff) + 360; 74 + } else if (max === g) { 75 + h = 60 * ((b - r) / diff) + 120; 76 + } else { 77 + // if( max === b ) { 78 + h = 60 * ((r - g) / diff) + 240; 79 + } 80 + 81 + return [h, s * 100, v * 100]; 82 + } 83 + 84 + /** 85 + * Converts an HSV color value to RGB 86 + * 87 + * @author https://github.com/Gavin-YYC/colorconvert 88 + * 89 + * @param {number} h - The hue 90 + * @param {number} s - The saturation 91 + * @param {number} v - The value 92 + * 93 + * @typedef {object} Hsv2rgbReturnObject 94 + * @property {number} r - The red value 95 + * @property {number} g - The green value 96 + * @property {number} b - The blue value 97 + * 98 + * @return {Hsv2rgbReturnObject} - The RGB representation 99 + */ 100 + function Hsv2rgb(h, s, v) { 101 + h /= 60; 102 + s /= 100; 103 + v /= 100; 104 + const hi = Math.floor(h) % 6; 105 + 106 + const f = h - Math.floor(h); 107 + const p = 255 * v * (1 - s); 108 + const q = 255 * v * (1 - s * f); 109 + const t = 255 * v * (1 - s * (1 - f)); 110 + v *= 255; 111 + 112 + switch (hi) { 113 + case 0: 114 + return { r: v, g: t, b: p }; 115 + case 1: 116 + return { r: q, g: v, b: p }; 117 + case 2: 118 + return { r: p, g: v, b: t }; 119 + case 3: 120 + return { r: p, g: q, b: v }; 121 + case 4: 122 + return { r: t, g: p, b: v }; 123 + case 5: 124 + return { r: v, g: p, b: q }; 125 + } 126 + } 127 + 128 + /** 129 + * Converts RGB to HEX 130 + * 131 + * @param {number} r - The Red value 132 + * @param {number} g - The Green value 133 + * @param {number} b - The Blue value 134 + * 135 + * @return {string} - A HEX color 136 + */ 137 + function Rgb2hex(r, g, b) { 138 + const val = (b | (g << 8) | (r << 16) | (1 << 24)).toString(16).slice(1); 139 + return '#' + val.toLowerCase(); 140 + } 141 + 142 + /** 143 + * Convert HEX to RGB 144 + * 145 + * @param {string} hex - The HEX color 146 + * 147 + * @return {array} - An object with RGB values 148 + */ 149 + function Hex2rgb(hex) { 150 + hex = hex.replace(/^#/, ''); 151 + 152 + if (hex.length > 6) { 153 + hex = hex.slice(0, 6); 154 + } 155 + 156 + if (hex.length === 4) { 157 + hex = hex.slice(0, 3); 158 + } 159 + 160 + if (hex.length === 3) { 161 + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; 162 + } 163 + 164 + const num = parseInt(hex, 16); 165 + const r = num >> 16; 166 + const g = (num >> 8) & 255; 167 + const b = num & 255; 168 + const rgb = [r, g, b]; 169 + 170 + return rgb; 171 + } 172 + 173 + /** 174 + * Convert HSV coordinate to HSVrad (degree to radian) 175 + * 176 + * @param {array} argument - The HSV representation of a color 177 + * 178 + * @return {array} - The HSVrad color 179 + */ 180 + function Hsv2hsvRad([h, s, v]) { 181 + return [(h * Math.PI) / 180, s, v]; 182 + } 183 + 184 + /** 185 + * Convert HSVrad color to HSV (radian to degree) 186 + * 187 + * @param {number} hRad - H in rad 188 + * @param {number} s - S 189 + * @param {number} v - V 190 + * 191 + * @return {array} - The HSV color 192 + */ 193 + function HsvRad2hsv(hRad, s, v) { 194 + const precision = 1000000000000; 195 + const h = Math.round(((hRad * 180) / Math.PI) * precision) / precision; 196 + return [h, s, v]; 197 + } 198 + 199 + /** 200 + * Convert HEX to HSVrad 201 + * 202 + * @param {string} hex - A HEX color 203 + * 204 + * @return {array} - The HSVrad color 205 + */ 206 + function Hex2hsvRad(hex) { 207 + const [r, g, b] = Hex2rgb(hex); 208 + const hsv = Rgb2hsv({ r, g, b }); 209 + const hsvRad = Hsv2hsvRad(hsv); 210 + 211 + return hsvRad; 212 + } 213 + 214 + /** 215 + * Convert HSVrad to HEX 216 + * 217 + * @param {number} hRad - The hue in rad 218 + * @param {number} s - The saturation 219 + * @param {number} v - The value 220 + * 221 + * @return {string} - The HEX color 222 + */ 223 + function HsvRad2hex(hRad, s, v) { 224 + const [h] = HsvRad2hsv(hRad, s, v); 225 + const { r, g, b } = Hsv2rgb(h, s, v); 226 + const hex = Rgb2hex(r, g, b); 227 + 228 + return hex; 229 + } 230 + 231 + /** 232 + * Convert RGB values to ANSI16 million colors - truecolor 233 + * 234 + * @param {number} r - Red value 235 + * @param {number} g - Green value 236 + * @param {number} b - Blue value 237 + * @param {boolean} bg - Is this a background color; default: false 238 + * 239 + * @return {string} - The opening ANSI escape sequence for the given color 240 + */ 241 + function rgb2ansi_16m(r, g, b, bg = false) { 242 + const layer_code = bg ? 48 : 38; 243 + return `\u001b[${layer_code};2;${r};${g};${b}m`; 244 + } 245 + 246 + /** 247 + * Convert RGB values to ANSI256 escape code 248 + * 249 + * @param {number} red - Red value 250 + * @param {number} green - Green value 251 + * @param {number} blue - Blue value 252 + * 253 + * @return {number} - The ANSI escape code for the given color 254 + */ 255 + function rgb2ansi256Code(red, green, blue) { 256 + if (red === green && green === blue) { 257 + if (red < 8) { 258 + return 16; 259 + } 260 + 261 + if (red > 248) { 262 + return 231; 263 + } 264 + 265 + return Math.round(((red - 8) / 247) * 24) + 232; 266 + } 267 + 268 + return 16 + 36 * Math.round((red / 255) * 5) + 6 * Math.round((green / 255) * 5) + Math.round((blue / 255) * 5); 269 + } 270 + 271 + /** 272 + * Convert RGB values to ANSI256 273 + * 274 + * @param {number} r - Red value 275 + * @param {number} g - Green value 276 + * @param {number} b - Blue value 277 + * @param {boolean} bg - Is this a background color; default: false 278 + * 279 + * @return {string} - The opening ANSI escape sequence for the given color 280 + */ 281 + function rgb2ansi_256(r, g, b, bg = false) { 282 + const layer_code = bg ? 48 : 38; 283 + const code = rgb2ansi256Code(r, g, b); 284 + return `\u001b[${layer_code};5;${code}m`; 285 + } 286 + 287 + /** 288 + * Convert ANSI256 code values to ANSI16 289 + * 290 + * @param {number} code - The code of the ANSI256 color 291 + * @param {boolean} bg - Is this a background color; default: false 292 + * 293 + * @return {string} - The opening ANSI escape sequence for the given color 294 + */ 295 + function ansi_2562ansi_16(code, bg = false) { 296 + let ansi_16_code; 297 + if (code <= 7) { 298 + ansi_16_code = code + 10; 299 + } 300 + if (code >= 8 && code <= 15) { 301 + ansi_16_code = code + 82; 302 + } 303 + if (code === 16) { 304 + ansi_16_code = 0; 305 + } 306 + if (code >= 17 && code <= 19) { 307 + ansi_16_code = 34; 308 + } 309 + if ((code >= 20 && code <= 21) || (code >= 25 && code <= 27)) { 310 + ansi_16_code = 94; 311 + } 312 + if ( 313 + (code >= 22 && code <= 24) || 314 + (code >= 58 && code <= 60) || 315 + (code >= 64 && code <= 66) || 316 + (code >= 94 && code <= 95) || 317 + (code >= 100 && code <= 102) || 318 + (code >= 106 && code <= 108) || 319 + (code >= 130 && code <= 131) || 320 + (code >= 136 && code <= 138) || 321 + (code >= 142 && code <= 144) || 322 + (code >= 148 && code <= 151) || 323 + (code >= 172 && code <= 174) || 324 + (code >= 178 && code <= 181) || 325 + (code >= 184 && code <= 189) 326 + ) { 327 + ansi_16_code = 33; 328 + } 329 + if ( 330 + (code >= 28 && code <= 30) || 331 + (code >= 34 && code <= 36) || 332 + (code >= 70 && code <= 72) || 333 + (code >= 76 && code <= 79) || 334 + (code >= 112 && code <= 114) 335 + ) { 336 + ansi_16_code = 32; 337 + } 338 + if ( 339 + (code >= 31 && code <= 33) || 340 + (code >= 37 && code <= 39) || 341 + (code >= 44 && code <= 45) || 342 + (code >= 61 && code <= 63) || 343 + (code >= 67 && code <= 69) || 344 + (code >= 73 && code <= 75) || 345 + (code >= 80 && code <= 81) || 346 + (code >= 103 && code <= 111) || 347 + (code >= 115 && code <= 117) || 348 + (code >= 152 && code <= 153) 349 + ) { 350 + ansi_16_code = 36; 351 + } 352 + if ( 353 + (code >= 40 && code <= 43) || 354 + (code >= 46 && code <= 49) || 355 + (code >= 82 && code <= 85) || 356 + (code >= 118 && code <= 120) || 357 + (code >= 154 && code <= 157) 358 + ) { 359 + ansi_16_code = 92; 360 + } 361 + if ( 362 + (code >= 50 && code <= 51) || 363 + (code >= 86 && code <= 87) || 364 + (code >= 121 && code <= 123) || 365 + (code >= 158 && code <= 159) 366 + ) { 367 + ansi_16_code = 96; 368 + } 369 + if ( 370 + (code >= 52 && code <= 54) || 371 + (code >= 88 && code <= 90) || 372 + (code >= 124 && code <= 126) || 373 + (code >= 166 && code <= 168) 374 + ) { 375 + ansi_16_code = 31; 376 + } 377 + if ( 378 + (code >= 55 && code <= 57) || 379 + (code >= 91 && code <= 93) || 380 + (code >= 96 && code <= 99) || 381 + (code >= 127 && code <= 129) || 382 + (code >= 132 && code <= 135) || 383 + (code >= 139 && code <= 141) || 384 + (code >= 145 && code <= 147) || 385 + (code >= 196 && code <= 171) || 386 + (code >= 175 && code <= 177) 387 + ) { 388 + ansi_16_code = 35; 389 + } 390 + if ((code >= 160 && code <= 163) || (code >= 196 && code <= 199) || (code >= 202 && code <= 213)) { 391 + ansi_16_code = 91; 392 + } 393 + if ( 394 + (code >= 164 && code <= 165) || 395 + (code >= 182 && code <= 183) || 396 + (code >= 200 && code <= 200) || 397 + (code >= 218 && code <= 219) 398 + ) { 399 + ansi_16_code = 95; 400 + } 401 + if ((code >= 190 && code <= 193) || (code >= 214 && code <= 217) || (code >= 220 && code <= 228)) { 402 + ansi_16_code = 93; 403 + } 404 + if ((code >= 194 && code <= 195) || (code >= 229 && code <= 231) || (code >= 253 && code <= 255)) { 405 + ansi_16_code = 97; 406 + } 407 + if (code >= 232 && code <= 239) { 408 + ansi_16_code = 30; 409 + } 410 + if (code >= 240 && code <= 246) { 411 + ansi_16_code = 90; 412 + } 413 + if (code >= 247 && code <= 252) { 414 + ansi_16_code = 37; 415 + } 416 + 417 + if (bg) { 418 + ansi_16_code = ansi_16_code + 10; 419 + } 420 + 421 + return `\u001b[${ansi_16_code}m`; 422 + } 423 + 424 + /** 425 + * Detect the ANSI support for the current terminal taking into account env vars NO_COLOR and FORCE_COLOR 426 + * 427 + * @return {number} - 0 = no color support; 1 = 16 colors support; 2 = 256 colors support; 3 = 16 million colors support 428 + */ 429 + function get_term_color_support() { 430 + let term_support = supportsColor().level || 3; 431 + 432 + if ('NO_COLOR' in process.env) { 433 + term_support = 0; 434 + } 435 + 436 + if (process.env['FORCE_COLOR'] === '0') { 437 + term_support = 0; 438 + } 439 + 440 + if (process.env['FORCE_COLOR'] === '1') { 441 + term_support = 1; 442 + } 443 + 444 + if (process.env['FORCE_COLOR'] === '2') { 445 + term_support = 2; 446 + } 447 + 448 + if (process.env['FORCE_COLOR'] === '3') { 449 + term_support = 3; 450 + } 451 + 452 + return term_support; 453 + } 454 + 455 + /** 456 + * Abstraction for coloring hex-, keyword- and background-colors 457 + * 458 + * @param {string} color - The color to be used 459 + * @param {boolean} bg - Whether this is a background or not 460 + * 461 + * @typedef {object} ColorReturnObject 462 + * @property {string} open - The open ansi code 463 + * @property {string} close - The close ansi code 464 + * 465 + * @return {ColorReturnObject} - An object with open and close ansi codes 466 + */ 467 + const Color = (color, bg = false) => { 468 + const COLORS = { 469 + black: '#000', 470 + red: '#ea3223', 471 + green: '#377d22', 472 + yellow: '#fffd54', 473 + blue: '#0020f5', 474 + magenta: '#ea3df7', 475 + cyan: '#74fbfd', 476 + white: '#fff', 477 + gray: '#808080', 478 + redbright: '#ee776d', 479 + greenbright: '#8cf57b', 480 + yellowbright: '#fffb7f', 481 + bluebright: '#6974f6', 482 + magentabright: '#ee82f8', 483 + cyanbright: '#8dfafd', 484 + whitebright: '#fff', 485 + }; 486 + 487 + const support = get_term_color_support(); 488 + 489 + // bail early if we use system color 490 + if (color === 'system' || support === 0) { 491 + return { open: '', close: '' }; 492 + } 493 + 494 + const OPTIONS = Options.get; 495 + 496 + if (OPTIONS.env === 'node') { 497 + let open; 498 + let close = bg ? '\u001b[49m' : '\u001b[39m'; 499 + 500 + switch (color.toLowerCase()) { 501 + case 'transparent': 502 + open = '\u001b[49m'; 503 + break; 504 + case 'black': 505 + open = bg ? '\u001b[40m' : '\u001b[30m'; 506 + break; 507 + case 'red': 508 + open = bg ? '\u001b[41m' : '\u001b[31m'; 509 + break; 510 + case 'green': 511 + open = bg ? '\u001b[42m' : '\u001b[32m'; 512 + break; 513 + case 'yellow': 514 + open = bg ? '\u001b[43m' : '\u001b[33m'; 515 + break; 516 + case 'blue': 517 + open = bg ? '\u001b[44m' : '\u001b[34m'; 518 + break; 519 + case 'magenta': 520 + open = bg ? '\u001b[45m' : '\u001b[35m'; 521 + break; 522 + case 'cyan': 523 + open = bg ? '\u001b[46m' : '\u001b[36m'; 524 + break; 525 + case 'white': 526 + open = bg ? '\u001b[47m' : '\u001b[37m'; 527 + break; 528 + case 'gray': 529 + open = bg ? '\u001b[100m' : '\u001b[90m'; 530 + break; 531 + case 'redbright': 532 + open = bg ? '\u001b[101m' : '\u001b[91m'; 533 + break; 534 + case 'greenbright': 535 + open = bg ? '\u001b[102m' : '\u001b[92m'; 536 + break; 537 + case 'yellowbright': 538 + open = bg ? '\u001b[103m' : '\u001b[93m'; 539 + break; 540 + case 'bluebright': 541 + open = bg ? '\u001b[104m' : '\u001b[94m'; 542 + break; 543 + case 'magentabright': 544 + open = bg ? '\u001b[105m' : '\u001b[95m'; 545 + break; 546 + case 'cyanbright': 547 + open = bg ? '\u001b[106m' : '\u001b[96m'; 548 + break; 549 + case 'whitebright': 550 + open = bg ? '\u001b[107m' : '\u001b[97m'; 551 + break; 552 + case 'candy': 553 + open = [ 554 + '\u001b[31m', 555 + '\u001b[32m', 556 + '\u001b[33m', 557 + '\u001b[35m', 558 + '\u001b[36m', 559 + '\u001b[91m', 560 + '\u001b[92m', 561 + '\u001b[93m', 562 + '\u001b[94m', 563 + '\u001b[95m', 564 + '\u001b[96m', 565 + ][Math.floor(Math.random() * 11)]; 566 + break; 567 + default: { 568 + let hex = color; 569 + if (!HEXTEST.test(color)) { 570 + return { open: '', close: '' }; 571 + } 572 + const rgb = Hex2rgb(hex); 573 + 574 + if (support === 1) { 575 + open = ansi_2562ansi_16(rgb2ansi256Code(rgb[0], rgb[1], rgb[2]), bg); 576 + } 577 + if (support === 2) { 578 + open = rgb2ansi_256(rgb[0], rgb[1], rgb[2], bg); 579 + } 580 + if (support === 3) { 581 + open = rgb2ansi_16m(rgb[0], rgb[1], rgb[2], bg); 582 + } 583 + } 584 + } 585 + return { open, close }; 586 + } else if (!OPTIONS.env) { 587 + return { open: '', close: '' }; 588 + } else { 589 + if (!HEXTEST.test(color)) { 590 + color = COLORS[color.toLowerCase()]; 591 + if (!color) { 592 + return { open: '', close: '' }; 593 + } 594 + } 595 + 596 + if (bg) { 597 + return { 598 + open: color, 599 + close: '', 600 + }; 601 + } 602 + 603 + return { 604 + open: `<span style="color:${color}">`, 605 + close: '</span>', 606 + }; 607 + } 608 + }; 609 + 610 + module.exports = exports = { 611 + HEXTEST, 612 + Rgb2hsv, 613 + Hsv2rgb, 614 + Rgb2hex, 615 + Hex2rgb, 616 + Hsv2hsvRad, 617 + HsvRad2hsv, 618 + Hex2hsvRad, 619 + HsvRad2hex, 620 + rgb2ansi_16m, 621 + rgb2ansi256Code, 622 + rgb2ansi_256, 623 + ansi_2562ansi_16, 624 + get_term_color_support, 625 + Color, 626 + }; 627 + -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * Colorize 12 + * Replace placeholders with color information 13 + * 14 + **************************************************************************************************************************************************************/ 15 + 16 + 'use strict'; 17 + 18 + const { Debugging } = require('./Debugging.js'); 19 + const { Color } = require('./Color.js'); 20 + 21 + /** 22 + * Replace placeholders with color information 23 + * 24 + * @param {string} character - The string to be converted 25 + * @param {number} fontColors - The number of allowed colors for this font 26 + * @param {array} optionColors - An array of user defined colors 27 + * 28 + * @return {string} - The character with color ansi escape sequences for CLI 29 + */ 30 + const Colorize = (character, fontColors, optionColors) => { 31 + Debugging.report(`Running Colorize`, 1); 32 + 33 + if (character !== undefined) { 34 + if (fontColors > 1) { 35 + // we have to replace all color placeholder with ansi escape sequences 36 + for (let i = 0; i < fontColors; i++) { 37 + const color = optionColors[i] || 'system'; 38 + 39 + const { open: openNew, close: closeNew } = Color(color); 40 + 41 + const open = new RegExp(`<c${i + 1}>`, 'g'); 42 + const close = new RegExp(`</c${i + 1}>`, 'g'); 43 + 44 + character = character.replace(open, openNew); 45 + character = character.replace(close, closeNew); 46 + } 47 + } 48 + 49 + // if only one color is allowed there won't be any color placeholders in the characters 50 + if (fontColors === 1) { 51 + const color = optionColors[0] || 'system'; 52 + 53 + const { open: openNew, close: closeNew } = Color(color); 54 + 55 + character = openNew + character + closeNew; 56 + } 57 + } 58 + 59 + return character; 60 + }; 61 + 62 + module.exports = exports = { 63 + Colorize, 64 + }; 65 + -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 - const { Chalk } = require('./Chalk.js'); 19 - 18 + const { Color } = require('./Color.js'); 20 19 21 20 /** 22 21 * DEBUG object for tracking debug mode and level skipped 6 lines 29 28 level: 2, 30 29 }, 31 30 32 - set enabled( value ) { 31 + set enabled(value) { 33 32 this.store.enabled = value; 34 33 }, 35 34 skipped 1 lines 37 36 return this.store.enabled; 38 37 }, 39 38 40 - set level( value ) { 39 + set level(value) { 41 40 this.store.level = value; 42 41 }, 43 42 skipped 16 lines 60 59 * @param {boolean} debug - Global debug mode on/off 61 60 * @param {number} debuglevel - Global debug level 62 61 */ 63 - headline: ( text, level = 99, debug = DEBUG.enabled, debuglevel = DEBUG.level ) => { 64 - if( debug && level >= debuglevel ) { 65 - console.log( 66 - Chalk.bgWhite(`\n${ Chalk.bold(' \u2611 ') } ${ text }`) 67 - ); 62 + headline: (text, level = 99, debug = DEBUG.enabled, debuglevel = DEBUG.level) => { 63 + if (debug && level >= debuglevel) { 64 + const { open, close } = Color('black', true); 65 + console.log(`${open}\n\u001b[1m \u2611 \u001b[22m ${text}${close}`); 68 66 } 69 67 }, 70 68 skipped 5 lines 76 74 * @param {boolean} debug - Global debug mode on/off 77 75 * @param {number} debuglevel - Global debug level 78 76 */ 79 - report: ( text, level = 99, debug = DEBUG.enabled, debuglevel = DEBUG.level ) => { 80 - if( debug && level >= debuglevel ) { 77 + report: (text, level = 99, debug = DEBUG.enabled, debuglevel = DEBUG.level) => { 78 + if (debug && level >= debuglevel) { 79 + const { open: blackbg_open, close: blackbg_close } = Color('black', true); 80 + const { open: green_open, close: green_close } = Color('green'); 81 + const { open: white_open, close: white_close } = Color('white'); 81 82 console.log( 82 - Chalk.bgWhite(`\n${ Chalk.bold.green(' \u2611 ') } ${ Chalk.black(`${ text } `) }`) 83 + `${blackbg_open}\n\u001b[1m${green_open} \u2611 ${green_close}\u001b[22m ${white_open}${text}${white_close}${blackbg_close}` 83 84 ); 84 85 } 85 86 }, skipped 6 lines 92 93 * @param {boolean} debug - Global debug mode on/off 93 94 * @param {number} debuglevel - Global debug level 94 95 */ 95 - error: ( text, level = 99, debug = DEBUG.enabled, debuglevel = DEBUG.level ) => { 96 - if( debug && level >= debuglevel ) { 96 + error: (text, level = 99, debug = DEBUG.enabled, debuglevel = DEBUG.level) => { 97 + if (debug && level >= debuglevel) { 98 + const { open: blackbg_open, close: blackbg_close } = Color('black', true); 99 + const { open: red_open, close: red_close } = Color('red'); 100 + const { open: white_open, close: white_close } = Color('white'); 97 101 console.error( 98 - Chalk.bgWhite(`\n${ Chalk.red(' \u2612 ') } ${ Chalk.black(`${ text } `) }`) 102 + `${blackbg_open}\n${red_open} \u2612 ${red_close} ${white_open}${text}${white_close}${blackbg_close}` 99 103 ); 100 104 } 101 105 }, 102 106 }; 103 - 104 107 105 108 module.exports = exports = { 106 109 DEBUG, skipped 3 lines -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * DisplayHelp 12 + * Display the help generated from our CLIOPTIONS 13 + * 14 + **************************************************************************************************************************************************************/ 15 + 16 + 'use strict'; 17 + 18 + const { CLIOPTIONS } = require('./constants.js'); 19 + const { Render } = require('./Render.js'); 20 + const { Color } = require('./Color.js'); 21 + 22 + /** 23 + * Display the help generated from our CLIOPTIONS 24 + */ 25 + const DisplayHelp = () => { 26 + const { string: headline } = Render('cfonts', { 27 + align: 'left', 28 + gradient: ['red', 'green'], 29 + }); 30 + 31 + console.log( 32 + ` ${headline}` + 33 + `This is a tool for sexy fonts in the console. Give your cli some love.\n\n` + 34 + `Usage: cfonts "<value>" [option1] <input1> [option2] <input1>,<input2> [option3]\n` + 35 + `Example: \u001b[1m$ cfonts "sexy font" -f chrome -a center -c red,green,gray\u001b[22m\n\n` + 36 + `Options:\n` 37 + ); 38 + 39 + const { open, close } = Color('green'); 40 + 41 + Object.keys(CLIOPTIONS).forEach((option) => { 42 + console.log(`\u001b[1m${option}, ${CLIOPTIONS[option].short}\u001b[22m`); 43 + console.log(CLIOPTIONS[option].description); 44 + console.log( 45 + `\u001b[1m$\u001b[22m cfonts ${CLIOPTIONS[option].example 46 + .replace(/\[green-open\]/g, open) 47 + .replace(/\[green-close\]/g, close)}\n` 48 + ); 49 + }); 50 + }; 51 + 52 + module.exports = exports = { 53 + DisplayHelp, 54 + }; 55 + -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 6 lines 17 17 18 18 const { PACKAGE } = require('./constants.js'); 19 19 20 - 21 20 /** 22 21 * Display the version of this package 23 22 */ 24 23 const DisplayVersion = () => { 25 - console.log( PACKAGE.version ); 24 + console.log(PACKAGE.version); 26 25 }; 27 - 28 26 29 27 module.exports = exports = { 30 28 DisplayVersion, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 - 19 18 /** 20 19 * Get the position of the first character out of all strings inside an array 21 20 * skipped 1 lines 23 22 * 24 23 * @return {number} - The position of the first character 25 24 */ 26 - function GetFirstCharacterPosition( lines ) { 25 + function GetFirstCharacterPosition(lines) { 27 26 const earliest = lines.reduce( 28 - ( prevLine, line ) => ( ( line.length - line.trimStart().length ) < ( prevLine.length - prevLine.trimStart().length ) && line !== '' ? line : prevLine ) 29 - , lines[ 0 ] 27 + (prevLine, line) => 28 + line.length - line.trimStart().length < prevLine.length - prevLine.trimStart().length && line !== '' 29 + ? line 30 + : prevLine, 31 + lines[0] 30 32 ); 31 33 32 - return ( earliest.length - earliest.trimStart().length ); 34 + return earliest.length - earliest.trimStart().length; 33 35 } 34 - 35 36 36 37 module.exports = exports = { 37 38 GetFirstCharacterPosition, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 + const path = require('path'); 19 + 18 20 const { Debugging } = require('./Debugging.js'); 19 - 20 21 21 22 /** 22 23 * Get a selected JSON font-file object skipped 2 lines 25 26 * 26 27 * @return {object} - The font object of that file 27 28 */ 28 - const GetFont = ( font ) => { 29 - Debugging.report( `Running GetFont`, 1 ); 29 + const GetFont = (font) => { 30 + Debugging.report(`Running GetFont`, 1); 30 31 31 32 // try loading the font file 32 33 try { 33 - let FONTFACE = require(`../fonts/${ font }.json`); // read font file 34 + let FONTFACE = require(path.normalize(`../fonts/${font}.json`)); // read font file 34 35 35 - Debugging.report( `GetFont: Fontface path selected: "${ font }.json"`, 2 ); 36 + Debugging.report(`GetFont: Fontface path selected: "${font}.json"`, 2); 36 37 37 38 return FONTFACE; 38 - } 39 - catch( error ) { 40 - Debugging.error( `Font file for "${ font }" errored out: ${ error }`, 2 ); 39 + } catch (error) { 40 + Debugging.error(`Font file for "${font}" errored out: ${error}`, 2); 41 41 42 42 return false; 43 43 } 44 44 }; 45 - 46 45 47 46 module.exports = exports = { 48 47 GetFont, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 - 19 18 /** 20 19 * Return the longest line of an Array 21 20 * skipped 1 lines 23 22 * 24 23 * @return {string} - The longest string from within the array 25 24 */ 26 - const GetLongestLine = lines => lines.reduce( ( longestLine, line ) => ( line.length > longestLine.length && line.length !== 0 ? line : longestLine ), '' ); 27 - 25 + const GetLongestLine = (lines) => 26 + lines.reduce((longestLine, line) => (line.length > longestLine.length && line.length !== 0 ? line : longestLine), ''); 28 27 29 28 module.exports = exports = { 30 29 GetLongestLine, skipped 2 lines -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * GetLinear - Interpolate a linear path from a number to another number 12 + * GetTheta - Interpolate a radial path from a number to another number 13 + * GetGradientColors - Generate the most colorful delta between two colors 14 + * PaintLines - Take a bunch of lines and color them in the colors provided 15 + * Color2hex - Make sure a color is hex 16 + * GetGaps - Calculate the gaps between an array of points 17 + * TransitionBetweenHex - Generate colors between two given colors 18 + * Transition - Generate n colors between x colors 19 + * PaintGradient - Paint finished output in a gradient 20 + * 21 + **************************************************************************************************************************************************************/ 22 + 23 + 'use strict'; 24 + 25 + const { GetFirstCharacterPosition } = require('./GetFirstCharacterPosition.js'); 26 + const { Color, Hex2rgb, Hex2hsvRad, HsvRad2hex, Rgb2hex } = require('./Color.js'); 27 + const { GetLongestLine } = require('./GetLongestLine.js'); 28 + const { GRADIENTS } = require('./constants.js'); 29 + const { Debugging } = require('./Debugging.js'); 30 + 31 + /** 32 + * Interpolate a linear path from a number to another number 33 + * 34 + * @param {number} pointA - The number from which to start 35 + * @param {number} pointB - The number to go to 36 + * @param {number} n - The current step 37 + * @param {number} steps - The amount of steps 38 + * 39 + * @return {number} - The number at step n 40 + */ 41 + function GetLinear(pointA, pointB, n, steps) { 42 + if (steps === 0) { 43 + return pointB; 44 + } 45 + 46 + return pointA + n * ((pointB - pointA) / steps); 47 + } 48 + 49 + /** 50 + * Interpolate a radial path from a number to another number 51 + * 52 + * @param {number} fromTheta - The radian from which to start 53 + * @param {number} toTheta - The radian to go to 54 + * @param {number} n - The current step 55 + * @param {number} steps - The amount of steps 56 + * 57 + * @return {number} - The radian at step n 58 + */ 59 + function GetTheta(fromTheta, toTheta, n, steps) { 60 + const TAU = 2 * Math.PI; 61 + let longDistance; 62 + 63 + if (steps === 0) { 64 + return toTheta; 65 + } 66 + 67 + if (fromTheta > toTheta) { 68 + if (fromTheta - toTheta < Math.PI) { 69 + longDistance = TAU - (fromTheta - toTheta); 70 + } else { 71 + longDistance = toTheta - fromTheta; 72 + } 73 + } else { 74 + if (toTheta - fromTheta < Math.PI) { 75 + longDistance = toTheta - fromTheta - TAU; 76 + } else { 77 + longDistance = -1 * (fromTheta - toTheta); 78 + } 79 + } 80 + 81 + let result = fromTheta + n * (longDistance / steps); 82 + 83 + if (result < 0) { 84 + result += TAU; 85 + } 86 + 87 + if (result > TAU) { 88 + result -= TAU; 89 + } 90 + 91 + return result; 92 + } 93 + 94 + /** 95 + * Generate the most colorful delta between two colors 96 + * 97 + * @param {string} fromColor - The color from which to start 98 + * @param {string} toColor - The color to go to 99 + * @param {number} steps - The amount of colors of the gradient 100 + * 101 + * @return {array} - An array of colors 102 + */ 103 + function GetGradientColors(fromColor, toColor, steps) { 104 + const [fromHRad, fromS, fromV] = Hex2hsvRad(fromColor); 105 + const [toHRad, toS, toV] = Hex2hsvRad(toColor); 106 + 107 + const hexColors = []; 108 + 109 + for (let n = 0; n < steps; n++) { 110 + const hRad = GetTheta(fromHRad, toHRad, n, steps - 1); 111 + const s = GetLinear(fromS, toS, n, steps - 1); 112 + const v = GetLinear(fromV, toV, n, steps - 1); 113 + 114 + hexColors.push(HsvRad2hex(hRad, s, v)); 115 + } 116 + 117 + return hexColors; 118 + } 119 + 120 + /** 121 + * Take a bunch of lines and color them in the colors provided 122 + * 123 + * @param {array} lines - The lines to be colored 124 + * @param {array} colors - The colors in an array 125 + * @param {number} firstCharacterPosition - We may have to cut something off from the start when text is aligned center, right 126 + * 127 + * @return {array} - The lines in color 128 + */ 129 + function PaintLines(lines, colors, firstCharacterPosition) { 130 + Debugging.report(`Running PaintLines`, 1); 131 + 132 + Debugging.report(colors, 2); 133 + 134 + const space = ' '.repeat(firstCharacterPosition); 135 + 136 + return lines.map((line) => { 137 + const coloredLine = line 138 + .slice(firstCharacterPosition) 139 + .split('') 140 + .map((char, i) => { 141 + const { open, close } = Color(colors[i]); 142 + return `${open}${char}${close}`; 143 + }) 144 + .join(''); 145 + 146 + return `${space}${coloredLine}`; 147 + }); 148 + } 149 + 150 + /** 151 + * Make sure a color is hex 152 + * 153 + * @param {string} color - The color 154 + * 155 + * @return {string} - The hex color 156 + */ 157 + function Color2hex(color) { 158 + const colorMap = { 159 + black: '#000000', 160 + red: '#ff0000', 161 + green: '#00ff00', 162 + yellow: '#ffff00', 163 + blue: '#0000ff', 164 + magenta: '#ff00ff', 165 + cyan: '#00ffff', 166 + white: '#ffffff', 167 + gray: '#808080', 168 + grey: '#808080', 169 + }; 170 + 171 + return colorMap[color] || color; 172 + } 173 + 174 + /** 175 + * Calculate the gaps between an array of points 176 + * 177 + * @param {array} points - An array of points, it's not important what's in the array for this function 178 + * @param {number} steps - The amount of steps we have to distribute between the above points 179 + * 180 + * @return {array} - An array of steps per gap 181 + */ 182 + function GetGaps(points, steps) { 183 + // steps per gap 184 + const gapSteps = Math.floor((steps - points.length) / (points.length - 1)); 185 + // steps left over to be distributed 186 + const rest = steps - (points.length + gapSteps * (points.length - 1)); 187 + // the gaps array has one less items than our points (cause it's gaps between each of the points) 188 + const gaps = Array(points.length - 1).fill(gapSteps); 189 + 190 + // let's fill in the rest from the right 191 + for (let i = 0; i < rest; i++) { 192 + gaps[gaps.length - 1 - i]++; 193 + } 194 + 195 + return gaps; 196 + } 197 + 198 + /** 199 + * Generate colors between two given colors 200 + * 201 + * @param {string} fromHex - The color we start from in hex 202 + * @param {string} toHex - The color we end up at in hex 203 + * @param {number} steps - How many colors should be returned 204 + * 205 + * @return {array} - An array for colors 206 + */ 207 + function TransitionBetweenHex(fromHex, toHex, steps) { 208 + const fromRgb = Hex2rgb(fromHex); 209 + const toRgb = Hex2rgb(toHex); 210 + const hexColors = []; 211 + steps++; 212 + 213 + for (let n = 1; n < steps; n++) { 214 + const red = GetLinear(fromRgb[0], toRgb[0], n, steps); 215 + const green = GetLinear(fromRgb[1], toRgb[1], n, steps); 216 + const blue = GetLinear(fromRgb[2], toRgb[2], n, steps); 217 + 218 + hexColors.push(Rgb2hex(red, green, blue)); 219 + } 220 + 221 + return hexColors; 222 + } 223 + 224 + /** 225 + * Generate n colors between x colors 226 + * 227 + * @param {array} colors - An array of colors in hex 228 + * @param {number} steps - The amount of colors to generate 229 + * @param {object} gradients - An object of pre-packaged gradient colors 230 + * 231 + * @return {array} - An array of colors 232 + */ 233 + function Transition(colors, steps, gradients = GRADIENTS) { 234 + let hexColors = []; 235 + if (colors.length === 1) { 236 + colors = gradients[colors[0].toLowerCase()]; 237 + } else { 238 + colors = colors.map((color) => Color2hex(color)); 239 + } 240 + const gaps = GetGaps(colors, steps); 241 + 242 + if (steps <= 1) { 243 + return [colors[colors.length - 1]]; 244 + } 245 + 246 + for (let i = 0; i < colors.length; i++) { 247 + const gap = gaps[i - 1]; 248 + 249 + if (colors[i - 1]) { 250 + const gapColors = TransitionBetweenHex(colors[i - 1], colors[i], gap); 251 + hexColors = [...hexColors, ...gapColors]; 252 + } 253 + 254 + if (gap !== -1) { 255 + hexColors.push(colors[i]); 256 + } 257 + } 258 + 259 + return hexColors; 260 + } 261 + 262 + /** 263 + * Paint finished output in a gradient 264 + * 265 + * @param {object} options - Arguments 266 + * @param {array} options.output - The output to be painted 267 + * @param {array} options.gradient - An array of two colors for start and end of gradient 268 + * @param {number} options.lines - How many lines the output contains 269 + * @param {number} options.lineHeight - The line height between lines 270 + * @param {number} options.fontLines - The line height (line breaks) of a single font line 271 + * @param {boolean} options.independentGradient - A switch to calculate gradient per line or not 272 + * @param {boolean} options.transitionGradient - A switch for transition gradients 273 + * 274 + * @return {array} - The output array painted in ANSI colors 275 + */ 276 + function PaintGradient({ output, gradient, lines, lineHeight, fontLines, independentGradient, transitionGradient }) { 277 + Debugging.report(`Running PaintGradient`, 1); 278 + let newOutput = []; 279 + 280 + if (transitionGradient) { 281 + Debugging.report(`Gradient transition with colors: ${JSON.stringify(gradient)}`, 2); 282 + } else { 283 + Debugging.report(`Gradient start: ${gradient[0]} | Gradient end: ${gradient[1]}`, 2); 284 + } 285 + 286 + let firstCharacterPosition = GetFirstCharacterPosition(output); 287 + let longestLine = GetLongestLine(output).length; 288 + 289 + for (let i = 0; i < lines; i++) { 290 + const start = i * (fontLines + lineHeight); 291 + const end = fontLines + start; 292 + const thisLine = output.slice(start, end); 293 + 294 + if (independentGradient) { 295 + firstCharacterPosition = GetFirstCharacterPosition(thisLine); 296 + longestLine = GetLongestLine(thisLine).length; 297 + } 298 + 299 + const colorsNeeded = longestLine - firstCharacterPosition; 300 + const linesInbetween = i === 0 ? [] : Array(lineHeight).fill(''); 301 + 302 + Debugging.report(`longestLine: ${longestLine} | firstCharacterPosition: ${firstCharacterPosition}`, 2); 303 + 304 + const colors = transitionGradient 305 + ? Transition(gradient, colorsNeeded) 306 + : GetGradientColors(Color2hex(gradient[0]), Color2hex(gradient[1]), colorsNeeded); 307 + 308 + newOutput = [...newOutput, ...linesInbetween, ...PaintLines(thisLine, colors, firstCharacterPosition)]; 309 + } 310 + 311 + return newOutput; 312 + } 313 + 314 + module.exports = exports = { 315 + GetLinear, 316 + GetTheta, 317 + GetGradientColors, 318 + PaintLines, 319 + Color2hex, 320 + GetGaps, 321 + TransitionBetweenHex, 322 + Transition, 323 + PaintGradient, 324 + }; 325 + -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 - const { Chalk } = require('./Chalk.js'); 19 - 18 + const { Color } = require('./Color.js'); 20 19 21 20 /** 22 21 * Logging prettiness skipped 6 lines 29 28 * 30 29 * @param {string} text - The sting you want to log 31 30 */ 32 - error: ( text ) => { 33 - text = text.replace( /(?:\r\n|\r|\n)/g, '\n ' ); // indent each line 34 - 35 - console.error(`\n ${ Chalk.bold.red('Ouch:') } ${ text }\n`); 31 + error: (text) => { 32 + text = text.replace(/(?:\r\n|\r|\n)/g, '\n '); // indent each line 33 + const { open, close } = Color('red'); 34 + console.error(`\n \u001b[1m${open}Ouch:${close}\u001b[22m ${text}\n`); 36 35 }, 37 36 }; 38 - 39 37 40 38 module.exports = exports = { 41 39 Log, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 - const { 19 - COLORS, 20 - BGCOLORS, 21 - FONTFACES, 22 - } = require('./constants.js'); 23 - 18 + const { COLORS, BGCOLORS, FONTFACES } = require('./constants.js'); 24 19 25 20 /** 26 21 * The options store with getter and setter methods skipped 38 lines 65 60 * @param {string} options.font - Font face, Default 'block' 66 61 * @param {string} options.align - Text alignment, Default: 'left' 67 62 * @param {array} options.colors - Colors for font, Default: [] 68 - * @param {string} options.background - Chalk color string for background, Default 'Black' 63 + * @param {string} options.background - Color string for background, Default 'Black' 69 64 * @param {string} options.backgroundColor - Alias for background 70 65 * @param {number} options.letterSpacing - Space between letters, Default: set by selected font face 71 66 * @param {number} options.lineHeight - Space between lines, Default: 1 skipped 25 lines 97 92 allowedBG = BGCOLORS, 98 93 allowedFont = FONTFACES, 99 94 }) { 100 - this.store.font = font !== '' 101 - ? allowedFont[ font.toLowerCase() ] || font 102 - : this.store.font; 95 + this.store.font = font !== '' ? allowedFont[font.toLowerCase()] || font : this.store.font; 103 96 104 - this.store.align = align !== undefined 105 - ? align.toLowerCase() 106 - : this.store.align; 97 + this.store.align = align !== undefined ? align.toLowerCase() : this.store.align; 107 98 108 - this.store.colors = Array.isArray( colors ) 109 - ? colors.map( color => allowedColors[ color.toLowerCase() ] || color ) 99 + this.store.colors = Array.isArray(colors) 100 + ? colors.map((color) => allowedColors[color.toLowerCase()] || color) 110 101 : this.store.colors; 111 102 112 103 const bg = backgroundColor || background; 113 - this.store.background = bg !== undefined 114 - ? allowedBG[ bg.toLowerCase() ] || bg 115 - : this.store.background; 104 + this.store.background = bg !== undefined ? allowedBG[bg.toLowerCase()] || bg : this.store.background; 116 105 117 - this.store.letterSpacing = letterSpacing !== undefined 118 - ? parseInt( letterSpacing.toString() ) 119 - : font.toLowerCase() === 'console' 106 + this.store.letterSpacing = 107 + letterSpacing !== undefined 108 + ? parseInt(letterSpacing.toString()) 109 + : font.toLowerCase() === 'console' 120 110 ? 0 121 111 : this.store.letterSpacing; 122 112 123 - this.store.lineHeight = lineHeight !== undefined 124 - ? parseInt( lineHeight.toString() ) 125 - : font.toLowerCase() === 'console' 113 + this.store.lineHeight = 114 + lineHeight !== undefined 115 + ? parseInt(lineHeight.toString()) 116 + : font.toLowerCase() === 'console' 126 117 ? 0 127 118 : this.store.lineHeight; 128 119 129 - this.store.space = typeof space === 'boolean' 130 - ? space 131 - : this.store.space; 120 + this.store.space = typeof space === 'boolean' ? space : this.store.space; 132 121 133 - this.store.maxLength = maxLength !== undefined 134 - ? maxLength 135 - : this.store.maxLength; 122 + this.store.maxLength = maxLength !== undefined ? maxLength : this.store.maxLength; 136 123 137 - this.store.gradient = gradient !== undefined && typeof gradient !== 'boolean' 138 - ? Array.isArray( gradient ) 139 - ? gradient 140 - : gradient.split(',') 141 - : gradient === false 124 + this.store.gradient = 125 + gradient !== undefined && typeof gradient !== 'boolean' 126 + ? Array.isArray(gradient) 127 + ? gradient 128 + : gradient.split(',') 129 + : gradient === false 142 130 ? false 143 131 : this.store.gradient; 144 132 145 - this.store.independentGradient = independentGradient !== undefined 146 - ? independentGradient 147 - : this.store.independentGradient; 133 + this.store.independentGradient = 134 + independentGradient !== undefined ? independentGradient : this.store.independentGradient; 148 135 149 - this.store.transitionGradient = transitionGradient !== undefined 150 - ? transitionGradient 151 - : this.store.transitionGradient; 136 + this.store.transitionGradient = 137 + transitionGradient !== undefined ? transitionGradient : this.store.transitionGradient; 152 138 153 - this.store.env = env !== undefined 154 - ? env 155 - : this.store.env; 139 + this.store.env = env !== undefined ? env : this.store.env; 156 140 }, 157 141 }; 158 - 159 142 160 143 module.exports = exports = { 161 144 Options, skipped 2 lines -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * ParseArgs 12 + * Parse cli arguments into a nice object 13 + * 14 + **************************************************************************************************************************************************************/ 15 + 16 + 'use strict'; 17 + 18 + const { AddShortcuts } = require('./AddShortcuts.js'); 19 + const { CLIOPTIONS } = require('./constants.js'); 20 + const { Debugging } = require('./Debugging.js'); 21 + 22 + /** 23 + * Parse cli arguments into a nice object 24 + * 25 + * @param {object} inputOptions - All possible options registered for this app 26 + * @param {array} inputArgs - The arguments given to us in our cli, default: process.argv 27 + * 28 + * @return {object} - An object of all options with at least their default values 29 + */ 30 + const ParseArgs = (inputOptions = CLIOPTIONS, inputArgs = process.argv) => { 31 + const parsedArgs = { 32 + text: inputArgs[2], 33 + }; 34 + 35 + // create defaults 36 + Object.keys(inputOptions).forEach((option) => { 37 + const name = option.replace('--', ''); 38 + 39 + parsedArgs[name] = inputOptions[option].default; 40 + }); 41 + 42 + if (inputArgs[2] === '--help' || inputArgs[2] === '-h') { 43 + parsedArgs.help = true; 44 + } 45 + 46 + if (inputArgs[2] === '--version' || inputArgs[2] === '-v') { 47 + parsedArgs.version = true; 48 + } 49 + 50 + const args = inputArgs.splice(3); // the first two are node specific, the third is our text 51 + 52 + const options = AddShortcuts(inputOptions); 53 + 54 + for (let index = 0; args.length > index; index++) { 55 + const option = options[args[index]]; 56 + 57 + if (option) { 58 + const name = option._name.replace('--', ''); 59 + 60 + if (option.options !== undefined) { 61 + index++; 62 + const value = args[index]; 63 + 64 + parsedArgs[name] = value; 65 + } else { 66 + parsedArgs[name] = true; 67 + } 68 + } else { 69 + Debugging.report(`The cli argument ${args[index]} was not found and ignored`, 2); 70 + } 71 + } 72 + 73 + return parsedArgs; 74 + }; 75 + 76 + module.exports = exports = { 77 + ParseArgs, 78 + }; 79 + -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * Render 12 + * Main method to get the ANSI output for a string 13 + * 14 + **************************************************************************************************************************************************************/ 15 + 16 + 'use strict'; 17 + 18 + const { AddLetterSpacing } = require('./AddLetterSpacing.js'); 19 + const { Debugging, DEBUG } = require('./Debugging.js'); 20 + const { PaintGradient } = require('./Gradient.js'); 21 + const { CharLength } = require('./CharLength.js'); 22 + const { CheckInput } = require('./CheckInput.js'); 23 + const { CleanInput } = require('./CleanInput.js'); 24 + const { AlignText } = require('./AlignText.js'); 25 + const { AddLine } = require('./AddLine.js'); 26 + const { AddChar } = require('./AddChar.js'); 27 + const { Options } = require('./Options.js'); 28 + const { GetFont } = require('./GetFont.js'); 29 + const { CHARS } = require('./constants.js'); 30 + const { Color } = require('./Color.js'); 31 + const { Size } = require('./Size.js'); 32 + const { Log } = require('./Log.js'); 33 + 34 + /** 35 + * Main method to get the ANSI output for a string 36 + * 37 + * @param {string} input - The string you want to write out 38 + * @param {object} SETTINGS - Settings object 39 + * @param {boolean} debug - A flag to enable debug mode 40 + * @param {number} debuglevel - The debug level we want to show 41 + * @param {object} size - The size of the terminal as an object, default: Size 42 + * @param {number} size.width - The width of the terminal 43 + * @param {number} size.height - The height of the terminal 44 + * 45 + * @typedef {(object|boolean)} ReturnObject 46 + * @property {string} string - The pure string for output with all line breaks 47 + * @property {array} array - Each line of output in an array 48 + * @property {number} lines - The number of lines 49 + * @property {object} options - All options used 50 + * 51 + * @return {ReturnObject} - CLI output of INPUT to be consoled out 52 + */ 53 + const Render = (input, SETTINGS = {}, debug = DEBUG.enabled, debuglevel = DEBUG.level, size = Size) => { 54 + Debugging.report(`Running render`, 1); 55 + 56 + DEBUG.enabled = debug; 57 + DEBUG.level = debuglevel; 58 + 59 + const INPUT = CleanInput(input, CHARS); 60 + Options.reset(); 61 + Options.set = SETTINGS; 62 + const OPTIONS = Options.get; 63 + 64 + let output = []; // for output where each line is an output line 65 + let lines = 0; // for counting each line 66 + let FONTFACE = {}; // scoping the fontface object higher for fonts with just one color 67 + 68 + const _isGoodHuman = CheckInput( 69 + INPUT, 70 + OPTIONS.font, 71 + OPTIONS.colors, 72 + OPTIONS.background, 73 + OPTIONS.align, 74 + OPTIONS.gradient, 75 + OPTIONS.transitionGradient, 76 + OPTIONS.env 77 + ); 78 + if (!_isGoodHuman.pass) { 79 + Log.error(_isGoodHuman.message); 80 + 81 + return false; 82 + } 83 + 84 + // the gradient option supersedes the color options 85 + if (OPTIONS.gradient) { 86 + OPTIONS.colors = []; 87 + } 88 + 89 + // display an overview of options if debug flag is enabled 90 + if (DEBUG.enabled) { 91 + let outOption = `OPTIONS:\n Text: ${INPUT}`; 92 + 93 + for (let key in OPTIONS) { 94 + outOption += `\n Options.${key}: ${OPTIONS[key]}`; 95 + } 96 + 97 + Debugging.report(outOption, 3); 98 + } 99 + 100 + if (OPTIONS.env === 'browser') { 101 + size = { ...size }; // we clone so we don't make changes to this object across multiple instances 102 + size.width = OPTIONS.maxLength === 0 ? 999999999999 : OPTIONS.maxLength; 103 + } 104 + 105 + FONTFACE = GetFont(OPTIONS.font); 106 + if (!FONTFACE) { 107 + Log.error(`Font file for the font "${OPTIONS.font}" could not be found.\nTry reinstalling this package.`); 108 + 109 + return false; 110 + } 111 + 112 + // setting the letterspacing preference from font face if there is no user overwrite 113 + if (SETTINGS.letterSpacing === undefined) { 114 + Debugging.report(`Looking up letter spacing from font face`, 1); 115 + 116 + let width = 0; 117 + 118 + FONTFACE.letterspace.forEach((item) => { 119 + let char = item.replace(/(<([^>]+)>)/gi, ''); // get character and strip color infos 120 + 121 + if (width < char.length) { 122 + width = char.length; 123 + } 124 + }); 125 + 126 + Debugging.report(`Letter spacing set to font face default: "${width}"`, 2); 127 + OPTIONS.letterSpacing = width; 128 + } 129 + 130 + let lineLength = CharLength(FONTFACE.buffer, FONTFACE.lines, OPTIONS); // count each output character per line and start with the buffer 131 + let maxChars = 0; // count each character we print for maxLength option 132 + 133 + output = AddLine([], FONTFACE.lines, FONTFACE.buffer, OPTIONS.lineHeight); // create first lines with buffer 134 + lines++; 135 + 136 + for (let i = 0; i < INPUT.length; i++) { 137 + // iterate through the message 138 + let CHAR = INPUT.charAt(i).toUpperCase(); // the current character we convert, only upper case is supported at this time 139 + let lastLineLength = lineLength; // we need the lineLength for alignment before we look up if the next char fits 140 + 141 + Debugging.report(`Character found in font: "${CHAR}"`, 2); 142 + 143 + if (CHAR !== `|`) { 144 + // what will the line length be if we add the next char? 145 + lineLength += CharLength(FONTFACE.chars[CHAR], FONTFACE.lines, OPTIONS); // get the length of this character 146 + lineLength += CharLength(FONTFACE.letterspace, FONTFACE.lines, OPTIONS) * OPTIONS.letterSpacing; // new line, new line length 147 + } 148 + 149 + // jump to next line after OPTIONS.maxLength characters or when line break is found or the console windows would have ran out of space 150 + if ((maxChars >= OPTIONS.maxLength && OPTIONS.maxLength != 0) || CHAR === `|` || lineLength > size.width) { 151 + lines++; 152 + 153 + Debugging.report( 154 + `NEWLINE: maxChars: ${maxChars}, ` + 155 + `OPTIONS.maxLength: ${OPTIONS.maxLength}, ` + 156 + `CHAR: ${CHAR}, ` + 157 + `lineLength: ${lineLength}, ` + 158 + `Size.width: ${size.width} `, 159 + 2 160 + ); 161 + 162 + if (OPTIONS.env === 'node') { 163 + output = AlignText(output, lastLineLength, FONTFACE.lines, OPTIONS.align, size); // calculate alignment based on lineLength 164 + } 165 + 166 + lineLength += CharLength(FONTFACE.letterspace, FONTFACE.lines, OPTIONS) * OPTIONS.letterSpacing; // each new line starts with letter spacing 167 + lineLength = CharLength(FONTFACE.buffer, FONTFACE.lines, OPTIONS); // new line: new line length 168 + 169 + if (CHAR !== `|`) { 170 + // if this is a character and not a line break 171 + lineLength += CharLength(FONTFACE.letterspace, FONTFACE.lines, OPTIONS) * OPTIONS.letterSpacing; // add letter spacing at the end 172 + lineLength += CharLength(FONTFACE.chars[CHAR], FONTFACE.lines, OPTIONS); // get the length of this character 173 + } 174 + 175 + maxChars = 0; // new line, new maxLength goal 176 + 177 + output = AddLine(output, FONTFACE.lines, FONTFACE.buffer, OPTIONS.lineHeight); // adding new line 178 + // add letter spacing to the beginning 179 + } 180 + 181 + Debugging.report(`lineLength at: "${lineLength}"`, 2); 182 + 183 + if (CHAR !== `|`) { 184 + maxChars++; // counting all printed characters 185 + output = AddLetterSpacing( 186 + output, 187 + FONTFACE.lines, 188 + FONTFACE.letterspace, 189 + FONTFACE.colors, 190 + OPTIONS.colors, 191 + OPTIONS.letterSpacing 192 + ); 193 + output = AddChar(CHAR, output, FONTFACE.lines, FONTFACE.chars, FONTFACE.colors, OPTIONS.colors); // add new character 194 + } 195 + } 196 + 197 + if (OPTIONS.env === 'node') { 198 + output = AlignText(output, lineLength, FONTFACE.lines, OPTIONS.align, size); // alignment last line 199 + } 200 + 201 + if (OPTIONS.gradient) { 202 + output = PaintGradient({ 203 + output, 204 + gradient: OPTIONS.gradient, 205 + lines, 206 + lineHeight: OPTIONS.lineHeight, 207 + fontLines: FONTFACE.lines, 208 + independentGradient: OPTIONS.independentGradient, 209 + transitionGradient: OPTIONS.transitionGradient, 210 + }); 211 + } 212 + 213 + if (OPTIONS.space) { 214 + // add space 215 + if (OPTIONS.align === 'top') { 216 + output[output.length - 1] = `${output[output.length - 1]}\n\n\n\n`; 217 + } else if (OPTIONS.align === 'bottom') { 218 + output[0] = `\n\n\n\n${output[0]}`; 219 + } else { 220 + output[0] = `\n\n${output[0]}`; 221 + output[output.length - 1] = `${output[output.length - 1]}\n\n`; 222 + } 223 + } 224 + 225 + if (OPTIONS.background !== 'transparent' && OPTIONS.env === 'node') { 226 + const { open: openNew, close: closeNew } = Color(OPTIONS.background, true); 227 + 228 + output[0] = `${openNew}\n${output[0]}`; 229 + output[output.length - 1] = `${output[output.length - 1]}${closeNew}`; 230 + } 231 + 232 + let write = output.join(OPTIONS.env === 'node' ? `\n` : '<br>\n'); 233 + 234 + if (OPTIONS.env === 'browser') { 235 + const { open: bgColor } = Color(OPTIONS.background, true); 236 + 237 + write = 238 + `<div style="font-family:monospace;white-space:pre;text-align:${ 239 + OPTIONS.align 240 + };max-width:100%;overflow:scroll;background:${bgColor ? bgColor : 'transparent'}">` + 241 + `${write}` + 242 + `</div>`; 243 + } 244 + 245 + return { 246 + string: write, 247 + array: output, 248 + lines: lines, 249 + options: OPTIONS, 250 + }; 251 + }; 252 + 253 + module.exports = exports = { 254 + Render, 255 + }; 256 + -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 7 lines 18 18 const { Debugging, DEBUG } = require('./Debugging.js'); 19 19 const { Render } = require('./Render.js'); 20 20 const { Size } = require('./Size.js'); 21 - 22 21 23 22 /** 24 23 * Print to console skipped 6 lines 31 30 * @param {number} size.width - The width of the terminal 32 31 * @param {number} size.height - The height of the terminal 33 32 */ 34 - const Say = ( INPUT, SETTINGS = {}, debug = DEBUG.enabled, debuglevel = DEBUG.level, size = Size ) => { 33 + const Say = (INPUT, SETTINGS = {}, debug = DEBUG.enabled, debuglevel = DEBUG.level, size = Size) => { 35 34 Debugging.report(`Running say`, 1); 36 35 37 36 DEBUG.enabled = debug; 38 37 DEBUG.level = debuglevel; 39 38 40 - const write = Render( INPUT, SETTINGS, debug, debuglevel, size ); 39 + const write = Render(INPUT, SETTINGS, debug, debuglevel, size); 41 40 42 - if( write ) { 43 - console.log( write.string ); // write out 41 + if (write) { 42 + console.log(write.string); // write out 44 43 } 45 44 }; 46 - 47 45 48 46 module.exports = exports = { 49 47 Say, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 6 lines 17 17 18 18 const WinSize = require('window-size'); 19 19 20 - 21 20 /** 22 21 * Abstraction for windows size 23 22 * 24 23 * @type {object} 25 24 */ 26 25 const Size = { 27 - width: WinSize 28 - ? WinSize.width > 0 29 - ? WinSize.width 30 - : 80 31 - : 80, 32 - height: WinSize 33 - ? WinSize.height > 0 34 - ? WinSize.height 35 - : 24 36 - : 24, 26 + width: WinSize ? (WinSize.width > 0 ? WinSize.width : 80) : 80, 27 + height: WinSize ? (WinSize.height > 0 ? WinSize.height : 24) : 24, 37 28 }; 38 - 39 29 40 30 module.exports = exports = { 41 31 Size, skipped 2 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 4 lines 15 15 16 16 'use strict'; 17 17 18 - 19 18 /** 20 19 * Upper case the first character of an input string. 21 20 * skipped 3 lines 25 24 * 26 25 * @return {string} - A string with the first letter in upper case 27 26 */ 28 - const UpperCaseFirst = input => typeof input === 'string' 29 - ? input.charAt(0).toUpperCase() + input.substr(1) 30 - : input; 31 - 27 + const UpperCaseFirst = (input) => (typeof input === 'string' ? input.charAt(0).toUpperCase() + input.substr(1) : input); 32 28 33 29 module.exports = exports = { 34 30 UpperCaseFirst, skipped 2 lines -
skipped 4 lines 5 5 * 6 6 * Sexy fonts for the console. (CLI output) 7 7 * 8 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 8 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 9 9 * @author Dominik Wilkowski [email protected] 10 10 * @repository https://github.com/dominikwilkowski/cfonts 11 11 * skipped 6 lines -
skipped 3 lines 4 4 * 5 5 * Sexy fonts for the console. (CLI output) 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 6 lines 17 17 * FONTFACES 18 18 * CLIOPTIONS 19 19 * PACKAGE 20 - * HEXTEST 21 20 * 22 21 **************************************************************************************************************************************************************/ 23 22 24 23 'use strict'; 25 - 26 - const { Chalk } = require('./Chalk.js'); 27 - 28 24 29 25 // global defaults 30 26 const CHARS = [ 31 - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 32 - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "|", 33 - "!", "?", ".", "+", "-", "_", "=", "@", "#", "$", "%", "&", "(", ")", "/", ":", ";", ",", " ", "'", "\"", 27 + 'A', 28 + 'B', 29 + 'C', 30 + 'D', 31 + 'E', 32 + 'F', 33 + 'G', 34 + 'H', 35 + 'I', 36 + 'J', 37 + 'K', 38 + 'L', 39 + 'M', 40 + 'N', 41 + 'O', 42 + 'P', 43 + 'Q', 44 + 'R', 45 + 'S', 46 + 'T', 47 + 'U', 48 + 'V', 49 + 'W', 50 + 'X', 51 + 'Y', 52 + 'Z', 53 + '0', 54 + '1', 55 + '2', 56 + '3', 57 + '4', 58 + '5', 59 + '6', 60 + '7', 61 + '8', 62 + '9', 63 + '|', 64 + '!', 65 + '?', 66 + '.', 67 + '+', 68 + '-', 69 + '_', 70 + '=', 71 + '@', 72 + '#', 73 + '$', 74 + '%', 75 + '&', 76 + '(', 77 + ')', 78 + '/', 79 + ':', 80 + ';', 81 + ',', 82 + ' ', 83 + "'", 84 + '"', 34 85 ]; 35 86 36 87 const COLORS = { skipped 49 lines 86 137 }; 87 138 88 139 const GRADIENTS = { 89 - lgbt: [ '#750787', '#004dff', '#008026', '#ffed00', '#ff8c00', '#e40303' ], 90 - lgbtq: [ '#750787', '#004dff', '#008026', '#ffed00', '#ff8c00', '#e40303' ], 91 - pride: [ '#750787', '#004dff', '#008026', '#ffed00', '#ff8c00', '#e40303' ], 92 - agender: [ '#000000', '#b9b9b9', '#ffffff', '#b8f483', '#ffffff', '#b9b9b9', '#000000' ], 93 - aromantic: [ '#3da542', '#a7d379', '#ffffff', '#a9a9a9', '#000000' ], 94 - asexual: [ '#000000', '#a3a3a3', '#ffffff', '#800080' ], 95 - bisexual: [ '#d60270', '#d60270', '#9b4f96', '#0038a8', '#0038a8' ], 96 - genderfluid: [ '#ff75a2', '#ffffff', '#be18d6', '#000000', '#333ebd' ], 97 - genderqueer: [ '#b57edc', '#ffffff', '#4a8123' ], 98 - intersex: [ '#ffd800', '#ffd800', '#7902aa', '#ffd800', '#ffd800' ], 99 - lesbian: [ '#d52d00', '#ff9a56', '#ffffff', '#d362a4', '#a30262' ], 100 - nonbinary: [ '#fcf434', '#ffffff', '#9c5cd4', '#2c2c2c' ], 101 - pansexual: [ '#ff218c', '#ffd800', '#21b1ff' ], 102 - polysexual: [ '#f61cb9', '#07d569', '#1c92f6' ], 103 - transgender: [ '#5bcefa', '#f5a9b8', '#ffffff', '#f5a9b8', '#5bcefa' ], 140 + lgbt: ['#750787', '#004dff', '#008026', '#ffed00', '#ff8c00', '#e40303'], 141 + lgbtq: ['#750787', '#004dff', '#008026', '#ffed00', '#ff8c00', '#e40303'], 142 + pride: ['#750787', '#004dff', '#008026', '#ffed00', '#ff8c00', '#e40303'], 143 + agender: ['#000000', '#b9b9b9', '#ffffff', '#b8f483', '#ffffff', '#b9b9b9', '#000000'], 144 + aromantic: ['#3da542', '#a7d379', '#ffffff', '#a9a9a9', '#000000'], 145 + asexual: ['#000000', '#a3a3a3', '#ffffff', '#800080'], 146 + bisexual: ['#d60270', '#d60270', '#9b4f96', '#0038a8', '#0038a8'], 147 + genderfluid: ['#ff75a2', '#ffffff', '#be18d6', '#000000', '#333ebd'], 148 + genderqueer: ['#b57edc', '#ffffff', '#4a8123'], 149 + intersex: ['#ffd800', '#ffd800', '#7902aa', '#ffd800', '#ffd800'], 150 + lesbian: ['#d52d00', '#ff9a56', '#ffffff', '#d362a4', '#a30262'], 151 + nonbinary: ['#fcf434', '#ffffff', '#9c5cd4', '#2c2c2c'], 152 + pansexual: ['#ff218c', '#ffd800', '#21b1ff'], 153 + polysexual: ['#f61cb9', '#07d569', '#1c92f6'], 154 + transgender: ['#5bcefa', '#f5a9b8', '#ffffff', '#f5a9b8', '#5bcefa'], 104 155 }; 105 156 106 - const ALIGNMENT = [ 107 - 'left', 108 - 'center', 109 - 'right', 110 - 'top', 111 - 'bottom', 112 - ]; 157 + const ALIGNMENT = ['left', 'center', 'right', 'top', 'bottom']; 113 158 114 159 const FONTFACES = { 115 160 console: 'console', skipped 26 lines 142 187 }, 143 188 '--font': { 144 189 description: 'Use to define the font face', 145 - example: `--font block ${ Chalk.green(`( ${ Object.keys( FONTFACES ).map( font => FONTFACES[ font ] ).join(', ') } )`) }`, 190 + example: `--font block [green-open][ ${Object.keys(FONTFACES) 191 + .map((font) => FONTFACES[font]) 192 + .join(', ')} ][green-close]`, 146 193 short: '-f', 147 - options: Object.keys( FONTFACES ).map( color => FONTFACES[ color ] ), 194 + options: Object.keys(FONTFACES).map((color) => FONTFACES[color]), 148 195 default: 'block', 149 196 }, 150 197 '--colors': { 151 198 description: 'Use to define the font color', 152 - example: `--colors red ${ Chalk.green(`( ${ Object.keys( COLORS ).map( color => COLORS[ color ] ).join(', ') }, #ff8800, hex-colors etc... )`) }`, 199 + example: `--colors red [green-open][ ${Object.keys(COLORS) 200 + .map((color) => COLORS[color]) 201 + .join(', ')}, #ff8800, hex-colors etc... ][green-close]`, 153 202 short: '-c', 154 203 options: true, 155 204 default: 'system', 156 205 }, 157 206 '--background': { 158 207 description: 'Use to define background color', 159 - example: `--background blue ${ Chalk.green(`( ${ Object.keys( BGCOLORS ).map( bgcolor => BGCOLORS[ bgcolor ] ).join(', ') } )`) }`, 208 + example: `--background blue [green-open][ ${Object.keys(BGCOLORS) 209 + .map((bgcolor) => BGCOLORS[bgcolor]) 210 + .join(', ')} ][green-close]`, 160 211 short: '-b', 161 - options: Object.keys( BGCOLORS ).map( color => BGCOLORS[ color ] ), 212 + options: Object.keys(BGCOLORS).map((color) => BGCOLORS[color]), 162 213 default: 'transparent', 163 214 }, 164 215 '--align': { 165 216 description: 'Use to align your text output', 166 - example: `--align ${ Chalk.green(`( ${ ALIGNMENT.join(', ') } )`) }`, 217 + example: `--align [green-open][ ${ALIGNMENT.join(', ')} ][green-close]`, 167 218 short: '-a', 168 219 options: ALIGNMENT, 169 220 default: 'left', skipped 27 lines 197 248 }, 198 249 '--gradient': { 199 250 description: 'Use to define a start and end color of a gradient', 200 - example: '--gradient red,blue', 251 + example: '--gradient red,blue,green', 201 252 short: '-g', 202 253 options: true, 203 254 default: false, skipped 12 lines 216 267 }, 217 268 '--env': { 218 269 description: 'Use to define what environment you run CFonts in.', 219 - example: `--env ${ Chalk.green('"node", "browser"') }`, 270 + example: `--env [green-open][ "node", "browser" ][green-close]`, 220 271 short: '-e', 221 272 options: true, 222 273 default: 'node', skipped 15 lines 238 289 239 290 const PACKAGE = require('../package.json'); 240 291 241 - const HEXTEST = RegExp('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'); 242 - 243 - 244 292 module.exports = exports = { 245 293 CHARS, 246 294 COLORS, skipped 4 lines 251 299 FONTFACES, 252 300 CLIOPTIONS, 253 301 PACKAGE, 254 - HEXTEST, 255 302 }; 256 303 -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts 4 + * 5 + * Sexy fonts for the console. (CLI output) 6 + * 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 + * @author Dominik Wilkowski [email protected] 9 + * @repository https://github.com/dominikwilkowski/cfonts 10 + * 11 + * Cli 12 + * Run cli commands 13 + * 14 + **************************************************************************************************************************************************************/ 15 + 16 + 'use strict'; 17 + 18 + const { DisplayVersion } = require('./DisplayVersion.js'); 19 + const { DisplayHelp } = require('./DisplayHelp.js'); 20 + const { CLIOPTIONS } = require('./constants.js'); 21 + const { Debugging } = require('./Debugging.js'); 22 + const { ParseArgs } = require('./ParseArgs.js'); 23 + const { Render } = require('./Render.js'); 24 + const { Color } = require('./Color.js'); 25 + const { Log } = require('./Log.js'); 26 + const { Say } = require('./Say.js'); 27 + 28 + /** 29 + * Run cli commands 30 + * 31 + * @param {object} inputOptions - All possible options registered for this app 32 + * @param {array} inputArgs - The arguments given to us in our cli, default: process.argv 33 + */ 34 + const Cli = (inputOptions = CLIOPTIONS, inputArgs = process.argv) => { 35 + const args = ParseArgs(inputOptions, inputArgs); 36 + 37 + Debugging.report( 38 + `OPTIONS:\n` + 39 + ` CFonts.say("${args.text}", {\n` + 40 + ` font: "${args.font}",\n` + 41 + ` align: "${args.align}",\n` + 42 + ` colors: ${args.colors ? JSON.stringify(args.colors.split(',')) : []},\n` + 43 + ` background: "${args.background}",\n` + 44 + ` letterSpacing: ${args['letter-spacing']},\n` + 45 + ` lineHeight: ${args['line-height']},\n` + 46 + ` space: ${!args.spaceless},\n` + 47 + ` maxLength: ${args['max-length']},\n` + 48 + ` gradient: ${args.gradient},\n` + 49 + ` independentGradient: ${args['independent-gradient']},\n` + 50 + ` transitionGradient: ${args['transition-gradient']},\n` + 51 + ` env: ${args.env},\n` + 52 + ` }, ${args.debug}, ${args.debugLevel} );`, 53 + 3, 54 + args.debug, 55 + args.debugLevel 56 + ); 57 + 58 + if (args.help) { 59 + DisplayHelp(); 60 + return; 61 + } 62 + 63 + if (args.version) { 64 + DisplayVersion(); 65 + return; 66 + } 67 + 68 + if (!args.text) { 69 + const { open: green_open, close: green_close } = Color('green'); 70 + Log.error( 71 + `Please provide text to convert with ${green_open}cfonts "Text"${green_close}\n` + 72 + `Run ${green_open}cfonts --help${green_close} for more infos` 73 + ); 74 + return; 75 + } 76 + 77 + Say( 78 + args.text, 79 + { 80 + font: args.font, 81 + align: args.align, 82 + colors: args.colors ? args.colors.split(',') : [], 83 + background: args.background, 84 + letterSpacing: args['letter-spacing'], 85 + lineHeight: args['line-height'], 86 + space: !args.spaceless, 87 + maxLength: args['max-length'], 88 + gradient: args.gradient, 89 + independentGradient: args['independent-gradient'], 90 + transitionGradient: args['transition-gradient'], 91 + env: args.env, 92 + }, 93 + args.debug, 94 + args.debugLevel 95 + ); 96 + }; 97 + 98 + module.exports = exports = { 99 + render: Render, 100 + say: Say, 101 + Cli, 102 + }; 103 + -
skipped 3 lines 4 4 * 5 5 * Testing the API side of things. 6 6 * 7 - * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv2 7 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 8 8 * @author Dominik Wilkowski [email protected] 9 9 * @repository https://github.com/dominikwilkowski/cfonts 10 10 * skipped 39 lines 50 50 colors: ['red'], 51 51 }); 52 52 53 - CFonts.say(`Hello 54 - world\nagain|!`, { 55 - font: 'simple', 56 - align: 'center', 57 - colors: ['red'], 58 - }); 53 + CFonts.say( 54 + `Hello 55 + world\nagain|!`, 56 + { 57 + font: 'simple', 58 + align: 'center', 59 + colors: ['red'], 60 + } 61 + ); 59 62 60 63 CFonts.say('Hi|world!', { 61 - gradient: ['red','green'], 64 + gradient: ['red', 'green'], 62 65 }); 63 66 64 67 CFonts.say('Hi|world!', { 65 - gradient: ['red','green'], 68 + gradient: ['red', 'green'], 66 69 independentGradient: true, 67 70 }); 68 71 69 72 CFonts.say('Hi|world!', { 70 - gradient: ['red','green'], 73 + gradient: ['red', 'green'], 71 74 transitionGradient: true, 72 75 }); 73 76 74 77 CFonts.say('Hi|world!', { 75 - gradient: ['red','green'], 78 + gradient: ['red', 'green'], 76 79 independentGradient: true, 77 80 transitionGradient: true, 78 81 }); skipped 50 lines 129 132 <body style="background:#f1f1f1"> 130 133 <h1>CFonts browser test</h1> 131 134 <h2>Font one</h2> 132 - ${ prettyFont2.string } 135 + ${prettyFont2.string} 133 136 <h2>Font two</h2> 134 - ${ prettyFont3.string } 137 + ${prettyFont3.string} 135 138 <h2>Font three</h2> 136 - ${ prettyFont4.string } 139 + ${prettyFont4.string} 137 140 <h2>Font four</h2> 138 - ${ prettyFont5.string } 141 + ${prettyFont5.string} 139 142 </body> 140 143 </html> 141 144 `; 142 145 143 - const check = fs.writeFileSync( path.normalize(`${ __dirname }/test.html`), html, { encoding: 'utf8' } ); 144 - 146 + const check = fs.writeFileSync(path.normalize(`${__dirname}/test.html`), html, { encoding: 'utf8' }); 145 147 146 148 // for issue #13 147 - Array.prototype.foo = () => { return 0; }; 148 - CFonts.say('Hello', { colors: [ 'green' ] }); 149 + Array.prototype.foo = () => { 150 + return 0; 151 + }; 152 + CFonts.say('Hello', { colors: ['green'] }); 149 153 -
1 + /*************************************************************************************************************************************************************** 2 + * 3 + * cfonts, Sexy fonts for the console. (CLI output) 4 + * 5 + * Testing the each font file: 6 + * - Font file has all font attributes? 7 + * - All characters included? 8 + * - All characters have the correct width? 9 + * - All characters have consistent lines? 10 + * 11 + * @license https://github.com/dominikwilkowski/cfonts/blob/released/LICENSE GNU GPLv3 12 + * @author Dominik Wilkowski [email protected] 13 + * @repository https://github.com/dominikwilkowski/cfonts 14 + * 15 + **************************************************************************************************************************************************************/ 16 + 17 + 'use strict'; 18 + 19 + // Dependencies 20 + const { CHARS: CFontsChars, FONTFACES: CFontsFontfaces } = require('../src/constants.js'); 21 + const { Size } = require('../src/Size.js'); 22 + const Readline = require('readline'); 23 + const Chalk = require(`chalk`); 24 + const Path = require('path'); 25 + const Fs = require(`fs`); 26 + 27 + // global defaults 28 + const DEBUG = true; 29 + const DEBUGLEVEL = 2; 30 + const CHARS = CFontsChars.filter((font) => font !== '|'); // we don’t need the pipe in the char-set 31 + const FONTFACES = Object.keys(CFontsFontfaces).map((font) => CFontsFontfaces[font]); // console is a font but not a font-file 32 + 33 + /** 34 + * Test each font for common issues 35 + * 36 + * @param {array} FONTFACES - All font faces to be checked in an array 37 + * @param {array} CHARS - All characters that should be included 38 + */ 39 + const FontTest = (FONTFACES, CHARS) => { 40 + Debugging.report(`Running FontTest`, 1); 41 + 42 + let font = ''; 43 + let fontFile = ''; 44 + let FONTFACE = {}; 45 + 46 + for (let i in FONTFACES) { 47 + font = FONTFACES[i]; 48 + fontFile = Path.normalize(`${__dirname}/../../fonts/${font}.json`); 49 + 50 + Log.headline(`${font}`); 51 + Log.check(`Checking: "${font}" existence`); 52 + 53 + try { 54 + FONTFACE = JSON.parse(Fs.readFileSync(fontFile, 'utf8')); 55 + 56 + Log.subdone(`FOUND!`); 57 + } catch (e) { 58 + Log.suberror(`NOT FOUND: "${fontFile}"`); 59 + } 60 + 61 + Attributes(FONTFACE); 62 + Letterspace_size(FONTFACE); 63 + Chars(FONTFACE, CHARS); 64 + Width(FONTFACE, CHARS); 65 + Lines(FONTFACE, CHARS); 66 + } 67 + 68 + console.log(`\n`); 69 + if (Log.errors > 0) { 70 + process.exit(1); 71 + } 72 + }; 73 + 74 + /** 75 + * Test the font has all attributes 76 + * 77 + * @param {object} FONTFACE - The font object for this font 78 + */ 79 + const Attributes = (FONTFACE) => { 80 + Debugging.report(`Running Attributes`, 1); 81 + Log.check(`Checking font attributes of "${FONTFACE.name}"`); 82 + let fails = []; 83 + 84 + if (FONTFACE.name === undefined) { 85 + fails.push(`name`); 86 + } 87 + 88 + if (FONTFACE.version === undefined) { 89 + fails.push(`version`); 90 + } 91 + 92 + if (FONTFACE.homepage === undefined) { 93 + fails.push(`homepage`); 94 + } 95 + 96 + if (FONTFACE.colors === undefined) { 97 + fails.push(`colors`); 98 + } 99 + 100 + if (FONTFACE.lines === undefined) { 101 + fails.push(`lines`); 102 + } 103 + 104 + if (FONTFACE.buffer === undefined) { 105 + fails.push(`buffer`); 106 + } 107 + 108 + if (FONTFACE.letterspace === undefined) { 109 + fails.push(`letterspace`); 110 + } 111 + 112 + if (FONTFACE.letterspace_size === undefined) { 113 + fails.push(`letterspace_size`); 114 + } 115 + 116 + if (FONTFACE.chars === undefined) { 117 + fails.push(`chars`); 118 + } 119 + 120 + if (fails.length > 0) { 121 + Log.suberror(`Font has missing attributes: "${fails.join(' ')}" in font: "${FONTFACE.name}"`); 122 + } else { 123 + Log.subdone(`All THERE!`); 124 + } 125 + }; 126 + 127 + /** 128 + * Test the font to include all characters 129 + * 130 + * @param {object} FONTFACE - The font object for this font 131 + * @param {array} CHARS - All characters that should be included 132 + */ 133 + const Letterspace_size = (FONTFACE) => { 134 + Debugging.report(`Running Letterspace_size`, 1); 135 + Log.check(`Checking letterspace_size in "${FONTFACE.name}"`); 136 + 137 + let width = 0; 138 + FONTFACE.letterspace.forEach((item) => { 139 + let char = item.replace(/(<([^>]+)>)/gi, ''); // get character and strip color infos 140 + 141 + if (width < char.length) { 142 + width = char.length; 143 + } 144 + }); 145 + 146 + if (FONTFACE.letterspace_size !== width) { 147 + Log.suberror( 148 + `Font has wrong letterspace_size attribute. Is: "${FONTFACE.letterspace_size}" but should be "${width}" in font: "${FONTFACE.name}"` 149 + ); 150 + } else { 151 + Log.subdone(`All CORRECT!`); 152 + } 153 + }; 154 + 155 + /** 156 + * Test the font to include all characters 157 + * 158 + * @param {object} FONTFACE - The font object for this font 159 + * @param {array} CHARS - All characters that should be included 160 + */ 161 + const Chars = (FONTFACE, CHARS) => { 162 + Debugging.report(`Running Chars`, 1); 163 + Log.check(`Checking all characters in "${FONTFACE.name}"`); 164 + let fails = []; 165 + 166 + for (let i in CHARS) { 167 + let char = CHARS[i]; 168 + 169 + if (FONTFACE.chars[char] === undefined) { 170 + fails.push(char); 171 + } 172 + } 173 + 174 + if (fails.length > 0) { 175 + Log.suberror(`Character could not be found: "${fails.join(' ')}" in font: "${FONTFACE.name}"`); 176 + } else { 177 + Log.subdone(`All THERE!`); 178 + } 179 + }; 180 + 181 + /** 182 + * Test each character has the right amount of lines 183 + * 184 + * @param {object} FONTFACE - The font object for this font 185 + * @param {array} CHARS - All characters that should be included 186 + */ 187 + const Lines = (FONTFACE, CHARS) => { 188 + Debugging.report(`Running Lines`, 1); 189 + Log.check(`Checking all character lines in "${FONTFACE.name}"`); 190 + let fails = []; 191 + 192 + if (FONTFACE.buffer.length !== FONTFACE.lines) { 193 + fails.push(`buffer`); 194 + } 195 + 196 + if (FONTFACE.letterspace.length !== FONTFACE.lines) { 197 + fails.push(`letterspace`); 198 + } 199 + 200 + for (let i in CHARS) { 201 + let char = CHARS[i]; 202 + 203 + if (FONTFACE.chars[char] !== undefined) { 204 + if (FONTFACE.chars[char].length !== FONTFACE.lines) { 205 + fails.push(char); 206 + } 207 + } 208 + } 209 + 210 + if (fails.length > 0) { 211 + Log.suberror(`Character lines are not correct in "${fails.join(' ')}" in font: "${FONTFACE.name}"`); 212 + } else { 213 + Log.subdone(`All CORRECT!`); 214 + } 215 + }; 216 + 217 + /** 218 + * Test each character to have the same width 219 + * 220 + * @param {object} FONTFACE - The font object for this font 221 + * @param {array} CHARS - All characters that should be included 222 + */ 223 + const Width = (FONTFACE, CHARS) => { 224 + Debugging.report(`Running Width`, 1); 225 + Log.check(`Checking all character widths in "${FONTFACE.name}"`); 226 + let fails = []; 227 + 228 + for (let i in CHARS) { 229 + let char = CHARS[i]; 230 + 231 + if (FONTFACE.chars[char] !== undefined) { 232 + let character = FONTFACE.chars[char]; 233 + let width = 0; 234 + 235 + for (let i = 0; i < character.length; i++) { 236 + character[i] = character[i].replace(/(<([^>]+)>)/gi, ''); 237 + 238 + if (i === 0) { 239 + width = character[i].length; 240 + } 241 + 242 + if (width !== character[i].length) { 243 + fails.push(`${char}((${width}) ${i}=${character[i].length})`); 244 + // break; // if we break here we fail on the first issue rather than collecting them all 245 + } 246 + } 247 + } 248 + } 249 + 250 + if (fails.length > 0) { 251 + Log.suberror(`Character width is not consistent in "${fails.join(' ')}" in font: "${FONTFACE.name}"`); 252 + } else { 253 + Log.subdone(`All CONSISTENT!`); 254 + } 255 + }; 256 + 257 + /** 258 + * A collection of methods to print debug message that will be logged to console if debug mode is enabled 259 + * 260 + * @type {Object} 261 + */ 262 + const Debugging = { 263 + /** 264 + * Print a headline preferably at the beginning of your app 265 + * 266 + * @param [text] {string} - The sting you want to log 267 + * @param [level] {integer} - (optional) The debug level. Show equal and greater levels. Default: 99 268 + */ 269 + headline: (text, level = 99) => { 270 + if (DEBUG && level >= DEBUGLEVEL) { 271 + console.log(Chalk.bgWhite(`\n${Chalk.bold(' \u2611 ')} ${text}`)); 272 + } 273 + }, 274 + 275 + /** 276 + * Print a message to report starting a process 277 + * 278 + * @param [text] {string} - The sting you want to log 279 + * @param [level] {integer} - (optional) The debug level. Show equal and greater levels. Default: 99 280 + */ 281 + report: (text, level = 99) => { 282 + if (DEBUG && level >= DEBUGLEVEL) { 283 + console.log(Chalk.bgWhite(`\n${Chalk.bold.green(' \u2611 ')} ${Chalk.black(`${text} `)}`)); 284 + } 285 + }, 286 + 287 + /** 288 + * Print a message to report an error 289 + * 290 + * @param [text] {string} - The sting you want to log 291 + * @param [level] {integer} - (optional) The debug level. Show equal and greater levels. Default: 99 292 + */ 293 + error: (text, level = 99) => { 294 + if (DEBUG && level >= DEBUGLEVEL) { 295 + console.log(Chalk.bgWhite(`\n${Chalk.red(' \u2612 ')} ${Chalk.black(`${text} `)}`)); 296 + } 297 + }, 298 + 299 + /** 300 + * Print a message to report an interaction 301 + * 302 + * @param [text] {string} - The sting you want to log 303 + * @param [level] {integer} - (optional) The debug level. Show equal and greater levels. Default: 99 304 + */ 305 + interaction: (text, level = 99) => { 306 + if (DEBUG && level >= DEBUGLEVEL) { 307 + console.log(Chalk.bgWhite(`\n${Chalk.blue(' \u261C ')} ${Chalk.black(`${text} `)}`)); 308 + } 309 + }, 310 + 311 + /** 312 + * Print a message to report data has been sent 313 + * 314 + * @param [text] {string} - The sting you want to log 315 + * @param [level] {integer} - (optional) The debug level. Show equal and greater levels. Default: 99 316 + */ 317 + send: (text, level = 99) => { 318 + if (DEBUG && level >= DEBUGLEVEL) { 319 + console.log(Chalk.bgWhite(`\n${Chalk.bold.cyan(' \u219D ')} ${Chalk.black(`${text} `)}`)); 320 + } 321 + }, 322 + 323 + /** 324 + * Print a message to report data has been received 325 + * 326 + * @param [text] {string} - The sting you want to log 327 + * @param [level] {integer} - (optional) The debug level. Show equal and greater levels. Default: 99 328 + */ 329 + received: (text, level = 99) => { 330 + if (DEBUG && level >= DEBUGLEVEL) { 331 + console.log(Chalk.bgWhite(`\n${Chalk.bold.cyan(' \u219C ')} ${Chalk.black(`${text} `)}`)); 332 + } 333 + }, 334 + }; 335 + 336 + /** 337 + * A collection of methods to print messages to console 338 + * 339 + * @type {Object} 340 + */ 341 + const Log = { 342 + errors: 0, 343 + 344 + /** 345 + * Start a test category 346 + * 347 + * @param {string} text - The name of the test 348 + */ 349 + headline: (text) => { 350 + let space = Math.floor((Size.width - text.length - 6) / 2); 351 + if (space < 0) { 352 + space = 1; 353 + } 354 + 355 + console.log(`\n${Chalk.bgWhite.black(`\n${' '.repeat(space)}══ ${text} ══`)}`); 356 + }, 357 + 358 + /** 359 + * Log a check and keep space for the result 360 + * 361 + * @param {string} text - The sting you want to log 362 + */ 363 + check: (text) => { 364 + let prefix = `${Chalk.bold.green(' \u231B ')} ${Chalk.bold.black('Testing:')} `; 365 + 366 + text = text.replace(/(?:\r\n|\r|\n)/g, `\n${' '.repeat(prefix.length)}`); 367 + process.stdout.write(`\n${Chalk.bgWhite(`${prefix}${Chalk.black(text)}`)}`); 368 + }, 369 + 370 + /** 371 + * Note positive outcome for previously run check method 372 + * 373 + * @param {string} text - Success message (not logged) 374 + */ 375 + subdone: (text) => { 376 + let prefix = ` ${Chalk.bold.black('OK')} `; 377 + text = text.replace(/(?:\r\n|\r|\n)/g, `\n ${' '.repeat(prefix.length)}`); 378 + 379 + Readline.cursorTo(process.stdout, 0); 380 + console.log(`${Chalk.bgGreen(` ${prefix}`)}`); 381 + // console.log(`${ Chalk.bgGreen(` ${ Chalk.black( text ) }`) }`); // not outputting message will keep things cleaner 382 + }, 383 + 384 + /** 385 + * Note negative outcome for previously run check method 386 + * 387 + * @param {string} text - Error message 388 + */ 389 + suberror: (text) => { 390 + Log.errors++; 391 + 392 + let prefix = ` ${Chalk.bold.black('FAIL')} `; 393 + text = text.replace(/(?:\r\n|\r|\n)/g, `\n ${' '.repeat(prefix.length)}`); 394 + 395 + Readline.cursorTo(process.stdout, 0); 396 + console.log(`${Chalk.bgRed(` ${prefix}`)}`); 397 + console.log(`${Chalk.bgRed(` ${Chalk.black(text)}`)}`); 398 + }, 399 + }; 400 + 401 + FontTest(FONTFACES, CHARS); 402 + -
test/test.html nodejs/test/test.htmlUnable to diff as some line is too long.
-
-
-
-
-
-