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

mobiledoc-kit

Package Overview
Dependencies
Maintainers
2
Versions
84
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mobiledoc-kit - npm Package Compare versions

Comparing version 0.9.8 to 0.10.0-beta.1

dist/commonjs/mobiledoc-kit/editor/selection-change-observer.js

58

dist/commonjs/mobiledoc-kit/editor/edit-state.js

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

var _utilsCursorRange = require('../utils/cursor/range');
/**

@@ -21,39 +23,49 @@ * Used by {@link Editor} to manage its current state (cursor, active markups

this.editor = editor;
this.prevState = this.state = this._readState();
var defaultState = {
range: _utilsCursorRange['default'].blankRange(),
activeMarkups: [],
activeSections: [],
activeSectionTagNames: []
};
this.prevState = this.state = defaultState;
}
/**
* Cache the last state, force a reread of current state
*/
_createClass(EditState, [{
key: 'reset',
value: function reset() {
key: 'updateRange',
value: function updateRange(newRange) {
this.prevState = this.state;
this.state = this._readState();
this.state = this._readState(newRange);
}
}, {
key: 'destroy',
value: function destroy() {
this.editor = null;
this.prevState = this.state = null;
}
/**
* @return {Boolean} Whether the input mode (active markups or active section tag names)
* has changed.
* @return {Boolean}
*/
}, {
key: 'inputModeDidChange',
value: function inputModeDidChange() {
var state = this.state;
var prevState = this.prevState;
key: 'rangeDidChange',
value: function rangeDidChange() {
var range = this.state.range;
var prevRange = this.prevState.range;
return !(0, _utilsArrayUtils.isArrayEqual)(state.activeMarkups, prevState.activeMarkups) || !(0, _utilsArrayUtils.isArrayEqual)(state.activeSectionTagNames, prevState.activeSectionTagNames);
return !prevRange.isEqual(range);
}
/**
* @return {Boolean} Whether the range has changed.
* @return {Boolean} Whether the input mode (active markups or active section tag names)
* has changed.
*/
}, {
key: 'rangeDidChange',
value: function rangeDidChange() {
key: 'inputModeDidChange',
value: function inputModeDidChange() {
var state = this.state;
var prevState = this.prevState;
return !state.range.isEqual(prevState.range);
return !(0, _utilsArrayUtils.isArrayEqual)(state.activeMarkups, prevState.activeMarkups) || !(0, _utilsArrayUtils.isArrayEqual)(state.activeSectionTagNames, prevState.activeSectionTagNames);
}

@@ -82,4 +94,3 @@

key: '_readState',
value: function _readState() {
var range = this._readRange();
value: function _readState(range) {
var state = {

@@ -100,7 +111,2 @@ range: range,

}, {
key: '_readRange',
value: function _readRange() {
return this.editor.range;
}
}, {
key: '_readActiveSections',

@@ -107,0 +113,0 @@ value: function _readActiveSections(range) {

@@ -314,7 +314,8 @@ 'use strict';

this._mutationHandler.init();
this._eventManager.init();
if (this.autofocus) {
this.element.focus();
this.selectRange(new _utilsCursorRange['default'](this.post.headPosition()));
}
this._mutationHandler.init();
this._eventManager.init();
}

@@ -431,17 +432,3 @@ }, {

}
}, {
key: 'selectSections',
value: function selectSections() {
var sections = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
if (sections.length) {
var headSection = sections[0],
tailSection = sections[sections.length - 1];
this.selectRange(new _utilsCursorRange['default'](headSection.headPosition(), tailSection.tailPosition()));
} else {
this.cursor.clearSelection();
}
this._reportSelectionState();
}
/**

@@ -456,43 +443,14 @@ * Selects the given range. If range is collapsed, this positions the cursor

value: function selectRange(range) {
this.renderRange(range);
}
/**
* @private
*/
}, {
key: 'renderRange',
value: function renderRange(range) {
this.cursor.selectRange(range);
this._notifyRangeChange();
this.range = range;
}
}, {
key: '_notifyRangeChange',
/**
* Used to notify the editor that the range (or state) may
* have changed (e.g. in response to a mouseup or keyup) and
* that the editor should re-read values from DOM and fire the
* necessary callbacks
* @private
*/
value: function _notifyRangeChange() {
if (this.isEditable) {
this._resetRange();
this._editState.reset();
if (this._editState.rangeDidChange()) {
this._rangeDidChange();
}
if (this._editState.inputModeDidChange()) {
this._inputModeDidChange();
}
key: '_readRangeFromDOM',
value: function _readRangeFromDOM() {
if (!this.isEditable) {
return;
}
this.range = this.cursor.offsets;
}
}, {
key: '_resetRange',
value: function _resetRange() {
delete this._range;
}
}, {
key: 'setPlaceholder',

@@ -700,3 +658,3 @@ value: function setPlaceholder(placeholder) {

value: function destroy() {
this._isDestroyed = true;
this.isDestroyed = true;
if (this.hasCursor()) {

@@ -710,2 +668,3 @@ this.cursor.clearSelection();

this._renderer.destroy();
this._editState.destroy();
}

@@ -722,6 +681,11 @@

value: function disableEditing() {
if (this.isEditable === false) {
return;
}
this.isEditable = false;
if (this.element) {
if (this.hasRendered) {
this.element.setAttribute('contentEditable', false);
this.setPlaceholder('');
this.selectRange(_utilsCursorRange['default'].blankRange());
}

@@ -808,2 +772,4 @@ }

postEditor.complete();
this._readRangeFromDOM();
if (postEditor._shouldCancelSnapshot) {

@@ -813,3 +779,2 @@ this._editHistory._pendingSnapshot = null;

this._editHistory.storeSnapshot();
this._notifyRangeChange();

@@ -902,25 +867,5 @@ return result;

}
/*
The following events/sequences can create a selection and are handled:
* mouseup -- can happen anywhere in document, must wait until next tick to read selection
* keyup when key is a movement key and shift is pressed -- in editor element
* keyup when key combo was cmd-A (alt-A) aka "select all"
* keyup when key combo was cmd-Z (browser may restore selection)
These cases can create a selection and are not handled:
* ctrl-click -> context menu -> click "select all"
*/
}, {
key: '_reportSelectionState',
value: function _reportSelectionState() {
this._cursorDidChange();
}
}, {
key: '_rangeDidChange',
value: function _rangeDidChange() {
this._cursorDidChange();
}
}, {
key: '_cursorDidChange',
value: function _cursorDidChange() {
if (this.hasRendered) {

@@ -960,3 +905,3 @@ this.runCallbacks(CALLBACK_QUEUES.CURSOR_DID_CHANGE);

value: function toggleMarkup(markup) {
markup = this.post.builder.createMarkup(markup);
markup = this.builder.createMarkup(markup);
var range = this.range;

@@ -1203,3 +1148,3 @@

if (this._isDestroyed) {
if (this.isDestroyed) {
// TODO warn that callback attempted after editor was destroyed

@@ -1245,4 +1190,2 @@ return;

* Return the current range for the editor (may be cached).
* The #_resetRange method forces a re-read of
* the range from DOM.
* @return {Range}

@@ -1253,11 +1196,14 @@ */

get: function get() {
if (this._range) {
return this._range;
return this._editState.range;
},
set: function set(newRange) {
this._editState.updateRange(newRange);
if (this._editState.rangeDidChange()) {
this._rangeDidChange();
}
var range = this.cursor.offsets;
if (!range.isBlank) {
// do not cache blank ranges
this._range = range;
if (this._editState.inputModeDidChange()) {
this._inputModeDidChange();
}
return range;
}

@@ -1264,0 +1210,0 @@ }, {

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

var _editorSelectionManager = require('../editor/selection-manager');
var ELEMENT_EVENT_TYPES = ['keydown', 'keyup', 'cut', 'copy', 'paste', 'keypress', 'drop'];
var DOCUMENT_EVENT_TYPES = ['mouseup'];

@@ -36,2 +37,4 @@ var EventManager = (function () {

this.isShift = false;
this._selectionManager = new _editorSelectionManager['default'](this.editor, this.selectionDidChange.bind(this));
}

@@ -52,5 +55,3 @@

DOCUMENT_EVENT_TYPES.forEach(function (type) {
_this._addListener(document, type);
});
this._selectionManager.start();
}

@@ -87,2 +88,3 @@ }, {

});
this._listeners = [];
}

@@ -116,4 +118,4 @@

this._textInputHandler.destroy();
this._selectionManager.destroy();
this._removeListeners();
this._listeners = [];
}

@@ -123,14 +125,38 @@ }, {

value: function _handleEvent(type, event) {
var editor = this.editor;
var element = event.target;
if ((0, _utilsArrayUtils.contains)(ELEMENT_EVENT_TYPES, type)) {
var element = event.target;
if (!this.isElementAddressable(element)) {
// abort handling this event
return true;
}
if (!editor.cursor.isAddressable(element)) {
// abort handling this event
return true;
this[type](event);
}
}, {
key: 'isElementAddressable',
value: function isElementAddressable(element) {
return this.editor.cursor.isAddressable(element);
}
}, {
key: 'selectionDidChange',
value: function selectionDidChange(selection /*, prevSelection */) {
var shouldNotify = true;
var anchorNode = selection.anchorNode;
if (!this.isElementAddressable(anchorNode)) {
if (!this.editor.range.isBlank) {
// Selection changed from something addressable to something
// not-addressable -- e.g., blur event, user clicked outside editor,
// etc
shouldNotify = true;
} else {
// selection changes wholly outside the editor should not trigger
// change notifications
shouldNotify = false;
}
}
this[type](event);
if (shouldNotify) {
this.editor._readRangeFromDOM();
}
}

@@ -184,3 +210,4 @@ }, {

switch (true) {
case key.isHorizontalArrow():
// FIXME This should be restricted to only card/atom boundaries
case key.isHorizontalArrowWithoutModifiersOtherThanShift():
var newRange = undefined;

@@ -212,4 +239,2 @@ if (key.isShift()) {

value: function keyup(event) {
var _this3 = this;
var editor = this.editor;

@@ -224,9 +249,2 @@

}
// Only movement-related keys require re-checking the active range
if (key.isMovement()) {
setTimeout(function () {
return _this3.editor._notifyRangeChange();
});
}
}

@@ -283,12 +301,2 @@ }, {

}, {
key: 'mouseup',
value: function mouseup() /* event */{
var _this4 = this;
// mouseup does not correctly report a selection until the next tick
setTimeout(function () {
return _this4.editor._notifyRangeChange();
});
}
}, {
key: 'drop',

@@ -295,0 +303,0 @@ value: function drop(event) {

@@ -87,9 +87,2 @@ 'use strict';

}, {
str: 'META+LEFT',
run: function run(editor) {
if (_utilsBrowser['default'].isMac) {
gotoStartOfLine(editor);
}
}
}, {
str: 'META+A',

@@ -109,9 +102,2 @@ run: function run(editor) {

}, {
str: 'META+RIGHT',
run: function run(editor) {
if (_utilsBrowser['default'].isMac) {
gotoEndOfLine(editor);
}
}
}, {
str: 'META+K',

@@ -118,0 +104,0 @@ run: function run(editor) {

@@ -66,3 +66,3 @@ 'use strict';

this._renderRange = function () {
return _this.editor.renderRange(_this._range);
return _this.editor.selectRange(_this._range);
};

@@ -1582,4 +1582,2 @@ this._postDidChange = function () {

this.runCallbacks(CALLBACK_QUEUES.AFTER_COMPLETE);
this.editor._notifyRangeChange();
}

@@ -1586,0 +1584,0 @@ }, {

@@ -107,7 +107,2 @@ 'use strict';

}, {
key: 'isMovement',
value: function isMovement() {
return this.isArrow() || this.isHome() || this.isEnd();
}
}, {
key: 'isArrow',

@@ -123,2 +118,7 @@ value: function isArrow() {

}, {
key: 'isHorizontalArrowWithoutModifiersOtherThanShift',
value: function isHorizontalArrowWithoutModifiersOtherThanShift() {
return this.isHorizontalArrow() && !(this.ctrlKey || this.metaKey || this.altKey);
}
}, {
key: 'isVerticalArrow',

@@ -219,3 +219,3 @@ value: function isVerticalArrow() {

return this.toString().length > 0 || code >= _keycodes['default']['0'] && code <= _keycodes['default']['9'] || // number keys
return code !== 0 || this.toString().length > 0 || code >= _keycodes['default']['0'] && code <= _keycodes['default']['9'] || // number keys
this.isSpace() || this.isTab() || this.isEnter() || code >= _keycodes['default'].A && code <= _keycodes['default'].Z || // letter keys

@@ -222,0 +222,0 @@ code >= _keycodes['default'].a && code <= _keycodes['default'].z || code >= _keycodes['default'].NUMPAD_0 && code <= _keycodes['default'].NUMPAD_9 || // numpad keys

'use strict';
exports['default'] = '0.9.8';
exports['default'] = '0.10.0-beta.1';

@@ -75,3 +75,3 @@ 'use strict';

this.hide();
this._isDestroyed = true;
this.isDestroyed = true;
}

@@ -78,0 +78,0 @@ }]);

{
"name": "mobiledoc-kit",
"version": "0.9.8",
"version": "0.10.0-beta.1",
"description": "A toolkit for building WYSIWYG editors with Mobiledoc",

@@ -14,3 +14,5 @@ "repository": "https://github.com/bustlelabs/mobiledoc-kit",

"update-changelog": "conventional-changelog -i CHANGELOG.md -r 0 -s",
"docs": "jsdoc -c ./.jsdoc"
"docs": "jsdoc -c ./.jsdoc",
"postversion": "npm run update-changelog",
"prepublish": "npm run build"
},

@@ -17,0 +19,0 @@ "keywords": [

import { contains, isArrayEqual } from 'mobiledoc-kit/utils/array-utils';
import Range from 'mobiledoc-kit/utils/cursor/range';

@@ -11,11 +12,30 @@ /**

this.editor = editor;
this.prevState = this.state = this._readState();
let defaultState = {
range: Range.blankRange(),
activeMarkups: [],
activeSections: [],
activeSectionTagNames: []
};
this.prevState = this.state = defaultState;
}
updateRange(newRange) {
this.prevState = this.state;
this.state = this._readState(newRange);
}
destroy() {
this.editor = null;
this.prevState = this.state = null;
}
/**
* Cache the last state, force a reread of current state
* @return {Boolean}
*/
reset() {
this.prevState = this.state;
this.state = this._readState();
rangeDidChange() {
let { state: { range } , prevState: {range: prevRange} } = this;
return !prevRange.isEqual(range);
}

@@ -34,10 +54,2 @@

/**
* @return {Boolean} Whether the range has changed.
*/
rangeDidChange() {
let { state, prevState } = this;
return !state.range.isEqual(prevState.range);
}
/**
* @return {Range}

@@ -77,6 +89,5 @@ */

_readState() {
let range = this._readRange();
_readState(range) {
let state = {
range: range,
range,
activeMarkups: this._readActiveMarkups(range),

@@ -95,6 +106,2 @@ activeSections: this._readActiveSections(range)

_readRange() {
return this.editor.range;
}
_readActiveSections(range) {

@@ -101,0 +108,0 @@ let { head, tail } = range;

@@ -250,7 +250,8 @@ import Tooltip from '../views/tooltip';

this._mutationHandler.init();
this._eventManager.init();
if (this.autofocus) {
this.element.focus();
this.selectRange(new Range(this.post.headPosition()));
}
this._mutationHandler.init();
this._eventManager.init();
}

@@ -354,14 +355,2 @@

selectSections(sections=[]) {
if (sections.length) {
let headSection = sections[0],
tailSection = sections[sections.length - 1];
this.selectRange(new Range(headSection.headPosition(),
tailSection.tailPosition()));
} else {
this.cursor.clearSelection();
}
this._reportSelectionState();
}
/**

@@ -374,11 +363,4 @@ * Selects the given range. If range is collapsed, this positions the cursor

selectRange(range) {
this.renderRange(range);
}
/**
* @private
*/
renderRange(range) {
this.cursor.selectRange(range);
this._notifyRangeChange();
this.range = range;
}

@@ -392,40 +374,25 @@

* Return the current range for the editor (may be cached).
* The #_resetRange method forces a re-read of
* the range from DOM.
* @return {Range}
*/
get range() {
if (this._range) {
return this._range;
}
let range = this.cursor.offsets;
if (!range.isBlank) { // do not cache blank ranges
this._range = range;
}
return range;
return this._editState.range;
}
/**
* Used to notify the editor that the range (or state) may
* have changed (e.g. in response to a mouseup or keyup) and
* that the editor should re-read values from DOM and fire the
* necessary callbacks
* @private
*/
_notifyRangeChange() {
if (this.isEditable) {
this._resetRange();
this._editState.reset();
set range(newRange) {
this._editState.updateRange(newRange);
if (this._editState.rangeDidChange()) {
this._rangeDidChange();
}
if (this._editState.inputModeDidChange()) {
this._inputModeDidChange();
}
if (this._editState.rangeDidChange()) {
this._rangeDidChange();
}
if (this._editState.inputModeDidChange()) {
this._inputModeDidChange();
}
}
_resetRange() {
delete this._range;
_readRangeFromDOM() {
if (!this.isEditable) {
return;
}
this.range = this.cursor.offsets;
}

@@ -617,3 +584,3 @@

destroy() {
this._isDestroyed = true;
this.isDestroyed = true;
if (this.hasCursor()) {

@@ -627,2 +594,3 @@ this.cursor.clearSelection();

this._renderer.destroy();
this._editState.destroy();
}

@@ -637,6 +605,9 @@

disableEditing() {
if (this.isEditable === false) { return; }
this.isEditable = false;
if (this.element) {
if (this.hasRendered) {
this.element.setAttribute('contentEditable', false);
this.setPlaceholder('');
this.selectRange(Range.blankRange());
}

@@ -715,2 +686,4 @@ }

postEditor.complete();
this._readRangeFromDOM();
if (postEditor._shouldCancelSnapshot) {

@@ -720,3 +693,2 @@ this._editHistory._pendingSnapshot = null;

this._editHistory.storeSnapshot();
this._notifyRangeChange();

@@ -796,20 +768,3 @@ return result;

/*
The following events/sequences can create a selection and are handled:
* mouseup -- can happen anywhere in document, must wait until next tick to read selection
* keyup when key is a movement key and shift is pressed -- in editor element
* keyup when key combo was cmd-A (alt-A) aka "select all"
* keyup when key combo was cmd-Z (browser may restore selection)
These cases can create a selection and are not handled:
* ctrl-click -> context menu -> click "select all"
*/
_reportSelectionState() {
this._cursorDidChange();
}
_rangeDidChange() {
this._cursorDidChange();
}
_cursorDidChange() {
if (this.hasRendered) {

@@ -843,3 +798,3 @@ this.runCallbacks(CALLBACK_QUEUES.CURSOR_DID_CHANGE);

toggleMarkup(markup) {
markup = this.post.builder.createMarkup(markup);
markup = this.builder.createMarkup(markup);
let { range } = this;

@@ -1035,3 +990,3 @@ if (range.isCollapsed) {

runCallbacks(...args) {
if (this._isDestroyed) {
if (this.isDestroyed) {
// TODO warn that callback attempted after editor was destroyed

@@ -1038,0 +993,0 @@ return;

@@ -8,6 +8,7 @@ import assert from 'mobiledoc-kit/utils/assert';

import Range from 'mobiledoc-kit/utils/cursor/range';
import { filter, forEach, contains } from 'mobiledoc-kit/utils/array-utils';
import { filter, forEach } from 'mobiledoc-kit/utils/array-utils';
import Key from 'mobiledoc-kit/utils/key';
import { TAB } from 'mobiledoc-kit/utils/characters';
import TextInputHandler from 'mobiledoc-kit/editor/text-input-handler';
import SelectionManager from 'mobiledoc-kit/editor/selection-manager';

@@ -17,3 +18,2 @@ const ELEMENT_EVENT_TYPES = [

];
const DOCUMENT_EVENT_TYPES = ['mouseup'];

@@ -27,2 +27,5 @@ export default class EventManager {

this.isShift = false;
this._selectionManager = new SelectionManager(
this.editor, this.selectionDidChange.bind(this));
}

@@ -38,5 +41,3 @@

DOCUMENT_EVENT_TYPES.forEach(type => {
this._addListener(document, type);
});
this._selectionManager.start();
}

@@ -60,2 +61,3 @@

});
this._listeners = [];
}

@@ -78,18 +80,39 @@

this._textInputHandler.destroy();
this._selectionManager.destroy();
this._removeListeners();
this._listeners = [];
}
_handleEvent(type, event) {
let { editor } = this;
let {target: element} = event;
if (!this.isElementAddressable(element)) {
// abort handling this event
return true;
}
if (contains(ELEMENT_EVENT_TYPES, type)) {
let {target: element} = event;
if (!editor.cursor.isAddressable(element)) {
// abort handling this event
return true;
this[type](event);
}
isElementAddressable(element) {
return this.editor.cursor.isAddressable(element);
}
selectionDidChange(selection /*, prevSelection */) {
let shouldNotify = true;
let { anchorNode } = selection;
if (!this.isElementAddressable(anchorNode)) {
if (!this.editor.range.isBlank) {
// Selection changed from something addressable to something
// not-addressable -- e.g., blur event, user clicked outside editor,
// etc
shouldNotify = true;
} else {
// selection changes wholly outside the editor should not trigger
// change notifications
shouldNotify = false;
}
}
this[type](event);
if (shouldNotify) {
this.editor._readRangeFromDOM();
}
}

@@ -130,3 +153,4 @@

switch(true) {
case key.isHorizontalArrow():
// FIXME This should be restricted to only card/atom boundaries
case key.isHorizontalArrowWithoutModifiersOtherThanShift():
let newRange;

@@ -163,7 +187,2 @@ if (key.isShift()) {

}
// Only movement-related keys require re-checking the active range
if (key.isMovement()) {
setTimeout(() => this.editor._notifyRangeChange());
}
}

@@ -212,7 +231,2 @@

mouseup(/* event */) {
// mouseup does not correctly report a selection until the next tick
setTimeout(() => this.editor._notifyRangeChange());
}
drop(event) {

@@ -219,0 +233,0 @@ event.preventDefault();

@@ -72,9 +72,2 @@ import Key from '../utils/key';

}, {
str: 'META+LEFT',
run(editor) {
if (Browser.isMac) {
gotoStartOfLine(editor);
}
}
}, {
str: 'META+A',

@@ -94,9 +87,2 @@ run(editor) {

}, {
str: 'META+RIGHT',
run(editor) {
if (Browser.isMac) {
gotoEndOfLine(editor);
}
}
}, {
str: 'META+K',

@@ -103,0 +89,0 @@ run(editor) {

@@ -44,3 +44,3 @@ import Position from '../utils/cursor/position';

this._renderRange = () => this.editor.renderRange(this._range);
this._renderRange = () => this.editor.selectRange(this._range);
this._postDidChange = () => this.editor._postDidChange();

@@ -1348,4 +1348,2 @@ this._rerender = () => this.editor.rerender();

this.runCallbacks(CALLBACK_QUEUES.AFTER_COMPLETE);
this.editor._notifyRangeChange();
}

@@ -1352,0 +1350,0 @@

@@ -93,6 +93,2 @@ import Keycodes from './keycodes';

isMovement() {
return this.isArrow() || this.isHome() || this.isEnd();
}
isArrow() {

@@ -104,5 +100,10 @@ return this.isHorizontalArrow() || this.isVerticalArrow();

return this.keyCode === Keycodes.LEFT ||
this.keyCode === Keycodes.RIGHT;
this.keyCode === Keycodes.RIGHT;
}
isHorizontalArrowWithoutModifiersOtherThanShift() {
return this.isHorizontalArrow() &&
!(this.ctrlKey || this.metaKey || this.altKey);
}
isVerticalArrow() {

@@ -214,2 +215,3 @@ return this.keyCode === Keycodes.UP ||

return (
code !== 0 ||
this.toString().length > 0 ||

@@ -216,0 +218,0 @@ (code >= Keycodes['0'] && code <= Keycodes['9']) || // number keys

@@ -47,3 +47,3 @@ import { addClassName } from '../utils/dom-utils';

this.hide();
this._isDestroyed = true;
this.isDestroyed = true;
}

@@ -50,0 +50,0 @@ }

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

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