From b630317841f9ceef4a834ee31c70bf82f27ba1e3 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Fri, 29 Oct 2021 01:14:39 +0700 Subject: [PATCH] Meta tweaks --- .github/workflows/main.yml | 6 +++--- fixtures/ansi-codes.js | 10 +++++----- fixtures/view-codes.js | 5 +++-- index.d.ts | 4 ++-- index.js | 2 +- package.json | 6 ++++-- readme.md | 16 ++------------- test.js | 40 ++++++++++++++++++-------------------- 8 files changed, 39 insertions(+), 50 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d36e1a8..54a4168 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,11 +10,11 @@ jobs: fail-fast: false matrix: node-version: + - 22 - 14 - - 12 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/fixtures/ansi-codes.js b/fixtures/ansi-codes.js index 935be0f..dc84cd4 100644 --- a/fixtures/ansi-codes.js +++ b/fixtures/ansi-codes.js @@ -17,7 +17,7 @@ export const vt52Codes = new Map([ ['2', ['Graphics processor off']], ['<', ['Enter ANSI mode']], ['s', ['Cursor save']], - ['u', ['Cursor restore']] + ['u', ['Cursor restore']], ]); // From https://espterm.github.io/docs/VT100%20escape%20codes.html @@ -76,7 +76,7 @@ export const ansiCompatible = new Map([ ['c', ['Causes power-up reset routine to be executed']], ['#8', ['Fill screen with "E"']], - ['[2;176y', ['Invoke Test(s), where Ps is a decimal computed by adding the numbers of the desired tests to be executed']] + ['[2;176y', ['Invoke Test(s), where Ps is a decimal computed by adding the numbers of the desired tests to be executed']], ]); // From http://ascii-table.com/ansi-escape-sequences-vt-100.php @@ -181,7 +181,7 @@ export const commonCodes = new Map([ ['[1q', ['Turn on LED #1', 'DECLL1']], ['[2q', ['Turn on LED #2', 'DECLL2']], ['[3q', ['Turn on LED #3', 'DECLL3']], - ['[4q', ['Turn on LED #4', 'DECLL4']] + ['[4q', ['Turn on LED #4', 'DECLL4']], ]); // From http://ascii-table.com/ansi-escape-sequences-vt-100.php @@ -212,7 +212,7 @@ export const otherCode = new Map([ ['5n', ['Device status report', 'DSR']], ['0n', ['Response: terminal is OK', 'DSR']], ['3n', ['Response: terminal is not OK', 'DSR']], - ['6n', ['Get cursor position', 'DSR']] + ['6n', ['Get cursor position', 'DSR']], ]); // `urxvt` escapes @@ -229,5 +229,5 @@ export const urxvt = new Map([ ['[3;5;606t', ['URxvt.keysym.C-M-y']], ['[3;1605;5t', ['URxvt.keysym.C-M-e']], ['[3;1605;606t', ['URxvt.keysym.C-M-c']], - [']710;9x15bold\u0007', ['URxvt.keysym.font']] + [']710;9x15bold\u0007', ['URxvt.keysym.font']], ]); diff --git a/fixtures/view-codes.js b/fixtures/view-codes.js index 2c9327c..bdfa997 100644 --- a/fixtures/view-codes.js +++ b/fixtures/view-codes.js @@ -1,5 +1,6 @@ -import ansiCodes from './ansi-codes.js'; +import process from 'node:process'; import ansiRegex from '../index.js'; +import ansiCodes from './ansi-codes.js'; const allCodes = {}; const supported = []; @@ -18,7 +19,7 @@ function identifySupportedCodes() { codeSupport = { code, matches: `\u001B${code}`.match(ansiRegex()), - description: value[0] + description: value[0], }; if (codeSupport.matches !== null && codeSupport.matches[0] === `\u001B${code}`) { diff --git a/index.d.ts b/index.d.ts index 50ef64d..7d562e9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,11 +1,11 @@ -export interface Options { +export type Options = { /** Match only the first ANSI escape. @default false */ readonly onlyFirst: boolean; -} +}; /** Regular expression for matching ANSI escape codes. diff --git a/index.js b/index.js index 0dfae22..9795fdc 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ export default function ansiRegex({onlyFirst = false} = {}) { const pattern = [ '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', - '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))' + '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))', ].join('|'); return new RegExp(pattern, onlyFirst ? undefined : 'g'); diff --git a/package.json b/package.json index 6445c00..5e4b9bd 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ }, "type": "module", "exports": "./index.js", + "types": "./index.d.ts", + "sideEffects": false, "engines": { "node": ">=12" }, @@ -53,7 +55,7 @@ "devDependencies": { "ansi-escapes": "^5.0.0", "ava": "^3.15.0", - "tsd": "^0.14.0", - "xo": "^0.38.2" + "tsd": "^0.21.0", + "xo": "^0.54.2" } } diff --git a/readme.md b/readme.md index 0e17e23..1e91ee1 100644 --- a/readme.md +++ b/readme.md @@ -4,8 +4,8 @@ ## Install -``` -$ npm install ansi-regex +```sh +npm install ansi-regex ``` ## Usage @@ -58,15 +58,3 @@ On the historical side, those ECMA standards were established in the early 90's - [Sindre Sorhus](https://github.com/sindresorhus) - [Josh Junon](https://github.com/qix-) - ---- - -
- - Get professional support for this package with a Tidelift subscription - -
- - Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. -
-
diff --git a/test.js b/test.js index 7cfb248..7c19d21 100644 --- a/test.js +++ b/test.js @@ -47,11 +47,11 @@ test('match terminal link', t => { t.regex('\u001B]8;;mailto:no-replay@mail.com\u0007mail\u001B]8;;\u0007', ansiRegex()); t.deepEqual('\u001B]8;k=v;https://example-a.com/?a_b=1&c=2#tit%20le\u0007click\u001B]8;;\u0007'.match(ansiRegex()), [ '\u001B]8;k=v;https://example-a.com/?a_b=1&c=2#tit%20le\u0007', - '\u001B]8;;\u0007' + '\u001B]8;;\u0007', ]); t.deepEqual('\u001B]8;;mailto:no-reply@mail.com\u0007mail-me\u001B]8;;\u0007'.match(ansiRegex()), [ '\u001B]8;;mailto:no-reply@mail.com\u0007', - '\u001B]8;;\u0007' + '\u001B]8;;\u0007', ]); }); @@ -60,14 +60,14 @@ test('match "change icon name and window title" in string', t => { }); // Testing against extended codes (excluding codes ending in 0-9) -for (const codeSet of Object.keys(ansiCodes)) { - for (const [code, codeInfo] of ansiCodes[codeSet]) { - const skip = /\d$/.test(code); - const skipText = skip ? '[SKIP] ' : ''; +for (const [codeSetKey, codeSetValue] of Object.entries(ansiCodes)) { + for (const [code, codeInfo] of codeSetValue) { + const shouldSkip = /\d$/.test(code); + const skipText = shouldSkip ? '[SKIP] ' : ''; const ecode = `\u001B${code}`; - test(`${codeSet} - ${skipText}${code} → ${codeInfo[0]}`, t => { - if (skip) { + test(`${codeSetKey} - ${skipText}${code} → ${codeInfo[0]}`, t => { + if (shouldSkip) { t.pass(); return; } @@ -78,36 +78,34 @@ for (const codeSet of Object.keys(ansiCodes)) { t.is(string.replace(ansiRegex(), ''), 'hello'); }); - test(`${codeSet} - ${skipText}${code} should not overconsume`, t => { - if (skip) { + test(`${codeSetKey} - ${skipText}${code} should not overconsume`, t => { + if (shouldSkip) { t.pass(); return; } - for (const c of consumptionCharacters) { - const string = ecode + c; + for (const character of consumptionCharacters) { + const string = ecode + character; t.regex(string, ansiRegex()); t.is(string.match(ansiRegex())[0], ecode); - t.is(string.replace(ansiRegex(), ''), c); + t.is(string.replace(ansiRegex(), ''), character); } }); } } -const escapeCodeFunctionArgs = [1, 2]; +const escapeCodeFunctionArguments = [1, 2]; const escapeCodeIgnoresList = new Set(['beep', 'image', 'iTerm']); -const escapeCodeResultMap = new Map([['link', escapeCodeFunctionArgs[0]]]); +const escapeCodeResultMap = new Map([['link', escapeCodeFunctionArguments[0]]]); -for (const key of Object.keys(ansiEscapes)) { +for (const [key, escapeCode] of Object.entries(ansiEscapes)) { if (escapeCodeIgnoresList.has(key)) { continue; } - const escapeCode = ansiEscapes[key]; - - const escapeCodeValue = typeof escapeCode === 'function' ? - escapeCode(...escapeCodeFunctionArgs) : - escapeCode; + const escapeCodeValue = typeof escapeCode === 'function' + ? escapeCode(...escapeCodeFunctionArguments) + : escapeCode; test(`ansi-escapes ${key}`, t => { for (const character of consumptionCharacters) {