New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

pretty-repl

Package Overview
Dependencies
Maintainers
28
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pretty-repl - npm Package Compare versions

Comparing version 3.0.2 to 3.1.0

lib/find-all-matching-brackets.js

7

lib/highlight.js

@@ -50,4 +50,7 @@ 'use strict';

}
const colorSheet = sheet(new chalk.Instance({ level }));
return (s) => emphasize.highlight('js', s, colorSheet).value;
const chalkInstance = new chalk.Instance({ level });
const colorSheet = sheet(chalkInstance);
const highlight = (s) => emphasize.highlight('js', s, colorSheet).value;
highlight.colorizeMatchingBracket = (s) => chalkInstance.bgBlue(s);
return highlight;
};

@@ -5,2 +5,3 @@ 'use strict';

const memoizeStringTransformerMethod = require('./memoize-string-transformer');
const findAllMatchingBrackets = require('./find-all-matching-brackets');
const ansiRegex = require('ansi-regex');

@@ -14,2 +15,6 @@ const stripAnsi = require('strip-ansi');

// Every open/close pair that should be matched against its counterpart for
// highlighting.
const allBrackets = '()[]{}\'"`$';
// Compute the length of the longest common prefix of 'before' and 'after',

@@ -57,3 +62,6 @@ // taking ANSI escape sequences into account. For example:

this.colorize = (options && options.colorize) || highlight(options.output);
this.colorizeMatchingBracket = (options && options.colorizeMatchingBracket) ||
highlight(options.output).colorizeMatchingBracket;
this.lineBeforeInsert = undefined;
this.highlightBracketPosition = -1;

@@ -67,2 +75,26 @@ // For some reason, tests fail if we don't initialize line to be the empty string.

// If the cursor is moved onto or off a bracket, refresh the whole line so that
// we can mark the matching bracket.
_moveCursor (dx) {
const cursorWasOnBracket = allBrackets.includes(this.line[this.cursor]);
super._moveCursor(dx);
const cursorIsOnBracket = allBrackets.includes(this.line[this.cursor]);
if (cursorWasOnBracket || cursorIsOnBracket) {
this._refreshLine();
}
}
// When refreshinng the whole line, find matching brackets and keep the position
// of the matching one in mind (if there is any).
_refreshLine () {
try {
if (this.colorizeMatchingBracket && allBrackets.includes(this.line[this.cursor])) {
this.highlightBracketPosition = this._findMatchingBracket(this.line, this.cursor);
}
return super._refreshLine();
} finally {
this.highlightBracketPosition = -1;
}
}
_writeToOutput (stringToWrite) {

@@ -148,3 +180,18 @@ // Skip false-y values, and if we print only whitespace or have not yet

stringToWrite = stringToWrite.substring(this._prompt.length);
this.output.write(this._prompt + this._doColorize(stringToWrite));
if (this.highlightBracketPosition !== -1) {
// If there is a matching bracket, we mark it in the string before
// highlighting using BOM characters (because it seems safe to assume
// that they are ignored by highlighting) so that we can remember where
// the bracket was.
stringToWrite =
stringToWrite.substring(0, this.highlightBracketPosition) +
'\ufeff' + stringToWrite[this.highlightBracketPosition] + '\ufeff' +
stringToWrite.substring(this.highlightBracketPosition + 1);
stringToWrite = this._doColorize(stringToWrite);
// Then remove the BOM characters again and colorize the bracket in between.
stringToWrite = stringToWrite.replace(/\ufeff(.+)\ufeff/, (_, bracket) => this.colorizeMatchingBracket(bracket));
} else {
stringToWrite = this._doColorize(stringToWrite);
}
this.output.write(this._prompt + stringToWrite);
}

@@ -165,43 +212,41 @@

_stripCompleteJSStructures(str) {
_stripCompleteJSStructures = memoizeStringTransformerMethod(1000, function(str) {
// Remove substructures of the JS input string `str` in order to simplify it,
// by repeatedly removing matching pairs of quotes and parentheses/brackets.
let before;
do {
before = str;
str = this._stripCompleteJSStructuresStep(before);
} while (before !== str);
return str;
}
// by removing matching pairs of quotes and parentheses/brackets.
_stripCompleteJSStructuresStep = memoizeStringTransformerMethod(10000, function(str) {
// This regular expression matches:
// - matching pairs of (), without any of ()[]{}`'" in between
// - matching pairs of [], without any of ()[]{}`'" in between
// - matching pairs of {}, without any of ()[]{}`'" in between
// - matching pairs of '', with only non-'\, \\, and \' preceded by an even number of \ in between
// - matching pairs of "", with only non-"\, \\, and \" preceded by an even number of \ in between
// - matching pairs of ``, with only non-`{}\, \\ and \` preceded by an even number of \ in between
const re = /\([^\(\)\[\]\{\}`'"]*\)|\[[^\(\)\[\]\{\}`'"]*\]|\{[^\(\)\[\]\{\}`'"]*\}|'([^'\\]|(?<=[^\\](\\\\)*)\\'|\\\\)*'|"([^"\\]|(?<=[^\\](\\\\)*)\\"|\\\\)*"|`([^\{\}`\\]|(?<=[^\\](\\\\)*)\\`|\\\\)*`/g;
// Match the regexp against the input. If there are no matches, we can just return.
const matches = [...str.matchAll(re)];
if (matches.length === 0) {
return str;
}
// Remove all but the last, non-nested pair of (), because () can affect
// whether the previous word is seen as a keyword.
// Specifically, remove all but the last, non-nested pair of (), because ()
// can affect whether the previous word is seen as a keyword.
// E.g.: When input is `function() {`, do not replace the ().
// When input is `{ foo(); }`, do replace the `()`, then afterwards the `{ ... }`.
let startsReplaceIndex = matches.length - 1;
const lastMatch = matches[matches.length - 1];
if (lastMatch[0].startsWith('(') && !str.substr(lastMatch.index + lastMatch[0].length).match(/[\)\]\}`'"]/)) {
startsReplaceIndex--;
const brackets = this._findAllMatchingBracketsIgnoreMismatches(str);
if (brackets.length > 0) {
const last = brackets[brackets.length - 1];
if (last.kind === '(' && (last.parent == null || last.parent.end === -1))
brackets.pop();
}
for (let i = startsReplaceIndex; i >= 0; i--) {
// Replace str1<match>str2 with str1str2. Go backwards so that the match
// indices into the string remain valid.
str = str.substr(0, matches[i].index) + str.substr(matches[i].index + matches[i][0].length);
// Remove brackets in reverse order, so that their indices remain valid.
for (let i = brackets.length - 1; i >= 0; i--) {
str = str.substr(0, brackets[i].start) + str.substr(brackets[i].end + 1);
}
return str;
});
_findAllMatchingBracketsIgnoreMismatches = memoizeStringTransformerMethod(1000, function(str) {
return findAllMatchingBrackets(str, true);
});
_findAllMatchingBracketsIncludeMismatches = memoizeStringTransformerMethod(1000, function(str) {
return findAllMatchingBrackets(str, false);
});
// Find the matching bracket opposite of the one at `position`.
_findMatchingBracket(line, position) {
const brackets = this._findAllMatchingBracketsIncludeMismatches(line);
for (const bracket of brackets) {
if (bracket.start === position)
return bracket.end;
if (bracket.end === position)
return bracket.start;
}
return -1;
}
}

@@ -208,0 +253,0 @@

@@ -9,3 +9,3 @@ {

],
"version": "3.0.2",
"version": "3.1.0",
"description": "Extends repl.REPLServer to allow for a colorize function",

@@ -24,3 +24,3 @@ "main": "index.js",

"ansi-regex": "^5.0.0",
"chalk": "^4.0.0",
"chalk": "^4.1.1",
"emphasize": "^3.0.0",

@@ -27,0 +27,0 @@ "strip-ansi": "^6.0.0"

@@ -42,8 +42,5 @@ # Pretty REPL

## Known issues
In order to highlighting matching pairs of brackets, a `colorizeMatchingBracket`
is also available.
* The implementation in Node.js versions 11 and 12, this module works by monkey-patching the Interface prototype (`readline` module).
If you use `readline` (or a module that depends on it) somewhere else, you may want to test everything thoroughly. In theory, there should be no side effects.
* For Node.js versions older than 11, this module does nothing.
## Credits

@@ -50,0 +47,0 @@

@@ -128,2 +128,24 @@ const test = require('tape');

test('findMatchingBracket', t => {
t.plan(10);
const { stdin } = stdio();
const output = new PassThrough();
output.isTTY = true;
output.getColorDepth = () => 8;
const prettyRepl = repl.start({
input: stdin,
output: output
});
t.equal(prettyRepl._findMatchingBracket('abc { def }', 4), 10);
t.equal(prettyRepl._findMatchingBracket('abc { def }', 10), 4);
t.equal(prettyRepl._findMatchingBracket('abc {( def }', 4), 11);
t.equal(prettyRepl._findMatchingBracket('abc {( def }', 5), -1);
t.equal(prettyRepl._findMatchingBracket('abc {( def }', 0), -1);
t.equal(prettyRepl._findMatchingBracket('abc {( def }', 11), 4);
t.equal(prettyRepl._findMatchingBracket('"(")', 0), 2);
t.equal(prettyRepl._findMatchingBracket('"(")', 1), -1);
t.equal(prettyRepl._findMatchingBracket('`${foo}`', 1), 6);
t.equal(prettyRepl._findMatchingBracket('(`${")"}`', 0), -1);
});
test('full pass-through test', t => {

@@ -130,0 +152,0 @@ t.plan(1);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc