From 151b2c1b3ea5a235cdd07f2018f94def98d12f99 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sun, 18 Apr 2021 12:35:01 +0700 Subject: [PATCH] Require Node.js 12 and move to ESM --- .github/funding.yml | 3 -- .github/workflows/main.yml | 4 +- index.d.ts | 84 +++++++++++++++++++------------------- index.js | 18 ++++---- index.test-d.ts | 6 +-- license | 2 +- package.json | 23 +++++++---- readme.md | 2 +- test.js | 52 +++++++++++------------ 9 files changed, 95 insertions(+), 99 deletions(-) delete mode 100644 .github/funding.yml diff --git a/.github/funding.yml b/.github/funding.yml deleted file mode 100644 index 1a630e9..0000000 --- a/.github/funding.yml +++ /dev/null @@ -1,3 +0,0 @@ -github: sindresorhus -open_collective: sindresorhus -custom: https://sindresorhus.com/donate diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 18531b3..d36e1a8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,11 +12,9 @@ jobs: node-version: - 14 - 12 - - 10 - - 8 steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/index.d.ts b/index.d.ts index 6c2c24e..968f3aa 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,43 +1,21 @@ -declare namespace terminalLink { - interface Options { - /** - Override the default fallback. If false, the fallback will be disabled. - - @default `${text} (${url})` - */ - fallback?: ((text: string, url: string) => string) | boolean; - } -} - -declare const terminalLink: { +export interface Options { /** - Create a clickable link in the terminal's stdout. - - [Supported terminals.](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda) - For unsupported terminals, the link will be printed in parens after the text: `My website (https://sindresorhus.com)`, - unless the fallback is disabled by setting the `fallback` option to `false`. - - @param text - Text to linkify. - @param url - URL to link to. + Override the default fallback. If false, the fallback will be disabled. - @example - ``` - import terminalLink = require('terminal-link'); - - const link = terminalLink('My Website', 'https://sindresorhus.com'); - console.log(link); - ``` + @default `${text} (${url})` */ - (text: string, url: string, options?: terminalLink.Options): string; + readonly fallback?: ((text: string, url: string) => string) | boolean; +} - /** - Check whether the terminal supports links. +declare const terminalLink: { + readonly stderr: { + /** + Check whether the terminal's stderr supports links. - Prefer just using the default fallback or the `fallback` option whenever possible. - */ - readonly isSupported: boolean; + Prefer just using the default fallback or the `fallback` option whenever possible. + */ + readonly isSupported: boolean; - readonly stderr: { /** Create a clickable link in the terminal's stderr. @@ -49,21 +27,41 @@ declare const terminalLink: { @example ``` - import terminalLink = require('terminal-link'); + import terminalLink from 'terminal-link'; const link = terminalLink.stderr('My Website', 'https://sindresorhus.com'); console.error(link); ``` */ - (text: string, url: string, options?: terminalLink.Options): string; + (text: string, url: string, options?: Options): string; + }; - /** - Check whether the terminal's stderr supports links. + /** + Check whether the terminal supports links. - Prefer just using the default fallback or the `fallback` option whenever possible. - */ - readonly isSupported: boolean; - } + Prefer just using the default fallback or the `fallback` option whenever possible. + */ + readonly isSupported: boolean; + + /** + Create a clickable link in the terminal's stdout. + + [Supported terminals.](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda) + For unsupported terminals, the link will be printed in parens after the text: `My website (https://sindresorhus.com)`, + unless the fallback is disabled by setting the `fallback` option to `false`. + + @param text - Text to linkify. + @param url - URL to link to. + + @example + ``` + import terminalLink from 'terminal-link'; + + const link = terminalLink('My Website', 'https://sindresorhus.com'); + console.log(link); + ``` + */ + (text: string, url: string, options?: Options): string; }; -export = terminalLink; +export default terminalLink; diff --git a/index.js b/index.js index 7bbc9cb..a6de1b7 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,7 @@ -'use strict'; -const ansiEscapes = require('ansi-escapes'); -const supportsHyperlinks = require('supports-hyperlinks'); +import ansiEscapes from 'ansi-escapes'; +import supportsHyperlinks from 'supports-hyperlinks'; -const terminalLink = (text, url, {target = 'stdout', ...options} = {}) => { +export default function terminalLink(text, url, {target = 'stdout', ...options} = {}) { if (!supportsHyperlinks[target]) { // If the fallback has been explicitly disabled, don't modify the text itself. if (options.fallback === false) { @@ -13,11 +12,8 @@ const terminalLink = (text, url, {target = 'stdout', ...options} = {}) => { } return ansiEscapes.link(text, url); -}; +} -module.exports = (text, url, options = {}) => terminalLink(text, url, options); - -module.exports.stderr = (text, url, options = {}) => terminalLink(text, url, {target: 'stderr', ...options}); - -module.exports.isSupported = supportsHyperlinks.stdout; -module.exports.stderr.isSupported = supportsHyperlinks.stderr; +terminalLink.isSupported = supportsHyperlinks.stdout; +terminalLink.stderr = (text, url, options = {}) => terminalLink(text, url, {target: 'stderr', ...options}); +terminalLink.stderr.isSupported = supportsHyperlinks.stderr; diff --git a/index.test-d.ts b/index.test-d.ts index 45b87f8..1c0dcbe 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,5 +1,5 @@ import {expectType} from 'tsd'; -import terminalLink = require('.'); +import terminalLink from './index.js'; expectType(terminalLink('text', 'url')); @@ -17,7 +17,7 @@ expectType( expectType(terminalLink.isSupported); -// stderr +// Stderr expectType(terminalLink.stderr('text', 'url')); @@ -27,4 +27,4 @@ expectType( }) ); -expectType(terminalLink.stderr.isSupported) +expectType(terminalLink.stderr.isSupported); diff --git a/license b/license index e7af2f7..fa7ceba 100644 --- a/license +++ b/license @@ -1,6 +1,6 @@ MIT License -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) Sindre Sorhus (https://sindresorhus.com) 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: diff --git a/package.json b/package.json index a5018e2..b921bda 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,16 @@ "author": { "name": "Sindre Sorhus", "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" + "url": "https://sindresorhus.com" }, + "type": "module", + "exports": "./index.js", "engines": { - "node": ">=8" + "node": ">=12" }, "scripts": { - "test": "xo && ava && tsd" + "//test": "xo && ava && tsd", + "test": "xo && tsd" }, "files": [ "index.js", @@ -32,13 +35,15 @@ "command-line" ], "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" + "ansi-escapes": "^5.0.0", + "supports-hyperlinks": "^2.2.0" }, "devDependencies": { - "ava": "^2.3.0", - "clear-module": "^4.0.0", - "tsd": "^0.11.0", - "xo": "^0.25.3" + "ava": "^3.15.0", + "tsd": "^0.14.0", + "xo": "^0.38.2" + }, + "ava": { + "serial": true } } diff --git a/readme.md b/readme.md index dcd3175..cd52c7b 100644 --- a/readme.md +++ b/readme.md @@ -13,7 +13,7 @@ $ npm install terminal-link ## Usage ```js -const terminalLink = require('terminal-link'); +import terminalLink from 'terminal-link'; const link = terminalLink('My Website', 'https://sindresorhus.com'); console.log(link); diff --git a/test.js b/test.js index efc01a5..e5a1578 100644 --- a/test.js +++ b/test.js @@ -1,44 +1,46 @@ -import {serial as test} from 'ava'; -import clearModule from 'clear-module'; +import test from 'ava'; -test.beforeEach(() => { - clearModule.all(); -}); +// TODO: Tests don't currently work as we need to be able to clear `supports-color`, but our `importFresh` helper can only bypass the cache at top-level. + +// eslint-disable-next-line node/no-unsupported-features/es-syntax +const importFresh = async modulePath => import(`${modulePath}?x=${new Date()}`); + +const importModule = async () => (await importFresh('./index.js')).default; test.afterEach(() => { delete process.env.FORCE_HYPERLINK; }); -test('main', t => { +test('main', async t => { process.env.FORCE_HYPERLINK = 1; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink('My Website', 'https://sindresorhus.com'); console.log(actual); t.is(actual, '\u001B]8;;https://sindresorhus.com\u0007My Website\u001B]8;;\u0007'); }); -test('stderr', t => { +test('stderr', async t => { process.env.FORCE_HYPERLINK = 1; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink.stderr('My Website', 'https://sindresorhus.com'); console.log(actual); t.is(actual, '\u001B]8;;https://sindresorhus.com\u0007My Website\u001B]8;;\u0007'); }); -test('default fallback', t => { +test('default fallback', async t => { process.env.FORCE_HYPERLINK = 0; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink('My Website', 'https://sindresorhus.com'); console.log(actual); t.is(actual, 'My Website (\u200Bhttps://sindresorhus.com\u200B)'); }); -test('disabled fallback', t => { +test('disabled fallback', async t => { process.env.FORCE_HYPERLINK = 0; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink('My Website', 'https://sindresorhus.com', { fallback: false @@ -47,9 +49,9 @@ test('disabled fallback', t => { t.is(actual, 'My Website'); }); -test('explicitly enabled fallback', t => { +test('explicitly enabled fallback', async t => { process.env.FORCE_HYPERLINK = 0; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink('My Website', 'https://sindresorhus.com', { fallback: true @@ -58,18 +60,18 @@ test('explicitly enabled fallback', t => { t.is(actual, 'My Website (\u200Bhttps://sindresorhus.com\u200B)'); }); -test('stderr default fallback', t => { +test('stderr default fallback', async t => { process.env.FORCE_HYPERLINK = 0; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink.stderr('My Website', 'https://sindresorhus.com'); console.log(actual); t.is(actual, 'My Website (\u200Bhttps://sindresorhus.com\u200B)'); }); -test('custom fallback', t => { +test('custom fallback', async t => { process.env.FORCE_HYPERLINK = 0; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink('My Website', 'https://sindresorhus.com', { fallback: (text, url) => `${text}: ${url}` @@ -78,9 +80,9 @@ test('custom fallback', t => { t.is(actual, 'My Website: https://sindresorhus.com'); }); -test('custom fallback stderr', t => { +test('custom fallback stderr', async t => { process.env.FORCE_HYPERLINK = 0; - const terminalLink = require('.'); + const terminalLink = await importModule(); const actual = terminalLink.stderr('My Website', 'https://sindresorhus.com', { fallback: (text, url) => `${text}: ${url}` @@ -89,12 +91,12 @@ test('custom fallback stderr', t => { t.is(actual, 'My Website: https://sindresorhus.com'); }); -test('isSupported', t => { - const terminalLink = require('.'); +test('isSupported', async t => { + const terminalLink = await importModule(); t.is(typeof terminalLink.isSupported, 'boolean'); }); -test('isSupported stderr', t => { - const terminalLink = require('.'); +test('isSupported stderr', async t => { + const terminalLink = await importModule(); t.is(typeof terminalLink.stderr.isSupported, 'boolean'); });