Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@medv/finder

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@medv/finder - npm Package Compare versions

Comparing version 3.0.0 to 3.1.0

107

finder.js

@@ -0,4 +1,6 @@

// License: MIT
// Author: Anton Medvedev <anton@medv.io>
// Source: https://github.com/antonmedv/finder
let config;
let rootDocument;
let uniqueCache;
export function finder(input, options) {

@@ -24,3 +26,2 @@ if (input.nodeType !== Node.ELEMENT_NODE) {

rootDocument = findRootDocument(config.root, defaults);
uniqueCache = new Map();
let path = bottomUpSearch(input, 'all', () => bottomUpSearch(input, 'two', () => bottomUpSearch(input, 'one', () => bottomUpSearch(input, 'none'))));

@@ -138,6 +139,4 @@ if (path) {

case 1:
uniqueCache.set(css, true);
return true;
default:
uniqueCache.set(css, false);
return false;

@@ -150,3 +149,3 @@ }

return {
name: '#' + cssesc(elementId, { isIdentifier: true }),
name: '#' + CSS.escape(elementId),
penalty: 0,

@@ -160,7 +159,3 @@ };

return attrs.map((attr) => ({
name: '[' +
cssesc(attr.name, { isIdentifier: true }) +
'="' +
cssesc(attr.value) +
'"]',
name: `[${CSS.escape(attr.name)}="${CSS.escape(attr.value)}"]`,
penalty: 0.5,

@@ -172,3 +167,3 @@ }));

return names.map((name) => ({
name: '.' + cssesc(name, { isIdentifier: true }),
name: '.' + CSS.escape(name),
penalty: 1,

@@ -273,91 +268,1 @@ }));

}
const regexAnySingleEscape = /[ -,\.\/:-@\[-\^`\{-~]/;
const regexSingleEscape = /[ -,\.\/:-@\[\]\^`\{-~]/;
const regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;
const defaultOptions = {
escapeEverything: false,
isIdentifier: false,
quotes: 'single',
wrap: false,
};
function cssesc(string, opt = {}) {
const options = { ...defaultOptions, ...opt };
if (options.quotes != 'single' && options.quotes != 'double') {
options.quotes = 'single';
}
const quote = options.quotes == 'double' ? '"' : '\'';
const isIdentifier = options.isIdentifier;
const firstChar = string.charAt(0);
let output = '';
let counter = 0;
const length = string.length;
while (counter < length) {
const character = string.charAt(counter++);
let codePoint = character.charCodeAt(0);
let value = void 0;
// If it’s not a printable ASCII character…
if (codePoint < 0x20 || codePoint > 0x7e) {
if (codePoint >= 0xd800 && codePoint <= 0xdbff && counter < length) {
// It’s a high surrogate, and there is a next character.
const extra = string.charCodeAt(counter++);
if ((extra & 0xfc00) == 0xdc00) {
// next character is low surrogate
codePoint = ((codePoint & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
}
else {
// It’s an unmatched surrogate; only append this code unit, in case
// the next code unit is the high surrogate of a surrogate pair.
counter--;
}
}
value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
}
else {
if (options.escapeEverything) {
if (regexAnySingleEscape.test(character)) {
value = '\\' + character;
}
else {
value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
}
}
else if (/[\t\n\f\r\x0B]/.test(character)) {
value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
}
else if (character == '\\' ||
(!isIdentifier &&
((character == '"' && quote == character) ||
(character == '\'' && quote == character))) ||
(isIdentifier && regexSingleEscape.test(character))) {
value = '\\' + character;
}
else {
value = character;
}
}
output += value;
}
if (isIdentifier) {
if (/^-[-\d]/.test(output)) {
output = '\\-' + output.slice(1);
}
else if (/\d/.test(firstChar)) {
output = '\\3' + firstChar + ' ' + output.slice(1);
}
}
// Remove spaces after `\HEX` escapes that are not followed by a hex digit,
// since they’re redundant. Note that this is only possible if the escape
// sequence isn’t preceded by an odd number of backslashes.
output = output.replace(regexExcessiveSpaces, function ($0, $1, $2) {
if ($1 && $1.length % 2) {
// It’s not safe to remove the space, so don’t.
return $0;
}
// Strip the space.
return ($1 || '') + $2;
});
if (!isIdentifier && options.wrap) {
return quote + output + quote;
}
return output;
}

@@ -191,3 +191,3 @@ // License: MIT

return {
name: '#' + cssesc(elementId, {isIdentifier: true}),
name: '#' + CSS.escape(elementId),
penalty: 0,

@@ -205,8 +205,3 @@ }

(attr): Knot => ({
name:
'[' +
cssesc(attr.name, {isIdentifier: true}) +
'="' +
cssesc(attr.value) +
'"]',
name: `[${CSS.escape(attr.name)}="${CSS.escape(attr.value)}"]`,
penalty: 0.5,

@@ -221,3 +216,3 @@ })

(name): Knot => ({
name: '.' + cssesc(name, {isIdentifier: true}),
name: '.' + CSS.escape(name),
penalty: 1,

@@ -342,90 +337,1 @@ })

}
const regexAnySingleEscape = /[ -,\.\/:-@\[-\^`\{-~]/
const regexSingleEscape = /[ -,\.\/:-@\[\]\^`\{-~]/
const regexExcessiveSpaces =
/(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g
const defaultOptions = {
escapeEverything: false,
isIdentifier: false,
quotes: 'single',
wrap: false,
}
function cssesc(string: string, opt: Partial<typeof defaultOptions> = {}) {
const options = {...defaultOptions, ...opt}
if (options.quotes != 'single' && options.quotes != 'double') {
options.quotes = 'single'
}
const quote = options.quotes == 'double' ? '"' : '\''
const isIdentifier = options.isIdentifier
const firstChar = string.charAt(0)
let output = ''
let counter = 0
const length = string.length
while (counter < length) {
const character = string.charAt(counter++)
let codePoint = character.charCodeAt(0)
let value: string | undefined = void 0
// If it’s not a printable ASCII character…
if (codePoint < 0x20 || codePoint > 0x7e) {
if (codePoint >= 0xd800 && codePoint <= 0xdbff && counter < length) {
// It’s a high surrogate, and there is a next character.
const extra = string.charCodeAt(counter++)
if ((extra & 0xfc00) == 0xdc00) {
// next character is low surrogate
codePoint = ((codePoint & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000
} else {
// It’s an unmatched surrogate; only append this code unit, in case
// the next code unit is the high surrogate of a surrogate pair.
counter--
}
}
value = '\\' + codePoint.toString(16).toUpperCase() + ' '
} else {
if (options.escapeEverything) {
if (regexAnySingleEscape.test(character)) {
value = '\\' + character
} else {
value = '\\' + codePoint.toString(16).toUpperCase() + ' '
}
} else if (/[\t\n\f\r\x0B]/.test(character)) {
value = '\\' + codePoint.toString(16).toUpperCase() + ' '
} else if (
character == '\\' ||
(!isIdentifier &&
((character == '"' && quote == character) ||
(character == '\'' && quote == character))) ||
(isIdentifier && regexSingleEscape.test(character))
) {
value = '\\' + character
} else {
value = character
}
}
output += value
}
if (isIdentifier) {
if (/^-[-\d]/.test(output)) {
output = '\\-' + output.slice(1)
} else if (/\d/.test(firstChar)) {
output = '\\3' + firstChar + ' ' + output.slice(1)
}
}
// Remove spaces after `\HEX` escapes that are not followed by a hex digit,
// since they’re redundant. Note that this is only possible if the escape
// sequence isn’t preceded by an odd number of backslashes.
output = output.replace(regexExcessiveSpaces, function ($0, $1, $2) {
if ($1 && $1.length % 2) {
// It’s not safe to remove the space, so don’t.
return $0
}
// Strip the space.
return ($1 || '') + $2
})
if (!isIdentifier && options.wrap) {
return quote + output + quote
}
return output
}

3

package.json
{
"name": "@medv/finder",
"version": "3.0.0",
"version": "3.1.0",
"description": "CSS Selector Generator",

@@ -18,2 +18,3 @@ "type": "module",

"devDependencies": {
"css.escape": "^1.5.1",
"jsdom": "^21.1.0",

@@ -20,0 +21,0 @@ "release-it": "^15.7.0",

@@ -5,5 +5,3 @@ ![finder](https://medv.io/assets/finder.png)

[![Version](https://img.shields.io/npm/v/@medv/finder?color=grightgreen)](https://www.npmjs.com/package/@medv/finder)
[![Test](https://github.com/antonmedv/finder/actions/workflows/test.yml/badge.svg)](https://github.com/antonmedv/finder/actions/workflows/test.yml)
[![Size](https://img.shields.io/bundlephobia/minzip/@medv/finder?label=size)](https://bundlephobia.com/result?p=@medv/finder)

@@ -64,3 +62,3 @@ **The CSS Selector Generator**

For more robust selectors give this param value around 4-5 depending on depth of
you DOM tree. If `finder` hits `root` this param is ignored.
you DOM tree. If finder hits the `root`, this param is ignored.

@@ -75,10 +73,9 @@ ### optimizedMinLength

Max number of selectors to check before falling into `nth-child` usage.
Checking for uniqueness of selector is very costs operation, if you have DOM
Checking for uniqueness of selector is very costly operation, if you have DOM
tree depth of 5, with 5 classes on each level, that gives you more than 3k
selectors to check. Finder uses two-step approach,Ï so it's reaching this
threshold in some cases twice. Default `1000` is good enough in most cases.
selectors to check. Default `1000` is good enough in most cases.
### maxNumberOfTries
Max number of tries when we do the optimization. It is a trade-off between
Max number of tries for the optimization. This is a trade-off between
optimization and efficiency. Default `10_000` is good enough in most cases.

@@ -85,0 +82,0 @@

Sorry, the diff of this file is not supported yet

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