171 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const convert = require( 'color-convert' );
 | |
| const fs = require( 'fs' );
 | |
| const path = require( 'path' );
 | |
| 
 | |
| /**
 | |
|  * Recursively find all files with extension in a directory
 | |
|  * @param {string} dir The directory to search. Either absolute or relative path
 | |
|  * @param {string} extension The file extension to look for
 | |
|  * @returns {string[]} returns a list of html files with their full path
 | |
|  */
 | |
| const treeWalker = ( dir, extension, ignoreList ) => {
 | |
|     const ls = fs.readdirSync( dir );
 | |
|     const fileList = [];
 | |
|     for ( let file in ls ) {
 | |
|         if ( fs.statSync( path.join( dir, ls[ file ] ) ).isDirectory() ) {
 | |
|             // Filter ignored directories
 | |
|             if ( ignoreList === undefined || !ignoreList.includes( ls[ file ] ) ) {
 | |
|                 const newFiles = treeWalker( path.join( dir, ls[ file ] ), extension, ignoreList );
 | |
|                 for (let file = 0; file < newFiles.length; file++) {
 | |
|                     fileList.push( newFiles[ file ] );
 | |
|                 }
 | |
|             }
 | |
|         } else if ( extension == '*' || ls[ file ].includes( extension ) ) {
 | |
|             if ( ignoreList === undefined || !ignoreList.includes( ls[ file ] ) ) {
 | |
|                 fileList.push( path.join( dir, ls[ file ] ) );
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return fileList;
 | |
| }
 | |
| 
 | |
| const renderColourAsHex = ( colour ) => {
 | |
|     return '#' + convert.default.rgb.hex( colour[ 0 ], colour[ 1 ], colour[ 2 ] );
 | |
| }
 | |
| 
 | |
| const renderColourAsRGB = ( colour ) => {
 | |
|     return `rgb(${ colour[ 0 ] }, ${ colour[ 1 ] }, ${ colour[ 2 ] })`
 | |
| }
 | |
| 
 | |
| const renderColourAsRGBA = ( colour, ambiance ) => {
 | |
|     return `rgba(${ colour[ 0 ] }, ${ colour[ 1 ] }, ${ colour[ 2 ] }, ${ ambiance })`
 | |
| }
 | |
| 
 | |
| const renderColourAsRGBHex = ( colour ) => {
 | |
|     const hexCol = convert.default.rgb.hex( colour[ 0 ], colour[ 1 ], colour[ 2 ] );
 | |
|     return `rgb(${hexCol})`.toLowerCase();
 | |
| }
 | |
| 
 | |
| function decimalToHex(decimal) {
 | |
|   const hexValue = Math.round(decimal * 255);
 | |
|   return hexValue.toString(16).padStart(2, '0');
 | |
| }
 | |
| 
 | |
| const renderColourAsRGBAHex = ( colour, ambiance ) => {
 | |
|     const hexCol = convert.default.rgb.hex( colour[ 0 ], colour[ 1 ], colour[ 2 ] );
 | |
|     return `rgba(${hexCol}${decimalToHex(ambiance)})`.toLowerCase();
 | |
| }
 | |
| 
 | |
| const removeUselessColours = ( palette ) => {
 | |
|     const p = [];
 | |
|     for ( let i = 0; i < palette.length; i++ ) {
 | |
|         const luminance = calculateLuminance( palette[ i ] );
 | |
|         if ( luminance < 215 && luminance > 40 ) {
 | |
|             p.push( palette[ i ] );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| const calculateLuminance = ( colour ) => {
 | |
|     return colour[ 0 ] + colour[ 1 ] + colour[ 2 ] / 3;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Replace the colours with variable names
 | |
|  */
 | |
| const replacements = { 
 | |
|     '#0f1011': '@bg',
 | |
|     'rgba(9, 9, 10, 0.9)': '@bg_rgba_07',
 | |
|     'rgba(26, 28, 30, 0.3)': '@bg_rgba_05',
 | |
|     '#000': '@bg_accent',
 | |
|     '#000000': '@bg_accent',
 | |
|     'rgba(0, 0, 0, 0.7)': '@bg_accent_rgba_07',
 | |
|     'rgba(0, 0, 0, 0.6)': '@bg_accent_rgba_06',
 | |
|     'rgba(0, 0, 0, 0.5)': '@bg_accent_rgba_05',
 | |
|     'rgba(0, 0, 0, 0.4)': '@bg_accent_rgba_04',
 | |
|     'rgba(0, 0, 0, 0.3)': '@bg_accent_rgba_03',
 | |
|     'rgba(0, 0, 0, 0.12)': '@bg_accent_rgba_015',
 | |
|     'rgba(0, 0, 0, 0.08)': '@bg_accent_rgba_01',
 | |
|     'rgba(9, 9, 10, 0.9)': '@bg_inactive',
 | |
|     '#80868b': '@inactive',
 | |
|     'rgba(128, 134, 139, 0.7)': '@inactive_rgba_07',
 | |
|     'rgba(128, 134, 139, 0.5)': '@inactive_rgba_05',
 | |
|     'rgba(128, 134, 139, 0.3)': '@inactive_rgba_03',
 | |
|     'rgba(128, 134, 139, 0.2)': '@inactive_rgba_02',
 | |
|     // '#555A': '@shadow_rgba',
 | |
|     // '#555': '@shadow',
 | |
|     '#387db7': '@accent',
 | |
|     'rgba(56, 125, 183, 0.5)': '@accent_rgba_05',
 | |
|     'rgba(56, 125, 183, 0.32)': '@accent_rgba_03',
 | |
|     'rgba(56, 125, 183, 0.24)': '@accent_rgba_02',
 | |
|     'rgba(56, 125, 183, 0.16)': '@accent_rgba_015',
 | |
|     'rgba(56, 125, 183, 0.12)': '@accent_rgba_011',
 | |
|     'rgba(56, 125, 183, 0.08)': '@accent_rgba_007',
 | |
|     '#1a1a1b': '@accent_gradient_5',
 | |
|     '#1f1f21': '@accent_gradient_4',
 | |
|     '#1a2530': '@accent_gradient_3',
 | |
|     '#1c2c3b': '@accent_gradient_2',
 | |
|     '#1e3040': '@accent_gradient_1',
 | |
|     '#4887bd': '@accent_gradient_inverse_1',
 | |
|     '#508dc0': '@accent_gradient_inverse_2',
 | |
|     '#5892c3': '@accent_gradient_inverse_3',
 | |
|     '#673ab7': '@accent2',
 | |
|     'rgba(103, 58, 183, 0.12)': '@accent2_rgba_015',
 | |
|     '#fff': '@fg_accent',
 | |
|     'rgba(255, 255, 255, 0.7)': '@fg_accent_rgba_07',
 | |
|     'rgba(255, 255, 255, 0.6)': '@fg_accent_rgba_06',
 | |
|     'rgba(255, 255, 255, 0.5)': '@fg_accent_rgba_05',
 | |
|     'rgba(255, 255, 255, 0.3)': '@fg_accent_rgba_03',
 | |
|     'rgba(255, 255, 255, 0.2)': '@fg_accent_rgba_02',
 | |
|     '#9e9e9e': '@fg',
 | |
|     'rgba(158, 158, 158, 0.7)': '@fg_rgba_07',
 | |
|     'rgba(158, 158, 158, 0.6)': '@fg_rgba_06',
 | |
|     'rgba(158, 158, 158, 0.5)': '@fg_rgba_05',
 | |
|     'rgba(158, 158, 158, 0.3)': '@fg_rgba_03',
 | |
|     'rgba(158, 158, 158, 0.2)': '@fg_rgba_02',
 | |
|     'rgba(158, 158, 158, 0.1168)': '@fg_rgba_01'
 | |
| };
 | |
| const themePreProcessor = ( file, replacement, out ) => {
 | |
|     const colours = Object.keys( replacements );
 | |
|     let data = '' + fs.readFileSync( file );
 | |
|     for (let index = 0; index < colours.length; index++) {
 | |
|         const colour = colours[index];
 | |
|         data = data.replaceAll(colour, replacements[ colour ]);
 | |
|     }
 | |
|     
 | |
|     const outPath = file.replace( replacement, out );
 | |
|     try {
 | |
|         fs.mkdirSync( path.dirname( outPath ), {
 | |
|             recursive: true,
 | |
|         } );
 | |
|     } catch ( e ) {
 | |
|         console.error( e );
 | |
|     }
 | |
| 
 | |
|     fs.writeFileSync( outPath, data );
 | |
| }
 | |
| 
 | |
| const getGradientColour = ( colour, index, multiplier ) => {
 | |
|     if ( index === 0 ) {
 | |
|         return [ colour[ 0 ] * multiplier, colour[ 1 ] * multiplier, colour[ 2 ] * multiplier ];
 | |
|     }
 | |
|     const gradient = getGradientColour( colour, index - 1, multiplier );
 | |
|     return [ Math.min( 255, gradient[ 0 ] * multiplier ), Math.min( 255, gradient[ 1 ] * multiplier ), Math.min( 255, gradient[ 2 ] * multiplier ) ];
 | |
| }
 | |
| 
 | |
| module.exports = {
 | |
|     treeWalker,
 | |
|     renderColourAsHex,
 | |
|     renderColourAsRGB,
 | |
|     renderColourAsRGBA,
 | |
|     renderColourAsRGBHex,
 | |
|     renderColourAsRGBAHex,
 | |
|     themePreProcessor,
 | |
|     getGradientColour,
 | |
|     removeUselessColours
 | |
| }
 |