mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-06 12:57:46 +00:00
[cli] Add Output#link() function to format terminal hyperlinks (#8370)
This adds a `link()` helper function to the `Output` class that is inspired by the `terminal-link` npm package.
The main difference with this version is that it's more tightly integrated with the `Output` class for the purposes of being able to toggle hyperlinks support on/off for [unit tests](4a54b19f46/packages/cli/test/unit/util/output/create-output.test.ts) by setting the `output.supportsHyperlink` boolean.
> **Note:** Since hyperlinks are still a relatively new feature, and users might not yet understand how to interact with them, we should only use this function for progressive enhancement scenarios at this time, and _not_ as part of a critical UX.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import chalk from 'chalk';
|
||||
import * as ansiEscapes from 'ansi-escapes';
|
||||
import { supportsHyperlink as detectSupportsHyperlink } from 'supports-hyperlinks';
|
||||
import renderLink from './link';
|
||||
import wait, { StopSpinner } from './wait';
|
||||
import type { WritableTTY } from '../../types';
|
||||
@@ -8,24 +10,34 @@ const IS_TEST = process.env.NODE_ENV === 'test';
|
||||
|
||||
export interface OutputOptions {
|
||||
debug?: boolean;
|
||||
supportsHyperlink?: boolean;
|
||||
}
|
||||
|
||||
export interface LogOptions {
|
||||
color?: typeof chalk;
|
||||
}
|
||||
|
||||
interface LinkOptions {
|
||||
fallback?: false | (() => string);
|
||||
}
|
||||
|
||||
export class Output {
|
||||
stream: WritableTTY;
|
||||
debugEnabled: boolean;
|
||||
supportsHyperlink: boolean;
|
||||
private spinnerMessage: string;
|
||||
private _spinner: StopSpinner | null;
|
||||
|
||||
constructor(
|
||||
stream: WritableTTY,
|
||||
{ debug: debugEnabled = false }: OutputOptions = {}
|
||||
{
|
||||
debug: debugEnabled = false,
|
||||
supportsHyperlink = detectSupportsHyperlink(stream),
|
||||
}: OutputOptions = {}
|
||||
) {
|
||||
this.stream = stream;
|
||||
this.debugEnabled = debugEnabled;
|
||||
this.supportsHyperlink = supportsHyperlink;
|
||||
this.spinnerMessage = '';
|
||||
this._spinner = null;
|
||||
}
|
||||
@@ -167,4 +179,27 @@ export class Output {
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an ANSI formatted hyperlink when support has been enabled.
|
||||
*/
|
||||
link = (
|
||||
text: string,
|
||||
url: string,
|
||||
{ fallback }: LinkOptions = {}
|
||||
): string => {
|
||||
// Based on https://github.com/sindresorhus/terminal-link (MIT license)
|
||||
if (!this.supportsHyperlink) {
|
||||
// If the fallback has been explicitly disabled, don't modify the text itself
|
||||
if (fallback === false) {
|
||||
return renderLink(text);
|
||||
}
|
||||
|
||||
return typeof fallback === 'function'
|
||||
? fallback()
|
||||
: `${text} (${renderLink(url)})`;
|
||||
}
|
||||
|
||||
return ansiEscapes.link(chalk.cyan(text), url);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user