Split out format ansi markup stuff into separate file. Add color tag
MODIFY
packages/@romejs/cli-diagnostics/buildPatchCodeFrame.ts
packages/@romejs/cli-diagnostics/buildPatchCodeFrame.ts
@@ -18,9 +18,9 @@ import {markupTag, escapeMarkup} from '@romejs/string-markup';
function formatDiffLine(diffs: Diffs) {
return diffs.map(([type, text]) => {
if (type === diffConstants.DELETE) {
- return markupTag('red', escapeMarkup(showInvisibles(text)));
+ return markupTag('error', escapeMarkup(showInvisibles(text)));
} else if (type === diffConstants.ADD) {
- return markupTag('green', escapeMarkup(showInvisibles(text)));
+ return markupTag('success', escapeMarkup(showInvisibles(text)));
} else {
// type === diffConstants.EQUAL
return escapeMarkup(text);
@@ -28,8 +28,8 @@ function formatDiffLine(diffs: Diffs) {
}).join('');
}
-const DELETE_MARKER = markupTag('red', '-');
-const ADD_MARKER = markupTag('green', '+');
+const DELETE_MARKER = markupTag('error', '-');
+const ADD_MARKER = markupTag('success', '+');
export default function buildPatchCodeFrame(
rawDiffs: Diffs,

MODIFY
packages/@romejs/cli-diagnostics/highlightCode.ts
packages/@romejs/cli-diagnostics/highlightCode.ts
@@ -78,7 +78,7 @@ function reduce<
}
function invalidHighlight(line: string): string {
- return markupTag('emphasis', markupTag('bgRed', line));
+ return markupTag('emphasis', markupTag('color', line, {bg: 'red'}));
}
function highlightJSON(path: UnknownFilePath, input: string): string {
@@ -93,20 +93,20 @@ function highlightJSON(path: UnknownFilePath, input: string): string {
switch (token.type) {
case 'BlockComment':
case 'LineComment':
- return markupTag('brightBlack', value);
+ return markupTag('color', value, {fg: 'brightBlack'});
case 'String':
- return markupTag('green', value);
+ return markupTag('color', value, {fg: 'green'});
case 'Number':
- return markupTag('magenta', value);
+ return markupTag('color', value, {fg: 'magenta'});
case 'Word':
switch (token.value) {
case 'true':
case 'false':
case 'null':
- return markupTag('cyan', value);
+ return markupTag('color', value, {fg: 'cyan'});
default:
return value;
@@ -115,7 +115,7 @@ function highlightJSON(path: UnknownFilePath, input: string): string {
case 'Comma':
case 'Colon':
case 'Dot':
- return markupTag('yellow', value);
+ return markupTag('color', value, {fg: 'yellow'});
case 'BracketOpen':
case 'BracketClose':
@@ -183,25 +183,25 @@ function highlightJS(input: string, sourceType: ConstSourceType): string {
case 'typeof':
case 'void':
case 'delete':
- return markupTag('cyan', value);
+ return markupTag('color', value, {fg: 'cyan'});
case 'num':
case 'bigint':
- return markupTag('magenta', value);
+ return markupTag('color', value, {fg: 'magenta'});
case 'regexp':
- return markupTag('magenta', value);
+ return markupTag('color', value, {fg: 'magenta'});
case 'string':
case 'template':
case '`':
- return markupTag('green', value);
+ return markupTag('color', value, {fg: 'green'});
case 'invalid':
return invalidHighlight(value);
case 'comment':
- return markupTag('brightBlack', value);
+ return markupTag('color', value, {fg: 'brightBlack'});
case ',':
case ';':
@@ -211,7 +211,7 @@ function highlightJS(input: string, sourceType: ConstSourceType): string {
case '.':
case '?':
case '?.':
- return markupTag('yellow', value);
+ return markupTag('color', value, {fg: 'yellow'});
case '[':
case ']':

MODIFY
packages/@romejs/cli-diagnostics/printAdvice.ts
packages/@romejs/cli-diagnostics/printAdvice.ts
@@ -178,8 +178,8 @@ function printDiff(
const {legend} = item;
if (legend !== undefined) {
opts.reporter.spacer();
- opts.reporter.logAll(`<success>+ ${escapeMarkup(legend.add)}</success>`);
opts.reporter.logAll(`<error>- ${escapeMarkup(legend.delete)}</error>`);
+ opts.reporter.logAll(`<success>+ ${escapeMarkup(legend.add)}</success>`);
opts.reporter.spacer();
}

MODIFY
packages/@romejs/cli-reporter/Reporter.ts
packages/@romejs/cli-reporter/Reporter.ts
@@ -1009,7 +1009,7 @@ export default class Reporter {
this.logAllWithCategory(msg, args, {
unicodePrefix: '\u26a1 ',
rawPrefix: '* ',
- markupTag: 'brightBlack',
+ markupTag: 'dim',
});
}

MODIFY
packages/@romejs/pretty-format/index.ts
packages/@romejs/pretty-format/index.ts
@@ -66,28 +66,28 @@ export default function prettyFormat(
switch (typeof obj) {
case 'symbol': {
const val = maybeEscapeMarkup(formatSymbol(obj), opts);
- return opts.markup ? markupTag('green', val) : val;
+ return opts.markup ? markupTag('color', val, {fg: 'green'}) : val;
}
case 'string': {
const val = maybeEscapeMarkup(formatString(obj), opts);
- return opts.markup ? markupTag('green', val) : val;
+ return opts.markup ? markupTag('color', val, {fg: 'green'}) : val;
}
case 'bigint':
case 'number': {
const val = formatNumber(obj);
- return opts.markup ? markupTag('yellow', val) : val;
+ return opts.markup ? markupTag('color', val, {fg: 'yellow'}) : val;
}
case 'boolean': {
const val = formatBoolean(obj);
- return opts.markup ? markupTag('yellow', val) : val;
+ return opts.markup ? markupTag('color', val, {fg: 'yellow'}) : val;
}
case 'undefined': {
const val = formatUndefined();
- return opts.markup ? markupTag('brightBlack', val) : val;
+ return opts.markup ? markupTag('color', val, {fg: 'brightBlack'}) : val;
}
case 'function':
@@ -275,7 +275,7 @@ function formatObject(
const {stack} = opts;
if (stack.length > 0 && stack.includes(obj)) {
label = `Circular ${label} ${stack.indexOf(obj)}`;
- return opts.markup ? markupTag('cyan', label) : label;
+ return opts.markup ? markupTag('color', label, {fg: 'cyan'}) : label;
}
//
@@ -344,7 +344,7 @@ function formatObject(
}
}
- label = opts.markup ? markupTag('cyan', label) : label;
+ label = opts.markup ? markupTag('color', label, {fg: 'cyan'}) : label;
return `${label} ${open}${inner}${close}`;
}
@@ -369,12 +369,12 @@ function formatObjectish(val: null | Objectish, opts: FormatOptions): string {
if (val instanceof RegExp) {
const str = formatRegExp(val);
- return opts.markup ? markupTag('red', str) : str;
+ return opts.markup ? markupTag('color', str, {fg: 'red'}) : str;
}
if (val instanceof Date) {
const str = formatDate(val);
- return opts.markup ? markupTag('magenta', str) : str;
+ return opts.markup ? markupTag('color', str, {fg: 'magenta'}) : str;
}
let label = 'null';

MODIFY
packages/@romejs/string-markup/format.ts
packages/@romejs/string-markup/format.ts
@@ -12,7 +12,7 @@ import {
humanizeTime,
humanizeFileSize,
} from '@romejs/string-utils';
-import {formatAnsi, ansiPad} from './ansi';
+import {ansiPad} from './ansi';
import {AbsoluteFilePath, createUnknownFilePath} from '@romejs/path';
import {escapeMarkup} from './escape';
@@ -40,7 +40,10 @@ type FormatReduceOptions = {
) => string;
};
-function formatReduceFromInput(input: string, opts: FormatReduceOptions): string {
+export function formatReduceFromInput(
+ input: string,
+ opts: FormatReduceOptions,
+): string {
return formatReduceFromChildren(parseMarkup(input), opts);
}
@@ -129,7 +132,7 @@ function formatReduceFromChildren(
return buff;
}
-function formatFileLink(
+export function formatFileLink(
attributes: TagAttributes,
value: string,
opts: MarkupFormatOptions,
@@ -164,7 +167,7 @@ function formatFileLink(
return {text, filename};
}
-function formatApprox(attributes: TagAttributes, value: string) {
+export function formatApprox(attributes: TagAttributes, value: string) {
if (attributes.get('approx') === 'true') {
return `~${value}`;
} else {
@@ -172,7 +175,7 @@ function formatApprox(attributes: TagAttributes, value: string) {
}
}
-function formatGrammarNumber(attributes: TagAttributes, value: string) {
+export function formatGrammarNumber(attributes: TagAttributes, value: string) {
const num = Number(value);
const none = attributes.get('none');
@@ -193,14 +196,14 @@ function formatGrammarNumber(attributes: TagAttributes, value: string) {
return '';
}
-function formatNumber(attributes: TagAttributes, value: string) {
+export function formatNumber(attributes: TagAttributes, value: string) {
const num = Number(value);
const human = humanizeNumber(num);
const humanWithApprox = formatApprox(attributes, human);
return humanWithApprox;
}
-function formatPad(attributes: TagAttributes, value: string) {
+export function formatPad(attributes: TagAttributes, value: string) {
const left = attributes.get('dir') !== 'right';
const count = Number(attributes.get('count') || 0);
const char = attributes.get('char');
@@ -298,135 +301,6 @@ export function normalizeMarkup(
});
}
-export function markupToAnsi(
- input: string,
- opts: MarkupFormatOptions = {},
-): string {
- return formatReduceFromInput(input, {
- ancestry: [],
- formatTag: ansiFormatTag,
- formatText: (value, tags) => {
- // Format tags in reverse
- for (let i = tags.length - 1; i >= 0; i--) {
- const tag = tags[i];
- value = ansiFormatText(tag, value, opts);
- }
-
- return formatAnsi.reset(value);
- },
- });
-}
-
-function ansiFormatTag(
- tagName: MarkupTagName,
- attributes: TagAttributes,
- value: string,
-): string {
- switch (tagName) {
- case 'pad':
- return formatPad(attributes, value);
-
- case 'command':
- return '`' + value + '`';
-
- default:
- return value;
- }
-}
-
-function ansiFormatText(
- {name: tagName, attributes}: TagNode,
- value: string,
- opts: MarkupFormatOptions,
-): string {
- switch (tagName) {
- case 'hyperlink': {
- let text = value;
- let hyperlink = attributes.get('target');
-
- if (hyperlink === undefined) {
- hyperlink = text;
- }
-
- if (text === '') {
- text = hyperlink;
- }
-
- return formatAnsi.hyperlink(text, hyperlink);
- }
-
- case 'pad':
- return value;
-
- case 'filelink': {
- const {text, filename} = formatFileLink(attributes, value, opts);
- return formatAnsi.hyperlink(text, `file://${filename}`);
- }
-
- case 'inverse':
- return formatAnsi.inverse(` ${value} `);
-
- case 'emphasis':
- return formatAnsi.bold(value);
-
- case 'dim':
- return formatAnsi.dim(value);
-
- case 'filesize':
- return humanizeFileSize(Number(value));
-
- case 'duration':
- return formatApprox(attributes, humanizeTime(Number(value), true));
-
- case 'number':
- return formatNumber(attributes, value);
-
- case 'grammarNumber':
- return formatGrammarNumber(attributes, value);
-
- case 'italic':
- return formatAnsi.italic(value);
-
- case 'underline':
- return formatAnsi.underline(value);
-
- case 'strike':
- return formatAnsi.strikethrough(value);
-
- case 'error':
- return formatAnsi.red(value);
-
- case 'success':
- return formatAnsi.green(value);
-
- case 'warn':
- return formatAnsi.yellow(value);
-
- case 'info':
- return formatAnsi.blue(value);
-
- case 'command':
- return formatAnsi.italic(value);
-
- case 'highlight': {
- const index = Math.min(0, Number(attributes.get('i')) || 0);
- const showLegend = attributes.get('legend') === 'true';
- const fn = ansiHighlightFactories[index % ansiHighlightFactories.length];
- let formatted = fn(value);
- if (showLegend) {
- formatted += formatAnsi.dim(`[${String(index + 1)}]`);
- }
- return formatted;
- }
- }
-}
-
-// TODO fill this
-const ansiHighlightFactories: Array<(str: string) => string> = [
- formatAnsi.magenta,
- formatAnsi.cyan,
-];
-
export function humanizeMarkupFilename(
filename: string,
opts: MarkupFormatOptions = {},

ADD
packages/@romejs/string-markup/formatAnsi.ts
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import {
+ MarkupFormatOptions,
+ formatReduceFromInput,
+ formatFileLink,
+ formatPad,
+ formatApprox,
+ formatNumber,
+ formatGrammarNumber,
+} from './format';
+import {humanizeTime, humanizeFileSize} from '@romejs/string-utils';
+import {formatAnsi} from './ansi';
+import {TagNode, MarkupTagName, TagAttributes} from './types';
+
+export function markupToAnsi(
+ input: string,
+ opts: MarkupFormatOptions = {},
+): string {
+ return formatReduceFromInput(input, {
+ ancestry: [],
+ formatTag: ansiFormatTag,
+ formatText: (value, tags) => {
+ // Format tags in reverse
+ for (let i = tags.length - 1; i >= 0; i--) {
+ const tag = tags[i];
+ value = ansiFormatText(tag, value, opts);
+ }
+
+ return formatAnsi.reset(value);
+ },
+ });
+}
+
+function ansiFormatTag(
+ tagName: MarkupTagName,
+ attributes: TagAttributes,
+ value: string,
+): string {
+ switch (tagName) {
+ case 'pad':
+ return formatPad(attributes, value);
+
+ case 'command':
+ return '`' + value + '`';
+
+ default:
+ return value;
+ }
+}
+
+function ansiFormatText(
+ {name: tagName, attributes}: TagNode,
+ value: string,
+ opts: MarkupFormatOptions,
+): string {
+ switch (tagName) {
+ case 'hyperlink': {
+ let text = value;
+ let hyperlink = attributes.get('target');
+
+ if (hyperlink === undefined) {
+ hyperlink = text;
+ }
+
+ if (text === '') {
+ text = hyperlink;
+ }
+
+ return formatAnsi.hyperlink(text, hyperlink);
+ }
+
+ case 'pad':
+ return value;
+
+ case 'filelink': {
+ const {text, filename} = formatFileLink(attributes, value, opts);
+ return formatAnsi.hyperlink(text, `file://${filename}`);
+ }
+
+ case 'inverse':
+ return formatAnsi.inverse(` ${value} `);
+
+ case 'emphasis':
+ return formatAnsi.bold(value);
+
+ case 'dim':
+ return formatAnsi.dim(value);
+
+ case 'filesize':
+ return humanizeFileSize(Number(value));
+
+ case 'duration':
+ return formatApprox(attributes, humanizeTime(Number(value), true));
+
+ case 'number':
+ return formatNumber(attributes, value);
+
+ case 'grammarNumber':
+ return formatGrammarNumber(attributes, value);
+
+ case 'italic':
+ return formatAnsi.italic(value);
+
+ case 'underline':
+ return formatAnsi.underline(value);
+
+ case 'strike':
+ return formatAnsi.strikethrough(value);
+
+ case 'error':
+ return formatAnsi.red(value);
+
+ case 'success':
+ return formatAnsi.green(value);
+
+ case 'warn':
+ return formatAnsi.yellow(value);
+
+ case 'info':
+ return formatAnsi.blue(value);
+
+ case 'command':
+ return formatAnsi.italic(value);
+
+ case 'highlight': {
+ const index = Math.min(0, Number(attributes.get('i')) || 0);
+ const showLegend = attributes.get('legend') === 'true';
+ const fn = ansiHighlightFactories[index % ansiHighlightFactories.length];
+ let formatted = fn(value);
+ if (showLegend) {
+ formatted += formatAnsi.dim(`[${String(index + 1)}]`);
+ }
+ return formatted;
+ }
+
+ case 'color':
+ return formatAnsiBackground(attributes.get('bg'), formatAnsiForeground(
+ attributes.get('fg'),
+ value,
+ ));
+ }
+}
+
+// TODO fill this
+const ansiHighlightFactories: Array<(str: string) => string> = [
+ formatAnsi.magenta,
+ formatAnsi.cyan,
+];
+
+function formatAnsiBackground(bg: undefined | string, text: string): string {
+ if (bg === undefined) {
+ return text;
+ }
+
+ switch (bg) {
+ case 'black':
+ return formatAnsi.bgBlack(text);
+
+ case 'brightBlack':
+ return formatAnsi.bgBrightBlack(text);
+
+ case 'red':
+ return formatAnsi.bgRed(text);
+
+ case 'brightRed':
+ return formatAnsi.bgBrightRed(text);
+
+ case 'green':
+ return formatAnsi.bgGreen(text);
+
+ case 'brightGreen':
+ return formatAnsi.bgBrightGreen(text);
+
+ case 'yellow':
+ return formatAnsi.bgYellow(text);
+
+ case 'brightYellow':
+ return formatAnsi.bgBrightYellow(text);
+
+ case 'blue':
+ return formatAnsi.bgBlue(text);
+
+ case 'brightBlue':
+ return formatAnsi.bgBrightBlue(text);
+
+ case 'magenta':
+ return formatAnsi.bgMagenta(text);
+
+ case 'brightMagenta':
+ return formatAnsi.bgBrightMagenta(text);
+
+ case 'cyan':
+ return formatAnsi.bgCyan(text);
+
+ case 'brightCyan':
+ return formatAnsi.bgBrightCyan(text);
+
+ case 'white':
+ return formatAnsi.bgWhite(text);
+
+ case 'brightWhite':
+ return formatAnsi.bgBrightWhite(text);
+
+ default:
+ return text;
+ }
+}
+
+function formatAnsiForeground(fg: undefined | string, text: string): string {
+ if (fg === undefined) {
+ return text;
+ }
+
+ switch (fg) {
+ case 'black':
+ return formatAnsi.black(text);
+
+ case 'brightBlack':
+ return formatAnsi.brightBlack(text);
+
+ case 'red':
+ return formatAnsi.red(text);
+
+ case 'brightRed':
+ return formatAnsi.brightRed(text);
+
+ case 'green':
+ return formatAnsi.green(text);
+
+ case 'brightGreen':
+ return formatAnsi.brightGreen(text);
+
+ case 'yellow':
+ return formatAnsi.yellow(text);
+
+ case 'brightYellow':
+ return formatAnsi.brightYellow(text);
+
+ case 'blue':
+ return formatAnsi.blue(text);
+
+ case 'brightBlue':
+ return formatAnsi.brightBlue(text);
+
+ case 'magenta':
+ return formatAnsi.magenta(text);
+
+ case 'brightMagenta':
+ return formatAnsi.brightMagenta(text);
+
+ case 'cyan':
+ return formatAnsi.cyan(text);
+
+ case 'brightCyan':
+ return formatAnsi.brightCyan(text);
+
+ case 'white':
+ return formatAnsi.white(text);
+
+ case 'brightWhite':
+ return formatAnsi.brightWhite(text);
+
+ default:
+ return text;
+ }
+}

MODIFY
packages/@romejs/string-markup/index.ts
packages/@romejs/string-markup/index.ts
export * from './parse';
-export * from './format';
+export {
+ MarkupFormatFilenameNormalizer,
+ MarkupFormatFilenameHumanizer,
+ MarkupFormatOptions,
+ markupToPlainText,
+ normalizeMarkup,
+ humanizeMarkupFilename,
+} from './format';
+
+export * from './formatAnsi';
export * from './escape';

MODIFY
packages/@romejs/string-markup/parse.ts
packages/@romejs/string-markup/parse.ts
@@ -46,6 +46,7 @@ tags.set('success', []);
tags.set('warn', []);
tags.set('info', []);
tags.set('command', []);
+tags.set('color', ['fg', 'bg']);
tags.set('highlight', ['i']);
//

MODIFY
packages/@romejs/string-markup/types.ts
packages/@romejs/string-markup/types.ts
@@ -55,4 +55,5 @@ export type MarkupTagName =
| 'success'
| 'warn'
| 'info'
- | 'highlight';
+ | 'highlight'
+ | 'color';

Split out format ansi markup stuff into separate file. Add color tag