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

postcss

Package Overview
Dependencies
Maintainers
1
Versions
261
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

postcss - npm Package Compare versions

Comparing version 8.3.11 to 8.4.0

lib/no-work-result.d.ts

4

lib/container.d.ts

@@ -184,6 +184,6 @@ import Node, { ChildNode, NodeProps, ChildProps } from './node.js'

selectorFilter: string | RegExp,
callback: (atRule: Rule, index: number) => false | void
callback: (rule: Rule, index: number) => false | void
): false | undefined
walkRules(
callback: (atRule: Rule, index: number) => false | void
callback: (rule: Rule, index: number) => false | void
): false | undefined

@@ -190,0 +190,0 @@

@@ -319,3 +319,3 @@ 'use strict'

let processed = nodes.map(i => {
// istanbul ignore next
/* c8 ignore next */
if (!i[my]) Container.rebuild(i)

@@ -414,3 +414,3 @@ i = i.proxyOf

// istanbul ignore next
/* c8 ignore start */
Container.rebuild = node => {

@@ -435,1 +435,2 @@ if (node.type === 'atrule') {

}
/* c8 ignore stop */
import { FilePosition } from './input.js'
/**
* A position that is part of a range.
*/
export interface RangePosition {
/**
* The line number in the input.
*/
line: number
/**
* The column number in the input.
*/
column: number
}
/**
* The CSS parser throws this error for broken CSS.

@@ -34,13 +49,17 @@ *

/**
* @param message Error message.
* @param line Source line of the error.
* @param column Source column of the error.
* @param source Source code of the broken file.
* @param file Absolute path to the broken file.
* @param plugin PostCSS plugin name, if error came from plugin.
* Instantiates a CSS syntax error. Can be instantiated for a single position
* or for a range.
* @param message Error message.
* @param lineOrStartPos If for a single position, the line number, or if for
* a range, the inclusive start position of the error.
* @param columnOrEndPos If for a single position, the column number, or if for
* a range, the exclusive end position of the error.
* @param source Source code of the broken file.
* @param file Absolute path to the broken file.
* @param plugin PostCSS plugin name, if error came from plugin.
*/
constructor(
message: string,
line?: number,
column?: number,
lineOrStartPos?: number | RangePosition,
columnOrEndPos?: number | RangePosition,
source?: string,

@@ -126,2 +145,30 @@ file?: string,

/**
* Source line of the error's end, exclusive. Provided if the error pertains
* to a range.
*
* ```js
* error.endLine //=> 3
* error.input.endLine //=> 4
* ```
*
* PostCSS will use the input source map to detect the original location.
* If you need the position in the PostCSS input, use `error.input.endLine`.
*/
endLine?: number
/**
* Source column of the error's end, exclusive. Provided if the error pertains
* to a range.
*
* ```js
* error.endColumn //=> 1
* error.input.endColumn //=> 4
* ```
*
* PostCSS will use the input source map to detect the original location.
* If you need the position in the PostCSS input, use `error.input.endColumn`.
*/
endColumn?: number
/**
* Source code of the broken file.

@@ -128,0 +175,0 @@ *

@@ -23,4 +23,11 @@ 'use strict'

if (typeof line !== 'undefined' && typeof column !== 'undefined') {
this.line = line
this.column = column
if (typeof line === 'number') {
this.line = line
this.column = column
} else {
this.line = line.line
this.column = line.column
this.endLine = column.line
this.endColumn = column.column
}
}

@@ -27,0 +34,0 @@

@@ -16,3 +16,3 @@ import { ProcessOptions } from './postcss.js'

/**
* Line in source file.
* Line of inclusive start position in source file.
*/

@@ -22,3 +22,3 @@ line: number

/**
* Column in source file.
* Column of inclusive start position in source file.
*/

@@ -28,2 +28,12 @@ column: number

/**
* Line of exclusive end position in source file.
*/
endLine?: number
/**
* Column of exclusive end position in source file.
*/
endColumn?: number
/**
* Source code.

@@ -114,14 +124,24 @@ */

* in the input source (e.g., in a Sass file that was compiled
* to CSS before being passed to PostCSS).
* to CSS before being passed to PostCSS). Optionally takes an
* end position, exclusive.
*
* ```js
* root.source.input.origin(1, 1) //=> { file: 'a.css', line: 3, column: 1 }
* root.source.input.origin(1, 1, 1, 4)
* //=> { file: 'a.css', line: 3, column: 1, endLine: 3, endColumn: 4 }
* ```
*
* @param line Line in input CSS.
* @param column Column in input CSS.
* @param line Line for inclusive start position in input CSS.
* @param column Column for inclusive start position in input CSS.
* @param endLine Line for exclusive end position in input CSS.
* @param endColumn Column for exclusive end position in input CSS.
*
* @return Position in input source.
*/
origin(line: number, column: number): FilePosition | false
origin(
line: number,
column: number,
endLine?: number,
endColumn?: number
): FilePosition | false

@@ -128,0 +148,0 @@ /**

@@ -106,4 +106,24 @@ 'use strict'

error(message, line, column, opts = {}) {
let result
if (!column) {
let result, endLine, endColumn
if (line && typeof line === 'object') {
let start = line
let end = column
if (typeof line.offset === 'number') {
let pos = this.fromOffset(start.offset)
line = pos.line
column = pos.col
} else {
line = start.line
column = start.column
}
if (typeof end.offset === 'number') {
let pos = this.fromOffset(end.offset)
endLine = pos.line
endColumn = pos.col
} else {
endLine = end.line
endColumn = end.column
}
} else if (!column) {
let pos = this.fromOffset(line)

@@ -113,8 +133,13 @@ line = pos.line

}
let origin = this.origin(line, column)
let origin = this.origin(line, column, endLine, endColumn)
if (origin) {
result = new CssSyntaxError(
message,
origin.line,
origin.column,
origin.endLine === undefined
? origin.line
: { line: origin.line, column: origin.column },
origin.endLine === undefined
? origin.column
: { line: origin.endLine, column: origin.endColumn },
origin.source,

@@ -127,4 +152,4 @@ origin.file,

message,
line,
column,
endLine === undefined ? line : { line, column },
endLine === undefined ? column : { line: endLine, column: endColumn },
this.css,

@@ -136,3 +161,3 @@ this.file,

result.input = { line, column, source: this.css }
result.input = { line, column, endLine, endColumn, source: this.css }
if (this.file) {

@@ -148,3 +173,3 @@ if (pathToFileURL) {

origin(line, column) {
origin(line, column, endLine, endColumn) {
if (!this.map) return false

@@ -156,2 +181,7 @@ let consumer = this.map.consumer()

let to
if (typeof endLine === 'number') {
to = consumer.originalPositionFor({ line: endLine, column: endColumn })
}
let fromUrl

@@ -171,3 +201,5 @@

line: from.line,
column: from.column
column: from.column,
endLine: to && to.line,
endColumn: to && to.column
}

@@ -179,3 +211,3 @@

} else {
// istanbul ignore next
/* c8 ignore next 2 */
throw new Error(`file: protocol is not available in this PostCSS build`)

@@ -182,0 +214,0 @@ }

@@ -92,4 +92,5 @@ import Result, { Message, ResultOptions } from './result.js'

* If the processor contains any asynchronous plugins
* it will throw an error. This is why this method is only
* for debug purpose, you should always use `LazyResult#then`.
* it will throw an error.
*
* PostCSS runners should always use `LazyResult#then`.
*/

@@ -104,4 +105,5 @@ get css(): string

* If the processor contains any asynchronous plugins
* it will throw an error. This is why this method is only
* for debug purpose, you should always use `LazyResult#then`.
* it will throw an error.
*
* PostCSS runners should always use `LazyResult#then`.
*/

@@ -116,4 +118,5 @@ get content(): string

* If the processor contains any asynchronous plugins
* it will throw an error. This is why this method is only
* for debug purpose, you should always use `LazyResult#then`.
* it will throw an error.
*
* PostCSS runners should always use `LazyResult#then`.
*/

@@ -129,4 +132,3 @@ get map(): SourceMap

*
* This is why this method is only for debug purpose,
* you should always use `LazyResult#then`.
* PostCSS runners should always use `LazyResult#then`.
*/

@@ -142,4 +144,3 @@ get root(): Root

*
* This is why this method is only for debug purpose,
* you should always use `LazyResult#then`.
* PostCSS runners should always use `LazyResult#then`.
*/

@@ -146,0 +147,0 @@ get messages(): Message[]

@@ -140,3 +140,3 @@ 'use strict'

if (root && !root[my]) {
// istanbul ignore next
/* c8 ignore next 2 */
Container.rebuild(root)

@@ -368,2 +368,3 @@ }

if (a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1])) {
// eslint-disable-next-line no-console
console.error(

@@ -383,3 +384,4 @@ 'Unknown error from PostCSS plugin. Your current PostCSS ' +

} catch (err) {
// istanbul ignore next
/* c8 ignore next 3 */
// eslint-disable-next-line no-console
if (console && console.error) console.error(err)

@@ -386,0 +388,0 @@ }

@@ -11,3 +11,3 @@ 'use strict'

class MapGenerator {
constructor(stringify, root, opts) {
constructor(stringify, root, opts, cssString) {
this.stringify = stringify

@@ -17,2 +17,3 @@ this.mapOpts = opts.map || {}

this.opts = opts
this.css = cssString
}

@@ -72,8 +73,12 @@

let node
for (let i = this.root.nodes.length - 1; i >= 0; i--) {
node = this.root.nodes[i]
if (node.type !== 'comment') continue
if (node.text.indexOf('# sourceMappingURL=') === 0) {
this.root.removeChild(i)
if (!this.root && typeof this.css === 'string') {
this.css = this.css.replace(/(\n)?\/\*#[\S\s]*?\*\/$/gm, '')
} else {
let node
for (let i = this.root.nodes.length - 1; i >= 0; i--) {
node = this.root.nodes[i]
if (node.type !== 'comment') continue
if (node.text.indexOf('# sourceMappingURL=') === 0) {
this.root.removeChild(i)
}
}

@@ -135,3 +140,3 @@ }

} else {
// istanbul ignore next
/* c8 ignore next 2 */
return window.btoa(unescape(encodeURIComponent(str)))

@@ -154,3 +159,3 @@ }

}
/* c8 ignore next 6 */
let eol = '\n'

@@ -184,2 +189,28 @@ if (this.css.includes('\r\n')) eol = '\r\n'

generateSimpleMap() {
this.map = new SourceMapGenerator({ file: this.outputFile() })
this.previousMaps = []
let source
if (this.opts.from) {
source = this.toUrl(this.opts.from)
} else {
source = '<no source>'
}
this.map.addMapping({
source,
generated: { line: 1, column: 0 },
original: { line: 1, column: 0 }
})
if (this.isAnnotation()) this.addAnnotation()
if (this.isInline()) {
return [this.css]
}
return [this.cssString, this.map]
}
path(file) {

@@ -202,3 +233,3 @@ if (file.indexOf('<') === 0) return file

if (sep === '\\') {
// istanbul ignore next
/* c8 ignore next 2 */
path = path.replace(/\\/g, '/')

@@ -216,3 +247,3 @@ }

} else {
// istanbul ignore next
/* c8 ignore next 4 */
throw new Error(

@@ -247,2 +278,3 @@ '`map.absolute` option is not available in this PostCSS build'

mapping.generated.line = line
/* c8 ignore next */
mapping.generated.column = column - 1

@@ -255,2 +287,3 @@ if (node.source && node.source.start) {

} else {
/* c8 ignore next 8 */
mapping.source = noSource

@@ -298,2 +331,6 @@ mapping.original.line = 1

if (pathAvailable && sourceMapAvailable && this.isMap() && !this.root) {
return this.generateSimpleMap()
}
if (pathAvailable && sourceMapAvailable && this.isMap()) {

@@ -300,0 +337,0 @@ return this.generateMap()

@@ -41,2 +41,14 @@ import Declaration, { DeclarationProps } from './declaration.js'

export interface Range {
/**
* Start position, inclusive.
*/
start: Position
/**
* End position, exclusive.
*/
end: Position
}
export interface Source {

@@ -48,7 +60,7 @@ /**

/**
* The starting position of the node’s source.
* The inclusive starting position of the node’s source.
*/
start?: Position
/**
* The ending position of the node's source.
* The inclusive ending position of the node's source.
*/

@@ -77,2 +89,7 @@ end?: Position

index?: number
/**
* An ending index inside a node's string that should be highlighted as
* source of error.
*/
endIndex?: number
}

@@ -447,2 +464,19 @@

positionInside(index: number): Position
/**
* Get the position for a word or an index inside the node.
*
* @param opts Options.
* @return Position.
*/
positionBy(opts?: Pick<WarningOptions, 'word' | 'index'>): Position
/**
* Get the range for a word or start and end index inside the node.
* The start index is inclusive; the end index is exclusive.
*
* @param opts Options.
* @return Range.
*/
rangeBy(opts?: Pick<WarningOptions, 'word' | 'index' | 'endIndex'>): Range
}

@@ -13,3 +13,3 @@ 'use strict'

if (!Object.prototype.hasOwnProperty.call(obj, i)) {
// istanbul ignore next
/* c8 ignore next 2 */
continue

@@ -60,4 +60,9 @@ }

if (this.source) {
let pos = this.positionBy(opts)
return this.source.input.error(message, pos.line, pos.column, opts)
let { start, end } = this.rangeBy(opts)
return this.source.input.error(
message,
{ line: start.line, column: start.column },
{ line: end.line, column: end.column },
opts
)
}

@@ -189,3 +194,3 @@ return new CssSyntaxError(message)

if (!Object.prototype.hasOwnProperty.call(this, name)) {
// istanbul ignore next
/* c8 ignore next 2 */
continue

@@ -258,2 +263,55 @@ }

rangeBy(opts) {
let start = {
line: this.source.start.line,
column: this.source.start.column
}
let end = this.source.end
? {
line: this.source.end.line,
column: this.source.end.column + 1
}
: {
line: start.line,
column: start.column + 1
}
if (opts.word) {
let index = this.toString().indexOf(opts.word)
if (index !== -1) {
start = this.positionInside(index)
end = this.positionInside(index + opts.word.length)
}
} else {
if (opts.start) {
start = {
line: opts.start.line,
column: opts.start.column
}
} else if (opts.index) {
start = this.positionInside(opts.index)
}
if (opts.end) {
end = {
line: opts.end.line,
column: opts.end.column
}
} else if (opts.endIndex) {
end = this.positionInside(opts.endIndex)
} else if (opts.index) {
end = this.positionInside(opts.index + 1)
}
}
if (
end.line < start.line ||
(end.line === start.line && end.column <= start.column)
) {
end = { line: start.line, column: start.column + 1 }
}
return { start, end }
}
getProxyProcessor() {

@@ -270,2 +328,3 @@ return {

prop === 'important' ||
/* c8 ignore next */
prop === 'text'

@@ -272,0 +331,0 @@ ) {

@@ -514,11 +514,23 @@ 'use strict'

unclosedBracket(bracket) {
throw this.input.error('Unclosed bracket', bracket[2])
throw this.input.error(
'Unclosed bracket',
{ offset: bracket[2] },
{ offset: bracket[2] + 1 }
)
}
unknownWord(tokens) {
throw this.input.error('Unknown word', tokens[0][2])
throw this.input.error(
'Unknown word',
{ offset: tokens[0][2] },
{ offset: tokens[0][2] + tokens[0][1].length }
)
}
unexpectedClose(token) {
throw this.input.error('Unexpected }', token[2])
throw this.input.error(
'Unexpected }',
{ offset: token[2] },
{ offset: token[2] + 1 }
)
}

@@ -532,7 +544,15 @@

doubleColon(token) {
throw this.input.error('Double colon', token[2])
throw this.input.error(
'Double colon',
{ offset: token[2] },
{ offset: token[2] + token[1].length }
)
}
unnamedAtrule(node, token) {
throw this.input.error('At-rule without name', token[2])
throw this.input.error(
'At-rule without name',
{ offset: token[2] },
{ offset: token[2] + token[1].length }
)
}

@@ -539,0 +559,0 @@

@@ -13,48 +13,49 @@ import { SourceMapGenerator, RawSourceMap } from 'source-map-js'

import Declaration, { DeclarationProps } from './declaration.js'
import Root, { RootProps } from './root.js'
import Container, { ContainerProps } from './container.js'
import Document, { DocumentProps } from './document.js'
import Warning, { WarningOptions } from './warning.js'
import Comment, { CommentProps } from './comment.js'
import AtRule, { AtRuleProps } from './at-rule.js'
import Input, { FilePosition } from './input.js'
import Result, { Message } from './result.js'
import LazyResult from './lazy-result.js'
import Root, { RootProps } from './root.js'
import Rule, { RuleProps } from './rule.js'
import Container, { ContainerProps } from './container.js'
import Warning, { WarningOptions } from './warning.js'
import Input, { FilePosition } from './input.js'
import CssSyntaxError from './css-syntax-error.js'
import list, { List } from './list.js'
import LazyResult from './lazy-result.js'
import Processor from './processor.js'
export {
NodeErrorOptions,
DeclarationProps,
CssSyntaxError,
ContainerProps,
WarningOptions,
DocumentProps,
FilePosition,
Position,
Source,
CommentProps,
AtRuleProps,
Declaration,
ChildProps,
LazyResult,
ChildNode,
AnyNode,
Message,
NodeErrorOptions,
NodeProps,
DeclarationProps,
ContainerProps,
CommentProps,
Processor,
RuleProps,
ChildProps,
AtRuleProps,
RootProps,
DocumentProps,
Container,
Position,
Document,
AnyNode,
Warning,
CssSyntaxError,
Message,
Comment,
Source,
AtRule,
Result,
Input,
Node,
Container,
list,
Declaration,
Comment,
AtRule,
Rule,
Root,
Document,
Result,
LazyResult,
Input
Root
}

@@ -225,3 +226,3 @@

export interface Parser<RootNode = Root> {
export interface Parser<RootNode = Root | Document> {
(

@@ -250,3 +251,3 @@ css: string | { toString(): string },

*/
parse?: Parser<Root | Document>
parse?: Parser

@@ -384,3 +385,3 @@ /**

*/
parse: Parser
parse: Parser<Root>

@@ -465,3 +466,3 @@ /**

export const stringify: Stringifier
export const parse: Parser
export const parse: Parser<Root>
export const fromJSON: JSONHydrator

@@ -468,0 +469,0 @@

@@ -30,3 +30,5 @@ 'use strict'

postcss.plugin = function plugin(name, initializer) {
// eslint-disable-next-line no-console
if (console && console.warn) {
// eslint-disable-next-line no-console
console.warn(

@@ -38,3 +40,4 @@ name +

if (process.env.LANG && process.env.LANG.startsWith('cn')) {
// istanbul ignore next
/* c8 ignore next 7 */
// eslint-disable-next-line no-console
console.warn(

@@ -84,2 +87,3 @@ name +

postcss.Container = Container
postcss.Processor = Processor
postcss.Document = Document

@@ -86,0 +90,0 @@ postcss.Comment = Comment

@@ -11,3 +11,3 @@ 'use strict'

} else {
// istanbul ignore next
/* c8 ignore next 2 */
return window.atob(str)

@@ -14,0 +14,0 @@ }

@@ -11,2 +11,3 @@ import {

import Root from './root.js'
import NoWorkResult from './no-work-result.js'

@@ -18,3 +19,3 @@ /**

* ```js
* const processor = postcss([autoprefixer, precss])
* const processor = postcss([autoprefixer, postcssNested])
* processor.process(css1).then(result => console.log(result.css))

@@ -40,3 +41,3 @@ * processor.process(css2).then(result => console.log(result.css))

* ```js
* const processor = postcss([autoprefixer, precss])
* const processor = postcss([autoprefixer, postcssNested])
* processor.plugins.length //=> 2

@@ -73,3 +74,3 @@ * ```

* .use(autoprefixer)
* .use(precss)
* .use(postcssNested)
* ```

@@ -104,3 +105,3 @@ *

options?: ProcessOptions
): LazyResult
): LazyResult | NoWorkResult
}

@@ -6,6 +6,7 @@ 'use strict'

let Root = require('./root')
let NoWorkResult = require('./no-work-result')
class Processor {
constructor(plugins = []) {
this.version = '8.3.11'
this.version = '8.4.0'
this.plugins = this.normalize(plugins)

@@ -24,16 +25,8 @@ }

typeof opts.stringifier === 'undefined' &&
typeof opts.syntax === 'undefined' &&
!opts.hideNothingWarning
typeof opts.syntax === 'undefined'
) {
if (process.env.NODE_ENV !== 'production') {
if (typeof console !== 'undefined' && console.warn) {
console.warn(
'You did not set any plugins, parser, or stringifier. ' +
'Right now, PostCSS does nothing. Pick plugins for your case ' +
'on https://www.postcss.parts/ and use them in postcss.config.js.'
)
}
}
return new NoWorkResult(this, css, opts)
} else {
return new LazyResult(this, css, opts)
}
return new LazyResult(this, css, opts)
}

@@ -40,0 +33,0 @@

@@ -7,2 +7,3 @@ import {

Root,
Document,
Node,

@@ -98,3 +99,3 @@ Warning,

*/
root: Root
root: Root | Document

@@ -146,3 +147,3 @@ /**

*/
constructor(processor: Processor, root: Root, opts: ResultOptions)
constructor(processor: Processor, root: Root | Document, opts: ResultOptions)

@@ -149,0 +150,0 @@ /**

@@ -28,3 +28,3 @@ 'use strict'

stringify(node, semicolon) {
/* istanbul ignore if */
/* c8 ignore start */
if (!this[node.type]) {

@@ -38,2 +38,3 @@ throw new Error(

}
/* c8 ignore stop */
this[node.type](node, semicolon)

@@ -354,1 +355,2 @@ }

module.exports = Stringifier
Stringifier.default = Stringifier

@@ -0,1 +1,2 @@

/* eslint-disable no-console */
'use strict'

@@ -2,0 +3,0 @@

@@ -0,1 +1,2 @@

import { RangePosition } from './css-syntax-error.js'
import Node from './node.js'

@@ -15,3 +16,3 @@

/**
* Index in CSS node string that caused the warning.
* Start index, inclusive, in CSS node string that caused the warning.
*/

@@ -21,2 +22,17 @@ index?: number

/**
* End index, exclusive, in CSS node string that caused the warning.
*/
endIndex?: number
/**
* Start position, inclusive, in CSS node string that caused the warning.
*/
start?: RangePosition
/**
* End position, exclusive, in CSS node string that caused the warning.
*/
end?: RangePosition
/**
* Name of the plugin that created this warning. `Result#warn` fills

@@ -73,3 +89,3 @@ * this property automatically.

/**
* Line in the input file with this warning’s source.
* Line for inclusive start position in the input file with this warning’s source.
*

@@ -83,3 +99,3 @@ * ```js

/**
* Column in the input file with this warning’s source.
* Column for inclusive start position in the input file with this warning’s source.
*

@@ -93,2 +109,20 @@ * ```js

/**
* Line for exclusive end position in the input file with this warning’s source.
*
* ```js
* warning.endLine //=> 6
* ```
*/
endLine?: number
/**
* Column for exclusive end position in the input file with this warning’s source.
*
* ```js
* warning.endColumn //=> 4
* ```
*/
endColumn?: number
/**
* @param text Warning message.

@@ -95,0 +129,0 @@ * @param opts Warning options.

@@ -9,5 +9,7 @@ 'use strict'

if (opts.node && opts.node.source) {
let pos = opts.node.positionBy(opts)
this.line = pos.line
this.column = pos.column
let range = opts.node.rangeBy(opts)
this.line = range.start.line
this.column = range.start.column
this.endLine = range.end.line
this.endColumn = range.end.column
}

@@ -14,0 +16,0 @@

{
"name": "postcss",
"version": "8.3.11",
"version": "8.4.0",
"description": "Tool for transforming styles with JS plugins",

@@ -22,2 +22,3 @@ "engines": {

"./lib/lazy-result": "./lib/lazy-result.js",
"./lib/no-work-result": "./lib/no-work-result.js",
"./lib/list": "./lib/list.js",

@@ -70,3 +71,3 @@ "./lib/map-generator": "./lib/map-generator.js",

"picocolors": "^1.0.0",
"source-map-js": "^0.6.2"
"source-map-js": "^1.0.1"
},

@@ -73,0 +74,0 @@ "browser": {

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