Socket
Socket
Sign inDemoInstall

postcss-selector-parser

Package Overview
Dependencies
Maintainers
3
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

postcss-selector-parser - npm Package Compare versions

Comparing version 3.0.0-rc.0 to 3.0.0

dist/selectors/constructors.js

159

API.md

@@ -14,3 +14,3 @@ # API Documentation

### `parser([transform])`
### `parser([transform], [options])`

@@ -24,3 +24,3 @@ Creates a new `processor` instance

const transform = selectors => {
selectors.eachUniversal(selector => {
selectors.walkUniversals(selector => {
selector.remove();

@@ -42,2 +42,3 @@ });

* `transform (function)`: Provide a function to work with the parsed AST.
* `options (object)`: Provide default options for all calls on the returned `Processor`.

@@ -603,20 +604,37 @@ ### `parser.attribute([props])`

## `processor`
## `Processor`
### `process|processSync(css, [options])`
### `ProcessorOptions`
Processes the `css`, returning the parsed output. An async method is exposed
as `process`.
* `lossless` - When `true`, whitespace is preserved. Defaults to `true`.
* `updateSelector` - When `true`, if any processor methods are passed a postcss
`Rule` node instead of a string, then that Rule's selector is updated
with the results of the processing. Defaults to `true`.
### `process|processSync(selectors, [options])`
Processes the `selectors`, returning a string from the result of processing.
Note: when the `updateSelector` option is set, the rule's selector
will be updated with the resulting string.
**Example:**
```js
const parser = require("postcss-selector-parser");
const processor = parser();
const result = processor.processSync(' .class');
let result = processor.processSync(' .class');
console.log(result);
// => .class
// Asynchronous operation
processor.process(' .class').then(result => /* ... */);
let promise = processor.process(' .class').then(result => {
console.log(result)
// => .class
});
// To have the parser normalize whitespace values, utilize the options
const result = processor.processSync(' .class ', {lossless: false});
result = processor.processSync(' .class ', {lossless: false});
console.log(result);
// => .class

@@ -626,4 +644,9 @@

const postcss = require('postcss');
const rule = postcss.rule({selector: 'a'});
const result = process.process(rule);
rule = postcss.rule({selector: ' #foo > a, .class '});
processor.process(rule, {lossless: false, updateSelector: true}).then(result => {
console.log(result);
// => #foo>a,.class
console.log("rule:", rule.selector);
// => rule: #foo>a,.class
})
```

@@ -633,7 +656,115 @@

* `css (string|object)`: Either a selector string or a PostCSS Rule node.
* `selectors (string|postcss.Rule)`: Either a selector string or a PostCSS Rule
node.
* `[options] (object)`: Process options
Options:
* `lossless (boolean)`: false to normalize the selector whitespace, defaults to true
### `ast|astSync(selectors, [options])`
Like `process()` and `processSync()` but after
processing the `selectors` these methods return the `Root` node of the result
instead of a string.
Note: when the `updateSelector` option is set, the rule's selector
will be updated with the resulting string.
### `transform|transformSync(selectors, [options])`
Like `process()` and `processSync()` but after
processing the `selectors` these methods return the value returned by the
processor callback.
Note: when the `updateSelector` option is set, the rule's selector
will be updated with the resulting string.
### Error Handling Within Selector Processors
The root node passed to the selector processor callback
has a method `error(message, options)` that returns an
error object. This method should always be used to raise
errors relating to the syntax of selectors. The options
to this method are passed to postcss's error constructor
([documentation](http://api.postcss.org/Container.html#error)).
#### Async Error Example
```js
let processor = (root) => {
return new Promise((resolve, reject) => {
root.walkClasses((classNode) => {
if (/^(.*)[-_]/.test(classNode.value)) {
let msg = "classes may not have underscores or dashes in them";
reject(root.error(msg, {
index: classNode.sourceIndex + RegExp.$1.length + 1,
word: classNode.value
}));
}
});
resolve();
});
};
const postcss = require("postcss");
const parser = require("postcss-selector-parser");
const selectorProcessor = parser(processor);
const plugin = postcss.plugin('classValidator', (options) => {
return (root) => {
let promises = [];
root.walkRules(rule => {
promises.push(selectorProcessor.process(rule));
});
return Promise.all(promises);
};
});
postcss(plugin()).process(`
.foo-bar {
color: red;
}
`.trim(), {from: 'test.css'}).catch((e) => console.error(e.toString()));
// CssSyntaxError: classValidator: ./test.css:1:5: classes may not have underscores or dashes in them
//
// > 1 | .foo-bar {
// | ^
// 2 | color: red;
// 3 | }
```
#### Synchronous Error Example
```js
let processor = (root) => {
root.walkClasses((classNode) => {
if (/.*[-_]/.test(classNode.value)) {
let msg = "classes may not have underscores or dashes in them";
throw root.error(msg, {
index: classNode.sourceIndex,
word: classNode.value
});
}
});
};
const postcss = require("postcss");
const parser = require("postcss-selector-parser");
const selectorProcessor = parser(processor);
const plugin = postcss.plugin('classValidator', (options) => {
return (root) => {
root.walkRules(rule => {
selectorProcessor.processSync(rule);
});
};
});
postcss(plugin()).process(`
.foo-bar {
color: red;
}
`.trim(), {from: 'test.css'}).catch((e) => console.error(e.toString()));
// CssSyntaxError: classValidator: ./test.css:1:5: classes may not have underscores or dashes in them
//
// > 1 | .foo-bar {
// | ^
// 2 | color: red;
// 3 | }
```

@@ -11,2 +11,4 @@ # 3.0.0-rc.0

async, and the sync API is now accessed through `processSync` instead.
* `process()` and `processSync()` now return a string instead of the Processor
instance.
* Tweaks handling of Less interpolation (thanks to @jwilsson).

@@ -17,8 +19,25 @@ * Removes support for Node 0.12.

* `ast()` and `astSync()` methods have been added to the `Processor`. These
return the `Root` node of the selectors after processing them.
* `transform()` and `transformSync()` methods have been added to the
`Processor`. These return the value returned by the processor callback
after processing the selectors.
* Set the parent when inserting a node (thanks to @chriseppstein).
* Correctly adjust indices when using insertBefore/insertAfter (thanks to @tivac).
* Fixes handling of namespaces with qualified tag selectors.
* Now accepts a PostCSS rule node for better syntax errors.
* `process`, `ast` and `transform` (and their sync variants) now accept a
`postcss` rule node. When provided, better errors are generated and selector
processing is automatically set back to the rule selector (unless the `updateSelector` option is set to `false`.)
* Now more memory efficient when tokenizing selectors.
### Upgrade hints
The pattern of:
`rule.selector = processor.process(rule.selector).result.toString();`
is now:
`processor.processSync(rule)`
# 2.2.3

@@ -25,0 +44,0 @@

98

dist/index.js

@@ -9,54 +9,6 @@ 'use strict';

var _attribute = require('./selectors/attribute');
var _selectors = require('./selectors');
var _attribute2 = _interopRequireDefault(_attribute);
var selectors = _interopRequireWildcard(_selectors);
var _className = require('./selectors/className');
var _className2 = _interopRequireDefault(_className);
var _combinator = require('./selectors/combinator');
var _combinator2 = _interopRequireDefault(_combinator);
var _comment = require('./selectors/comment');
var _comment2 = _interopRequireDefault(_comment);
var _id = require('./selectors/id');
var _id2 = _interopRequireDefault(_id);
var _nesting = require('./selectors/nesting');
var _nesting2 = _interopRequireDefault(_nesting);
var _pseudo = require('./selectors/pseudo');
var _pseudo2 = _interopRequireDefault(_pseudo);
var _root = require('./selectors/root');
var _root2 = _interopRequireDefault(_root);
var _selector = require('./selectors/selector');
var _selector2 = _interopRequireDefault(_selector);
var _string = require('./selectors/string');
var _string2 = _interopRequireDefault(_string);
var _tag = require('./selectors/tag');
var _tag2 = _interopRequireDefault(_tag);
var _universal = require('./selectors/universal');
var _universal2 = _interopRequireDefault(_universal);
var _types = require('./selectors/types');
var types = _interopRequireWildcard(_types);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

@@ -67,50 +19,10 @@

var parser = function parser(processor) {
return new _processor2.default(processor);
return new _processor2.default(processor);
};
parser.attribute = function (opts) {
return new _attribute2.default(opts);
};
parser.className = function (opts) {
return new _className2.default(opts);
};
parser.combinator = function (opts) {
return new _combinator2.default(opts);
};
parser.comment = function (opts) {
return new _comment2.default(opts);
};
parser.id = function (opts) {
return new _id2.default(opts);
};
parser.nesting = function (opts) {
return new _nesting2.default(opts);
};
parser.pseudo = function (opts) {
return new _pseudo2.default(opts);
};
parser.root = function (opts) {
return new _root2.default(opts);
};
parser.selector = function (opts) {
return new _selector2.default(opts);
};
parser.string = function (opts) {
return new _string2.default(opts);
};
parser.tag = function (opts) {
return new _tag2.default(opts);
};
parser.universal = function (opts) {
return new _universal2.default(opts);
};
Object.assign(parser, selectors);
Object.keys(types).forEach(function (type) {
if (type === '__esModule') {
return;
}
parser[type] = types[type]; // eslint-disable-line
});
delete parser.__esModule;
exports.default = parser;
module.exports = exports['default'];

@@ -103,9 +103,12 @@ 'use strict';

var Parser = function () {
function Parser(input) {
function Parser(rule) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, Parser);
this.input = input;
this.lossy = input.options.lossless === false;
this.rule = rule;
this.options = Object.assign({ lossy: false, safe: false }, options);
this.position = 0;
this.root = new _root2.default();
this.root.errorGenerator = this._errorGenerator();

@@ -116,14 +119,27 @@ var selector = new _selector2.default();

this.css = typeof input.css === 'string' ? input.css : input.css.selector;
this.css = typeof this.rule === 'string' ? this.rule : this.rule.selector;
if (this.lossy) {
if (this.options.lossy) {
this.css = this.css.trim();
this.tokens = (0, _tokenize2.default)({ safe: input.safe, css: this.css });
} else {
this.tokens = (0, _tokenize2.default)(Object.assign({}, input, { css: this.css }));
}
this.tokens = (0, _tokenize2.default)({
css: this.css,
error: this._errorGenerator(),
safe: this.options.safe
});
return this.loop();
this.loop();
}
Parser.prototype._errorGenerator = function _errorGenerator() {
var _this = this;
return function (message, errorOptions) {
if (typeof _this.rule === 'string') {
return new Error(message);
}
return _this.rule.error(message, errorOptions);
};
};
Parser.prototype.attribute = function attribute() {

@@ -166,3 +182,3 @@ var attr = [];

}
if (this.lossy) {
if (this.options.lossy) {
break;

@@ -173,3 +189,7 @@ }

} else {
_dotProp2.default.set(node, lastAdded, _dotProp2.default.get(node, lastAdded) + content);
if (lastAdded === 'operator') {
_dotProp2.default.set(node, 'raws.' + lastAdded, _dotProp2.default.get(node, lastAdded) + content);
} else {
_dotProp2.default.set(node, lastAdded, _dotProp2.default.get(node, lastAdded) + content);
}
}

@@ -224,3 +244,3 @@ break;

node.insensitive = true;
if (!this.lossy) {
if (!this.options.lossy) {
lastAdded = 'raws.insensitive';

@@ -250,3 +270,3 @@ _dotProp2.default.set(node, lastAdded, '' + spaceBefore + content);

}
node.operator = node.operator ? '' + node.operator + content : content;
node.operator = node.operator ? node.operator + content : content;
lastAdded = 'operator';

@@ -322,3 +342,3 @@ break;

Parser.prototype.error = function error(message, opts) {
throw new this.input.error(message, opts); // eslint-disable-line new-cap
throw this.root.error(message, opts);
};

@@ -405,3 +425,3 @@

Parser.prototype.pseudo = function pseudo() {
var _this = this;
var _this2 = this;

@@ -420,10 +440,10 @@ var pseudoStr = '';

pseudoStr += first;
_this.newNode(new _pseudo2.default({
_this2.newNode(new _pseudo2.default({
value: pseudoStr,
source: getSource(startingToken[1], startingToken[2], _this.currToken[3], _this.currToken[4]),
source: getSource(startingToken[1], startingToken[2], _this2.currToken[3], _this2.currToken[4]),
sourceIndex: startingToken[5]
}));
if (length > 1 && _this.nextToken && _this.nextToken[0] === tokens.openParenthesis) {
_this.error('Misplaced parenthesis.', {
index: _this.nextToken[5]
if (length > 1 && _this2.nextToken && _this2.nextToken[0] === tokens.openParenthesis) {
_this2.error('Misplaced parenthesis.', {
index: _this2.nextToken[5]
});

@@ -477,3 +497,3 @@ }

Parser.prototype.splitWord = function splitWord(namespace, firstCallback) {
var _this2 = this;
var _this3 = this;

@@ -509,6 +529,6 @@ var nextToken = this.nextToken;

if (i === 0 && firstCallback) {
return firstCallback.call(_this2, value, indices.length);
return firstCallback.call(_this3, value, indices.length);
}
var node = void 0;
var current = _this2.currToken;
var current = _this3.currToken;
var sourceIndex = current[5] + indices[i];

@@ -535,3 +555,3 @@ var source = getSource(current[1], current[2] + ind, current[3], current[2] + (index - 1));

}
_this2.newNode(node, namespace);
_this3.newNode(node, namespace);
// Ensure that the namespace is used only once

@@ -627,3 +647,3 @@ namespace = null;

Parser.prototype.parseNamespace = function parseNamespace(namespace) {
if (this.lossy && typeof namespace === 'string') {
if (this.options.lossy && typeof namespace === 'string') {
var trimmed = namespace.trim();

@@ -643,7 +663,7 @@ if (!trimmed.length) {

return this.lossy ? replacement : space;
return this.options.lossy ? replacement : space;
};
Parser.prototype.parseValue = function parseValue(value) {
if (!this.lossy || !value || typeof value !== 'string') {
if (!this.options.lossy || !value || typeof value !== 'string') {
return value;

@@ -656,3 +676,3 @@ }

var content = this.content(token);
if (!this.lossy) {
if (!this.options.lossy) {
return content;

@@ -659,0 +679,0 @@ }

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

'use strict';
"use strict";
exports.__esModule = true;
var _parser = require('./parser');
var _parser = require("./parser");

@@ -14,3 +14,3 @@ var _parser2 = _interopRequireDefault(_parser);

var Processor = function () {
function Processor(func) {
function Processor(func, options) {
_classCallCheck(this, Processor);

@@ -20,40 +20,164 @@

this.funcRes = null;
return this;
this.options = options;
}
Processor.prototype._input = function _input(rule) {
Processor.prototype._shouldUpdateSelector = function _shouldUpdateSelector(rule) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return new _parser2.default({
css: rule,
error: function error(e, opts) {
if (typeof rule === 'string') {
throw new Error(e);
}
throw rule.error(e, opts); // eslint-disable-line new-cap
},
options: options
});
var merged = Object.assign({}, this.options, options);
if (merged.updateSelector === false) {
return false;
} else {
return typeof rule !== "string";
}
};
Processor.prototype.process = function process(rule, options) {
var input = void 0;
try {
input = this._input(rule, options);
} catch (e) {
return Promise.reject(e);
Processor.prototype._isLossy = function _isLossy() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var merged = Object.assign({}, this.options, options);
if (merged.lossless === false) {
return true;
} else {
return false;
}
return Promise.resolve(this.func(input)).then(function () {
return String(input);
};
Processor.prototype._root = function _root(rule) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var parser = new _parser2.default(rule, this._parseOptions(options));
return parser.root;
};
Processor.prototype._parseOptions = function _parseOptions(options) {
return {
lossy: this._isLossy(options)
};
};
Processor.prototype._run = function _run(rule) {
var _this = this;
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return new Promise(function (resolve, reject) {
try {
var root = _this._root(rule, options);
Promise.resolve(_this.func(root)).then(function (transform) {
var string = undefined;
if (_this._shouldUpdateSelector(rule, options)) {
string = root.toString();
rule.selector = string;
}
return { transform: transform, root: root, string: string };
}).then(resolve, reject);
} catch (e) {
reject(e);
return;
}
});
};
Processor.prototype.processSync = function processSync(rule) {
Processor.prototype._runSync = function _runSync(rule) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var input = this._input(rule, options);
this.func(input);
return String(input);
var root = this._root(rule, options);
var transform = this.func(root);
if (transform && typeof transform.then === "function") {
throw new Error("Selector processor returned a promise to a synchronous call.");
}
var string = undefined;
if (options.updateSelector && typeof rule !== "string") {
string = root.toString();
rule.selector = string;
}
return { transform: transform, root: root, string: string };
};
/**
* Process rule into a selector AST.
*
* @param rule {postcss.Rule | string} The css selector to be processed
* @param options The options for processing
* @returns {Promise<parser.Root>} The AST of the selector after processing it.
*/
Processor.prototype.ast = function ast(rule, options) {
return this._run(rule, options).then(function (result) {
return result.root;
});
};
/**
* Process rule into a selector AST synchronously.
*
* @param rule {postcss.Rule | string} The css selector to be processed
* @param options The options for processing
* @returns {parser.Root} The AST of the selector after processing it.
*/
Processor.prototype.astSync = function astSync(rule, options) {
return this._runSync(rule, options).root;
};
/**
* Process a selector into a transformed value asynchronously
*
* @param rule {postcss.Rule | string} The css selector to be processed
* @param options The options for processing
* @returns {Promise<any>} The value returned by the processor.
*/
Processor.prototype.transform = function transform(rule, options) {
return this._run(rule, options).then(function (result) {
return result.transform;
});
};
/**
* Process a selector into a transformed value synchronously.
*
* @param rule {postcss.Rule | string} The css selector to be processed
* @param options The options for processing
* @returns {any} The value returned by the processor.
*/
Processor.prototype.transformSync = function transformSync(rule, options) {
return this._runSync(rule, options).transform;
};
/**
* Process a selector into a new selector string asynchronously.
*
* @param rule {postcss.Rule | string} The css selector to be processed
* @param options The options for processing
* @returns {string} the selector after processing.
*/
Processor.prototype.process = function process(rule, options) {
return this._run(rule, options).then(function (result) {
return result.string || result.root.toString();
});
};
/**
* Process a selector into a new selector string synchronously.
*
* @param rule {postcss.Rule | string} The css selector to be processed
* @param options The options for processing
* @returns {string} the selector after processing.
*/
Processor.prototype.processSync = function processSync(rule, options) {
var result = this._runSync(rule, options);
return result.string || result.root.toString();
};
return Processor;

@@ -63,2 +187,2 @@ }();

exports.default = Processor;
module.exports = exports['default'];
module.exports = exports["default"];

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

if (this.operator) {
if (this.raws.operator) {
selector.push(this.raws.operator);
} else if (this.operator) {
selector.push(this.operator);

@@ -40,0 +42,0 @@ }

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

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _container = require('./container');

@@ -40,2 +42,17 @@

Root.prototype.error = function error(message, options) {
if (this._error) {
return this._error(message, options);
} else {
return new Error(message);
}
};
_createClass(Root, [{
key: 'errorGenerator',
set: function set(handler) {
this._error = handler;
}
}]);
return Root;

@@ -42,0 +59,0 @@ }(_container2.default);

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

if (input.safe) {
// fyi: this is never set to true.
css += fix;

@@ -204,4 +205,3 @@ next = css.length - 1;

start, // [5] Start position / Source index
end] // [6] End position
);
end]);

@@ -208,0 +208,0 @@ // Reset offset for the next token

'use strict';
exports.__esModule = true;
var ampersand = exports.ampersand = 38;
var asterisk = exports.asterisk = 42;
var at = exports.at = 64;
var comma = exports.comma = 44;
var colon = exports.colon = 58;
var semicolon = exports.semicolon = 59;
var openParenthesis = exports.openParenthesis = 40;
var closeParenthesis = exports.closeParenthesis = 41;
var openSquare = exports.openSquare = 91;
var closeSquare = exports.closeSquare = 93;
var dollar = exports.dollar = 36;
var tilde = exports.tilde = 126;
var caret = exports.caret = 94;
var plus = exports.plus = 43;
var equals = exports.equals = 61;
var pipe = exports.pipe = 124;
var greaterThan = exports.greaterThan = 62;
var space = exports.space = 32;
var singleQuote = exports.singleQuote = 39;
var doubleQuote = exports.doubleQuote = 34;
var slash = exports.slash = 47;
var ampersand = exports.ampersand = '&'.charCodeAt(0);
var asterisk = exports.asterisk = '*'.charCodeAt(0);
var at = exports.at = '@'.charCodeAt(0);
var comma = exports.comma = ','.charCodeAt(0);
var colon = exports.colon = ':'.charCodeAt(0);
var semicolon = exports.semicolon = ';'.charCodeAt(0);
var openParenthesis = exports.openParenthesis = '('.charCodeAt(0);
var closeParenthesis = exports.closeParenthesis = ')'.charCodeAt(0);
var openSquare = exports.openSquare = '['.charCodeAt(0);
var closeSquare = exports.closeSquare = ']'.charCodeAt(0);
var dollar = exports.dollar = '$'.charCodeAt(0);
var tilde = exports.tilde = '~'.charCodeAt(0);
var caret = exports.caret = '^'.charCodeAt(0);
var plus = exports.plus = '+'.charCodeAt(0);
var equals = exports.equals = '='.charCodeAt(0);
var pipe = exports.pipe = '|'.charCodeAt(0);
var greaterThan = exports.greaterThan = '>'.charCodeAt(0);
var space = exports.space = ' '.charCodeAt(0);
var singleQuote = exports.singleQuote = '\''.charCodeAt(0);
var doubleQuote = exports.doubleQuote = '"'.charCodeAt(0);
var slash = exports.slash = '/'.charCodeAt(0);

@@ -26,0 +26,0 @@ var backslash = exports.backslash = 92;

{
"name": "postcss-selector-parser",
"version": "3.0.0-rc.0",
"version": "3.0.0",
"devDependencies": {

@@ -26,2 +26,3 @@ "ava": "^0.20.0",

"main": "dist/index.js",
"types": "postcss-selector-parser.d.ts",
"files": [

@@ -49,7 +50,14 @@ "API.md",

"homepage": "https://github.com/postcss/postcss-selector-parser",
"author": {
"name": "Ben Briggs",
"email": "beneb.info@gmail.com",
"url": "http://beneb.info"
},
"contributors": [
{
"name": "Ben Briggs",
"email": "beneb.info@gmail.com",
"url": "http://beneb.info"
},
{
"name": "Chris Eppstein",
"email": "chris@eppsteins.net",
"url": "http://twitter.com/chriseppstein"
}
],
"repository": "postcss/postcss-selector-parser",

@@ -56,0 +64,0 @@ "ava": {

@@ -18,3 +18,3 @@ # postcss-selector-parser [![Build Status](https://travis-ci.org/postcss/postcss-selector-parser.svg?branch=master)](https://travis-ci.org/postcss/postcss-selector-parser)

const transform = selectors => {
selectors.eachInside(selector => {
selectors.walk(selector => {
// do something with the selector

@@ -21,0 +21,0 @@ console.log(String(selector))

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