Remove support for tagged template literals (#524)
This commit is contained in:
parent
f478655c3c
commit
c987c61486
6 changed files with 8 additions and 442 deletions
31
source/index.d.ts
vendored
31
source/index.d.ts
vendored
|
|
@ -121,36 +121,9 @@ export interface ColorSupport {
|
|||
has16m: boolean;
|
||||
}
|
||||
|
||||
interface ChalkFunction {
|
||||
/**
|
||||
Use a template string.
|
||||
|
||||
@remarks Template literals are unsupported for nested calls (see [issue #341](https://github.com/chalk/chalk/issues/341))
|
||||
|
||||
@example
|
||||
```
|
||||
import chalk from 'chalk';
|
||||
|
||||
log(chalk`
|
||||
CPU: {red ${cpu.totalPercent}%}
|
||||
RAM: {green ${ram.used / ram.total * 100}%}
|
||||
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
|
||||
`);
|
||||
```
|
||||
|
||||
@example
|
||||
```
|
||||
import chalk from 'chalk';
|
||||
|
||||
log(chalk.red.bgBlack`2 + 3 = {bold ${2 + 3}}`)
|
||||
```
|
||||
*/
|
||||
(text: TemplateStringsArray, ...placeholders: unknown[]): string;
|
||||
|
||||
export interface ChalkInstance {
|
||||
(...text: unknown[]): string;
|
||||
}
|
||||
|
||||
export interface ChalkInstance extends ChalkFunction {
|
||||
/**
|
||||
The color support for Chalk.
|
||||
|
||||
|
|
@ -358,7 +331,7 @@ Order doesn't matter, and later styles take precedent in case of a conflict.
|
|||
|
||||
This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
|
||||
*/
|
||||
declare const chalk: ChalkInstance & ChalkFunction;
|
||||
declare const chalk: ChalkInstance;
|
||||
|
||||
export const supportsColor: ColorSupport | false;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,8 @@ import {
|
|||
stringReplaceAll,
|
||||
stringEncaseCRLFWithFirstIndex,
|
||||
} from './util.js';
|
||||
import template from './templates.js';
|
||||
|
||||
const {stdout: stdoutColor, stderr: stderrColor} = supportsColor;
|
||||
const {isArray} = Array;
|
||||
|
||||
const GENERATOR = Symbol('GENERATOR');
|
||||
const STYLER = Symbol('STYLER');
|
||||
|
|
@ -41,17 +39,12 @@ export class Chalk {
|
|||
}
|
||||
|
||||
const chalkFactory = options => {
|
||||
const chalk = {};
|
||||
const chalk = (...strings) => strings.join(' ');
|
||||
applyOptions(chalk, options);
|
||||
|
||||
chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
|
||||
|
||||
Object.setPrototypeOf(chalk, createChalk.prototype);
|
||||
Object.setPrototypeOf(chalk.template, chalk);
|
||||
|
||||
chalk.template.Chalk = Chalk;
|
||||
|
||||
return chalk.template;
|
||||
return chalk;
|
||||
};
|
||||
|
||||
function createChalk(options) {
|
||||
|
|
@ -157,16 +150,9 @@ const createStyler = (open, close, parent) => {
|
|||
};
|
||||
|
||||
const createBuilder = (self, _styler, _isEmpty) => {
|
||||
const builder = (...arguments_) => {
|
||||
if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) {
|
||||
// Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}`
|
||||
return applyStyle(builder, chalkTag(builder, ...arguments_));
|
||||
}
|
||||
|
||||
// Single argument is hot path, implicit coercion is faster than anything
|
||||
// eslint-disable-next-line no-implicit-coercion
|
||||
return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
|
||||
};
|
||||
// Single argument is hot path, implicit coercion is faster than anything
|
||||
// eslint-disable-next-line no-implicit-coercion
|
||||
const builder = (...arguments_) => applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
|
||||
|
||||
// We alter the prototype because we must return a function, but there is
|
||||
// no way to create a function with a different prototype
|
||||
|
|
@ -213,28 +199,6 @@ const applyStyle = (self, string) => {
|
|||
return openAll + string + closeAll;
|
||||
};
|
||||
|
||||
const chalkTag = (chalk, ...strings) => {
|
||||
const [firstString] = strings;
|
||||
|
||||
if (!isArray(firstString) || !isArray(firstString.raw)) {
|
||||
// If chalk() was called by itself or with a string,
|
||||
// return the string itself as a string.
|
||||
return strings.join(' ');
|
||||
}
|
||||
|
||||
const arguments_ = strings.slice(1);
|
||||
const parts = [firstString.raw[0]];
|
||||
|
||||
for (let i = 1; i < firstString.length; i++) {
|
||||
parts.push(
|
||||
String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
|
||||
String(firstString.raw[i]),
|
||||
);
|
||||
}
|
||||
|
||||
return template(chalk, parts.join(''));
|
||||
};
|
||||
|
||||
Object.defineProperties(createChalk.prototype, styles);
|
||||
|
||||
const chalk = createChalk();
|
||||
|
|
|
|||
|
|
@ -34,12 +34,6 @@ expectType<ChalkInstance>(new Chalk({level: 1}));
|
|||
// -- Properties --
|
||||
expectType<ColorSupportLevel>(chalk.level);
|
||||
|
||||
// -- Template literal --
|
||||
expectType<string>(chalk``);
|
||||
const name = 'John';
|
||||
expectType<string>(chalk`Hello {bold.red ${name}}`);
|
||||
expectType<string>(chalk`Works with numbers {bold.red ${1}}`);
|
||||
|
||||
// -- Color methods --
|
||||
expectAssignable<colorReturn>(chalk.rgb(0, 0, 0));
|
||||
expectAssignable<colorReturn>(chalk.hex('#DEADED'));
|
||||
|
|
|
|||
|
|
@ -1,133 +0,0 @@
|
|||
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+)(?:\(([^)]*)\))?/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.fromCharCode(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, (m, escape, character) => escape ? unescape(escape) : character));
|
||||
} else {
|
||||
throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
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]) {
|
||||
const args = parseArguments(name, matches[2]);
|
||||
results.push([name, ...args]);
|
||||
} else {
|
||||
results.push([name]);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function buildStyle(chalk, 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;
|
||||
}
|
||||
|
||||
export default function template(chalk, temporary) {
|
||||
const styles = [];
|
||||
const chunks = [];
|
||||
let chunk = [];
|
||||
|
||||
// eslint-disable-next-line max-params
|
||||
temporary.replace(TEMPLATE_REGEX, (m, 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(chalk, 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(chalk, styles)(chunk.join('')));
|
||||
chunk = [];
|
||||
styles.pop();
|
||||
} else {
|
||||
chunk.push(character);
|
||||
}
|
||||
});
|
||||
|
||||
chunks.push(chunk.join(''));
|
||||
|
||||
if (styles.length > 0) {
|
||||
const errorMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
return chunks.join('');
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue