Skip to content

Commit

Permalink
use denoify to support deno
Browse files Browse the repository at this point in the history
  • Loading branch information
Im-Beast committed May 8, 2021
1 parent d6498d8 commit d84312b
Show file tree
Hide file tree
Showing 9 changed files with 793 additions and 3 deletions.
21 changes: 21 additions & 0 deletions deno_lib/LICENSE.md
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.
30 changes: 30 additions & 0 deletions deno_lib/README.md
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.
61 changes: 61 additions & 0 deletions deno_lib/conversions.ts
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)]
}
245 changes: 245 additions & 0 deletions deno_lib/index.ts
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
3 changes: 3 additions & 0 deletions deno_lib/mod.ts
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'
Loading

0 comments on commit d84312b

Please sign in to comment.