This repository has been archived by the owner on Jun 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Better [ACTION REQUIRED] warning (#335)
* feat(ux): Using more saturated color for warnings * feat(common): Adding `chalk` templating utility * feat(ux): Using chalk templating in UX messages * feat: Better message when provider needs attention
- Loading branch information
Showing
3 changed files
with
230 additions
and
8 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
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,212 @@ | ||
// This is taken 1:1 from `chalk-template` npm package. | ||
// Due to the package being ESModule only, it couldn't be imported. | ||
// Source: https://github.com/chalk/chalk-template | ||
// ============================================================================= | ||
|
||
/* eslint-disable */ | ||
// @ts-nocheck | ||
import chalk from 'chalk'; | ||
|
||
const TEMPLATE_REGEX = | ||
/(?:\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.))|(?:{(~)?(#?[\w:]+(?:\([^)]*\))?(?:\.#?[\w:]+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(})|((?:.|[\r\n\f])+?)/gi; | ||
const STYLE_REGEX = | ||
/(?:^|\.)(?:(?:(\w+)(?:\(([^)]*)\))?)|(?:#(?=[:a-fA-F\d]{2,})([a-fA-F\d]{6})?(?::([a-fA-F\d]{6}))?))/g; | ||
const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; | ||
const ESCAPE_REGEX = | ||
/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi; | ||
|
||
const ESCAPES = new Map([ | ||
['n', '\n'], | ||
['r', '\r'], | ||
['t', '\t'], | ||
['b', '\b'], | ||
['f', '\f'], | ||
['v', '\v'], | ||
['0', '\0'], | ||
['\\', '\\'], | ||
['e', '\u001B'], | ||
['a', '\u0007'], | ||
]); | ||
|
||
function unescape(c) { | ||
const u = c[0] === 'u'; | ||
const bracket = c[1] === '{'; | ||
|
||
if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) { | ||
return String.fromCodePoint(Number.parseInt(c.slice(1), 16)); | ||
} | ||
|
||
if (u && bracket) { | ||
return String.fromCodePoint(Number.parseInt(c.slice(2, -1), 16)); | ||
} | ||
|
||
return ESCAPES.get(c) || c; | ||
} | ||
|
||
function parseArguments(name, arguments_) { | ||
const results = []; | ||
const chunks = arguments_.trim().split(/\s*,\s*/g); | ||
let matches; | ||
|
||
for (const chunk of chunks) { | ||
const number = Number(chunk); | ||
if (!Number.isNaN(number)) { | ||
results.push(number); | ||
} else if ((matches = chunk.match(STRING_REGEX))) { | ||
results.push( | ||
matches[2].replace(ESCAPE_REGEX, (_, escape, character) => | ||
escape ? unescape(escape) : character | ||
) | ||
); | ||
} else { | ||
throw new Error( | ||
`Invalid Chalk template style argument: ${chunk} (in style '${name}')` | ||
); | ||
} | ||
} | ||
|
||
return results; | ||
} | ||
|
||
function parseHex(hex) { | ||
const n = Number.parseInt(hex, 16); | ||
|
||
return [ | ||
// eslint-disable-next-line no-bitwise | ||
(n >> 16) & 0xff, | ||
// eslint-disable-next-line no-bitwise | ||
(n >> 8) & 0xff, | ||
// eslint-disable-next-line no-bitwise | ||
n & 0xff, | ||
]; | ||
} | ||
|
||
function parseStyle(style) { | ||
STYLE_REGEX.lastIndex = 0; | ||
|
||
const results = []; | ||
let matches; | ||
|
||
while ((matches = STYLE_REGEX.exec(style)) !== null) { | ||
const name = matches[1]; | ||
|
||
if (matches[2]) { | ||
results.push([name, ...parseArguments(name, matches[2])]); | ||
} else if (matches[3] || matches[4]) { | ||
if (matches[3]) { | ||
results.push(['rgb', ...parseHex(matches[3])]); | ||
} | ||
|
||
if (matches[4]) { | ||
results.push(['bgRgb', ...parseHex(matches[4])]); | ||
} | ||
} else { | ||
results.push([name]); | ||
} | ||
} | ||
|
||
return results; | ||
} | ||
|
||
export function makeTemplate(chalk) { | ||
function buildStyle(styles) { | ||
const enabled = {}; | ||
|
||
for (const layer of styles) { | ||
for (const style of layer.styles) { | ||
enabled[style[0]] = layer.inverse ? null : style.slice(1); | ||
} | ||
} | ||
|
||
let current = chalk; | ||
for (const [styleName, styles] of Object.entries(enabled)) { | ||
if (!Array.isArray(styles)) { | ||
continue; | ||
} | ||
|
||
if (!(styleName in current)) { | ||
throw new Error(`Unknown Chalk style: ${styleName}`); | ||
} | ||
|
||
current = | ||
styles.length > 0 ? current[styleName](...styles) : current[styleName]; | ||
} | ||
|
||
return current; | ||
} | ||
|
||
function template(string) { | ||
const styles = []; | ||
const chunks = []; | ||
let chunk = []; | ||
|
||
// eslint-disable-next-line max-params | ||
string.replace( | ||
TEMPLATE_REGEX, | ||
(_, escapeCharacter, inverse, style, close, character) => { | ||
if (escapeCharacter) { | ||
chunk.push(unescape(escapeCharacter)); | ||
} else if (style) { | ||
const string = chunk.join(''); | ||
chunk = []; | ||
chunks.push( | ||
styles.length === 0 ? string : buildStyle(styles)(string) | ||
); | ||
styles.push({ inverse, styles: parseStyle(style) }); | ||
} else if (close) { | ||
if (styles.length === 0) { | ||
throw new Error('Found extraneous } in Chalk template literal'); | ||
} | ||
|
||
chunks.push(buildStyle(styles)(chunk.join(''))); | ||
chunk = []; | ||
styles.pop(); | ||
} else { | ||
chunk.push(character); | ||
} | ||
} | ||
); | ||
|
||
chunks.push(chunk.join('')); | ||
|
||
if (styles.length > 0) { | ||
throw new Error( | ||
`Chalk template literal is missing ${styles.length} closing bracket${ | ||
styles.length === 1 ? '' : 's' | ||
} (\`}\`)` | ||
); | ||
} | ||
|
||
return chunks.join(''); | ||
} | ||
|
||
return template; | ||
} | ||
|
||
function makeChalkTemplate(template) { | ||
function chalkTemplate(firstString, ...arguments_) { | ||
if (!Array.isArray(firstString) || !Array.isArray(firstString.raw)) { | ||
// If chalkTemplate() was called by itself or with a string | ||
throw new TypeError('A tagged template literal must be provided'); | ||
} | ||
|
||
const parts = [firstString.raw[0]]; | ||
|
||
for (let index = 1; index < firstString.raw.length; index++) { | ||
parts.push( | ||
String(arguments_[index - 1]).replace(/[{}\\]/g, '\\$&'), | ||
String(firstString.raw[index]) | ||
); | ||
} | ||
|
||
return template(parts.join('')); | ||
} | ||
|
||
return chalkTemplate; | ||
} | ||
|
||
export const makeTaggedTemplate = chalkInstance => | ||
makeChalkTemplate(makeTemplate(chalkInstance)); | ||
|
||
export const template = makeTemplate(chalk); | ||
export default makeChalkTemplate(template); |
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