-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
793 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2021 Im-Beast | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<font size="6"><p align="center"><b>🖍️ Crayon.js</b></p></font> | ||
<hr /> | ||
|
||
## :books: About | ||
##### Crayon.js is **one of the best**<sup><sup>[1](https://github.com/crayon-js/crayon/wiki/Comparison)</sup></sup> performing terminal styling. Additionaly written in TypeScript. | ||
|
||
Instead of straight up saying "use it, it's better" check yourself what meets your requirements. | ||
|
||
#### 🖍️ Crayon.js has: | ||
* ⚡ High performance | ||
* 📦 No dependencies | ||
* ⏱️ Low import times | ||
* 🦄 Automatic color support detection & fallbacking | ||
* 🔗 Supported nesting & chaining | ||
* 🌈 8bit (256) and 24bit (16.7m) color support | ||
* 🌟 Emojis, really just bcs of that you should star this repo | ||
|
||
### Installation | ||
```bash | ||
npm install crayon.js #yarn add crayon.js | ||
``` | ||
|
||
### Wiki | ||
To learn more about Crayon and its API look [here](https://github.com/crayon-js/crayon/wiki) | ||
|
||
## :handshake: Contributing | ||
#### Feel free to add any commits, issues and pull requests | ||
|
||
## :memo: Licensing | ||
#### This project is available under MIT License conditions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { clamp } from './util.ts' | ||
|
||
export const ansi4ToAnsi3 = (code: number) => code % 8 | ||
|
||
export const rgbToAnsi4 = (r: number, g: number, b: number): number => { | ||
const value = Math.round(Math.max(r, g, b) / 255) | ||
return value > 0 | ||
? (value === 1 ? 0 : -8) + | ||
((Math.round(b / 255) << 2) | | ||
(Math.round(g / 255) << 1) | | ||
Math.round(r / 255)) | ||
: 0 | ||
} | ||
|
||
export const rgbToAnsi8 = (r: number, g: number, b: number): number => { | ||
r = Math.round(r) | ||
g = Math.round(g) | ||
b = Math.round(b) | ||
return Math.round( | ||
r === g && b == g | ||
? r < 8 | ||
? 16 | ||
: r > 248 | ||
? 231 | ||
: ((r - 8) / 247) * 24 + 232 | ||
: 36 * (r / 255) * 5 + 6 * (g / 255) * 5 + (b / 255) * 5 + 16 | ||
) | ||
} | ||
|
||
// https://github.com/Qix-/color-convert/blob/master/conversions.js | ||
export const ansi8ToAnsi4 = (code: number): number => { | ||
if (code >= 232) { | ||
const grayness = (code - 232) * 10 + 8 | ||
return rgbToAnsi4(grayness, grayness, grayness) | ||
} | ||
|
||
code -= 16 | ||
|
||
const rem = code % 36 | ||
const r = (Math.floor(code / 36) / 5) * 255 | ||
const g = (Math.floor(rem / 6) / 5) * 255 | ||
const b = ((rem % 6) / 5) * 255 | ||
|
||
return rgbToAnsi4(r, g, b) | ||
} | ||
|
||
export const hslToRgb = ( | ||
h: number, | ||
s: number, | ||
l: number | ||
): [number, number, number] => { | ||
l /= 100 | ||
const a = (s * Math.min(l, 1 - l)) / 100 | ||
const f = (number: number) => { | ||
const k = (number + h / 30) % 12 | ||
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1) | ||
return clamp(Math.round(255 * color), 0, 255) | ||
} | ||
|
||
return [f(0), f(8), f(4)] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
import { | ||
addStyle, | ||
addStyleAlias, | ||
addStyleAliases, | ||
addStyleFunction, | ||
addStyles, | ||
colorSupport, | ||
functions, | ||
styles, | ||
} from './styles.ts' | ||
import { Crayon, CrayonStyle } from './types.ts' | ||
import { errorConfig } from './util.ts' | ||
|
||
/** @internal */ | ||
type func = (...args: any[]) => string | '' | ||
/** @internal */ | ||
type funcs = { | ||
[name: string]: func | ||
} | ||
|
||
const config = new Proxy( | ||
{ | ||
colorSupport, | ||
optimizeStyles: { | ||
chain: false, | ||
literal: false, | ||
}, | ||
errors: errorConfig, | ||
} as Crayon['config'], | ||
{} | ||
) | ||
|
||
const optimizeStyles = (string: string): string => | ||
string.replace(/(\x1b\[([0-9]|;|)+?m)+\x1b\[0m/, styles.reset) //TODO: improve that | ||
|
||
const crayonPrototype: any = { | ||
styleCache: '', | ||
preserveCache: false, | ||
|
||
config, | ||
colorSupport, | ||
|
||
instance(preserveCache: boolean, styleCache?: string): Crayon { | ||
return buildCrayon(preserveCache, styleCache) | ||
}, | ||
clone(clear: boolean, addCache?: string): Crayon { | ||
return buildCrayon( | ||
this.preserveCache, | ||
(clear ? this.clearCache() : this.styleCache) + (addCache || '') | ||
) | ||
}, | ||
clearCache(): string { | ||
const cache = this.styleCache | ||
if (this.preserveCache) return cache | ||
this.styleCache = '' | ||
return cache | ||
}, | ||
strip(text: string): string { | ||
return text.replace(/\x1b\[[0-9]([0-9])?([0-9])?m/gi, '') | ||
}, | ||
} | ||
|
||
export const reloadStyles = () => { | ||
for (const value in styles) { | ||
Object.defineProperty(crayonPrototype, value, { | ||
configurable: true, | ||
get() { | ||
return this.clone(true, styles[value as CrayonStyle]) | ||
}, | ||
}) | ||
} | ||
} | ||
reloadStyles() | ||
|
||
export const reloadFunctions = () => { | ||
for (const name in functions) { | ||
if (name.startsWith('bg')) continue | ||
const bgName = `bg${name[0].toUpperCase() + name.slice(1)}` | ||
|
||
const func = (functions as funcs)[name] | ||
|
||
let needsSpecification = false | ||
const bgFunc = | ||
(functions as any)[bgName] || | ||
(() => { | ||
needsSpecification = true | ||
return (functions as funcs)[name] | ||
})() | ||
|
||
Object.defineProperties(crayonPrototype, { | ||
[name]: { | ||
configurable: true, | ||
value(...args: unknown[]) { | ||
const style = func(...args) | ||
if (style !== '') return this.clone(true, style) | ||
return this | ||
}, | ||
}, | ||
[bgName]: { | ||
configurable: true, | ||
value(...args: unknown[]) { | ||
if (needsSpecification) args.push(true) | ||
const style = bgFunc(...args) | ||
if (style !== '') return this.clone(true, style) | ||
return this | ||
}, | ||
}, | ||
}) | ||
} | ||
} | ||
reloadFunctions() | ||
|
||
const buildCrayon = (preserveCache: boolean, styleCache?: string): Crayon => { | ||
const crayon = function (...args: unknown[]) { | ||
if (!args.length) return buildCrayon(true) | ||
|
||
if (Array.isArray((args[0] as any).raw)) { | ||
const returned = compileLiteral(...args) | ||
return crayon.config.optimizeStyles.literal | ||
? optimizeStyles(returned) | ||
: returned | ||
} | ||
|
||
const text = String(args.join(' ')) | ||
const style = crayon.clearCache() | ||
if (!style) return text | ||
|
||
const returned = | ||
style + text.replace(resetRegex, styles.reset + style) + styles.reset | ||
return crayon.config.optimizeStyles.chain | ||
? optimizeStyles(returned) | ||
: returned | ||
} as Crayon | ||
|
||
Object.setPrototypeOf(crayon, crayonPrototype) | ||
crayon.preserveCache = !!preserveCache | ||
crayon.styleCache = styleCache || '' | ||
|
||
return crayon | ||
} | ||
|
||
const resetRegex = /\x1b\[0m/gi | ||
const literalStyleRegex = /{([^\s]+\s)([^{}]+)}/ | ||
const literalFuncRegex = /(\w+)\((.*)\)/ | ||
const literalStringRegex = /^("|'|`)(.*)\1$/ | ||
|
||
const compileLiteral = (...texts: any[]): string => { | ||
const args = texts.slice(1) as string[] | ||
const baseText = [...texts[0]] | ||
|
||
let text = '' | ||
while (args.length || baseText.length) { | ||
if (baseText.length) text += baseText.shift() | ||
if (args.length) text += args.shift() | ||
} | ||
|
||
let matches = text.match(literalStyleRegex) | ||
|
||
while (matches?.length) { | ||
// Get value of given styles as one string | ||
const style = matches[1] | ||
.trimEnd() | ||
.split('.') | ||
.map((value) => { | ||
const style: string = styles[value as CrayonStyle] | ||
if (style) return style | ||
else { | ||
const match = value.match(literalFuncRegex) | ||
if (match?.length) { | ||
const name = match[1] | ||
// Format arguments to proper types | ||
const args = match[2].split(',').map((arg) => { | ||
const stringMatch = arg.match(literalStringRegex) | ||
if (stringMatch?.length) return stringMatch[2] | ||
const num = Number(arg) | ||
if (num) return num | ||
return arg === 'false' || arg === 'true' ? Boolean(arg) : arg | ||
}) | ||
|
||
if (!name.startsWith('bg')) { | ||
const func = (functions as funcs)[name] | ||
if (func) return func(...args) | ||
} else { | ||
const nameWithoutBg = | ||
name[2].toLowerCase() + name.replace('bg', '').substr(1) | ||
const bgFunc = | ||
(functions as funcs)[name] || | ||
(() => { | ||
args.push(true) | ||
return (functions as funcs)[nameWithoutBg] | ||
})() | ||
|
||
if (bgFunc) return bgFunc(...args) | ||
} | ||
} | ||
} | ||
}) | ||
.join('') | ||
|
||
const matchedText = matches[2].split(styles.reset).join(styles.reset + style) | ||
text = text.replace(matches[0], style + matchedText + styles.reset) | ||
|
||
matches = text.match(literalStyleRegex) | ||
} | ||
|
||
return text | ||
} | ||
|
||
/** | ||
* | ||
* Main Crayon object used to chain styles: | ||
* * call as function after chaining with given argument to get styled string | ||
* | ||
* @example | ||
* ```ts | ||
* import crayon = require('crayon.js') | ||
* | ||
* crayon.red.bgBlue.bold('🖍️ crayon') | ||
* ``` | ||
* | ||
* * call as function at the beginning without arguments to receive new Crayon object which can be used to cache styling | ||
* @example | ||
* ```ts | ||
* import crayon = require('crayon.js') | ||
* | ||
* const warning = crayon().bgRed.keyword('orange').italic | ||
* | ||
* console.log(warning('THIS IS REALLY WARNY')) | ||
* console.log(warning('something failed')) | ||
* ``` | ||
*/ | ||
const crayonInstance = buildCrayon(false) | ||
|
||
export { | ||
addStyleFunction, | ||
addStyleAliases, | ||
optimizeStyles, | ||
addStyleAlias, | ||
addStyles, | ||
addStyle, | ||
functions, | ||
styles, | ||
} | ||
|
||
export default crayonInstance |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import crayon from './index.ts' | ||
export default crayon | ||
export * from './index.ts' |
Oops, something went wrong.