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

fela-font-renderer

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fela-font-renderer - npm Package Compare versions

Comparing version 4.0.1 to 4.1.0

471

dist/fela-font-renderer.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('fela')) :
typeof define === 'function' && define.amd ? define(['fela'], factory) :
(global.FelaFontRenderer = factory(global.Fela));
}(this, function (fela) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('hyphenate-style-name')) :
typeof define === 'function' && define.amd ? define(['hyphenate-style-name'], factory) :
(global.FelaFontRenderer = factory(global.hyphenateStyleName));
}(this, function (hyphenateStyleName) { 'use strict';
hyphenateStyleName = 'default' in hyphenateStyleName ? hyphenateStyleName['default'] : hyphenateStyleName;
var babelHelpers = {};

@@ -14,2 +16,17 @@ babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {

babelHelpers.defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
babelHelpers.extends = Object.assign || function (target) {

@@ -31,16 +48,442 @@ for (var i = 1; i < arguments.length; i++) {

/**
* adds a special renderer only used for font rendering
* to prevent flickering on changes
*
* @param {Object} renderer - renderer which gets enhanced
* @param {DOMElement} mountNode - stylesheet to render fonts into
* @return {Object} enhanced renderer
*/
function generateCSSDeclaration(property, value) {
return hyphenateStyleName(property) + ':' + value;
}
/* weak */
var warning = function warning() {
return true;
};
if (true) {
warning = function warning(condition, message) {
if (!condition) {
if (typeof console !== 'undefined') {
console.error(message); // eslint-disable-line
}
}
};
}
var warning$1 = warning;
function cssifyObject(style) {
var css = '';
for (var property in style) {
warning$1(typeof style[property] === 'string' || typeof style[property] === 'number', 'The invalid value `' + style[property] + '` has been used as `' + property + '`.');
// prevents the semicolon after
// the last rule declaration
if (css) {
css += ';';
}
css += generateCSSDeclaration(property, style[property]);
}
return css;
}
function cssifyFontFace(fontFace) {
return '@font-face{' + cssifyObject(fontFace) + '}';
}
function cssifyKeyframe(frames, animationName) {
var prefixes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [''];
var keyframe = Object.keys(frames).reduce(function (css, percentage) {
return css + percentage + '{' + cssifyObject(frames[percentage]) + '}';
}, '');
return prefixes.reduce(function (css, prefix) {
return css + '@' + prefix + 'keyframes ' + animationName + '{' + keyframe + '}';
}, '');
}
/* weak */
function cssifyMediaQueryRules(mediaQuery, mediaQueryRules) {
return '@media ' + mediaQuery + '{' + mediaQueryRules + '}';
}
/* weak */
function generateAnimationName(id) {
return 'k' + id;
}
/* weak */
var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
function generateClassName(id) {
var className = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
if (id <= 52) {
return chars[id - 1] + className;
}
// Bitwise floor as safari performs much faster https://jsperf.com/math-floor-vs-math-round-vs-parseint/55
return generateClassName(id / 52 | 0, chars[id % 52] + className);
}
/* weak */
function generateCombinedMediaQuery(currentMediaQuery, nestedMediaQuery) {
if (currentMediaQuery.length === 0) {
return nestedMediaQuery;
}
return currentMediaQuery + ' and ' + nestedMediaQuery;
}
/* weak */
function generateCSSRule(selector, cssDeclaration) {
return selector + '{' + cssDeclaration + '}';
}
/* weak */
function getCSSSelector(className) {
var pseudo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
return '.' + className + pseudo;
}
/* weak */
function minifyCSSString(style) {
return style.replace(/\s{2,}/g, '');
}
/* weak */
function processStyleWithPlugins(style, plugins, type) {
for (var i = 0; i < plugins.length; ++i) {
style = plugins[i](style, type);
}
return style;
}
/* weak */
var RULE_TYPE = 1;
var KEYFRAME_TYPE = 2;
var FONT_TYPE = 3;
var STATIC_TYPE = 4;
var CLEAR_TYPE = 5;
function cssifyStaticStyle(staticStyle, plugins) {
if (typeof staticStyle === 'string') {
return minifyCSSString(staticStyle);
}
var processedStaticStyle = processStyleWithPlugins(staticStyle, plugins, STATIC_TYPE);
return cssifyObject(processedStaticStyle);
}
/* weak */
function generateStaticReference(style, selector) {
if (typeof style === 'string') {
return style;
}
return selector + JSON.stringify(style);
}
/* weak */
function isAttributeSelector(property) {
return property.charAt(0) === '[';
}
/* weak */
function isPseudoSelector(property) {
return property.charAt(0) === ':';
}
/* weak */
function isMediaQuery(property) {
return property.substr(0, 6) === '@media';
}
/* weak */
function applyMediaRulesInOrder(order) {
var mediaRules = {};
for (var i = 0, len = order.length; i < len; ++i) {
mediaRules[order[i]] = '';
}
return mediaRules;
}
/* weak */
function toCSSString(value) {
if (value.charAt(0) === '"') {
return value;
}
return '"' + value + '"';
}
/* weak */
var formats = {
'.woff': 'woff',
'.eot': 'eot',
'.ttf': 'truetype',
'.svg': 'svg'
};
var extensions = Object.keys(formats);
function checkFontFormat(src) {
for (var i = 0, len = extensions.length; i < len; ++i) {
var extension = extensions[i];
if (src.indexOf(extension) !== -1) {
return formats[extension];
}
}
// TODO: warning: wrong font format
}
function createRenderer() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var renderer = {
listeners: [],
keyframePrefixes: config.keyframePrefixes || ['-webkit-', '-moz-'],
plugins: config.plugins || [],
// prettySelectors is currently useless, might reimplement better DX classNames later
// prettySelectors: config.prettySelectors && process.env.NODE_ENV !== 'production',
mediaQueryOrder: config.mediaQueryOrder || [],
clear: function clear() {
renderer.fontFaces = '';
renderer.keyframes = '';
renderer.statics = '';
renderer.rules = '';
// apply media rules in an explicit order to ensure
// correct media query execution order
renderer.mediaRules = applyMediaRulesInOrder(renderer.mediaQueryOrder);
renderer.rendered = [];
renderer.uniqueRuleIdentifier = 0;
renderer.uniqueKeyframeIdentifier = 0;
// use a flat cache object with pure string references
// to achieve maximal lookup performance and memoization speed
renderer.cache = {};
// initial change emit to enforce a clear start
renderer._emitChange({ type: CLEAR_TYPE });
},
renderRule: function renderRule(rule) {
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var processedStyle = processStyleWithPlugins(rule(props), renderer.plugins, RULE_TYPE);
return renderer._renderStyleToClassNames(processedStyle).slice(1);
},
_renderStyleToClassNames: function _renderStyleToClassNames(style) {
var pseudo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var media = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
var classNames = '';
for (var property in style) {
var value = style[property];
if (value instanceof Object) {
if (isPseudoSelector(property) || isAttributeSelector(property)) {
classNames += renderer._renderStyleToClassNames(value, pseudo + property, media);
} else if (isMediaQuery(property)) {
var combinedMediaQuery = generateCombinedMediaQuery(media, property.slice(6).trim());
classNames += renderer._renderStyleToClassNames(value, pseudo, combinedMediaQuery);
} else {
// TODO: warning
}
} else {
var delcarationReference = media + pseudo + property + value;
if (!renderer.cache[delcarationReference]) {
var className = generateClassName(++renderer.uniqueRuleIdentifier);
renderer.cache[delcarationReference] = className;
var cssDeclaration = generateCSSDeclaration(property, value);
var selector = getCSSSelector(className, pseudo);
var cssRule = generateCSSRule(selector, cssDeclaration);
if (media) {
if (!renderer.mediaRules.hasOwnProperty(media)) {
renderer.mediaRules[media] = '';
}
renderer.mediaRules[media] += cssRule;
} else {
renderer.rules += cssRule;
}
renderer._emitChange({
selector: selector,
declaration: cssDeclaration,
media: media,
type: RULE_TYPE
});
}
classNames += ' ' + renderer.cache[delcarationReference];
}
}
return classNames;
},
renderKeyframe: function renderKeyframe(keyframe) {
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var resolvedKeyframe = keyframe(props);
var keyframeReference = JSON.stringify(resolvedKeyframe);
if (!renderer.cache[keyframeReference]) {
// use another unique identifier to ensure minimal css markup
var animationName = generateAnimationName(++renderer.uniqueKeyframeIdentifier);
var processedKeyframe = processStyleWithPlugins(resolvedKeyframe, renderer.plugins, KEYFRAME_TYPE);
var cssKeyframe = cssifyKeyframe(processedKeyframe, animationName, renderer.keyframePrefixes);
renderer.cache[keyframeReference] = animationName;
renderer.keyframes += cssKeyframe;
renderer._emitChange({
name: animationName,
keyframe: cssKeyframe,
type: KEYFRAME_TYPE
});
}
return renderer.cache[keyframeReference];
},
renderFont: function renderFont(family, files) {
var properties = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var fontReference = family + JSON.stringify(properties);
if (!renderer.cache[fontReference]) {
var fontFamily = toCSSString(family);
// TODO: proper font family generation with error proofing
var fontFace = babelHelpers.extends({}, properties, {
src: files.map(function (src) {
return 'url(\'' + src + '\') format(\'' + checkFontFormat(src) + '\')';
}).join(','),
fontFamily: fontFamily
});
var cssFontFace = cssifyFontFace(fontFace);
renderer.cache[fontReference] = fontFamily;
renderer.fontFaces += cssFontFace;
renderer._emitChange({
fontFamily: fontFamily,
fontFace: cssFontFace,
type: FONT_TYPE
});
}
return renderer.cache[fontReference];
},
renderStatic: function renderStatic(staticStyle, selector) {
var staticReference = generateStaticReference(staticStyle, selector);
if (!renderer.cache[staticReference]) {
var cssDeclarations = cssifyStaticStyle(staticStyle, renderer.plugins);
renderer.cache[staticReference] = true;
if (typeof staticStyle === 'string') {
renderer.statics += cssDeclarations;
renderer._emitChange({
type: STATIC_TYPE,
css: cssDeclarations
});
} else {
renderer.statics += generateCSSRule(selector, cssDeclarations);
renderer._emitChange({
selector: selector,
declaration: cssDeclarations,
type: RULE_TYPE,
media: ''
});
}
}
},
renderToString: function renderToString() {
var css = renderer.fontFaces + renderer.statics + renderer.keyframes + renderer.rules;
for (var media in renderer.mediaRules) {
css += cssifyMediaQueryRules(media, renderer.mediaRules[media]);
}
return css;
},
subscribe: function subscribe(callback) {
renderer.listeners.push(callback);
return {
unsubscribe: function unsubscribe() {
return renderer.listeners.splice(renderer.listeners.indexOf(callback), 1);
}
};
},
_emitChange: function _emitChange(change) {
for (var i = 0, len = renderer.listeners.length; i < len; ++i) {
renderer.listeners[i](change);
}
}
};
// initial setup
renderer.keyframePrefixes.push('');
renderer.clear();
if (config.enhancers) {
for (var i = 0, len = config.enhancers.length; i < len; ++i) {
renderer = config.enhancers[i](renderer);
}
}
return renderer;
}
function createDOMInterface(renderer, node) {
return function (change) {
// only use insertRule in production as browser devtools might have
// weird behavior if used together with insertRule at runtime
if (false && change.type === RULE_TYPE && !change.media) {} else {
node.textContent = renderer.renderToString();
}
};
}
function isValidHTMLElement(mountNode) {
return mountNode && mountNode.nodeType === 1;
}
function render(renderer, mountNode) {
// mountNode must be a valid HTML element to be able
// to set mountNode.textContent later on
if (!isValidHTMLElement(mountNode)) {
throw new Error('You need to specify a valid element node (nodeType = 1) to render into.');
}
// warns if the DOM node either is not a valid <style> element thus the styles do not get applied as Expected
// or if the node already got the data-fela-stylesheet attribute applied suggesting it is already used by another Renderer
warning$1(mountNode.nodeName === 'STYLE', 'You are using a node other than `<style>`. Your styles might not get applied correctly.');
warning$1(!mountNode.hasAttribute('data-fela-stylesheet'), 'This node is already used by another renderer. Rendering might overwrite other styles.');
// mark and clean the DOM node to prevent side-effects
mountNode.setAttribute('data-fela-stylesheet', '');
var updateNode = createDOMInterface(renderer, mountNode);
renderer.subscribe(updateNode);
var css = renderer.renderToString();
if (mountNode.textContent !== css) {
// render currently rendered styles to the DOM once
mountNode.textContent = css;
}
}
function addFontRenderer(renderer, mountNode) {
renderer.fontRenderer = fela.createRenderer();
renderer.fontRenderer = createRenderer();
// mount font styles into the mountNode
if (mountNode) {
fela.render(renderer.fontRenderer, mountNode);
render(renderer.fontRenderer, mountNode);
}

@@ -47,0 +490,0 @@

2

dist/fela-font-renderer.min.js

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

!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n(require("fela")):"function"==typeof define&&define.amd?define(["fela"],n):e.FelaFontRenderer=n(e.Fela)}(this,function(e){"use strict";function n(n,t){return n.fontRenderer=e.createRenderer(),t&&e.render(n.fontRenderer,t),n.renderFont=function(e,t,r){return n.fontRenderer.renderFont(e,t,r)},n}var t={};t.typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t.extends=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e};var r=function(e){return function(t){return n(t,e)}};return r});
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n(require("hyphenate-style-name")):"function"==typeof define&&define.amd?define(["hyphenate-style-name"],n):e.FelaFontRenderer=n(e.hyphenateStyleName)}(this,function(e){"use strict";function n(n,r){return e(n)+":"+r}function r(e){var r="";for(var t in e)r&&(r+=";"),r+=n(t,e[t]);return r}function t(e){return"@font-face{"+r(e)+"}"}function i(e,n){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[""],i=Object.keys(e).reduce(function(n,t){return n+t+"{"+r(e[t])+"}"},"");return t.reduce(function(e,r){return e+"@"+r+"keyframes "+n+"{"+i+"}"},"")}function o(e,n){return"@media "+e+"{"+n+"}"}function u(e){return"k"+e}function a(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return e<=52?_[e-1]+n:a(e/52|0,_[e%52]+n)}function f(e,n){return 0===e.length?n:e+" and "+n}function c(e,n){return e+"{"+n+"}"}function s(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return"."+e+n}function l(e){return e.replace(/\s{2,}/g,"")}function d(e,n,r){for(var t=0;t<n.length;++t)e=n[t](e,r);return e}function y(e,n){if("string"==typeof e)return l(e);var t=d(e,n,N);return r(t)}function m(e,n){return"string"==typeof e?e:n+JSON.stringify(e)}function h(e){return"["===e.charAt(0)}function v(e){return":"===e.charAt(0)}function p(e){return"@media"===e.substr(0,6)}function g(e){for(var n={},r=0,t=e.length;r<t;++r)n[e[r]]="";return n}function b(e){return'"'===e.charAt(0)?e:'"'+e+'"'}function S(e){for(var n=0,r=A.length;n<r;++n){var t=A[n];if(e.indexOf(t)!==-1)return q[t]}}function O(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r={listeners:[],keyframePrefixes:e.keyframePrefixes||["-webkit-","-moz-"],plugins:e.plugins||[],mediaQueryOrder:e.mediaQueryOrder||[],clear:function(){r.fontFaces="",r.keyframes="",r.statics="",r.rules="",r.mediaRules=g(r.mediaQueryOrder),r.rendered=[],r.uniqueRuleIdentifier=0,r.uniqueKeyframeIdentifier=0,r.cache={},r._emitChange({type:P})},renderRule:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=d(e(n),r.plugins,T);return r._renderStyleToClassNames(t).slice(1)},_renderStyleToClassNames:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",o="";for(var u in e){var l=e[u];if(l instanceof Object){if(v(u)||h(u))o+=r._renderStyleToClassNames(l,t+u,i);else if(p(u)){var d=f(i,u.slice(6).trim());o+=r._renderStyleToClassNames(l,t,d)}}else{var y=i+t+u+l;if(!r.cache[y]){var m=a(++r.uniqueRuleIdentifier);r.cache[y]=m;var g=n(u,l),b=s(m,t),S=c(b,g);i?(r.mediaRules.hasOwnProperty(i)||(r.mediaRules[i]=""),r.mediaRules[i]+=S):r.rules+=S,r._emitChange({selector:b,declaration:g,media:i,type:T})}o+=" "+r.cache[y]}}return o},renderKeyframe:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=e(n),o=JSON.stringify(t);if(!r.cache[o]){var a=u(++r.uniqueKeyframeIdentifier),f=d(t,r.plugins,j),c=i(f,a,r.keyframePrefixes);r.cache[o]=a,r.keyframes+=c,r._emitChange({name:a,keyframe:c,type:j})}return r.cache[o]},renderFont:function(e,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=e+JSON.stringify(i);if(!r.cache[o]){var u=b(e),a=F.extends({},i,{src:n.map(function(e){return"url('"+e+"') format('"+S(e)+"')"}).join(","),fontFamily:u}),f=t(a);r.cache[o]=u,r.fontFaces+=f,r._emitChange({fontFamily:u,fontFace:f,type:w})}return r.cache[o]},renderStatic:function(e,n){var t=m(e,n);if(!r.cache[t]){var i=y(e,r.plugins);r.cache[t]=!0,"string"==typeof e?(r.statics+=i,r._emitChange({type:N,css:i})):(r.statics+=c(n,i),r._emitChange({selector:n,declaration:i,type:T,media:""}))}},renderToString:function(){var e=r.fontFaces+r.statics+r.keyframes+r.rules;for(var n in r.mediaRules)e+=o(n,r.mediaRules[n]);return e},subscribe:function(e){return r.listeners.push(e),{unsubscribe:function(){return r.listeners.splice(r.listeners.indexOf(e),1)}}},_emitChange:function(e){for(var n=0,t=r.listeners.length;n<t;++n)r.listeners[n](e)}};if(r.keyframePrefixes.push(""),r.clear(),e.enhancers)for(var l=0,O=e.enhancers.length;l<O;++l)r=e.enhancers[l](r);return r}function R(e,n){return function(r){r.type!==T||r.media?n.textContent=e.renderToString():n.sheet.insertRule(r.selector+"{"+r.declaration+"}",n.sheet.cssRules.length)}}function C(e){return e&&1===e.nodeType}function k(e,n){if(!C(n))throw new Error("You need to specify a valid element node (nodeType = 1) to render into.");n.setAttribute("data-fela-stylesheet","");var r=R(e,n);e.subscribe(r);var t=e.renderToString();n.textContent!==t&&(n.textContent=t)}function x(e,n){return e.fontRenderer=O(),n&&k(e.fontRenderer,n),e.renderFont=function(n,r,t){return e.fontRenderer.renderFont(n,r,t)},e}e="default"in e?e.default:e;var F={};F.typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},F.defineProperty=function(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e},F.extends=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var r=arguments[n];for(var t in r)Object.prototype.hasOwnProperty.call(r,t)&&(e[t]=r[t])}return e};var _="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",T=1,j=2,w=3,N=4,P=5,q={".woff":"woff",".eot":"eot",".ttf":"truetype",".svg":"svg"},A=Object.keys(q),I=function(e){return function(n){return x(n,e)}};return I});
{
"name": "fela-font-renderer",
"version": "4.0.1",
"version": "4.1.0",
"description": "Fela enhancer to render fonts into a separate stylesheet",

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

"peerDependencies": {
"fela": "4.0.1"
"fela": "4.1.0"
}
}
# fela-font-renderer
<img alt="npm downloads" src="https://img.shields.io/npm/dm/fela-font-renderer.svg">
<img alt="gzipped size" src="https://img.shields.io/badge/gzipped-0.40kb-brightgreen.svg">
<img alt="gzipped size" src="https://img.shields.io/badge/gzipped-2.16kb-brightgreen.svg">

@@ -12,9 +12,9 @@ Allocates all `renderFont` calls to a separate renderer which renders into a separate `mountNode` to prevent refetching the `@font-face` every time.

```
Assuming you are using [npm](https://www.npmjs.com) as your package mananger you can just `npm install`.<br>
Assuming you are using [npm](https://www.npmjs.com) as your package manager you can just `npm install`.<br>
Otherwise we also provide a [UMD](https://github.com/umdjs/umd). You can easily use it via [unpkg](https://unpkg.com/). It registers a `FelaFontRenderer` global.
```HTML
<!-- Fela (Development): Unminified version including all warnings -->
<script src="https://unpkg.com/fela-font-renderer@4.0.1/dist/fela-font-renderer.js"></script>
<script src="https://unpkg.com/fela-font-renderer@4.1.0/dist/fela-font-renderer.js"></script>
<!-- Fela (Production): Minified version -->
<script src="https://unpkg.com/fela-font-renderer@4.0.1/dist/fela-font-renderer.min.js"></script>
<script src="https://unpkg.com/fela-font-renderer@4.1.0/dist/fela-font-renderer.min.js"></script>
```

@@ -21,0 +21,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